# 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** |