180 lines
9.4 KiB
Markdown
180 lines
9.4 KiB
Markdown
|
|
# 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é |
|