# PHASE H — DETTE TECHNIQUE FRONTEND --- ## H1. Complexité excessive ### Fichiers > 300 lignes (hors tests et types générés) | Fichier | Lignes | Raison | Split possible ? | Complexité | |---------|--------|--------|-----------------|------------| | `services/api/client.ts` | **2 237** | Client API monolithique : interceptors, retry, cache, CSRF, dedup | 🔴 Oui — split en modules (interceptors, retry, cache, csrf) | Très haute | | `mocks/handlers.ts` | **1 716** | Tous les handlers MSW dans un seul fichier | 🔴 Oui — split par feature | Haute (linéaire) | | `features/tracks/api/trackApi.ts` | **848** | Endpoints track API + types | 🟡 Oui — split par domaine | Moyenne | | `utils/optimisticUpdates.ts` | **682** | Utilitaires d'updates optimistes | 🟡 Possible | Haute | | `features/playlists/hooks/usePlaylist.ts` | **631** | Hook monolithique playlist | 🔴 Oui — split usePlaylistData, usePlaylistActions | Très haute | | `features/streaming/services/playbackAnalyticsService.ts` | **656** | Service analytics streaming | 🟡 Possible | Haute | | `utils/apiErrorHandler.ts` | **578** | Gestion d'erreurs API | 🟡 Possible | Haute | | `features/streaming/hooks/usePlaybackRealtime.ts` | **496** | Hook temps réel | 🔴 Oui — responsabilités multiples | Très haute | | `services/api/auth.ts` | **493** | Auth API (login, register, refresh, CSRF) | 🟡 Possible | Haute | | `schemas/apiRequestSchemas.ts` | **476** | Schemas Zod requêtes | ⚠️ Normal pour des schemas | Moyenne | | `schemas/apiSchemas.ts` | **468** | Schemas Zod réponses | ⚠️ Normal pour des schemas | Moyenne | | `features/tracks/services/trackService.ts` | **453** | Service tracks | 🟡 Possible | Moyenne | | `features/playlists/services/playlistService.ts` | **448** | Service playlists | 🟡 Possible | Moyenne | | `utils/sanitize.ts` | **429** | Sanitization XSS | ⚠️ Justifié (sécurité) | Moyenne | | `features/tracks/services/commentService.ts` | **425** | Service commentaires | 🟡 Possible | Moyenne | **Résumé** : 5 fichiers nécessitent un split urgent (client.ts, handlers.ts, usePlaylist.ts, usePlaybackRealtime.ts, trackApi.ts). --- ## H2. Props drilling Pas de chaîne de prop drilling > 3 niveaux détectée. Les données circulent via : - **Zustand stores** (accès direct via hooks) - **React Query** (accès direct via hooks) - **Context API** (auth, theme, toast) - **Props directes** rarement au-delà de 2 niveaux ✅ Architecture saine sur ce point. --- ## H3. Hooks complexes ### Custom hooks > 50 lignes | Hook | Lignes | Responsabilités | Testé ? | Verdict | |------|--------|----------------|---------|---------| | `usePlaylist.ts` | **631** | Toutes les opérations playlist (CRUD, share, collab, follow) | ✅ Oui (595L de tests) | 🔴 Trop de responsabilités — split | | `usePlaybackRealtime.ts` | **496** | Temps réel playback (WebSocket, events, state) | ✅ Oui (490L de tests) | 🔴 Trop de responsabilités | | `usePlaybackAnalytics.test.ts` | ~458 | Analytics temps réel | ✅ Testé | 🟡 Acceptable | | `useTrackList.ts` | ~300+ | Liste de tracks (pagination, filters, sort) | ✅ Oui (761L de tests) | 🟡 Complexe mais testé | | `useEducationView.ts` | ~100+ | Education view data | ❌ Non (et import fantôme !) | 🔴 Cassé | --- ## H4. Duplication ### Composants quasi-identiques | Duplication | Fichiers | Impact | |-------------|----------|--------| | Spinner / LoadingSpinner | `ui/Spinner.tsx`, `ui/loading-spinner.tsx` | 2 composants pour le même usage | | Modal / Dialog | `ui/modal.tsx`, `ui/dialog/` | 2 systèmes de modales | | Button / ButtonLoading | `ui/button.tsx`, `ui/button-loading.tsx` | Button a déjà un prop `loading` | | DataList (legacy) / DataList (new) | `ui/DataList.tsx`, `ui/data-list/DataList.tsx` | Migration en cours | | Accordion (legacy) / Accordion (new) | `ui/accordion.tsx`, `ui/accordion/Accordion.tsx` | Migration en cours | | player/ (components) | `components/player/`, `features/player/` | Deux emplacements | | settings/ (components) | `components/settings/`, `features/settings/` | Deux emplacements | ### CSS dupliqué | Pattern CSS | Composant React | Duplication | |------------|----------------|------------| | `.btn-veza` (button.css) | `Button` (button.tsx) | 100% dupliqué | | `.card-veza` (card.css) | `Card` (card.tsx) | 100% dupliqué | | `.input-veza` (input.css) | `Input` (input.tsx) | 100% dupliqué | | `.badge-veza` (badge-avatar.css) | `Badge` (badge.tsx) | 100% dupliqué | | `.avatar-veza` (badge-avatar.css) | `Avatar` (avatar.tsx) | 100% dupliqué | ### Styles dupliqués fréquents Les patterns Tailwind les plus répétés sont des combinaisons de classes utilitaires standard — c'est normal avec Tailwind et ne constitue pas une duplication problématique. Les duplications CSS vanilla (ci-dessus) sont le vrai problème. --- ## H5. TypeScript ### Statistiques | Métrique | Valeur | Verdict | |----------|--------|---------| | `: any` explicites | ~120+ | ⚠️ Problématique | | `as any` casts | **706** | 🔴 Critique | | `@ts-ignore` | 3 | ✅ Acceptable | | `@ts-expect-error` | 5 | ✅ Acceptable | ### Répartition des `as any` | Source | Count | Justification | |--------|-------|---------------| | `types/generated/api.ts` | **145** | ⚠️ Code généré — devrait être corrigé dans le générateur | | Fichiers `.test.ts/tsx` | **~500** | ⚠️ Tests utilisent massivement `as any` pour les mocks | | Services source | **~50** | 🔴 Doit être corrigé | | Composants source | **~10** | ⚠️ À corriger progressivement | **Le problème majeur** : 500+ `as any` dans les tests est une dette technique significative. Les mocks devraient être typés correctement. ### ESLint `no-explicit-any: 'off'` - 🔴 La règle ESLint `@typescript-eslint/no-explicit-any` est explicitement **désactivée** [eslint.config.js:148] - Cela signifie que les `any` ne sont jamais signalés — la dette grandit silencieusement --- ## H6. Code mort ### Fichiers orphelins (non importés) | Fichier | Raison probable | |---------|----------------| | `components/library/playlists/PlaylistDetailView.tsx` | Remplacé par feature/playlists | | `components/library/playlists/AddToPlaylistModal.tsx` | Remplacé par feature | | `components/BulkModeBanner.tsx` | Feature abandonnée | | `components/AdvancedFilters.tsx` | Non connecté | | `components/gamification/ProfileXPView.tsx` | Prototype | | `components/keyboard/KeyboardShortcutsHelp.tsx` | Duplication KeyboardShortcutsPanel | | `components/inventory/AddEquipmentView.tsx` | Feature abandonnée | | `hooks/useLongRunningOperation.ts` | Non utilisé | | `hooks/useThrottledCallback.ts` | Non importé | | `hooks/usePreventDoubleClick.ts` | Non importé | | `hooks/useDebouncedCallback.ts` | Non importé | | `services/cookieService.ts` | Non utilisé | | `features/search/services/unifiedSearchService.ts` | Non connecté | | `features/dashboard/hooks/useDashboard.ts` | Non importé | | `features/playlists/components/PlaylistHeaderSkeleton.tsx` | Non importé | | `features/playlists/components/DuplicatePlaylistButton.tsx` | Non connecté | | `features/playlists/components/ImportPlaylistButton.tsx` | Non connecté | | `features/playlists/hooks/useTouchGestures.ts` | Non utilisé | | `features/chat/services/conversationService.ts` | Non importé | | `features/webhooks/api/webhookApi.ts` | Non connecté | | `utils/aggressiveVisualFix.ts` | Hack non utilisé | | `utils/firstTime.ts` | Non utilisé | | `utils/csp.ts` | Non connecté (utilitaire prêt mais pas intégré) | | `utils/optimisticUpdates.ts` | Non importé (682 lignes de code mort) | | `utils/safeStorage.ts` | Non utilisé | **Total** : ~25 fichiers orphelins représentant ~3 000+ lignes de code mort. --- ## H7. Dépendances inutilisées [DONNÉES INSUFFISANTES — nécessite une analyse `depcheck` ou similaire sur le package.json vs les imports. Cependant, sur la base de l'arborescence : | Dépendance suspecte | Usage trouvé ? | Verdict | |--------------------|---------------|---------| | `rollup-plugin-visualizer` | Oui (vite.config.ts) | ⚠️ Devrait être en devDeps | | `@types/dompurify` | Oui (sanitize.ts) | ⚠️ Devrait être en devDeps | | `swagger-ui-dist` | ❓ À vérifier | ⚠️ Possiblement inutile si swagger-ui-react suffit | --- ## Priorisation de la dette | Priorité | Élément | Impact | Effort | Ratio | |----------|---------|--------|--------|-------| | **P0** | Build cassé (educationService manquant) | 🔴 Bloquant déploiement | XS (5 min) | ∞ | | **P0** | `client.ts` 2 237L → split en modules | 🔴 Maintenance impossible | L (3-5j) | Élevé | | **P0** | 706 `as any` + ESLint rule off | 🔴 TypeScript safety annulée | XL (semaines) | Moyen | | **P1** | 25 fichiers orphelins → supprimer | 🟠 Code mort confus | S (1j) | Élevé | | **P1** | CSS vanilla parallèle → supprimer | 🟠 Double maintenance | M (2-3j) | Élevé | | **P1** | Dualité components/ ↔ features/ | 🟠 Architecture confuse | L (semaine) | Moyen | | **P1** | `usePlaylist.ts` 631L → split | 🟠 Hook ingérable | M (2j) | Élevé | | **P1** | Duplications (Modal/Dialog, Spinner) | 🟠 API confuse | S (1j) | Élevé | | **P2** | `handlers.ts` 1 716L → split par feature | 🟡 Maintenance difficile | M (2j) | Moyen | | **P2** | Auth state duplication (Context + Store) | 🟡 Source de vérité ambiguë | M (2j) | Moyen | | **P2** | Vendor chunk 925 KB → optimiser | 🟡 Performance | M (2-3j) | Moyen | | **P2** | Hacks CSS `!important` | 🟡 Fragilité | S (1j) | Élevé |