let visitors pick a day on the public page
Clicking a day shows its mode and illustration in the header, with a link back to today. The journal stays private: the calendar helper now separates interactivity from journal exposure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7a7fa4c095
commit
764cb542ac
6 changed files with 101 additions and 28 deletions
|
|
@ -27,6 +27,21 @@ input.bouton {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bouton d'action présenté comme un lien de la charte */
|
||||||
|
button.lien {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
color: var(--encre);
|
||||||
|
font: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration-line: underline;
|
||||||
|
text-decoration-color: var(--vert);
|
||||||
|
text-decoration-thickness: 0.12em;
|
||||||
|
text-underline-offset: 0.2em;
|
||||||
|
}
|
||||||
|
button.lien:hover { text-decoration-color: var(--encre); }
|
||||||
|
|
||||||
/* button_to enveloppe son bouton dans un formulaire : le garder en ligne */
|
/* button_to enveloppe son bouton dans un formulaire : le garder en ligne */
|
||||||
.nav form.button_to { display: inline; }
|
.nav form.button_to { display: inline; }
|
||||||
|
|
||||||
|
|
@ -371,6 +386,8 @@ button.jour:focus-visible {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.public-autre-jour .detail-statut:not(:empty) { margin-right: 0.75rem; }
|
||||||
|
|
||||||
.public-historique h2 {
|
.public-historique h2 {
|
||||||
margin: 2.5rem 0 0.75rem;
|
margin: 2.5rem 0 0.75rem;
|
||||||
font-size: 1.35rem;
|
font-size: 1.35rem;
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,13 @@ module MoodsHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Un jour du calendrier : un bouton pour le propriétaire, une simple case pour les visiteurs.
|
# Un jour du calendrier : un bouton si on peut le choisir, sinon une simple case.
|
||||||
def case_jour(mood, user, interactive:, selected: false)
|
# 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
|
date = mood[:recorded_at].to_date
|
||||||
status = day_status(mood, user)
|
status = day_status(mood, user)
|
||||||
mode = mode_for(mood, user)
|
mode = mode_for(mood, user)
|
||||||
day_log = mood[:day_log] if interactive
|
day_log = mood[:day_log] if journal
|
||||||
|
|
||||||
description = [ date_longue(date), mode&.label, libelle_statut(status), ("journal écrit" if day_log) ].compact.join(", ")
|
description = [ date_longue(date), mode&.label, libelle_statut(status), ("journal écrit" if day_log) ].compact.join(", ")
|
||||||
classes = [ "jour", "jour-#{status}" ]
|
classes = [ "jour", "jour-#{status}" ]
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
import { Controller } from "@hotwired/stimulus"
|
import { Controller } from "@hotwired/stimulus"
|
||||||
|
|
||||||
// Calendrier des humeurs : choisir un jour affiche son détail (illustration, mode, journal).
|
// Calendrier des humeurs : choisir un jour affiche son détail (illustration, mode, et
|
||||||
|
// sur le tableau de bord, le journal). Sert au tableau de bord comme à la page publique :
|
||||||
|
// chaque cible est facultative.
|
||||||
// Au clavier, les flèches se déplacent d'un jour (haut, bas) ou d'une semaine (gauche, droite).
|
// Au clavier, les flèches se déplacent d'un jour (haut, bas) ou d'une semaine (gauche, droite).
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = [ "carte", "image", "date", "mode", "statut", "journal", "lien" ]
|
static targets = [ "carte", "image", "date", "qui", "mode", "statut", "depuis", "retour", "journal", "lien" ]
|
||||||
|
static values = { nom: String, aujourdhui: String, aujourdhuiMode: String, aujourdhuiImage: String, aujourdhuiCouleur: String }
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
const selectionne = this.element.querySelector(".jour[aria-pressed='true']")
|
const selectionne = this.element.querySelector(".jour[aria-pressed='true']")
|
||||||
if (selectionne && new URLSearchParams(window.location.search).has("day")) {
|
if (selectionne && new URLSearchParams(window.location.search).has("day")) {
|
||||||
selectionne.scrollIntoView({ block: "center" })
|
selectionne.scrollIntoView({ block: "nearest" })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16,6 +19,11 @@ export default class extends Controller {
|
||||||
this.selectionner(event.currentTarget)
|
this.selectionner(event.currentTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revenir() {
|
||||||
|
const aujourdhui = this.element.querySelector(`button.jour[data-day="${this.aujourdhuiValue}"]`)
|
||||||
|
if (aujourdhui) this.selectionner(aujourdhui)
|
||||||
|
}
|
||||||
|
|
||||||
naviguer(event) {
|
naviguer(event) {
|
||||||
const decalages = { ArrowUp: -1, ArrowDown: 1, ArrowLeft: -7, ArrowRight: 7 }
|
const decalages = { ArrowUp: -1, ArrowDown: 1, ArrowLeft: -7, ArrowRight: 7 }
|
||||||
const decalage = decalages[event.key]
|
const decalage = decalages[event.key]
|
||||||
|
|
@ -40,17 +48,42 @@ export default class extends Controller {
|
||||||
jour.setAttribute("aria-pressed", "true")
|
jour.setAttribute("aria-pressed", "true")
|
||||||
jour.tabIndex = 0
|
jour.tabIndex = 0
|
||||||
|
|
||||||
|
// Sur la page publique, aujourd'hui montre la dernière tasse posée et depuis quand
|
||||||
|
if (jour.dataset.day === this.aujourdhuiValue && this.hasDepuisTarget) {
|
||||||
|
this.afficherAujourdhui()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const { day, date, mode, statut, couleur, image, info } = jour.dataset
|
const { day, date, mode, statut, couleur, image, info } = jour.dataset
|
||||||
this.carteTarget.style.setProperty("--humeur", couleur || "")
|
this.carteTarget.style.setProperty("--humeur", couleur || "")
|
||||||
this.imageTarget.src = image
|
this.imageTarget.src = image
|
||||||
this.dateTarget.textContent = date
|
|
||||||
this.modeTarget.textContent = mode || "Pas de tasse posée"
|
this.modeTarget.textContent = mode || "Pas de tasse posée"
|
||||||
this.statutTarget.textContent = mode ? (statut || "") : ""
|
this.statutTarget.textContent = mode ? (statut || "") : ""
|
||||||
this.journalTarget.textContent = info || this.journalTarget.dataset.vide
|
|
||||||
this.journalTarget.classList.toggle("detail-journal-vide", !info)
|
if (this.hasDateTarget) this.dateTarget.textContent = date
|
||||||
this.lienTarget.href = `/day_logs/edit?day=${day}`
|
if (this.hasQuiTarget) this.quiTarget.textContent = `Le ${date} chez ${this.nomValue}`
|
||||||
this.lienTarget.textContent = info ? "Modifier le journal" : "Écrire dans le journal"
|
if (this.hasDepuisTarget) this.depuisTarget.hidden = true
|
||||||
|
if (this.hasRetourTarget) this.retourTarget.hidden = false
|
||||||
|
|
||||||
|
if (this.hasJournalTarget) {
|
||||||
|
this.journalTarget.textContent = info || this.journalTarget.dataset.vide
|
||||||
|
this.journalTarget.classList.toggle("detail-journal-vide", !info)
|
||||||
|
}
|
||||||
|
if (this.hasLienTarget) {
|
||||||
|
this.lienTarget.href = `/day_logs/edit?day=${day}`
|
||||||
|
this.lienTarget.textContent = info ? "Modifier le journal" : "Écrire dans le journal"
|
||||||
|
}
|
||||||
|
|
||||||
history.replaceState({}, "", `?day=${day}`)
|
history.replaceState({}, "", `?day=${day}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afficherAujourdhui() {
|
||||||
|
this.carteTarget.style.setProperty("--humeur", this.aujourdhuiCouleurValue)
|
||||||
|
this.imageTarget.src = this.aujourdhuiImageValue
|
||||||
|
this.modeTarget.textContent = this.aujourdhuiModeValue
|
||||||
|
this.quiTarget.textContent = `Aujourd’hui chez ${this.nomValue}`
|
||||||
|
this.depuisTarget.hidden = false
|
||||||
|
this.retourTarget.hidden = true
|
||||||
|
history.replaceState({}, "", window.location.pathname)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<%# Calendrier des humeurs « à la GitHub » : une colonne par semaine, une ligne par jour,
|
<%# Calendrier des humeurs « à la GitHub » : une colonne par semaine, une ligne par jour,
|
||||||
regroupé par mois. Par défaut, un bloc par année, la plus récente d'abord ;
|
regroupé par mois. Par défaut, un bloc par année, la plus récente d'abord ;
|
||||||
avec par_annee: false, tous les mois à la suite (l'année est ajoutée aux mois d'une autre année). %>
|
avec par_annee: false, tous les mois à la suite (l'année est ajoutée aux mois d'une autre année). %>
|
||||||
<%# locals: (history:, user:, interactive: false, selected_date: nil, par_annee: true) -%>
|
<%# locals: (history:, user:, interactive: false, journal: false, selected_date: nil, par_annee: true) -%>
|
||||||
<% blocs = par_annee ? history_by_year(history) : [ [ nil, history ] ] %>
|
<% blocs = par_annee ? history_by_year(history) : [ [ nil, history ] ] %>
|
||||||
<div class="calendrier-humeurs">
|
<div class="calendrier-humeurs">
|
||||||
<% blocs.each do |year, months| %>
|
<% blocs.each do |year, months| %>
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
<h3 class="mois-nom"><%= l(month[:month], format: year || month[:month].year == Date.current.year ? "%B" : "%B %Y") %></h3>
|
<h3 class="mois-nom"><%= l(month[:month], format: year || month[:month].year == Date.current.year ? "%B" : "%B %Y") %></h3>
|
||||||
<div class="mois-jours">
|
<div class="mois-jours">
|
||||||
<% month[:weeks].flatten.each do |mood| %>
|
<% month[:weeks].flatten.each do |mood| %>
|
||||||
<%= case_jour(mood, user, interactive: interactive,
|
<%= case_jour(mood, user, interactive: interactive, journal: journal,
|
||||||
selected: mood[:recorded_at].to_date == selected_date) %>
|
selected: mood[:recorded_at].to_date == selected_date) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<div class="tableau-calendrier">
|
<div class="tableau-calendrier">
|
||||||
<h1 class="tableau-titre">Mes humeurs</h1>
|
<h1 class="tableau-titre">Mes humeurs</h1>
|
||||||
<%= render "moods/legende", user: @user, journal: true %>
|
<%= render "moods/legende", user: @user, journal: true %>
|
||||||
<%= render "moods/calendrier", history: history, user: @user, interactive: true, selected_date: selected_date %>
|
<%= render "moods/calendrier", history: history, user: @user, interactive: true, journal: true, selected_date: selected_date %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<aside class="detail" aria-live="polite" aria-label="Jour sélectionné">
|
<aside class="detail" aria-live="polite" aria-label="Jour sélectionné">
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,52 @@
|
||||||
<% content_for :title, "Comment ça Kluk chez #{@user.username} ?" %>
|
<% content_for :title, "Comment ça Kluk chez #{@user.username} ?" %>
|
||||||
<% mode = @user.moods.last&.mode %>
|
<% history = MoodCalendarService.generate_calendar(@user, start_date: 5.months.ago.beginning_of_month, end_date: Date.current) %>
|
||||||
|
<% selected_date = (Date.parse(params[:day]) rescue Date.current) %>
|
||||||
|
<% selected = find_day(history, selected_date) if selected_date < Date.current %>
|
||||||
|
<% selected_date = Date.current unless selected %>
|
||||||
|
<% aujourdhui = selected_date == Date.current %>
|
||||||
|
<% mode_du_jour = @user.moods.last&.mode %>
|
||||||
|
<% mode = aujourdhui ? mode_du_jour : mode_for(selected, @user) %>
|
||||||
|
<% status = day_status(selected, @user) unless aujourdhui %>
|
||||||
<% since = @user.current_mode_since %>
|
<% since = @user.current_mode_since %>
|
||||||
|
|
||||||
<article class="public">
|
<article class="public" data-controller="calendrier"
|
||||||
<figure class="carte-humeur carte-humeur-grande" style="<%= "--humeur: #{mode.color}" if mode %>">
|
data-calendrier-nom-value="<%= @user.username %>"
|
||||||
<%= image_tag (mode || Mode.new).image_url, alt: "" %>
|
data-calendrier-aujourdhui-value="<%= Date.current.iso8601 %>"
|
||||||
|
data-calendrier-aujourdhui-mode-value="<%= mode_du_jour&.label || "Pas de tasse posée" %>"
|
||||||
|
data-calendrier-aujourdhui-image-value="<%= (mode_du_jour || Mode.new).image_url %>"
|
||||||
|
data-calendrier-aujourdhui-couleur-value="<%= mode_du_jour&.color %>">
|
||||||
|
<figure class="carte-humeur carte-humeur-grande" data-calendrier-target="carte" style="<%= "--humeur: #{mode.color}" if mode %>">
|
||||||
|
<%= image_tag (mode || Mode.new).image_url, alt: "", data: { calendrier_target: "image" } %>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
<div class="public-texte">
|
<div class="public-texte" aria-live="polite">
|
||||||
<p class="public-qui">Aujourd’hui chez <%= @user.username %></p>
|
<p class="public-qui" data-calendrier-target="qui">
|
||||||
<h1 class="public-mode"><%= mode&.label || "Pas encore de tasse posée" %></h1>
|
<% if aujourdhui %>
|
||||||
<% if since %>
|
Aujourd’hui chez <%= @user.username %>
|
||||||
<p class="public-depuis">
|
<% else %>
|
||||||
|
Le <%= date_longue(selected_date) %> chez <%= @user.username %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
<h1 class="public-mode" data-calendrier-target="mode"><%= mode&.label || "Pas de tasse posée" %></h1>
|
||||||
|
<p class="public-depuis">
|
||||||
|
<span data-calendrier-target="depuis" <%= "hidden" unless aujourdhui %>>
|
||||||
<% if since == Date.current %>
|
<% if since == Date.current %>
|
||||||
Depuis ce matin.
|
Depuis ce matin.
|
||||||
<% else %>
|
<% elsif since %>
|
||||||
Depuis le <%= l(since, format: since.year == Date.current.year ? "%A %-d %B" : "%-d %B %Y") %>.
|
Depuis le <%= l(since, format: since.year == Date.current.year ? "%A %-d %B" : "%-d %B %Y") %>.
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</span>
|
||||||
<% end %>
|
<span class="public-autre-jour" data-calendrier-target="retour" <%= "hidden" if aujourdhui %>>
|
||||||
|
<span class="detail-statut" data-calendrier-target="statut"><%= libelle_statut(status) if mode %></span>
|
||||||
|
<button type="button" class="lien" data-action="calendrier#revenir">Revenir à aujourd’hui</button>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
<section class="public-historique" aria-labelledby="public-historique-titre">
|
<section class="public-historique" aria-labelledby="public-historique-titre">
|
||||||
<h2 id="public-historique-titre">Les derniers mois</h2>
|
<h2 id="public-historique-titre">Les derniers mois</h2>
|
||||||
<%= render "moods/legende", user: @user %>
|
<%= render "moods/legende", user: @user %>
|
||||||
<%= render "moods/calendrier", user: @user, par_annee: false,
|
<%= render "moods/calendrier", history: history, user: @user, par_annee: false,
|
||||||
history: MoodCalendarService.generate_calendar(@user, start_date: 5.months.ago.beginning_of_month, end_date: Date.current) %>
|
interactive: true, selected_date: selected_date %>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue