## Fonctionnel - Calendrier MalioDate en vue Jour (écrans Heures ET Heures Conducteurs) : les jours entièrement validés par un admin sont peints en vert. - Endpoint `GET /work-hours/validation-status?from=&to=[&driver=1]` (scope conducteur inversé via `driver=1`), périmètre complet (ignore le filtre sites). - Chargement à la volée par mois (event `@month-change`), refresh après validation / saisie / absence. ## Harmonisation @malio/layer-ui 1.7.11 - `reserveMessageSpace=false` sur tous les champs (alignement). - Tous les drawers migrés sur `MalioDrawer` (titre via slot `#header`, `AppDrawer` custom supprimé). - Boutons d'action en `MalioButton` ; deux boutons côte à côte partagent l'espace. - Inputs date en `MalioDate`, sélecteur semaine en `MalioDateWeek`. - Boutons d'ajout uniformisés sur « Ajouter » + icône. ## Divers - `.env` : `EXCLUDED_PUBLIC_HOLIDAYS="null"`. - Doc : `doc/hours-validated-days.md`, `documentation-content.ts`, `CLAUDE.md`. - Tests : provider `WorkHourValidationStatus` (suite complète 236/236 OK via pre-commit hook). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #30 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
4.5 KiB
Calendrier des jours validés (écran Heures — vue Jour)
Objectif
Sur l'écran Heures, en vue Jour, le sélecteur de date est un calendrier
(composant MalioDate du layer @malio/layer-ui) qui peint en vert les jours
entièrement validés par un admin. La RH repère ainsi d'un coup d'œil les jours où
il reste de la validation à faire.
Définition « jour validé » (vert)
Un jour est vert ssi, dans le périmètre complet de l'utilisateur :
- il porte au moins une ligne
WorkHourdans le scope ciblé ce jour-là, et - aucune de ces lignes n'est en attente de validation (
isValid = false).
La même mécanique sert les deux écrans, avec un scope opposé : écran Heures →
non-conducteurs (défaut) ; écran Heures Conducteurs → conducteurs (?driver=1).
Conséquences :
- Un jour sans aucune ligne (rien saisi, ex. week-end, jour futur) reste neutre (jamais vert) — « rien fait » n'est pas « tout validé ».
- On se base sur la seule colonne
work_hours.is_valid(validation admin/RH).isSiteValid(chef de site) n'entre pas en compte → modifier une validation site ne change pas la couleur. - Scope conducteur : écran Heures → conducteurs exclus ; écran Heures Conducteurs →
seuls les conducteurs (le filtre est inversé via
?driver=1).
Périmètre
ROLE_ADMIN→ tous les employés / tous les sites.- Chef de site → ses sites uniquement.
- Le filtre sites de l'écran est volontairement ignoré : le vert reflète tout le périmètre (objectif : repérer le moindre jour incomplet, où qu'il soit). Changer le filtre sites de la vue Jour ne recalcule pas le calendrier.
Chargement des données
- Endpoint :
GET /work-hours/validation-status?from=YYYY-MM-DD&to=YYYY-MM-DD[&driver=1](ROLE_USER). Réponse :{ from, to, validatedDays: string[] }(datesY-m-d). - Provider :
App\State\WorkHourValidationStatusProvider(ressourceApp\ApiResource\WorkHourValidationStatus).EmployeeRepository::findScoped($user)pour le périmètre (ignore toutsiteIds).- Une requête
WorkHourReadRepositoryInterface::findByDateRangeAndEmployees. - Filtrage conducteur par date via
EmployeeContractResolver::resolveIsDriverForEmployeeAndDate(mémoïsé par couple employé/jour) :if ($isDriver !== $driverOnly) continue;(driverOnly=?driver=1). - Agrégation par jour : vert ⇔
total > 0(lignes du scope) etpending = 0(aucuneisValid=false). - Garde-fou : plage bornée à 366 jours.
- Le chargement est à la volée par mois affiché (jamais préchargé sur plusieurs
années) :
MalioDateémet@month-change { month, year }à l'ouverture du popover et à chaque navigation ; le front fetch la grille visible (lundi avant le 1er → dimanche après le dernier jour, pour colorer aussi les jours débordants) et met le résultat en cache par mois (useHoursPage/useDriverHoursPage→validatedDaysByMonth; ce dernier appelle le service avec{ driver: true }). La prop réactivemarkedDates(ISO →'success') recolore la grille.
Rafraîchissement
Toute action qui touche la validation d'un jour recharge le mois concerné s'il est en
cache (reloadValidationMonth), donc le calendrier se recolore aussitôt :
- validation admin d'une ligne (
toggleValidation) ou en masse (toggleValidationBulk) ; - sauvegarde d'heures (
handleSave) — toute modification réelle remetisValid=false; - création / suppression d'absence (
refreshAfterAbsenceChange). La validation site ne déclenche pas de rechargement (sans effet sur le vert).
Périmètre d'affichage
- Vue Jour uniquement : le vert (calendrier
MalioDate+markedDates) est à la maille jour, sur les deux écrans (Heures et Heures Conducteurs, viashowValidationCalendar). La vue Semaine utilise unMalioDateWeek(sélecteur de semaine, sans coloration). LePeriodStepperPickerne subsiste que comme fallback de la vue Jour quandshowValidationCalendarest absent (aucun appelant actuel, conservé par flexibilité). - Précédence d'affichage dans la grille (côté layer) : sélection (fond plein primary) >
variante marquée ; le jour courant (
today) garde sa bordure et reçoit le fond vert s'il est validé.
Dépendance layer
Nécessite @malio/layer-ui >= 1.7.x : prop markedDates
(Record<"YYYY-MM-DD", 'success' | 'danger'>) + event month-change sur MalioDate
(ticket Malio UI MUI-45).