diff --git a/docs/TECH_DEBT.md b/docs/TECH_DEBT.md index 9b40017..c0c2a1e 100644 --- a/docs/TECH_DEBT.md +++ b/docs/TECH_DEBT.md @@ -161,6 +161,21 @@ Vient du pattern `c.json(result, result.status)` où `result` contient déjà `s --- +### FTD-17 — Clé `['plan']` dupliquée entre features +**Priorité :** 🟢 Mineur +**Statut :** Ouvert — accepté par design (Sprint 3) +**Estimation de session :** 30 min +**Description :** La queryKey TanStack Query `['plan']` est écrite littéralement dans deux endroits : `features/dashboard/hooks/usePlan.ts` (via `PLAN_QUERY_KEY`) et `features/simulations/pages/SimulationPage.tsx` (inline). TanStack Query partage bien le cache par clé identique, donc la déduplication fonctionne en pratique. Mais toute faute de frappe dans l'une des occurrences briserait silencieusement la mise en cache partagée. + +**À faire :** +- Déplacer `PLAN_QUERY_KEY` vers `src/entities/user/api.ts` (ou un nouveau `src/entities/user/query-keys.ts`) +- Importer `PLAN_QUERY_KEY` dans `usePlan.ts` et `SimulationPage.tsx` depuis ce fichier partagé +- Supprimer la constante locale dans `usePlan.ts` + +**Condition de résolution :** avant l'ajout d'une troisième feature qui consomme `['plan']` (T2 Live page, rapport page). + +--- + ## 3. Fonctionnalités reportées ### FTD-06 — AudioWorklet au lieu de ScriptProcessorNode (T2 Live) @@ -270,3 +285,4 @@ Vient du pattern `c.json(result, result.status)` où `result` contient déjà `s | 1.2 | 2026-04-17 | Ajout FTD-13 résolu (incompatibilité Vitest 3 / Vite 8) suite à l'étape 12-bis du Sprint 0 | | 1.3 | 2026-04-18 | FTD-11 résolu (design system Sprint 0.5) ; ajout FTD-14 (anti-FOUC), FTD-15 (option 'system' thème) | | 1.4 | 2026-04-18 | FTD-16 résolu (VITE_MAINTENANCE_MODE implémenté — Sprint 1 étape 6) | +| 1.5 | 2026-04-19 | Ajout FTD-17 (clé ['plan'] dupliquée entre features — Sprint 3 étape 14) | diff --git a/src/app/router.tsx b/src/app/router.tsx index 2654f7f..28de9a8 100644 --- a/src/app/router.tsx +++ b/src/app/router.tsx @@ -5,6 +5,7 @@ import { LoginPage } from '@/features/auth/pages/LoginPage' import { RegisterPage } from '@/features/auth/pages/RegisterPage' import { ProtectedRoute } from '@/features/auth/components/ProtectedRoute' import { DashboardPage } from '@/features/dashboard/pages/DashboardPage' +import { SimulationPage } from '@/features/simulations/pages/SimulationPage' const DesignSystemPage = import.meta.env.DEV ? React.lazy(() => import('@/features/design-system/DesignSystemPage')) @@ -24,6 +25,14 @@ export function AppRouter() { } /> + + + + } + /> {import.meta.env.DEV && ( void + onBack: () => void +} + +export function SimulationForm({ tache, isSubmitting, error, onSubmit, onBack }: Props) { + const [texte, setTexte] = useState('') + const [fieldError, setFieldError] = useState(null) + + function handleSubmit(e: FormEvent) { + e.preventDefault() + setFieldError(null) + + const parsed = textSchema.safeParse({ texte }) + if (!parsed.success) { + setFieldError(parsed.error.flatten().fieldErrors.texte?.[0] ?? null) + return + } + + onSubmit(parsed.data.texte) + } + + const apiError = mapCorrectError(error) + const charCount = texte.length + + return ( +
+
+ +

{formatTache(tache)}

+
+ + {apiError && ( +
+ {apiError} +
+ )} + +
+
+ +