- Rewrite index.css with complete SUMI token system (dark + light themes) - All --sumi-* variables: backgrounds, surfaces, borders, text, pigments, spacing, radius, shadows, glass, scrollbar, motion, z-index, layout - shadcn/Radix semantic mapping (--background, --foreground, etc.) - Tailwind @theme mapping with new fonts (Inter, Space Grotesk, JetBrains Mono) - SUMI keyframe animations (sumi-fade-in, sumi-slide-up, sumi-scale-in, etc.) - Delete 11 redundant CSS files (design-system.css, design-tokens.css, button.css, card.css, input.css, badge-avatar.css, header.css, fix-input-focus.css, fix-login-form.css, visual-enhancements.css, premium-utilities.css) - Update main.tsx: single CSS import (index.css only) - Update ThemeProvider: data-theme attribute instead of .dark class toggle - Update index.html FOUC script: data-theme attribute Co-authored-by: Cursor <cursoragent@cursor.com>
9.4 KiB
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-anyest explicitement désactivée [eslint.config.js:148] - Cela signifie que les
anyne 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é |