# 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 `