# Chantier — Refonte UX liste des missions techniciens (mobile)

> ## ✅ CHANTIER LIVRÉ EN PRODUCTION
> **Vérifié le 2026-05-29** — Ne plus relire pour valider la livraison.

**Date** : 2026-04-29
**Repo** : coolcare-app (puis port à prévoir sur missioflow-app)
**Contexte** : Incident 2026-04-28 — un technicien a confondu deux interventions sur le même site (machine GF1 vs GF2, même type, même jour). Le PDF rendu correct mais avec le mauvais intitulé machine. Cause racine : sur la carte mobile actuelle, le nom de la machine est noyé dans la ligne meta (gris clair, taille égale à date/type) et identique au site → seul le nom machine différencie, pas assez visible.

## Périmètre

- **Vue impactée** : `public/historique.php`, fonction `renderMobileCards` (ligne 1006+) et CSS `.mobile-card*` (ligne 181+).
- **Mobile only** — la version desktop (DataTables) reste inchangée. Les techniciens utilisent exclusivement la PWA mobile en intervention.
- **Doit fonctionner hors ligne** — toute la logique est côté front sur les données déjà cachées par la PWA.

## Décisions validées (entretien 2026-04-29)

| # | Choix | Détail |
|---|-------|--------|
| 1 | 2 onglets | "En cours" / "Terminées". Annulées cachées par défaut. |
| 2 | Compteurs onglets | Affichage du nombre dans chaque onglet : "En cours (12) · Terminées (98)" |
| 3 | Tri | Par date, aujourd'hui en haut, puis demain, après-demain… (chronologique ascendant côté futur ; passé en bas). À ajuster si dérangeant. |
| 4 | Labels date | "Aujourd'hui — 30 avr. 2026" / "Demain — 1er mai 2026" / "Hier — 29 avr. 2026" / autres dates en clair. |
| 5 | Missions en retard | Restent sous leur date d'origine, mais badge "⏰ En retard" sur la carte. |
| 6 | Modal de confirmation | **Seulement** sur les missions en doublon (même site + même date + machines différentes). Pas de modal pour les missions uniques. |
| 7 | Offline | Tout fonctionne offline (groupement + détection doublons + modal sur les données cachées). |
| 8 | Scope | Mobile only. Desktop inchangé. |

## Comportement final attendu

### Carte mobile redesignée (option A)
```
┌──────────────────────────────────────┐
│ SITE TEST                          → │  ← titre site (gras, 1rem)
│ 🏭 machine GF2                       │  ← machine (gras, 0.95rem, bleu primaire)
│ 30 avr. 2026 · maintenance           │  ← meta secondaire (gris, 0.82rem)
│ [Planifiée]                          │
└──────────────────────────────────────┘
```

### Carte mobile en doublon détecté (option C)
```
┌🟧 SITE TEST  ⚠️                    → │  ← bordure orange à gauche, picto alerte
│ 🏭 machine GF2                       │  ← machine surlignée (jaune pâle)
│ 30 avr. 2026 · maintenance           │
│ [Planifiée]                          │
└──────────────────────────────────────┘
```

### Modal de confirmation (option E, déclenchée uniquement si doublon)
```
⚠️ Plusieurs missions sur SITE TEST aujourd'hui

Tu vas commencer la mission sur :
┌──────────────────────────────┐
│ 🏭 machine GF2               │
│ Daikin – RXYQ8U              │
│ N° série : 12345             │
│ 📍 Local technique R+2       │
└──────────────────────────────┘
Type : Maintenance

[Annuler]              [✓ Continuer]
```

### Onglets sous le header
```
─────────────────────────────────
 [ En cours (12) ]  Terminées (98)
─────────────────────────────────
📅 Aujourd'hui — 30 avr. 2026
  ┌─ carte mission 1 ─┐
  ┌─ carte mission 2 ─┐
📅 Demain — 1er mai 2026
  ┌─ carte mission 3 ─┐
─────────────────────────────────
```

## Plan d'implémentation (3 étapes testables séparément)

### Étape 1 — Option A : refonte visuelle carte
- Modifier `renderMobileCards` (`public/historique.php` ligne 1006+) : machine sortie de la zone meta, ligne dédiée avec icône.
- CSS `.mobile-card-machine` : font-weight 600, font-size 0.95rem, couleur primaire, icône 🏭.
- Bénéfice immédiat sur tous les cas (pas que doublons).

### Étape 2 — Onglets + groupement par date
- Ajouter 2 boutons d'onglet sous `.page-header` (HTML + CSS sticky).
- Filtrer `interventionsData` par statut selon onglet sélectionné :
  - En cours = `planifiee | en_cours | en_attente | reportee`
  - Terminées = `terminee` (annulées exclues)
- Compteurs dynamiques sur les onglets.
- Grouper par date dans le rendu : map `{date_iso → [interventions]}` triée chronologiquement.
- Pour chaque groupe, en-tête sticky avec label intelligent (Aujourd'hui/Demain/Hier/date).
- Détection retard : `date_prevue < today && statut !== terminee && statut !== annulee` → badge "⏰ En retard" sur la carte.

### Étape 3 — Option C + E : alerte doublons + modal
- Côté JS au render : détecter les groupes `(site_id, date_jour, type_intervention)` ayant plusieurs interventions avec `machine_id` différents.
- Marquer ces cartes `.mobile-card--doublon` (CSS bordure orange + machine surlignée + picto ⚠️).
- Override du `onclick` sur ces cartes : ouvrir une modal au lieu d'aller directement sur `intervention_etapes.php`.
- Modal récap : nom machine + marque/modèle + n° série + localisation + type. Boutons Annuler / Continuer.

## Tests

- Local : stack `docker-compose.local-test.yml` (BDD locale isolée).
- Vérifier : compte technicien avec ≥2 missions du jour sur même site / machines différentes pour valider C + E.
- Vérifier offline : kill BDD, recharge la page → cartes rendues depuis cache, modal fonctionnelle.
- DataTables desktop : aucune régression (la fonction qui peuple `dataTable` reste inchangée).

## Validation

- [x] Étape 1 testée et validée visuellement (carte avec machine en sous-titre bleu)
- [x] Étape 2 testée et validée visuellement (onglets + groupement par date avec labels intelligents + badge En retard)
- [x] Étape 3 testée et validée visuellement (bordure orange + machine surlignée + modal de confirmation)
- [x] Test offline OK (templates matérialisés au prefetch automatique)
- [x] Test desktop : pas de régression (modifs CSS sont en @media mobile uniquement, DataTables intact)
- [x] Commit 1 : `6d7abf3` "feat(historique/mobile): refonte UX liste missions techniciens"
- [x] Commit 2 : `cbb31c9` "feat(historique/desktop): meme rendu que mobile (cartes + onglets)" — tableau DataTables masqué, cartes/onglets centrés 900px sur grand écran
- [x] Push prod 2026-04-29 (1 seule session authentifiée active = utilisateur lui-même)
- [x] Markdown port créé pour missioflow-app : `missioflow-app/docs/CHANTIER_MISSIONS_TECHNICIEN_UX.md` (mis à jour avec les 2 commits)

## Décisions clés actées (option D vraie pour la détection)

Après débat, on N'A PAS retenu l'option D1 (heuristique type+marque+modèle) car elle rate le cas "même machine modèle mais template_id_override admin différent". On a retenu l'**option D vraie** (clé d'identité du template effectif) :

```
templateKey = report_template_id_override
            ?? report_template_id_selected
            ?? template_name@version (snapshot enrichi via prefetch)
            ?? null  (silencieux, pas d'alerte)
```

La chaîne offline est compatible : sur entrée historique.php en ligne, le prefetch automatique appelle `intervention_workflow.php?id=X` ce qui déclenche `createWorkflow` côté serveur et matérialise `report_template_id_selected` + écrit en IndexedDB. Le tech peut ensuite passer offline avec toutes les données.

## Fichiers modifiés

**Commit 6d7abf3 (refonte mobile)** :
- `public/historique.php` : +657 lignes (HTML onglets + modal, CSS scoped, JS détection/groupement/modal)
- `public/css/responsive.css` : +60 lignes (header mobile : logo + boutons row + nom dessous, cas 3 boutons via `:has()`)
- `public/intervention_etapes.php` : 2 lignes (label "Tableau de bord" → "Accueil")
- `public/profile.php` : 2 lignes (idem)

**Commit cbb31c9 (alignement desktop)** :
- `public/historique.php` : +15 -11 lignes (sortie des règles `.mobile-*` du media query, masquage tableau DataTables, max-width 900px sur cartes/onglets en desktop)

Total cumulé : 4 fichiers, 100% frontend, 0 backend. Aucune migration BDD, aucun endpoint API touché, aucun fichier de test modifié (pre-commit hook PHPUnit 3622 tests OK sur les 2 commits).

## Port missioflow-app

Plan détaillé dans `missioflow-app/docs/CHANTIER_MISSIONS_TECHNICIEN_UX.md`. Le repo missioflow-app est un fork SaaS de coolcare-app : la structure des fichiers `public/historique.php` + `public/css/responsive.css` + `public/profile.php` + `public/intervention_etapes.php` est identique. Le port est essentiellement un cherry-pick avec adaptation du logo et des libellés tenant si besoin.
