- title "Les humeurs de …" (with elision) above both columns - selected date shown above the mode, in ink instead of grey - brief fade when another day is selected (public page and dashboard) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
98 lines
3.7 KiB
JavaScript
98 lines
3.7 KiB
JavaScript
import { Controller } from "@hotwired/stimulus"
|
|
|
|
// 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).
|
|
export default class extends Controller {
|
|
static targets = [ "carte", "image", "date", "mode", "statut", "depuis", "retour", "journal", "lien", "anime" ]
|
|
static values = { aujourdhui: String, aujourdhuiDate: String, aujourdhuiMode: String, aujourdhuiImage: String, aujourdhuiCouleur: String }
|
|
|
|
connect() {
|
|
const selectionne = this.element.querySelector(".jour[aria-pressed='true']")
|
|
if (selectionne && new URLSearchParams(window.location.search).has("day")) {
|
|
selectionne.scrollIntoView({ block: "nearest" })
|
|
}
|
|
}
|
|
|
|
choisir(event) {
|
|
this.selectionner(event.currentTarget)
|
|
}
|
|
|
|
revenir() {
|
|
const aujourdhui = this.element.querySelector(`button.jour[data-day="${this.aujourdhuiValue}"]`)
|
|
if (aujourdhui) this.selectionner(aujourdhui)
|
|
}
|
|
|
|
naviguer(event) {
|
|
const decalages = { ArrowUp: -1, ArrowDown: 1, ArrowLeft: -7, ArrowRight: 7 }
|
|
const decalage = decalages[event.key]
|
|
if (!decalage) return
|
|
|
|
const date = new Date(`${event.currentTarget.dataset.day}T12:00:00`)
|
|
date.setDate(date.getDate() + decalage)
|
|
const cible = this.element.querySelector(`button.jour[data-day="${date.toISOString().slice(0, 10)}"]`)
|
|
if (!cible) return
|
|
|
|
event.preventDefault()
|
|
this.selectionner(cible)
|
|
cible.focus()
|
|
}
|
|
|
|
selectionner(jour) {
|
|
const precedent = this.element.querySelector(".jour[aria-pressed='true']")
|
|
if (precedent) {
|
|
precedent.setAttribute("aria-pressed", "false")
|
|
precedent.tabIndex = -1
|
|
}
|
|
jour.setAttribute("aria-pressed", "true")
|
|
jour.tabIndex = 0
|
|
this.animer()
|
|
|
|
// 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
|
|
this.carteTarget.style.setProperty("--humeur", couleur || "")
|
|
this.imageTarget.src = image
|
|
this.modeTarget.textContent = mode || "Pas de tasse posée"
|
|
this.statutTarget.textContent = mode ? (statut || "") : ""
|
|
|
|
this.dateTarget.textContent = date
|
|
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}`)
|
|
}
|
|
|
|
afficherAujourdhui() {
|
|
this.carteTarget.style.setProperty("--humeur", this.aujourdhuiCouleurValue)
|
|
this.imageTarget.src = this.aujourdhuiImageValue
|
|
this.modeTarget.textContent = this.aujourdhuiModeValue
|
|
this.dateTarget.textContent = this.aujourdhuiDateValue
|
|
this.depuisTarget.hidden = false
|
|
this.retourTarget.hidden = true
|
|
history.replaceState({}, "", window.location.pathname)
|
|
}
|
|
|
|
// Un bref fondu signale que le détail a changé, même quand le mode est le même
|
|
animer() {
|
|
this.animeTargets.forEach((element) => {
|
|
element.classList.remove("apparition")
|
|
void element.offsetWidth
|
|
element.classList.add("apparition")
|
|
})
|
|
}
|
|
}
|