docs: FTD-21 résolu partiellement pour /simulation/ee

This commit is contained in:
Hermann_Kitio 2026-04-21 04:54:09 +03:00
parent ae8d8af1df
commit 656b42e6c4
2 changed files with 43 additions and 16 deletions

View file

@ -37,6 +37,27 @@ Chaque entrée suit ce format :
- Code source de `src/entities/user/access.ts` et `lib.ts` avec tests
## 2026-04-21 — FTD-21 — Persistance session `/simulation/ee`
### Added
- `useAutosave(simulationId, contenu, enabled)` : autosave debounce 30 s + flush sur `beforeunload`, dedup par dernier contenu sauvegardé (6 tests).
- `SimulationFlowProvider` hydrate la session au montage depuis `localStorage` (`expria_simulation_id`) → `GET /simulations/:id` → restaure `step='task-selected'` + `production` + `sujet` si `rapport=null` ; nettoie la clé sinon (3 tests resume).
- Types `SimulationState`, `SimulationRapport` + API `getSimulationState`, `autosaveContenu`, `updateSujet` dans `entities/production`.
- Indicateur "Sauvegardé à HH:MM" sous la textarea `SimulationForm` (text-xs, `aria-live="polite"`).
### Changed
- `getReport` délègue désormais à `getSimulationState` et lève `REPORT_NOT_READY` si `rapport=null`. `RapportPage` catche cette erreur et redirige vers `/simulation/ee` avec message discret "Votre simulation est en cours.".
- `SimulationForm` accepte `simulationId`, `initialContenu`, `step` et persiste `expria_simulation_id` dans `localStorage` tant que la simulation est active ; nettoie la clé quand `step='done'`.
- `changeSubject` persiste le changement côté backend via `PATCH /simulations/:id/sujet` (best-effort, silencieux si échec).
### Security
- localStorage ne stocke que `simulation_id` (UUID non-sensible) — conforme SECURITY.md §2.6.
### Notes
- FTD-21 reste ouvert pour `/simulation/eo` (Sprint 4) et `/examen` (Sprint 7).
---
## 2026-04-21 — Tâche G5 — Suggestions d'idées DeepSeek
### Ajouté

View file

@ -270,42 +270,47 @@ Vient du pattern `c.json(result, result.status)` où `result` contient déjà `s
### FTD-21 — Persistance session simulation
**Priorité :** 🔴 Critique
**Statut :** Partiellement résolu — `/simulation/ee` en cours
**Statut :** Partiellement résolu — `/simulation/ee` ✅ (2026-04-21)
**Pages concernées par ordre de priorité :**
🔴 **`/simulation/ee`** (cette session)
- Autosave contenu toutes les 30 s
**`/simulation/ee`** (résolu 2026-04-21)
- Autosave contenu toutes les 30 s (`useAutosave`)
- Save on `beforeunload`
- Reprise au refresh via `localStorage` + `GET /simulations/:id`
- Reprise au refresh via `localStorage` (`expria_simulation_id`) + `GET /simulations/:id`
- `PATCH /simulations/:id/contenu` + `PATCH /simulations/:id/sujet` (Option C)
- `getById` tolère `rapport=null` (Option A)
- `RapportPage` redirige vers `/simulation/ee` si simulation en cours
🟡 **`/simulation/eo`** (Sprint 4)
🟡 **`/simulation/eo`** (Sprint 4 — ouvert)
- Identique EE + état audio/enregistrement
🟡 **`/examen`** (Sprint 7)
🟡 **`/examen`** (Sprint 7 — ouvert)
- Autosave critique — timer inarrêtable + 3 tâches
- Crash pendant examen = perte totale
🟢 **`/sujets`** (inclus dans cette session)
🟢 **`/sujets`** (inclus dans la résolution EE)
- `localStorage simulation_id` suffit
- Pas d'autosave (pas de données saisies)
**Pas nécessaire :** `/dashboard`, `/rapport/:id`, `/historique`, `/progression`
**À faire pour `/simulation/ee` :**
**Résolution EE livrée (2026-04-21) :**
Backend :
- Migration Supabase : ajouter `sujet_id uuid REFERENCES sujets(id)` dans `productions`
- `simulationController` : stocker `sujet_id` à la création
- `GET /simulations/:id` : retourner sujet associé
- Nouveau endpoint `PATCH /simulations/:id/contenu` pour autosave
- `simulationController.create` persiste `sujet_id` à la création
- `getById` retourne `SimulationState` (tolère `rapport=null` pour resume)
- `autosaveContenu` + `updateSujet` controllers (refuse si `rapport !== null`)
- Routes `PATCH /simulations/:id/contenu` + `PATCH /simulations/:id/sujet`
- CORS : `allowMethods` étendu à PATCH/PUT/DELETE
Frontend :
- `localStorage` : stocker/lire `simulation_id` courant
- `SimulationForm` : autosave debounce 30 s + save on `beforeunload`
- `SimulationFlowProvider` : au chargement, détecter simulation en cours via `localStorage``GET /simulations/:id` → restaurer state
- `useAutosave` : debounce 30 s + `beforeunload` flush + dedup par contenu
- `SimulationForm` : hydrate `initialContenu`, affiche "Sauvegardé à HH:MM"
- `SimulationFlowProvider` : hydratation au montage depuis `localStorage` → restaure step `task-selected` si rapport null, nettoie sinon
- `getReport` délègue à `getSimulationState` et throw `REPORT_NOT_READY` si rapport null
**Condition de résolution :** session dédiée après G1-G5 (EE d'abord, EO + examen ultérieurement).
**Condition de résolution complète :** intégration EO (Sprint 4) + examen (Sprint 7).
---
@ -378,3 +383,4 @@ Frontend :
| 1.7 | 2026-04-20 | Ajout FTD-20 🔴 (GET /simulations/:id manquant backend — bloque RapportPage Sprint 3 étape 15) |
| 1.8 | 2026-04-20 | Ajout FTD-21 🔴 (persistance session simulation — prod + sujet perdus au refresh, session dédiée après G1-G5) |
| 1.9 | 2026-04-21 | FTD-22 résolu partiellement (nettoyage code orphelin refonte `/sujets``SujetSelector` + `selectSujet` supprimés ; `choosing-subject` + `goToSubjectPicker` conservés) |
| 1.10 | 2026-04-21 | FTD-21 résolu partiellement pour `/simulation/ee` (autosave 30 s + `beforeunload` + reprise via `localStorage` + `PATCH /:id/contenu` + `PATCH /:id/sujet` + `getById` tolère `rapport=null`) ; EO + examen restent ouverts |