expria-frontend/docs/CHANGELOG.md
Hermann_Kitio 886ecbb433 docs(changelog): tâche G5 — suggestions d'idées DeepSeek
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 03:24:39 +03:00

10 KiB

Changelog — Expria Frontend

Toutes les modifications notables du projet frontend sont documentées dans ce fichier.

Format basé sur Keep a Changelog.

Convention

Chaque entrée suit ce format :

## [Unreleased] — YYYY-MM-DD — Session <nom>

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

2026-04-21 — Tâche G5 — Suggestions d'idées DeepSeek

Ajouté

  • BackendPOST /sujets/idees : génère 5 suggestions d'idées via DeepSeek pour aider l'étudiant à prolonger sa rédaction (prompt coach TCF Canada, temperature 0.5, timeout 15 s via AbortSignal, JSON strict { idees: string[] })
  • generateIdees(consigne, contenu) dans src/lib/deepseek.ts (validation tableau non vide)
  • 5 tests route POST /sujets/idees : 401 sans auth, 400 sujet_consigne manquant, 400 contenu < 30 mots, 200 succès avec idees[], 500 DeepSeek throw
  • FrontendgetIdees(consigne, contenu) dans entities/report/api.ts (POST /sujets/idees, timeoutMs 15 000)
  • Hook useIdeesuseMutation exposant { idees, isLoading, error, fetchIdees, reset }
  • Composant IdeesSuggestions — modal shadcn Dialog avec liste à puces, états loading/erreur/succès, reset() automatique à la fermeture
  • Bouton "Suggestions d'idées" (icône Lightbulb) dans SimulationForm à côté de "Changer de sujet"
  • Prop plan: Plan ajouté à SimulationForm (wiring planData.plan depuis SimulationPage)

Règles d'accès

  • Règle D respectée : hasAccess(plan, 'tips') obligatoire
  • Plan Free : bouton visible mais désactivé avec tooltip "Disponible en Standard" (tips=false pour Free)
  • Standard + Premium : bouton actif dès 30 mots écrits
  • Désactivé également si !sujet, isSubmitting, ou idees.isLoading

Tests

  • Backend — Typecheck : 0 erreur, Vitest : 144/144 passés (+5 tests POST /sujets/idees)
  • Frontend — Typecheck : 0 erreur, Vitest : 67/67 passés
  • Test manuel : validé avec compte Standard (bouton actif à 30+ mots, modal affiche 5 idées) et Free (bouton verrouillé avec tooltip)

2026-04-21 — Tâche G4 + Refonte page /sujets + Fix quota simulations

Ajouté

  • Tâche G4 — choix du sujet avec dropdown intégré et bouton aléatoire dans SimulationForm (hook useSujets, composant SujetSelector, getSujets() sur GET /sujets?mode=&tache=)
  • Refonte UX /sujets (Option A) — page dédiée avec grille de cartes SujetCard (responsive 1/2/3 colonnes), état partagé via SimulationFlowProvider pour survivre aux navigations entre /simulation/ee et /sujets. MVP : refresh sur /sujets redirige vers /simulation/ee.
  • Bouton "Changer de sujet" dans SimulationForm — retour à /sujets via goToSubjectPicker
  • Prop type: 'EE' | 'EO' sur TaskSelector (EO_CARDS réservé usage futur — non routé, /simulation/eo reste ComingSoon jusqu'au Sprint EO)

Modifié

  • useSimulation refacto en consommateur de SimulationFlowProvider (source de vérité déplacée hors du hook)
  • SujetDisplay redevient présentationnel (dropdown retiré)
  • TaskSelector : retrait des cartes EO de la page Expression Écrite (affiche uniquement EE T1/T2/T3)

Corrigé

  • Quota simulations (backend — commit ecb478e, expria-backend) : incrément simulations_used déplacé de simulationController.create() vers correctionController.correctEE/EO (Option B). Une simulation créée mais jamais corrigée ne consomme plus le quota utilisateur.

Supprimé

  • SujetSelector.tsx — orphelin après refonte /sujets
  • Helper selectSujet de useSimulation — orphelin
  • FTD-22 tracée résolue partiellement (step 'choosing-subject'
    • goToSubjectPicker conservés intentionnellement)

Tests

  • Typecheck : 0 erreur
  • Vitest : 67/67 passés
  • Test manuel : flux complet EE T1 avec choix de sujet (carte + aléatoire + changement de sujet) validé

2026-04-21 — Tâches G2+G3 — Clavier + Minuteur

Ajouté

  • Composant SpecialCharsKeyboard — 30 caractères spéciaux français en flex-wrap, sticky au scroll
  • Bloc "Temps restant" sticky avec TimerDisplay MM:SS (critique < 2min : rouge + pulse, expiré : rouge bold)
  • Composant WordCountBar — barre de progression colorée (orange < cible, vert dans cible, rouge > cible)
  • Hook useTimer avec 7 tests unitaires
  • Config par tâche dans simulationConfig.ts (EE T1: 10min/60-120 mots, T2: 20min/120-150, T3: 30min/120-180)
  • Auto-submit à l'expiration si ≥ 30 mots
  • Bouton "Soumettre ma production" (était "Envoyer")
  • Textarea auto-resize sans scroll interne

Changed

  • Compteur de caractères remplacé par WordCountBar
  • Bouton soumission bloqué si < 30 mots

Tests

  • Typecheck : 0 erreur
  • Vitest : 66/66 passés (+7 tests useTimer)
  • Test manuel : minuteur + clavier validés sur mobile et desktop

2026-04-21 — Tâche G1 — Affichage de la consigne

Ajouté

  • Interface SujetData dans entities/production/types.ts
  • Production enrichie avec sujet: SujetData | null
  • Composant SujetDisplay — affiche consigne, rôle, contexte, doc1, doc2 selon le sujet retourné
  • useSimulation expose sujet dans son retour
  • SimulationForm intègre SujetDisplay au-dessus de la textarea
  • FTD-21 tracée (persistance session simulation)

Tests

  • Typecheck : 0 erreur
  • Vitest : 59/59 passés
  • Test manuel : consigne affichée sur /simulation/ee

2026-04-20 — Audit frontend ↔ backend — alignement types Report

Modifié

  • src/entities/report/types.tsCritere.noteCritere.score, Report.exercices: Exercice[]Report.exercices: string[], JSDoc ajusté
  • src/features/simulations/pages/RapportPage.tsx — import Exercice retiré, critere.notecritere.score, ExerciceCard refactoré pour consommer une string rendue en Markdown, clé d'itération par index

Supprimé

  • Interface Exercice { titre, contenu } de entities/report/types.ts — remplacée par string[] pour coller au contrat backend

Contexte (backend associé, expria-backend)

Quatre commits côté backend finalisent l'alignement du contrat Report :

  • feat(corrections): renommages production_modelemodele, suggestions_ideesidees, ajout feedback_court + prompts DeepSeek mis à jour + validations runtime
  • feat(corrections): réponse enrichie avec simulation_id côté correctionController
  • feat(simulations): nouvelle route GET /simulations/:id (auth owner, gestion SIMULATION_NOT_FOUND/AUTH_REQUIRED/REPORT_NOT_READY) + 4 tests
  • feat(simulations): sujet aléatoire (table sujets) retourné avec chaque production créée (EO_T2_LIVE exclu, non bloquant si aucun sujet actif)

Tests

  • Typecheck : 0 erreur
  • Vitest : 59/59 passés

À faire (hors scope — session frontend dédiée ultérieurement)

  • Ajouter sujet: SujetData | null dans entities/production/types.ts
  • Consommer le sujet retourné dans SimulationPage (affichage consigne + docs)
  • Consommer feedback_court dans RapportPage (rendu toujours visible — cf. PLANS_TARIFAIRES §2 — déjà supporté par le type Report, reste à brancher dans l'UI si ce n'est pas déjà le cas)

2026-04-20 — Sprint 0.5 bis — AppLayout + primitives UI + refonte visuelle

Ajouté

  • src/app/AppLayout.tsx — layout applicatif desktop/mobile (sidebar fixe 240px, drawer mobile, BottomNav)
  • src/app/Sidebar.tsx — navigation latérale avec verrouillage hasAccess() (Progression, Examen blanc, Historique)
  • src/app/MobileHeader.tsx — header mobile sticky (Logo, ThemeToggle, bouton menu hamburger)
  • src/app/BottomNav.tsx — navigation mobile fixe (4 items, bottom sheet "Simuler", tap target min 44px)
  • src/shared/ui/Button.tsx — primitive Button (variants: primary/secondary/ghost/upgrade ; sizes: sm/md/lg ; loading Loader2)
  • src/shared/ui/Card.tsx — primitive Card (variants: default/raised/interactive ; rendu <button> si onClick fourni)
  • src/shared/ui/Badge.tsx — primitive Badge (variants: plan/nclc/neutral ; couleur selon planValue pour variant plan)

Modifié

  • src/app/router.tsx — layout routes via PrivateLayout (ProtectedRoute + AppLayout + Outlet) ; ComingSoon inline ; redirect /simulation/simulation/ee
  • src/features/simulations/components/TaskSelector.tsx — refonte avec Card interactive / Card default opacity-60, Badge "EE"/"EO", eyebrow tracking-widest, icône verrou
  • src/features/simulations/pages/SimulationPage.tsx — suppression header interne (Logo + ThemeToggle) ; root <main> ; Button migré vers @/shared/ui/Button variant="secondary"
  • src/features/dashboard/pages/DashboardPage.tsx — suppression header interne ; Button variant="primary" avec navigate('/simulation/ee') ; Badge variant="plan" planValue={data.plan} ; tout migré vers @/shared/ui/

Documentation

  • docs/TECH_DEBT.md v1.6 — ajout FTD-18 (SimulationForm migration Button), FTD-19 (token --shadow-focus manquant)

Tests

  • Typecheck : 0 erreur
  • Vitest : 59/59 passés
  • Tests manuels : à valider par Hermann

2026-04-19 — Sprint 1 / Étape 6 — Maintenance mode + outillage sécurité

Ajouté

  • Page de maintenance statique (src/app/MaintenancePage.tsx) — logo + message, tokens Direction H, zéro dépendance
  • Guard VITE_MAINTENANCE_MODE dans main.tsx — si true, aucun provider ne se monte, aucun appel réseau
  • Variable VITE_MAINTENANCE_MODE dans env.ts (optionnelle, défaut false)
  • Hook PreToolUse Claude Code (security-check.sh) — 9 patterns SECURITY.md §2
  • Hook Stop Claude Code (check-file-size.sh) — alerte fichiers > 200 lignes
  • MCP server Semgrep enregistré dans Claude Code

Documentation

  • ARCHITECTURE.md §7 — ajout VITE_MAINTENANCE_MODE dans la liste des variables
  • TECH_DEBT.md — FTD-16 résolu (maintenance mode implémenté)

Tests

  • Typecheck : 0 erreur
  • Vitest : 37/37 passés
  • Test manuel : maintenance mode vérifié (page affichée, aucun appel réseau, routing bloqué)