# Changelog — Expria Frontend Toutes les modifications notables du projet frontend sont documentées dans ce fichier. Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/). ## Convention Chaque entrée suit ce format : ``` ## [Unreleased] — YYYY-MM-DD — Session ### Added (nouveautés) - ... ### Changed (modifications) - ... ### Fixed (corrections) - ... ### Removed (suppressions) - ... ### Security (sécurité) - ... ``` --- ## [Unreleased] ### Added - Documentation initiale du projet (ARCHITECTURE, ONBOARDING, SECURITY, etc.) - 5 ADRs pour les décisions architecturales majeures - Code source de `src/entities/user/access.ts` et `lib.ts` avec tests ## [Unreleased] — 2026-04-22 — Sprint 3.5 — Clean post-Sprint 3 ### Changed - **FTD-17 résolu** : `PLAN_QUERY_KEY` centralisé dans `src/entities/user/query-keys.ts` (constantes pures, aucun import runtime). `usePlan` le ré-exporte ; `SimulationPage` et `RapportPage` remplacent leur `useQuery` inline par le hook `usePlan()` — déduplication totale de la clé et de la config `staleTime`. - **FTD-18 résolu** : `SimulationForm` migré de `@/shared/components/ui/button` (shadcn) vers la primitive canonique `@/shared/ui/Button`. Aucun variant à adapter (usage sans prop `variant`). - **FTD-19 résolu** : token `--shadow-focus` ajouté dans `@theme {}` (`0 0 0 3px rgba(27, 79, 216, 0.18)` — conforme `DESIGN_SYSTEM.md §2`) et dans `.dark {}` (recalculé sur la teinte expria dark). Migration de 5 occurrences `ring-2 ring-expria/20` → utility `shadow-focus` dans `Button`, `Card`, `SimulationForm` (×3), `SpecialCharsKeyboard`. - Factorisation `SimulationForm` : className dupliquée des deux boutons secondaires (« Suggestions d'idées » / « Changer de sujet ») extraite en const locale `secondaryActionBtn`. - `TECH_DEBT.md` → v1.11. 15 FTD actives (cap de 15 respecté). ### Notes - Timeouts DeepSeek intermittents observés pendant les tests manuels Groupe B + C — cause externe (API tierce), hors périmètre refactor Sprint 3.5. - B8 : comportement actuel diffère du spec `PARCOURS_UTILISATEURS.md §2 "Quota atteint"` — affichage d'une bannière inline au lieu du modal de blocage attendu. À corriger dans un sprint dédié (non inclus dans ce clean, qui n'introduit aucune nouvelle fonctionnalité). ## [Unreleased] — 2026-04-22 — Sprint 3.6b — Qualité correction — Frontend ### Added - `NclcCibleSelector` (segmented control NCLC 9 / NCLC 10) dans `SimulationForm` — valeur propagée au payload `POST /corrections/ee` via `SimulationFlowProvider.submitText(texte, nclcCible)`. - Composants `rapport/` dans `features/simulations/components/` : - `ScoreHero` — score /20, jauge avec marqueur du seuil NCLC cible, écart vs objectif (« X points avant NCLC 9 »), badges NCLC atteint / cible. - `RevelationCards` — 3 colonnes : ce que le candidat croit / ce que le correcteur observe / conséquence. - `DiagnosticCallout` — callout « Ce qui freine votre progression ». - `CritereCard` — carte enrichie par critère (exemple / suggestion / astuce + badges codes taxonomie). - `ConseilNclcCallout` — plan d'action NCLC (objectif, écart, action prioritaire). - `ExerciceInteractive` — carte exercice avec zone texte, bouton Indice (révélé une fois), bouton « Voir la correction » (activé après saisie), explication. - `ProductionModeleSection` — texte final + notes pédagogiques + transformations original/amélioré + message encourageant. - `JobStatusFallback` — fallback pour `exercices_status` / `modele_status` en `'pending'` ou `'error'`. - Helpers dans `entities/report/lib.ts` : `groupErreursByCritere`, `ecartVsCible`, `critereCodeFromNom`. - Tests `ExerciceInteractive.test.tsx` (6 tests) — couvre état interne : révélation unique indice, activation bouton correction, affichage correction + explication. - FTD-24 🟡 dans `TECH_DEBT.md` — polling automatique pour exercices/modèle `pending` (refresh manuel en MVP). ### Changed - `entities/report/types.ts` — refonte complète alignée sur le backend Sprint 3.6a : `Report` remplace l'ancien (revelation, diagnostic, criteres enrichis, conseil_nclc, erreurs_codes top-level, exercices dynamiques, modele structuré, statuts pending/ready/error). Suppression de `feedback_court`, `erreurs[]`, `modele:string`, `idees[]` (obsolètes). - `entities/report/lib.ts` — `BlurableSection` réduite à `'criteres' | 'exercices' | 'modele'` : `revelation`, `diagnostic`, `conseil_nclc` deviennent visibles pour tous les plans conformément à PLANS_TARIFAIRES.md §2. - `entities/production/types.ts` — `SimulationState` étendu avec `nclc_cible`, `exercices`, `exercices_status`, `modele`, `modele_status` ; `SimulationRapport` aligné sur `CorrectionRapport` backend. - `entities/report/api.ts` — `getReport` recombine `SimulationState.rapport` + `exercices` + `modele` + statuts en un `Report` unifié pour `useRapport`. - `RapportPage.tsx` — réécriture complète : câble tous les nouveaux composants, branche le gating plan via `isSectionVisible`, affiche `JobStatusFallback` pour les jobs asynchrones. Résout l'écran blanc post-Sprint 3.6a. - `floutage.test.ts` réécrit (17 tests — matrice de visibilité + helpers lib). ### Fixed - **Race condition `modele_status`** (backend) : l'update principal de correction écrasait `modele_status='ready'` déjà posé par `runModeleJob` (lancé en parallèle option b). `correctionController.correctEE` ne touche plus aux colonnes `*_status` — pilotées exclusivement par les jobs asynchrones. - **Boucle infinie retour rapport → SimulationPage** : le useEffect sticky `step === 'done' → navigate('/rapport/:id')` renvoyait l'utilisateur sur le rapport à chaque tentative de retour vers `/simulation/ee`. Supprimé ; la navigation initiale vers `/rapport/:id` est déclenchée une seule fois dans `correctMutation.onSuccess` du provider. - **Boucle retour /sujets → SimulationPage** : même pattern sticky pour `step === 'choosing-subject' → navigate('/sujets')`. Supprimé ; navigation initiale vers `/sujets` déplacée dans `createMutation.onSuccess`. - **RapportPage hors SimulationFlowProvider** : la route `/rapport/:id` n'était pas sous `SimulationFlowLayout` — l'appel à `useSimulation()` depuis RapportPage throw. Route déplacée sous le layout, l'instance du provider est partagée avec `/simulation/ee` et `/sujets`. ### Added - Bouton « Nouvelle simulation » en bas de `RapportPage` qui `reset()` + `navigate('/simulation/ee')`. - `reset()` explicite dans le bouton « ← Retour » de `SujetsPage` avant la navigation, pour empêcher tout re-déclenchement de la garde sticky. ### Changed - Navigations post-mutation déplacées dans `onSuccess` du provider (pattern cohérent pour `createMutation` → `/sujets` et `correctMutation` → `/rapport/:id`). Plus de useEffect réactif aux changements de `step` côté SimulationPage. - `SujetsPage` : garde étendue de `!production` à `!production \|\| step === 'idle' \|\| step === 'done'` pour couvrir le cas post-rapport (évite le 400 VALIDATION_ERROR sur `PATCH /simulations/:id/sujet` d'une simulation déjà corrigée). - `RapportPage` breadcrumb : `` remplacé par `