module MoodsHelper # État d'un jour du calendrier : # :filled une tasse a été posée ce jour-là # :guessed pas de tasse posée, on suppose que le mode de la veille continue # :unknown pas de tasse posée, et l'utilisateur ne veut pas de supposition # :empty avant le premier enregistrement # :future après aujourd'hui def day_status(mood, user) return :future if mood[:recorded_at].to_date > Date.current return :filled if mood[:mode].present? return :guessed if mood[:guess].present? && user.guess? return :unknown if mood[:guess].present? && !user.guess? :empty end def mode_for(mood, user) case day_status(mood, user) when :filled then mood[:mode] when :guessed then mood[:guess] end end # Les années du calendrier, la plus récente d'abord ; les mois dans l'ordre à l'intérieur. def history_by_year(history) history.group_by { |month| month[:month].year }.sort_by { |year, _| -year } end def find_day(history, date) history.each do |month| month[:weeks].each do |week| week.each { |mood| return mood if mood[:recorded_at].to_date == date } end end nil end def date_longue(date) l(date, format: "%A %-d %B %Y") end # « de robi », mais « d’Anne » : élision devant une voyelle ou un h muet def de_nom(nom) nom.match?(/\A[aeiouyhàâéèêëîïôöùûü]/i) ? "d’#{nom}" : "de #{nom}" end def libelle_statut(status) case status when :guessed then "supposé" when :unknown then "pas de tasse posée" end end # Un jour du calendrier : un bouton si on peut le choisir, sinon une simple case. # Le journal n'est exposé que s'il est demandé (jamais sur la page publique). def case_jour(mood, user, interactive:, selected: false, journal: false) date = mood[:recorded_at].to_date status = day_status(mood, user) mode = mode_for(mood, user) day_log = mood[:day_log] if journal description = [ date_longue(date), mode&.label, libelle_statut(status), ("journal écrit" if day_log) ].compact.join(", ") classes = [ "jour", "jour-#{status}" ] classes << "jour-journal" if day_log classes << "jour-aujourdhui" if date == Date.current options = { class: classes, style: ("--humeur: #{mode.color}" if mode), title: description } if interactive && status != :future tag.button(type: "button", **options, tabindex: selected ? 0 : -1, "aria-label": description, "aria-pressed": selected.to_s, data: { day: date.iso8601, date: date_longue(date), mode: mode&.label, statut: libelle_statut(status), couleur: mode&.color, image: (mode || Mode.new).image_url, info: day_log&.info, action: "calendrier#choisir keydown->calendrier#naviguer" }) else tag.span(**options, "aria-hidden": true) end end end