From d4420500e59940e06891383573419351271bbf88 Mon Sep 17 00:00:00 2001 From: CCS Admin Date: Thu, 26 Feb 2026 18:11:55 +0000 Subject: [PATCH] docs: add state management refactoring design (TanStack Query) Co-Authored-By: Claude Opus 4.6 --- .../2026-02-26-state-management-design.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/plans/2026-02-26-state-management-design.md diff --git a/docs/plans/2026-02-26-state-management-design.md b/docs/plans/2026-02-26-state-management-design.md new file mode 100644 index 0000000..5546d5f --- /dev/null +++ b/docs/plans/2026-02-26-state-management-design.md @@ -0,0 +1,101 @@ +# State Management Refactoring — Design + +## Ziel + +Boilerplate reduzieren und Zukunftssicherheit schaffen durch Einführung von TanStack Query für Server-State-Management. UI-State bleibt bei useState/Context. + +## Ansatz + +TanStack Query (`@tanstack/react-query`) übernimmt alles was mit API-Daten zu tun hat: Fetching, Caching, Refetch, Mutations mit automatischer Cache-Invalidierung. + +## Architektur + +### Provider-Hierarchie + +``` +App.tsx +└── QueryClientProvider (NEU) + └── AuthProvider (bleibt) + └── BrowserRouter + └── Routes... +``` + +### Globale Query-Konfiguration + +- `staleTime: 30s` — Daten gelten 30 Sekunden als frisch +- `retry: 1` — Einmal wiederholen bei Fehler +- `refetchOnWindowFocus: false` — Kein automatischer Refetch bei Tab-Wechsel + +### Was migriert wird + +Alle `useEffect(() => api.get(...), [deps])` Patterns → `useQuery()` +Alle `api.put/post` in Save-Handlern → `useMutation()` mit Cache-Invalidierung +useNotifications Polling → `useQuery()` mit `refetchInterval: 60000` + +### Was bleibt + +- AuthContext (Token + User) +- useTheme +- UI-State (Modals, Sidebar-Toggle, Filter-Inputs) — useState +- useInlineEdit — bleibt als Hook, nutzt aber TanStack Mutations intern + +## Custom Query-Hooks + +Domänenspezifische Hooks in `frontend/src/hooks/`: + +| Hook | Ersetzt | Datei | +|------|---------|-------| +| `useCases(filters)` | useState+useEffect in CasesPage | `hooks/useCases.ts` | +| `useCase(id)` | Einzelfall-Fetch in CaseDetail | `hooks/useCases.ts` | +| `useCaseMutation()` | api.put in useInlineEdit | `hooks/useCases.ts` | +| `useDashboard(jahr)` | useState+useEffect in DashboardPage | `hooks/useDashboard.ts` | +| `useNotifications()` | Bestehender Polling-Hook | `hooks/useNotifications.ts` | +| `useUsers()` | useState+useEffect in AdminUsersPage | `hooks/useUsers.ts` | +| `useDisclosures(status)` | useState+useEffect in DisclosuresPage | `hooks/useDisclosures.ts` | +| `useAuditLog(filters)` | useState+useEffect in AdminAuditPage | `hooks/useAuditLog.ts` | +| `useImportLogs(page)` | useState+useEffect in ImportLogTab | `hooks/useImportLogs.ts` | + +### Query Key Konvention + +- `['cases']` — alle Fälle +- `['cases', { page, search, jahr, fallgruppe }]` — gefilterte Liste +- `['cases', id]` — Einzelfall +- `['dashboard', jahr]` — Dashboard-KPIs +- `['notifications']` — Benachrichtigungen +- `['users']` — Admin-Benutzerliste +- `['disclosures', status]` — Disclosure-Anfragen +- `['audit-log', filters]` — Audit-Log +- `['import-logs', page]` — Import-Logs + +## Mutations & Cache-Invalidierung + +| Mutation | Invalidiert | +|----------|-------------| +| Case updaten | `['cases']` | +| KVNR setzen | `['cases']` | +| ICD setzen | `['cases']`, `['dashboard']` | +| Coding setzen | `['cases']`, `['dashboard']` | +| Disclosure genehmigen/ablehnen | `['disclosures']`, `['notifications']` | +| Notification lesen | `['notifications']` | +| User anlegen/bearbeiten | `['users']` | + +useInlineEdit nutzt intern `useMutation()` statt direkter `api.put()`. Der `onCaseSaved`-Callback durch den Komponentenbaum entfällt komplett. + +## Migrations-Strategie + +Schrittweise Migration, Page für Page: + +### Phase 1: Setup +- `pnpm add @tanstack/react-query @tanstack/react-query-devtools` +- `QueryClientProvider` in App.tsx + +### Phase 2: Einfache Pages +- DashboardPage, ReportsPage, AdminAuditPage, DisclosuresPage + +### Phase 3: Mittlere Komplexität +- AdminUsersPage, ImportLogTab, useNotifications + +### Phase 4: CasesPage (komplexeste) +- useCases, useCaseMutation, useKvnrMutation, useIcdMutation +- useInlineEdit intern auf Mutations umstellen +- onCaseSaved-Callback entfernen