veza/apps/web/dev_audit/frontend/03_component_map.md

208 lines
11 KiB
Markdown
Raw Normal View History

# PHASE C — CARTOGRAPHIE DES COMPOSANTS
> **Total composants .tsx** : 1 450 fichiers
> **Total .ts** : 620 fichiers
> **Exclus** : .test.tsx, .stories.tsx, types, configs
---
## Composants UI primitifs (`components/ui/`)
```
src/components/ui/
├── button.tsx [149L] [dumb] [~200x imports] [props: 6+ButtonHTMLAttrs]
├── card.tsx [190L] [dumb] [~200x imports] [props: 3+HTMLAttrs] [7 sub-components]
├── skeleton.tsx [94L] [dumb] [~200x imports] [props: 3]
├── Toast.tsx [112L] [dumb] [~200x imports] [props: 4]
├── input.tsx [69L] [dumb] [~100x imports] [props: 3+InputHTMLAttrs]
├── modal.tsx [151L] [dumb] [~100x imports] [props: 8]
├── badge.tsx [225L] [dumb] [~30x imports] [props: 8]
├── avatar.tsx [306L] [dumb] [~30x imports] [props: 7] ⚠️ > 300L
├── table.tsx [306L] [dumb] [~30x imports] [props: 3+HTMLAttrs] ⚠️ > 300L
├── checkbox.tsx [130L] [dumb] [~50x imports] [props: 2+InputHTMLAttrs]
├── label.tsx [51L] [dumb] [~50x imports] [props: LabelHTMLAttrs]
├── FormField.tsx [218L] [dumb] [~50x imports] [props: 5]
├── textarea.tsx [105L] [dumb] [~30x imports] [props: 2+TextareaHTMLAttrs]
├── switch.tsx [103L] [dumb] [~20x imports] [props: 2+InputHTMLAttrs]
├── radio-group.tsx [229L] [dumb] [~10x imports] [props: 3]
├── slider.tsx [171L] [dumb] [~5x imports] [props: 7]
├── progress.tsx [209L] [dumb] [~10x imports] [props: 7]
├── alert.tsx [186L] [dumb] [~20x imports] [props: 3]
├── Spinner.tsx [109L] [dumb] [~30x imports] [props: 3]
├── loading-spinner.tsx [93L] [dumb] [~30x imports] [props: 2] ⚠️ Duplique Spinner
├── LoadingState.tsx [215L] [dumb] [~20x imports] [props: 6]
├── ErrorDisplay.tsx [247L] [dumb] [~10x imports] [props: 12]
├── ErrorBoundary.tsx [78L] [smart] [~5x imports] [props: 3]
├── empty-state.tsx [238L] [dumb] [~10x imports] [props: 6]
├── FAB.tsx [115L] [dumb] [~5x imports] [props: 5]
├── ImageCropper.tsx [212L] [smart] [~5x imports] [props: 5]
├── ImageViewerModal.tsx [231L] [dumb] [~5x imports] [props: 9]
├── WaveformVisualizer.tsx [166L] [smart] [~5x imports] [props: 7]
├── AstralBackground.tsx [142L] [smart] [~2x imports] [props: 0]
├── NavigationProgress.tsx [52L] [smart] [~1x imports] [props: 0]
├── ComingSoon.tsx [15L] [dumb] [~5x imports] [props: 1]
├── AnimatedNumber.tsx [17L] [dumb] [~5x imports] [props: 3]
├── ContentFadeIn.tsx [34L] [dumb] [~5x imports] [props: 2]
├── KeyboardShortcutsPanel.tsx [152L] [smart] [~1x imports] [props: 2]
├── Sidebar.tsx [218L] [dumb] [~10x imports] [props: 9]
├── DataList.tsx [42L] [dumb] [~10x imports] [props: 6] (generic)
├── scroll-area.tsx [57L] [dumb] [~20x imports] [props: HTMLAttrs]
├── dropdown.tsx [216L] [smart] [interne] [props: 6]
├── floating-input.tsx [95L] [dumb] [~5x imports] [props: 4+InputHTMLAttrs]
├── confirmation-dialog.tsx [166L] [dumb] [~20x imports] [props: 9]
├── button-loading.tsx [101L] [dumb] [~10x imports] [props: 2] ⚠️ Duplique Button.loading
├── focus-trap.tsx [127L] [smart] [interne] [props: 3]
├── dialog/ [~350L total] [dumb] [~100x imports] [9 sub-components]
├── dropdown-menu/ [~300L total] [dumb] [~30x imports] [11 sub-components]
├── tabs/ [~200L total] [dumb] [~20x imports] [4 sub-components]
├── tooltip/ [~200L total] [dumb] [~15x imports] [3 sub-components]
├── select/ [~250L total] [dumb] [~20x imports] [4 sub-components]
├── accordion/ [~200L total] [dumb] [~5x imports] [4 sub-components]
├── hover-card/ [~350L total] [smart] [~10x imports] [3 sub-components]
├── context-menu/ [359L] [smart] [~5x imports] [props: 3] 🔴 > 300L
├── date-picker/ [~250L total] [smart] [~5x imports] [3 sub-components]
├── file-upload/ [~300L total] [smart] [~10x imports] [5 sub-components]
├── avatar-upload/ [~250L total] [smart] [~10x imports] [5 sub-components]
├── optimized-image/ [~300L total] [smart] [~20x imports] [3 sub-components]
├── virtualized-list/ [~300L total] [smart] [~5x imports] [3 sub-components]
├── data-list/ [~200L total] [dumb] [~10x imports] [4 sub-components]
├── lazy-component/ [~250L total] [smart] [routes] [3 sub-components]
├── content-transition/ [~50L total] [dumb] [~5x imports] [1 component]
└── feature-highlight/ [~100L total] [dumb] [~5x imports] [1 component]
```
---
## Layout (`components/layout/`)
```
src/components/layout/
├── Layout.tsx [58L] [dumb] [~1x] [props: 1]
├── DashboardLayout.tsx [61L] [dumb] [~1x] [props: 1]
├── Sidebar.tsx [295L] [dumb] [~2x] [props: 1]
├── Header.tsx [172L] [hybrid] [~2x] [props: 0] ⚠️ mélange auth/theme
├── Navbar.tsx [~100L] [dumb] [~1x] [props: ~3]
├── MobileBottomNav.tsx [~80L] [dumb] [~1x] [props: ~2]
├── PageTransition.tsx [~40L] [dumb] [~1x] [props: 1]
└── AudioPlayer.tsx [~100L] [smart] [~1x] [props: ~3]
```
---
## Feature modules — Structure type
```
src/features/
├── auth/
│ ├── components/ [RegisterForm, LoginForm, AuthInput, OAuthButton, ...]
│ ├── hooks/ [useLogin, useRegister, ...]
│ ├── pages/ [LoginPage, RegisterPage, ForgotPasswordPage, ...]
│ ├── services/ [authService, emailVerificationService]
│ ├── store/ [authStore (Zustand)]
│ └── __tests__/ [integration tests]
├── player/
│ ├── components/ [GlobalPlayer, PlayerControls, PlayerBar, ...]
│ ├── hooks/ [usePlayer, useStreamSync, ...]
│ ├── services/ [playerService, syncClient]
│ └── store/ [playerStore (Zustand)]
├── tracks/
│ ├── api/ [trackApi (848L)]
│ ├── components/ [TrackList, TrackCard, TrackGrid, TrackSearch, ...]
│ ├── hooks/ [useTrackList, useInfiniteScroll, ...]
│ ├── pages/ [track-detail-page/ (décomposé)]
│ ├── services/ [trackService, commentService, uploadService, ...]
│ ├── types/ [types locaux]
│ └── __tests__/ [integration tests]
├── playlists/
│ ├── components/ [PlaylistHeader, PlaylistList, PlaylistSearch, ...]
│ ├── hooks/ [usePlaylist (631L ⚠️), ...]
│ ├── pages/ [playlist-detail-page/ (décomposé)]
│ ├── services/ [playlistService]
│ └── __tests__/ [integration tests]
├── chat/
│ ├── components/ [ChatMessages, ChatInput, VirtualizedChat, ...]
│ ├── pages/ [ChatPage]
│ ├── services/ [conversationService]
│ └── store/ [chatStore (Zustand)]
├── streaming/
│ ├── components/ [PlaybackDashboard, PlaybackHeatmap, BitrateSelector, ...]
│ ├── hooks/ [usePlaybackRealtime (496L ⚠️), usePlaybackAnalytics, ...]
│ └── services/ [hlsService, bitrateService, playbackAnalyticsService]
├── dashboard/
│ ├── hooks/ [useDashboard]
│ ├── pages/ [DashboardPage (329L ⚠️)]
│ └── services/ [dashboardService]
├── search/
│ ├── components/ [search/, search-page/]
│ ├── pages/ [SearchPage]
│ ├── services/ [searchService, unifiedSearchService]
│ └── utils/ [search utils]
├── profile/
│ ├── components/ [ProfileActions, ...]
│ ├── pages/ [user-profile-page/ (décomposé)]
│ ├── services/ [profileService, avatarService]
│ └── schemas/ [profile schemas]
├── settings/
│ ├── components/ [account-settings/]
│ ├── pages/ [SettingsPage]
│ ├── services/ [settingsService]
│ └── schemas/ [settings schemas]
├── notifications/
│ ├── components/ [notifications-page/]
│ └── services/ [notificationService]
├── upload/
│ └── components/ [upload-modal/]
├── admin/
│ └── api/ [auditService]
├── roles/
│ ├── components/ [RolesPage, ...]
│ ├── services/ [roleService]
│ └── types/ [role types]
├── sessions/
│ └── api/ [sessionsApi]
├── webhooks/
│ └── api/ [webhookApi]
├── stream/
│ └── pages/ [StreamPage]
├── studio/
│ └── components/ [cloud-file-browser/]
├── user/
│ └── components/ [profile/, profile-form/]
└── library/ (or inventory/)
├── hooks/ [useLibraryItems, useMyTracks]
└── pages/ [library-page/]
```
---
## Tests associés — Couverture
| Module | Tests unitaires | Tests intégration | Stories | Verdict |
|--------|----------------|-------------------|---------|---------|
| `components/ui/` | ✅ 20+ .test.tsx | — | ✅ 30+ .stories.tsx | Bon |
| `features/auth/` | ✅ LoginPage.test, RegisterPage.test | ✅ auth.integration.test | ✅ AuthView.stories | Bon |
| `features/tracks/` | ✅ TrackUpload.test, TrackGrid.test | ✅ trackUpload.integration | ✅ Multiple stories | Bon |
| `features/playlists/` | ✅ Multiple tests | ✅ 2 integration tests | ✅ Multiple stories | Bon |
| `features/player/` | ✅ playerStore.test | — | ✅ PlayerBar stories | Partiel |
| `features/streaming/` | ✅ Multiple tests | — | — | Partiel |
| `features/chat/` | — | — | ✅ ChatView.stories | ⚠️ Faible |
| `features/search/` | — | — | — | 🔴 Absent |
| `features/dashboard/` | — | — | — | 🔴 Absent |
| `components/layout/` | ✅ DashboardLayout.test | — | ✅ Multiple stories | Partiel |
---
## Statistiques globales
| Métrique | Valeur |
|----------|--------|
| Total composants UI primitifs | **60+** |
| Composants > 300 lignes | **3** (avatar, table, context-menu) |
| Composants bien typés (props interface) | **97%** |
| Feature modules structurés | **20** |
| Feature modules avec tests | **~60%** |
| Feature modules avec stories | **~50%** |
| Hooks custom | **50+** |
| Stores Zustand | **7** |
| Contextes React | **4** |