# Phase H — Dette Technique Frontend --- ## H1. Complexité excessive ### Fichiers > 300 lignes (source, hors tests/generated) | Fichier | Lignes | Raison probable | Split possible ? | Complexité | |---------|--------|-----------------|-----------------|-----------| | `services/api/client.ts` | 2 237 | Client HTTP + validation + caching + retry + dedup + metrics | ✅ Oui, 5 modules | 🔴 Élevée | | `mocks/handlers.ts` | 1 716 | MSW handlers pour toutes les routes | ✅ Par feature | 🟡 Linéaire | | `features/tracks/api/trackApi.ts` | 848 | API tracks complète | ✅ CRUD/Upload/Share/Analytics | 🟠 Moyenne | | `utils/optimisticUpdates.ts` | 682 | Optimistic updates multi-feature | ⚠️ Difficilement | 🟠 Moyenne | | `features/streaming/services/playbackAnalyticsService.ts` | 656 | Analytics streaming | ⚠️ Cohérent | 🟡 Linéaire | | `features/playlists/hooks/usePlaylist.ts` | 631 | Hook playlist (CRUD + collab + analytics) | ✅ 3 hooks | 🔴 Élevée | | `utils/apiErrorHandler.ts` | 578 | Error parsing exhaustif | ⚠️ Cohérent | 🟡 Linéaire | | `features/streaming/hooks/usePlaybackRealtime.ts` | 496 | WebSocket + state + analytics | ⚠️ Justifié temps réel | 🟠 Moyenne | | `services/api/auth.ts` | 493 | Auth API (login, register, 2FA, OAuth) | ⚠️ Cohérent | 🟡 Linéaire | | `schemas/apiRequestSchemas.ts` | 476 | Zod schemas | ❌ Normal | 🟢 Faible | | `schemas/apiSchemas.ts` | 468 | Zod schemas | ❌ Normal | 🟢 Faible | | `features/tracks/services/trackService.ts` | 453 | Service tracks | ⚠️ Cohérent | 🟡 Linéaire | | `features/playlists/services/playlistService.ts` | 448 | Service playlists | ⚠️ Cohérent | 🟡 Linéaire | | `utils/sanitize.ts` | 429 | Sanitization XSS | ❌ Critique | 🟢 Faible | | `features/chat/hooks/useChat.ts` | 360 | Hook chat | ✅ 2-3 hooks | 🟠 Moyenne | | `features/auth/store/authStore.ts` | 330 | Store auth | ⚠️ Acceptable | 🟡 Linéaire | | `features/dashboard/pages/DashboardPage.tsx` | 328 | Page dashboard | ✅ Extraire sections | 🟡 Moyenne | | `features/tracks/components/TrackListRow.tsx` | 320 | Ligne de track | ✅ Sous-composants | 🟡 Moyenne | **Priorité de split** : 1. `client.ts` (2237L) → `httpClient.ts`, `validators.ts`, `caching.ts`, `interceptors.ts`, `metrics.ts` 2. `usePlaylist.ts` (631L) → `usePlaylistCrud.ts`, `usePlaylistCollaboration.ts`, `usePlaylistAnalytics.ts` 3. `useChat.ts` (360L) → `useChatMessages.ts`, `useChatConnection.ts` --- ## H2. Props drilling Grâce à l'utilisation de Zustand (7 stores) et React Query, le prop drilling est **minimal**. Aucune chaîne de props > 3 niveaux intermédiaires identifiée dans le code audité. **Pattern positif** : Les stores Zustand sont accédés directement dans les composants enfants via `useAuthStore()`, `useUIStore()`, `useCartStore()`, etc. — pas besoin de passer les props à travers les composants intermédiaires. --- ## H3. Hooks complexes ### Custom hooks > 50 lignes | Hook | Lignes | Responsabilités | Testé ? | |------|--------|----------------|---------| | `features/playlists/hooks/usePlaylist.ts` | 631 | CRUD + collaboration + analytics + permissions | ✅ (595L de tests) | | `features/streaming/hooks/usePlaybackRealtime.ts` | 496 | WebSocket + state + analytics + reconnection | ✅ (490L de tests) | | `features/chat/hooks/useChat.ts` | 360 | Messages + connection + typing + presence | ❌ Non vérifié | | `features/tracks/hooks/useTrackList.ts` | 286 | List + filters + sort + pagination + localStorage | ✅ (761L de tests) | | `features/playlists/hooks/usePlaylistNotifications.ts` | 264 | Notification handling + navigation | ❌ Peu testé | | `features/player/hooks/usePlayer.ts` | 249 | Playback control + queue + history | ✅ Tests partiels | | `hooks/useRoutePreload.ts` | 239 | Route prefetching + intersection observer | ✅ Tests | | `features/library/hooks/useLibraryItems.ts` | 152 | Library items + filters | ❌ Non vérifié | **Verdict** : Les 3 plus gros hooks (usePlaylist, usePlaybackRealtime, useTrackList) sont bien testés. Les hooks de taille moyenne (useChat, usePlaylistNotifications) sont moins bien couverts. --- ## H4. Duplication ### Patterns CSS les plus répétés | Pattern | Occurrences approximatives | Action recommandée | |---------|---------------------------|-------------------| | `flex items-center` | ~230 | Normal (utility-first) | | `flex flex-col` | ~230 | Normal | | `text-muted-foreground` | ~145 | Normal (sémantique) | | `rounded-*` | ~230 | Normal | | `w-full h-full` | ~90 | Normal | Ces répétitions sont **attendues** avec Tailwind utility-first et ne constituent pas de la dette technique. ### Composants dupliqués | Duplication | Fichiers | Impact | |------------|---------|--------| | `layout/Sidebar.tsx` (294L) + `ui/Sidebar.tsx` (217L) | 2 fichiers | 🟠 Confusion | | `components/player/` (14 fichiers) + `features/player/components/` (~20 fichiers) | 34 fichiers | 🟠 Migration incomplète | | `pages/auth/` + `features/auth/pages/` | 4+ fichiers | 🟠 Legacy | | `context/AuthContext.tsx` + `features/auth/store/authStore.ts` | 2 fichiers | 🔴 Deux sources de vérité | | `ui/modal.tsx` + `ui/dialog/` | 2 systèmes | 🟡 Redondance | | `ui/dropdown-menu.tsx` + `ui/dropdown-menu/` | Fichier plat + dossier | 🟡 Legacy wrapper | ### Logique métier dupliquée - **Auth** : `authService.login()` est appelé par `authStore.login()` ET `AuthContext.login()` — deux chemins d'exécution pour la même action. - **Toast** : `toast()` (react-hot-toast) et `addToast()` (custom) — deux APIs pour le même feedback. --- ## H5. TypeScript ### Statistiques | Métrique | Nombre | Zone | |----------|--------|------| | `: any` explicites (prod) | ~82 | Code source hors tests/generated | | `as any` casts (prod) | ~180 | Code source hors tests/generated | | `as any` dans `generated/api.ts` | 145 | Auto-généré — acceptable | | `@ts-ignore` / `@ts-expect-error` | 7 fichiers | Minimal ✅ | ### Fichiers avec le plus de `as any` (source) | Fichier | `as any` | Justification | |---------|----------|---------------| | `services/api/client.ts` | 48 | Error handling, interceptors — type narrowing difficile | | `utils/typeGuards.ts` | 44 | Type guards by design — acceptable | | `utils/toast.ts` | 11 | Wrapper react-hot-toast | | `features/playlists/services/playlistService.ts` | 9 | API response casting | | `utils/apiErrorHandler.ts` | 7 | Error type narrowing | | `features/tracks/services/trackListService.ts` | 7 | API response casting | ### Configuration TypeScript - **Mode strict complet** ✅ [tsconfig.json] : `strict: true`, `noImplicitAny`, `strictNullChecks`, `strictFunctionTypes`, `noUnusedLocals`, `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch` - **`noUncheckedIndexedAccess: true`** — option avancée ✅ (peu de projets l'activent) - **`@typescript-eslint/no-explicit-any: off`** — ESLint n'interdit pas `any` ⚠️ **Verdict TS** : Configuration stricte exemplaire mais `no-explicit-any` désactivé dans ESLint permet l'accumulation de `any`. Le comptage (~82 source + ~180 `as any`) est modéré pour un projet de 218K LOC. --- ## H6. Code mort ### Orphelins structurels identifiés | Fichier/Dossier | Raison | Impact | |----------------|--------|--------| | `pages/auth/Login.tsx`, `pages/auth/Register.tsx` | Remplacés par `features/auth/pages/` | 🟡 Dead code | | `context/AuthContext.tsx` | Remplacé par `features/auth/store/authStore.ts` | 🟠 Source de confusion | | `providers/AuthProvider.tsx` | Wrapper de AuthContext — non utilisé dans App.tsx | 🟡 Dead code | | `components/views/*.tsx` (fichiers plats) | Wrappers vers les sous-dossiers refactorés | 🟡 Indirection inutile | | `ui/dropdown-menu.tsx`, `ui/tabs.tsx`, `ui/accordion.tsx` (plats) | Re-exports vers les dossiers refactorés | 🟢 Acceptable | ### Recommandation Exécuter `npx ts-prune` ou `npx madge --extensions ts,tsx --circular src/` pour un rapport complet d'orphelins et de dépendances circulaires. --- ## H7. Dépendances inutilisées ### Potentiellement inutilisées | Dépendance | Status | Raison | |-----------|--------|--------| | `@dnd-kit/utilities` | ⚠️ À vérifier | Peut être importé indirectement par `@dnd-kit/sortable` | | `swagger-ui-dist` | ⚠️ À vérifier | `swagger-ui-react` pourrait l'importer en interne | | `rollup-plugin-visualizer` | ✅ OK | Utilisé dans vite.config.ts (pas dans src/) | [DONNÉES INSUFFISANTES — nécessite `npx depcheck` pour un rapport exhaustif] --- ## Priorisation de la dette | Priorité | Élément | Impact | Effort | Ratio | |----------|---------|--------|--------|-------| | P0 | Split `client.ts` (2237L) | Maintenabilité, testabilité | L | Élevé | | P0 | Résoudre dualité AuthContext vs authStore | Bugs auth, confusion | M | Très élevé | | P1 | Supprimer `pages/auth/` legacy | Clarté code | S | Élevé | | P1 | Unifier toast API (addToast vs toast) | Cohérence DX | M | Élevé | | P1 | Split `usePlaylist.ts` (631L) | Maintenabilité | M | Moyen | | P1 | Résoudre layout/Sidebar vs ui/Sidebar | Clarté | S | Élevé | | P2 | Migrer z-[N] vers tokens SUMI | Cohérence design | M | Moyen | | P2 | Ajouter `React.memo` sur les composants de liste | Performance | S | Moyen | | P2 | Réduire `as any` dans client.ts (48 occ.) | Type safety | L | Faible | | P2 | Nettoyer components/views/ wrappers legacy | Clarté | M | Moyen | **Score dette technique implicite : 6/10** — Dette structurelle significative (migration incomplète) mais codebase fonctionnelle avec de bons patterns.