From fe9e127b8530e47e9e65285b8dc0241e0a6ceaa3 Mon Sep 17 00:00:00 2001 From: tristan Date: Wed, 20 May 2026 15:10:25 +0200 Subject: [PATCH] docs : spec de conception du composant MalioDateWeek (#MUI-33) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../specs/2026-05-20-dateweek-design.md | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-20-dateweek-design.md diff --git a/docs/superpowers/specs/2026-05-20-dateweek-design.md b/docs/superpowers/specs/2026-05-20-dateweek-design.md new file mode 100644 index 0000000..5d6d37a --- /dev/null +++ b/docs/superpowers/specs/2026-05-20-dateweek-design.md @@ -0,0 +1,168 @@ +# MalioDateWeek — Design Spec + +Composant de sélection d'une **semaine ISO complète** (lundi→dimanche) via le shell calendrier partagé. Troisième brique de la famille temporelle. + +**Ticket :** MUI-33 (suite) +**Branche :** `feature/MUI-33-developper-le-composant-datepicker` +**Specs liées :** `2026-05-19-datepicker-design.md`, `2026-05-20-daterange-design.md` + +## Périmètre + +Sélection d'une semaine entière en **un clic** (sur n'importe quel jour OU le numéro de semaine). Visuellement : la ligne de la semaine se surligne en pilule `bg-m-primary-light` (lundi arrondi gauche, dimanche arrondi droit), exactement comme une plage `DateRange` figée lun→dim. Survol = aperçu de la semaine. La cellule n° de la semaine sélectionnée passe en `bg-m-primary` (repère). + +**Inclus :** clic jour/n° → semaine, hover de semaine, surlignage pilule, repère n° semaine, bornes `min`/`max` (semaine sélectionnable si elle chevauche), effacement, vue mois conservée. + +**Reporté :** deux mois, saisie/navigation clavier. + +## Donnée retournée + +`modelValue: string | null` au format **ISO 8601 semaine `YYYY-Www`** (ex. `"2026-W21"`), comme l'`` natif. L'année est l'**année ISO de numérotation** (peut différer de l'année calendaire aux bords d'année). Affichage humain dans le champ : `"Semaine 21 (18/05 → 24/05/2026)"` (le `modelValue` reste `2026-W21`). + +## Architecture (Approche 1 — réutilisation du rendu plage) + +Une semaine sélectionnée **est** une plage lundi→dimanche : on réutilise le rendu pilule de `MonthGrid` (mode plage) en passant les bornes de la semaine active. Les events `select`/`hover` (jour) sont réutilisés ; l'enveloppe `DateWeek` mappe jour → semaine. + +``` +app/components/malio/date/ + DateWeek.vue # NOUVEAU — enveloppe + DateWeek.test.ts # nouveau + internal/ + MonthGrid.vue # étendu : interactiveWeekNumber + markedWeekStart (additifs) + CalendarField.vue # inchangé (shell réutilisé) + CalendarHeader.vue # inchangé + MonthPicker.vue # inchangé + composables/ + dateWeek.ts # NOUVEAU — helpers semaine ISO (purs) + dateWeek.test.ts # nouveau + dateRange.ts # inchangé (rendu pilule réutilisé) + dateFormat.ts # inchangé + useCalendarView.ts # inchangé + useCalendarPopover.ts # inchangé + useMonthMatrix.ts # inchangé +app/story/date/dateWeek.story.vue +.playground/pages/composant/date/dateWeek.vue +``` + +Flux : + +``` +DateWeek.vue (enveloppe) + ├─ état : hoverWeekStart (lundi de la semaine survolée) + ├─ validWeek = isValidIsoWeek(modelValue) ? { monday: isoWeekToMonday(modelValue) } : null + ├─ activeMonday = hoverWeekStart ?? validWeek.monday → activeSunday = sundayOf(activeMonday) + ├─ displayValue = formatWeekDisplay(modelValue) + └─ + └─ +``` + +## `dateWeek.ts` (helpers purs) + +```ts +function mondayOf(iso: string): string // "2026-05-20" → "2026-05-18" +function sundayOf(iso: string): string // "2026-05-20" → "2026-05-24" +function toIsoWeek(iso: string): string // "2026-05-20" → "2026-W21" (année ISO + n° semaine) +function isoWeekToMonday(week: string): string | null // "2026-W21" → "2026-05-18" ; invalide → null +function isValidIsoWeek(week: string): boolean // "2026-W21" → true ; "2026-W54"/"2026-21" → false +function formatWeekDisplay(week: string): string // "2026-W21" → "Semaine 21 (18/05 → 24/05/2026)" ; invalide → "" +``` + +- Algo ISO 8601 : jeudi de la semaine pour l'année de numérotation ; lundi de la semaine contenant le 4 janvier = semaine 1. +- `formatWeekDisplay` : `Semaine {n° sans zéro} ({JJ/MM lundi} → {JJ/MM/AAAA dimanche})`, réutilise `formatIsoToDisplay`. +- Cas pièges testés : `2025-12-31` → `2026-W01`, `2027-01-01` → `2026-W53`, `2026-01-01` → `2026-W01`. + +## `MonthGrid.vue` — ajouts additifs + +Nouvelles props optionnelles (n'altèrent pas les modes simple/plage) : +```ts +interactiveWeekNumber?: boolean // défaut false +markedWeekStart?: string | null // défaut null — lundi de la semaine repère +``` + +Quand `interactiveWeekNumber === true` : +- La cellule n° de semaine devient un `