From 76d95ecfb4262e9b04a3b2333c0ba4003db6ed8a Mon Sep 17 00:00:00 2001 From: senke Date: Tue, 13 Jan 2026 19:47:57 +0100 Subject: [PATCH] incus deployement fully implemented, Makefile updated and make fmt ran --- Makefile | 86 +- apps/web/src/__tests__/accessibility.test.tsx | 58 +- apps/web/src/app/App.tsx | 7 +- apps/web/src/components/ErrorBoundary.tsx | 16 +- apps/web/src/components/OfflineIndicator.tsx | 6 +- .../components/admin/AdminDashboardView.tsx | 393 +- .../components/admin/AdminModerationView.tsx | 238 +- .../components/admin/AdminSettingsView.tsx | 184 +- .../src/components/admin/AdminUsersView.tsx | 247 +- .../web/src/components/admin/UserTableRow.tsx | 194 +- .../components/admin/modals/BanUserModal.tsx | 175 +- .../analytics/TrackAnalyticsView.tsx | 268 +- apps/web/src/components/base/Badge.tsx | 216 +- apps/web/src/components/base/Button.tsx | 29 +- apps/web/src/components/base/Card.tsx | 140 +- apps/web/src/components/base/Input.tsx | 11 +- apps/web/src/components/commerce/CartItem.tsx | 72 +- .../src/components/commerce/OrderSummary.tsx | 120 +- .../src/components/commerce/WishlistView.tsx | 247 +- .../commerce/modals/PromoCodeModal.tsx | 90 +- .../commerce/modals/RefundRequestModal.tsx | 94 +- .../web/src/components/dashboard/StatCard.tsx | 120 +- .../src/components/dashboard/TrackList.tsx | 76 +- apps/web/src/components/data/Table.tsx | 2 +- .../developer/APIPlaygroundView.tsx | 228 +- .../developer/DeveloperDashboardView.tsx | 262 +- .../src/components/developer/WebhooksView.tsx | 175 +- .../developer/modals/CreateAPIKeyModal.tsx | 188 +- .../src/components/education/CourseCard.tsx | 145 +- .../components/education/CourseDetailView.tsx | 506 +- .../education/CourseLearningView.tsx | 513 +- .../components/education/MyCoursesView.tsx | 199 +- .../education/modals/CertificateModal.tsx | 111 +- .../components/education/modals/QuizModal.tsx | 190 +- apps/web/src/components/filters/FilterBar.tsx | 1 - apps/web/src/components/filters/Sort.tsx | 14 +- apps/web/src/components/filters/index.ts | 1 - apps/web/src/components/forms/FormBuilder.tsx | 21 +- .../gamification/AchievementCard.tsx | 99 +- .../gamification/AchievementsView.tsx | 157 +- .../gamification/LeaderboardView.tsx | 254 +- .../components/gamification/ProfileXPView.tsx | 283 +- .../web/src/components/gamification/XPBar.tsx | 44 +- apps/web/src/components/index.ts | 1 - .../components/inventory/AddEquipmentView.tsx | 261 +- .../components/inventory/EquipmentCard.tsx | 76 +- .../inventory/EquipmentDetailView.tsx | 402 +- .../components/inventory/InventoryView.tsx | 194 +- .../keyboard/KeyboardShortcutsHelp.tsx | 11 +- .../web/src/components/layout/AudioPlayer.tsx | 348 +- apps/web/src/components/layout/Header.tsx | 66 +- apps/web/src/components/layout/Navbar.tsx | 117 +- apps/web/src/components/layout/Sidebar.tsx | 199 +- .../library/AutoMetadataDetectionModal.tsx | 70 +- .../library/WatermarkSettingsModal.tsx | 224 +- .../library/playlists/AddToPlaylistModal.tsx | 216 +- .../library/playlists/CreatePlaylistModal.tsx | 143 +- .../library/playlists/EditPlaylistModal.tsx | 239 +- .../library/playlists/PlaylistDetailView.tsx | 384 +- .../library/playlists/PlaylistsView.tsx | 267 +- .../library/playlists/QueueView.tsx | 348 +- .../playlists/SaveQueueAsPlaylistModal.tsx | 78 +- .../components/live/LiveStreamDetailView.tsx | 308 +- .../live/modals/TipStreamerModal.tsx | 162 +- .../components/marketplace/LicenceCard.tsx | 88 +- .../components/marketplace/ProductCard.tsx | 169 +- .../marketplace/ProductDetailView.tsx | 559 +- .../modals/LicenceDetailsModal.tsx | 126 +- .../marketplace/modals/ReviewProductModal.tsx | 109 +- .../src/components/modals/CreatorModal.tsx | 254 +- .../src/components/navigation/Pagination.tsx | 32 +- apps/web/src/components/navigation/Tabs.tsx | 3 +- .../notifications/NotificationBell.tsx | 103 +- .../notifications/NotificationItem.tsx | 59 +- .../notifications/NotificationMenu.tsx | 15 +- .../web/src/components/player/AudioPlayer.tsx | 14 +- apps/web/src/components/player/FullPlayer.tsx | 155 +- .../web/src/components/player/LyricsPanel.tsx | 99 +- apps/web/src/components/player/MiniPlayer.tsx | 148 +- .../components/player/PlaybackSpeedModal.tsx | 90 +- .../src/components/player/PlayerControls.tsx | 225 +- apps/web/src/components/player/QueuePanel.tsx | 5 +- .../player/VisualizerSettingsModal.tsx | 87 +- .../src/components/pwa/PWAInstallBanner.tsx | 10 +- .../src/components/search/GlobalSearchBar.tsx | 24 +- apps/web/src/components/search/Search.tsx | 6 +- apps/web/src/components/search/SearchBar.tsx | 248 +- .../components/seller/CreateProductView.tsx | 361 +- .../components/seller/SellerDashboardView.tsx | 385 +- .../seller/modals/FlashSaleModal.tsx | 224 +- .../AccessibilitySettingsView.tsx | 211 +- .../settings/account/AccountSettings.tsx | 381 +- .../settings/account/ChangeEmailModal.tsx | 130 +- .../settings/account/ChangeUsernameModal.tsx | 126 +- .../account/DeleteAccountConfirmModal.tsx | 74 +- .../settings/account/DeleteAccountView.tsx | 204 +- .../appearance/AppearanceSettingsView.tsx | 322 +- .../settings/backups/BackupsView.tsx | 320 +- .../settings/cloud/CloudIntegrationView.tsx | 313 +- .../settings/data/DataExportModal.tsx | 145 +- .../settings/data/DataExportView.tsx | 134 +- .../integrations/IntegrationsView.tsx | 242 +- .../settings/profile/EditProfile.tsx | 127 +- .../settings/security/LoginHistory.tsx | 111 +- .../settings/security/PasskeyModal.tsx | 51 +- .../settings/security/SecuritySettings.tsx | 61 +- .../settings/security/SessionManagement.tsx | 144 +- .../settings/security/TwoFactorSetup.tsx | 158 +- .../src/components/share/ShareLinkManager.tsx | 39 +- .../web/src/components/social/CommentItem.tsx | 49 +- .../src/components/social/CreatePostModal.tsx | 196 +- .../web/src/components/social/ExploreView.tsx | 299 +- apps/web/src/components/social/FeedView.tsx | 187 +- apps/web/src/components/social/PostCard.tsx | 388 +- .../src/components/social/SharePostModal.tsx | 209 +- .../social/connections/ConnectionsView.tsx | 143 +- .../social/groups/CreateGroupModal.tsx | 152 +- .../components/social/groups/GroupCard.tsx | 101 +- .../social/groups/GroupDetailView.tsx | 448 +- .../components/social/groups/GroupsView.tsx | 218 +- .../web/src/components/studio/AIToolsView.tsx | 247 +- .../components/studio/CloudFileBrowser.tsx | 758 +- .../components/studio/CloudSettingsView.tsx | 167 +- .../components/studio/ConnectivityView.tsx | 250 +- apps/web/src/components/studio/GoLiveView.tsx | 362 +- .../src/components/studio/ProjectsManager.tsx | 431 +- .../studio/projects/CreateProjectModal.tsx | 134 +- .../studio/projects/ProjectDetailView.tsx | 563 +- .../src/components/theme/ThemeSwitcher.tsx | 188 +- apps/web/src/components/types.ts | 15 +- .../web/src/components/ui.backup/HelpText.tsx | 7 +- .../components/ui.backup/LazyComponent.tsx | 34 +- .../components/ui.backup/avatar-upload.tsx | 70 +- apps/web/src/components/ui.backup/badge.tsx | 20 +- .../components/ui.backup/button-loading.tsx | 1 - .../ui.backup/confirmation-dialog.tsx | 1 - .../src/components/ui.backup/date-picker.tsx | 4 +- apps/web/src/components/ui.backup/dialog.tsx | 4 +- .../src/components/ui.backup/empty-state.tsx | 1 - .../src/components/ui.backup/file-upload.tsx | 1 - .../components/ui.backup/optimized-image.tsx | 11 +- .../src/components/ui.backup/scroll-area.tsx | 24 +- .../components/ui.backup/virtualized-list.tsx | 7 +- .../src/components/ui/AstralBackground.tsx | 48 +- apps/web/src/components/ui/DataList.test.tsx | 29 +- apps/web/src/components/ui/DataList.tsx | 80 +- .../ui/ERROR_DISPLAY_COMPONENT_API.md | 43 +- .../components/ui/ERROR_DISPLAY_STRATEGY.md | 96 +- apps/web/src/components/ui/ErrorDisplay.tsx | 220 +- apps/web/src/components/ui/FormField.test.tsx | 29 +- apps/web/src/components/ui/FormField.tsx | 40 +- apps/web/src/components/ui/HelpText.test.tsx | 19 +- apps/web/src/components/ui/HelpText.tsx | 31 +- .../src/components/ui/ImageCropper.test.tsx | 33 +- apps/web/src/components/ui/ImageCropper.tsx | 66 +- .../components/ui/ImageViewerModal.test.tsx | 38 +- .../src/components/ui/ImageViewerModal.tsx | 107 +- apps/web/src/components/ui/KodoEmptyState.tsx | 84 +- .../src/components/ui/LazyComponent.test.tsx | 33 +- apps/web/src/components/ui/LazyComponent.tsx | 117 +- apps/web/src/components/ui/LoadingState.tsx | 53 +- apps/web/src/components/ui/Toast.test.tsx | 41 +- apps/web/src/components/ui/Toast.tsx | 35 +- .../components/ui/WaveformVisualizer.test.tsx | 61 +- .../src/components/ui/WaveformVisualizer.tsx | 42 +- apps/web/src/components/ui/alert.test.tsx | 23 +- apps/web/src/components/ui/alert.tsx | 56 +- .../src/components/ui/avatar-upload.test.tsx | 74 +- apps/web/src/components/ui/avatar-upload.tsx | 96 +- apps/web/src/components/ui/avatar.tsx | 195 +- apps/web/src/components/ui/badge.tsx | 95 +- .../src/components/ui/button-loading.test.tsx | 21 +- apps/web/src/components/ui/button-loading.tsx | 27 +- apps/web/src/components/ui/button.tsx | 60 +- apps/web/src/components/ui/card.tsx | 56 +- apps/web/src/components/ui/checkbox.test.tsx | 29 +- apps/web/src/components/ui/checkbox.tsx | 57 +- .../ui/confirmation-dialog.test.tsx | 39 +- .../src/components/ui/confirmation-dialog.tsx | 43 +- apps/web/src/components/ui/date-picker.tsx | 36 +- apps/web/src/components/ui/dialog.test.tsx | 2 +- apps/web/src/components/ui/dialog.tsx | 62 +- .../src/components/ui/dropdown-menu.test.tsx | 39 +- apps/web/src/components/ui/dropdown-menu.tsx | 356 +- .../src/components/ui/empty-state.test.tsx | 40 +- apps/web/src/components/ui/empty-state.tsx | 46 +- .../src/components/ui/file-upload.test.tsx | 67 +- apps/web/src/components/ui/file-upload.tsx | 45 +- .../web/src/components/ui/focus-trap.test.tsx | 41 +- apps/web/src/components/ui/focus-trap.tsx | 16 +- apps/web/src/components/ui/input.test.tsx | 25 +- apps/web/src/components/ui/input.tsx | 18 +- apps/web/src/components/ui/label.test.tsx | 15 +- apps/web/src/components/ui/label.tsx | 15 +- .../web/src/components/ui/loading-spinner.tsx | 22 +- apps/web/src/components/ui/modal.tsx | 10 +- .../components/ui/optimized-image.test.tsx | 48 +- .../web/src/components/ui/optimized-image.tsx | 51 +- apps/web/src/components/ui/progress.test.tsx | 15 +- apps/web/src/components/ui/progress.tsx | 80 +- .../src/components/ui/radio-group.test.tsx | 45 +- apps/web/src/components/ui/radio-group.tsx | 62 +- .../src/components/ui/scroll-area.test.tsx | 23 +- apps/web/src/components/ui/scroll-area.tsx | 59 +- apps/web/src/components/ui/select.tsx | 56 +- apps/web/src/components/ui/skeleton.tsx | 26 +- apps/web/src/components/ui/slider.test.tsx | 21 +- apps/web/src/components/ui/slider.tsx | 77 +- apps/web/src/components/ui/switch.test.tsx | 25 +- apps/web/src/components/ui/switch.tsx | 45 +- apps/web/src/components/ui/table.test.tsx | 34 +- apps/web/src/components/ui/table.tsx | 82 +- apps/web/src/components/ui/tabs.test.tsx | 35 +- apps/web/src/components/ui/tabs.tsx | 96 +- apps/web/src/components/ui/textarea.test.tsx | 17 +- apps/web/src/components/ui/textarea.tsx | 39 +- apps/web/src/components/ui/tooltip.tsx | 50 +- .../components/ui/virtualized-list.test.tsx | 21 +- .../src/components/ui/virtualized-list.tsx | 39 +- .../src/components/upload/BulkUploadModal.tsx | 125 +- .../src/components/upload/FilePreviewCard.tsx | 82 +- .../src/components/upload/FileUploadZone.tsx | 86 +- .../components/upload/UploadProgressBar.tsx | 38 +- .../upload/metadata/CoverArtUploadModal.tsx | 128 +- .../upload/metadata/LyricsEditorModal.tsx | 127 +- .../upload/metadata/MetadataEditor.tsx | 274 +- .../upload/metadata/MetadataForm.tsx | 349 +- .../upload/metadata/TagSuggestionsModal.tsx | 158 +- apps/web/src/components/user/UserCard.tsx | 124 +- apps/web/src/components/views/AdminView.tsx | 110 +- .../src/components/views/AnalyticsView.tsx | 417 +- apps/web/src/components/views/AuthView.tsx | 25 +- apps/web/src/components/views/CartView.tsx | 227 +- apps/web/src/components/views/ChatView.tsx | 11 +- .../web/src/components/views/CheckoutView.tsx | 446 +- .../web/src/components/views/DiscoverView.tsx | 447 +- .../src/components/views/EducationView.tsx | 184 +- .../src/components/views/FileDetailsView.tsx | 392 +- .../src/components/views/FileManagerView.tsx | 578 +- apps/web/src/components/views/GearView.tsx | 752 +- apps/web/src/components/views/LiveView.tsx | 379 +- .../src/components/views/MarketplaceView.tsx | 303 +- .../components/views/NotificationsView.tsx | 171 +- apps/web/src/components/views/ProfileView.tsx | 904 +- .../src/components/views/PurchasesView.tsx | 250 +- .../src/components/views/SearchPageView.tsx | 436 +- .../web/src/components/views/SettingsView.tsx | 219 +- apps/web/src/components/views/SocialView.tsx | 282 +- apps/web/src/components/views/StudioView.tsx | 196 +- apps/web/src/components/views/UploadView.tsx | 484 +- apps/web/src/config/env.ts | 8 +- apps/web/src/config/features.ts | 5 +- apps/web/src/context/AudioContext.test.tsx | 57 +- apps/web/src/context/AudioContext.tsx | 190 +- apps/web/src/context/AuthContext.test.tsx | 6 +- apps/web/src/context/AuthContext.tsx | 18 +- apps/web/src/context/CartContext.test.tsx | 33 +- apps/web/src/context/CartContext.tsx | 46 +- apps/web/src/context/ThemeContext.test.tsx | 17 +- apps/web/src/context/ThemeContext.tsx | 20 +- apps/web/src/context/ToastContext.test.tsx | 43 +- apps/web/src/context/ToastContext.tsx | 17 +- apps/web/src/docs/LOADING_STATES_PATTERN.md | 28 +- apps/web/src/docs/MSW_SETUP.md | 28 +- apps/web/src/docs/OPTIMISTIC_UPDATES.md | 3 +- apps/web/src/docs/STATE_DEBUGGING.md | 11 +- apps/web/src/docs/STATE_SELECTORS.md | 18 +- .../src/features/admin/api/auditService.ts | 16 +- apps/web/src/features/admin/api/index.ts | 1 - .../analytics/services/analyticsService.ts | 92 +- .../auth/__tests__/auth.integration.test.tsx | 98 +- apps/web/src/features/auth/api/authApi.ts | 39 +- .../auth/components/AuthButton.test.tsx | 5 +- .../auth/components/AuthErrorMessage.test.tsx | 9 +- .../auth/components/AuthErrorMessage.tsx | 4 +- .../auth/components/AuthFormField.test.tsx | 10 +- .../features/auth/components/AuthInput.tsx | 14 +- .../features/auth/components/AuthLayout.tsx | 9 +- .../components/ForgotPasswordForm.test.tsx | 37 +- .../features/auth/components/LoginForm.tsx | 21 +- .../features/auth/components/OAuthButton.tsx | 1 - .../features/auth/components/OAuthButtons.tsx | 1 - .../components/PasswordStrengthIndicator.tsx | 2 - .../features/auth/components/RegisterForm.tsx | 17 +- .../auth/components/TwoFactorVerify.test.tsx | 10 +- .../features/auth/components/UserProfile.tsx | 4 +- apps/web/src/features/auth/hooks/useAuth.ts | 6 +- apps/web/src/features/auth/hooks/useLogin.ts | 11 +- .../features/auth/hooks/useOAuthCallback.ts | 16 +- apps/web/src/features/auth/hooks/useUser.ts | 10 +- .../features/auth/pages/LoginPage.test.tsx | 4 +- .../web/src/features/auth/pages/LoginPage.tsx | 4 +- .../auth/pages/ResetPasswordPage.test.tsx | 4 +- .../features/auth/pages/SessionsPage.test.tsx | 84 +- .../src/features/auth/pages/SessionsPage.tsx | 41 +- .../src/features/auth/services/authService.ts | 4 +- .../auth/services/emailVerificationService.ts | 8 +- apps/web/src/features/auth/store/authStore.ts | 50 +- .../web/src/features/auth/utils/ipLocation.ts | 9 +- .../features/auth/utils/userAgentParser.ts | 21 +- .../features/chat/components/ChatInput.tsx | 74 +- .../chat/components/ChatInterface.tsx | 13 +- .../features/chat/components/ChatMessage.tsx | 98 +- .../src/features/chat/components/ChatRoom.tsx | 44 +- .../features/chat/components/ChatSidebar.tsx | 132 +- .../chat/components/CreateRoomDialog.tsx | 14 +- .../chat/components/MessageSearch.tsx | 9 +- .../chat/components/TypingIndicator.tsx | 5 +- .../components/VirtualizedChatMessages.tsx | 5 +- apps/web/src/features/chat/hooks/useChat.ts | 67 +- apps/web/src/features/chat/pages/ChatPage.tsx | 42 +- .../chat/services/conversationService.ts | 43 +- apps/web/src/features/chat/store/chatStore.ts | 54 +- apps/web/src/features/chat/types/index.ts | 36 +- .../features/dashboard/hooks/useDashboard.ts | 8 +- .../dashboard/pages/DashboardPage.tsx | 6 +- .../dashboard/services/dashboardService.ts | 58 +- .../src/features/error/pages/NotFoundPage.tsx | 1 - .../features/error/pages/ServerErrorPage.tsx | 18 +- .../library/components/LibraryManager.tsx | 8 +- .../library/components/UploadModal.tsx | 6 +- .../features/library/hooks/useLibraryItems.ts | 27 +- .../features/library/pages/LibraryPage.tsx | 124 +- .../features/marketplace/components/Cart.tsx | 5 +- .../marketplace/components/ProductCard.tsx | 7 +- .../notifications/pages/NotificationsPage.tsx | 39 +- .../services/notificationService.ts | 29 +- .../player/components/GlobalPlayer.tsx | 57 +- .../features/player/components/MiniPlayer.tsx | 1 - .../player/components/NextPreviousButtons.tsx | 1 - .../components/PlaybackSpeedControl.tsx | 2 +- .../player/components/PlayerError.tsx | 4 +- .../player/components/PlayerLoading.tsx | 1 - .../player/components/QualitySelector.tsx | 3 +- .../components/RepeatShuffleButtons.tsx | 5 +- .../player/components/TimeDisplay.tsx | 1 - .../features/player/components/TrackInfo.tsx | 1 - .../player/components/VolumeControl.tsx | 4 +- .../src/features/player/hooks/usePlayer.ts | 6 +- .../features/player/services/syncClient.ts | 22 +- .../__tests__/playlist.integration.test.tsx | 27 +- .../components/AddCollaboratorModal.test.tsx | 21 +- .../components/AddCollaboratorModal.tsx | 21 +- .../CollaboratorManagement.test.tsx | 1 - .../components/CollaboratorManagement.tsx | 1 - .../components/PlaylistAnalytics.tsx | 86 +- .../components/PlaylistErrorBoundary.tsx | 6 +- .../components/PlaylistFollowButton.test.tsx | 16 +- .../components/PlaylistFollowButton.tsx | 15 +- .../components/PlaylistHeader.test.tsx | 1 - .../playlists/components/PlaylistList.tsx | 64 +- .../components/PlaylistTrackList.tsx | 2 +- .../components/SharePlaylistModal.tsx | 3 +- .../hooks/usePlaylistNotifications.ts | 48 +- .../playlists/pages/PlaylistDetailPage.tsx | 23 +- .../playlists/pages/PlaylistListPage.tsx | 41 +- apps/web/src/features/playlists/routes.tsx | 5 +- .../playlists/services/playlistService.ts | 45 +- .../profile/components/FollowButton.tsx | 7 +- .../profile/pages/UserProfilePage.tsx | 62 +- .../profile/services/avatarService.test.ts | 7 +- .../profile/services/profileService.test.ts | 19 +- .../profile/services/profileService.ts | 4 +- .../roles/components/AssignRoleModal.tsx | 5 +- .../roles/components/CreateRoleModal.tsx | 39 +- .../roles/components/EditRoleModal.tsx | 40 +- .../src/features/roles/pages/RolesPage.tsx | 22 +- .../features/roles/services/roleService.ts | 4 +- .../features/search/services/searchService.ts | 8 +- .../search/services/unifiedSearchService.ts | 36 +- .../src/features/sessions/api/sessionsApi.ts | 3 +- .../settings/components/AccountSettings.tsx | 26 +- .../settings/components/PlaybackSettings.tsx | 5 +- .../components/PreferenceSettings.tsx | 5 +- .../settings/components/SettingsTabs.tsx | 10 +- .../features/settings/pages/SettingsPage.tsx | 22 +- .../components/PlaybackDashboard.tsx | 17 +- .../streaming/components/PlaybackHeatmap.tsx | 4 +- .../streaming/components/PlaybackSummary.tsx | 4 +- .../streaming/hooks/usePlaybackAnalytics.ts | 7 +- .../streaming/hooks/usePlaybackRealtime.ts | 10 +- .../streaming/services/bitrateService.ts | 10 +- .../features/streaming/services/hlsService.ts | 4 +- .../services/playbackAnalyticsService.ts | 68 +- .../trackUpload.integration.test.tsx | 131 +- apps/web/src/features/tracks/api/trackApi.ts | 43 +- .../tracks/components/CommentSection.tsx | 19 +- .../tracks/components/CommentThread.test.tsx | 54 +- .../tracks/components/CommentThread.tsx | 13 +- .../tracks/components/LikeButton.test.tsx | 5 +- .../features/tracks/components/LikeButton.tsx | 16 +- .../tracks/components/ShareDialog.test.tsx | 1 - .../tracks/components/ShareDialog.tsx | 9 +- .../features/tracks/components/TrackCard.tsx | 14 +- .../tracks/components/TrackSearch.test.tsx | 10 +- .../tracks/components/TrackStats.test.tsx | 2 +- .../components/TrackStatsDisplay.test.tsx | 2 +- .../tracks/components/TrackStatsDisplay.tsx | 5 +- .../tracks/components/UploadQuota.test.tsx | 2 +- .../tracks/components/UploadQuota.tsx | 5 +- .../docs/TRACK_QUERIES_REACT_QUERY_AUDIT.md | 6 +- .../src/features/tracks/errors/trackErrors.ts | 18 +- .../features/tracks/pages/TrackDetailPage.tsx | 55 +- .../tracks/services/analyticsService.ts | 646 +- .../services/chunkedUploadService.test.ts | 16 +- .../tracks/services/chunkedUploadService.ts | 9 +- .../tracks/services/interactionService.ts | 446 +- .../features/tracks/services/uploadService.ts | 606 +- .../upload/components/UploadModal.tsx | 67 +- .../features/user/components/ProfileForm.tsx | 96 +- .../src/features/webhooks/api/webhookApi.ts | 13 +- apps/web/src/hooks/index.ts | 1 - apps/web/src/hooks/types.ts | 14 +- apps/web/src/hooks/useDebounce.test.ts | 24 +- .../hooks/useGlobalKeyboardShortcuts.test.ts | 15 +- .../src/hooks/useGlobalKeyboardShortcuts.ts | 14 +- .../src/hooks/useIntersectionObserver.test.ts | 13 +- apps/web/src/hooks/useIntersectionObserver.ts | 44 +- .../src/hooks/useKeyboardNavigation.test.ts | 61 +- apps/web/src/hooks/useLocalStorage.test.ts | 35 +- apps/web/src/hooks/useLocalStorage.ts | 114 +- apps/web/src/hooks/useMutationRetry.ts | 10 +- apps/web/src/hooks/useOnlineStatus.test.ts | 11 +- apps/web/src/hooks/usePWA.test.ts | 19 +- apps/web/src/hooks/usePWA.ts | 14 +- apps/web/src/hooks/usePreload.test.ts | 87 +- .../src/hooks/useQueryInvalidation.test.ts | 9 +- apps/web/src/hooks/useQueryInvalidation.ts | 19 +- .../hooks/useRoutePreload-additional.test.ts | 78 +- apps/web/src/hooks/useRoutePreload.test.ts | 11 +- apps/web/src/hooks/useRoutePreload.ts | 12 +- apps/web/src/hooks/useToast.test.ts | 1 - apps/web/src/hooks/useTranslation.test.ts | 15 +- apps/web/src/index.css | 88 +- apps/web/src/lib/sentry.ts | 1 - apps/web/src/lib/utils.ts | 8 +- apps/web/src/mocks/handlers.ts | 2 +- apps/web/src/pages/AdminDashboardPage.tsx | 79 +- apps/web/src/pages/AnalyticsPage.tsx | 26 +- apps/web/src/pages/DashboardPage.tsx | 153 +- apps/web/src/pages/DesignSystemDemo.tsx | 740 +- apps/web/src/pages/DesignSystemDemoPage.tsx | 323 +- apps/web/src/pages/DeveloperPage.tsx | 103 +- apps/web/src/pages/EducationPage.tsx | 65 +- apps/web/src/pages/GearPage.tsx | 65 +- apps/web/src/pages/LivePage.tsx | 67 +- apps/web/src/pages/LoginPage.tsx | 4 +- apps/web/src/pages/QueuePage.tsx | 73 +- apps/web/src/pages/SearchPage.tsx | 59 +- apps/web/src/pages/SettingsPage.tsx | 313 +- apps/web/src/pages/SocialPage.tsx | 256 +- apps/web/src/pages/WebhooksPage.tsx | 26 +- apps/web/src/pages/auth/Login.test.tsx | 7 +- apps/web/src/pages/auth/Register.test.tsx | 3 +- .../src/pages/marketplace/MarketplaceHome.tsx | 19 +- .../web/src/schemas/apiRequestSchemas.test.ts | 5 +- apps/web/src/schemas/apiRequestSchemas.ts | 65 +- apps/web/src/schemas/apiSchemas.test.ts | 1 - apps/web/src/schemas/apiSchemas.ts | 199 +- apps/web/src/services/2fa-service.test.ts | 1 - apps/web/src/services/2fa-service.ts | 7 +- .../services/__tests__/authService.test.ts | 5 +- .../__tests__/playlistService.test.ts | 5 +- .../services/__tests__/trackService.test.ts | 10 +- apps/web/src/services/adminService.test.ts | 15 +- apps/web/src/services/adminService.ts | 121 +- .../web/src/services/analyticsService.test.ts | 17 +- apps/web/src/services/analyticsService.ts | 85 +- apps/web/src/services/api/auth.ts | 18 +- apps/web/src/services/api/client.test.ts | 14 +- apps/web/src/services/api/client.ts | 546 +- apps/web/src/services/api/index.ts | 11 +- apps/web/src/services/authService.ts | 42 +- apps/web/src/services/chatService.test.ts | 13 +- apps/web/src/services/chatService.ts | 160 +- apps/web/src/services/commerceService.test.ts | 14 +- apps/web/src/services/commerceService.ts | 125 +- apps/web/src/services/cookieService.ts | 1 - apps/web/src/services/csrf.ts | 4 +- .../web/src/services/developerService.test.ts | 9 +- apps/web/src/services/developerService.ts | 91 +- .../web/src/services/educationService.test.ts | 7 +- apps/web/src/services/educationService.ts | 128 +- .../src/services/gamificationService.test.ts | 13 +- apps/web/src/services/gamificationService.ts | 167 +- apps/web/src/services/gearService.test.ts | 13 +- apps/web/src/services/gearService.ts | 76 +- apps/web/src/services/groupService.test.ts | 11 +- apps/web/src/services/groupService.ts | 131 +- .../src/services/marketplaceService.test.ts | 15 +- apps/web/src/services/marketplaceService.ts | 30 +- apps/web/src/services/offlineQueue.test.ts | 26 +- apps/web/src/services/offlineQueue.ts | 104 +- apps/web/src/services/playlistService.test.ts | 23 +- apps/web/src/services/playlistService.ts | 252 +- apps/web/src/services/projectService.test.ts | 11 +- apps/web/src/services/projectService.ts | 67 +- .../src/services/requestDeduplication.test.ts | 52 +- apps/web/src/services/requestDeduplication.ts | 66 +- apps/web/src/services/responseCache.test.ts | 5 +- apps/web/src/services/responseCache.ts | 52 +- apps/web/src/services/roleService.ts | 1 - apps/web/src/services/searchService.test.ts | 9 +- apps/web/src/services/searchService.ts | 83 +- apps/web/src/services/sessionService.test.ts | 11 +- apps/web/src/services/sessionService.ts | 26 +- apps/web/src/services/socialService.test.ts | 21 +- apps/web/src/services/socialService.ts | 67 +- apps/web/src/services/storageService.test.ts | 16 +- apps/web/src/services/storageService.ts | 89 +- apps/web/src/services/tokenRefresh.ts | 55 +- apps/web/src/services/tokenStorage.ts | 39 +- apps/web/src/services/trackService.ts | 101 +- apps/web/src/services/uploadService.test.ts | 19 +- apps/web/src/services/uploadService.ts | 54 +- apps/web/src/services/userService.test.ts | 9 +- apps/web/src/services/userService.ts | 196 +- apps/web/src/stores/auth.test.ts | 5 +- apps/web/src/stores/cartStore.test.ts | 1 - apps/web/src/stores/cartStore.ts | 1 - apps/web/src/stores/chat.ts | 58 +- .../docs/LIBRARY_STORE_DOMAIN_DATA_AUDIT.md | 6 +- .../stores/docs/LIBRARY_STORE_USAGE_AUDIT.md | 17 +- apps/web/src/stores/index.ts | 14 +- apps/web/src/stores/library.ts | 85 +- apps/web/src/stores/types.ts | 13 +- apps/web/src/stores/ui.test.ts | 3 +- apps/web/src/stores/ui.ts | 4 +- apps/web/src/styles/badge-avatar.css | 276 +- apps/web/src/styles/button.css | 305 +- apps/web/src/styles/card.css | 216 +- apps/web/src/styles/design-system.css | 244 +- apps/web/src/styles/design-tokens.css | 87 +- apps/web/src/styles/global-effects.css | 212 +- apps/web/src/styles/header.css | 336 +- apps/web/src/styles/input.css | 286 +- apps/web/src/styles/premium-utilities.css | 110 +- apps/web/src/styles/visual-enhancements.css | 242 +- apps/web/src/test/mocks.tsx | 4 +- apps/web/src/test/setup.ts | 4 +- apps/web/src/test/test-utils.tsx | 14 +- apps/web/src/types/api.ts | 11 +- apps/web/src/types/backend-types.ts | 35 +- apps/web/src/types/dto.ts | 3 +- apps/web/src/types/forms.ts | 8 +- apps/web/src/types/generated/api.ts | 16070 ++++++++++------ apps/web/src/types/generated/base.ts | 55 +- apps/web/src/types/generated/common.ts | 206 +- apps/web/src/types/generated/configuration.ts | 215 +- .../src/types/generated/docs/AnalyticsApi.md | 330 +- .../docs/AnalyticsEventsPost200Response.md | 17 +- ...AnalyticsEventsPost200ResponseAllOfData.md | 9 +- .../generated/docs/AnalyticsGet200Response.md | 17 +- .../docs/AnalyticsGet200ResponseAllOfData.md | 17 +- .../docs/AnalyticsTracksIdGet200Response.md | 17 +- ...nalyticsTracksIdGet200ResponseAllOfData.md | 9 +- .../docs/AnalyticsTracksTopGet200Response.md | 17 +- ...alyticsTracksTopGet200ResponseAllOfData.md | 9 +- .../docs/ApiV1LogsFrontendPost200Response.md | 17 +- ...iV1LogsFrontendPost200ResponseAllOfData.md | 9 +- .../docs/AuditActivityGet200Response.md | 17 +- .../AuditActivityGet200ResponseAllOfData.md | 9 +- apps/web/src/types/generated/docs/AuditApi.md | 153 +- .../generated/docs/AuditLogsGet200Response.md | 17 +- .../docs/AuditLogsGet200ResponseAllOfData.md | 13 +- .../docs/AuditStatsGet200Response.md | 17 +- .../docs/AuditStatsGet200ResponseAllOfData.md | 9 +- .../docs/Auth2faSetupPost200Response.md | 17 +- .../docs/Auth2faStatusGet200Response.md | 17 +- .../Auth2faStatusGet200ResponseAllOfData.md | 9 +- apps/web/src/types/generated/docs/AuthApi.md | 413 +- .../docs/AuthCheckUsernameGet200Response.md | 17 +- ...uthCheckUsernameGet200ResponseAllOfData.md | 13 +- .../generated/docs/AuthLogoutPostRequest.md | 9 +- .../generated/docs/AuthMeGet200Response.md | 17 +- apps/web/src/types/generated/docs/ChatApi.md | 33 +- .../generated/docs/ChatTokenGet200Response.md | 17 +- .../docs/ChatTokenGet200ResponseAllOfData.md | 9 +- .../src/types/generated/docs/CommentApi.md | 222 +- .../docs/CommentsIdPut200Response.md | 17 +- .../docs/CommentsIdPut200ResponseAllOfData.md | 9 +- .../docs/CommentsIdRepliesGet200Response.md | 17 +- ...ommentsIdRepliesGet200ResponseAllOfData.md | 13 +- .../InternalCoreTrackBatchDeleteRequest.md | 9 +- ...alCoreTrackCompleteChunkedUploadRequest.md | 9 +- ...alCoreTrackInitiateChunkedUploadRequest.md | 17 +- .../InternalCoreTrackUpdateTrackRequest.md | 29 +- .../docs/InternalHandlersAPIResponse.md | 17 +- .../InternalHandlersCreateCommentRequest.md | 13 +- .../InternalHandlersCreateOrderRequest.md | 9 +- ...nalHandlersCreateOrderRequestItemsInner.md | 9 +- .../InternalHandlersCreatePlaylistRequest.md | 17 +- .../InternalHandlersCreateProductRequest.md | 29 +- ...InternalHandlersDisableTwoFactorRequest.md | 9 +- .../InternalHandlersFrontendLogRequest.md | 25 +- .../InternalHandlersRecordEventRequest.md | 13 +- .../docs/InternalHandlersRecordPlayRequest.md | 13 +- .../InternalHandlersReorderTracksRequest.md | 9 +- .../InternalHandlersSetupTwoFactorResponse.md | 17 +- .../InternalHandlersUpdateCommentRequest.md | 9 +- .../InternalHandlersUpdatePlaylistRequest.md | 17 +- .../InternalHandlersUpdateProductRequest.md | 21 +- .../InternalHandlersUpdateProfileRequest.md | 37 +- .../InternalHandlersVerifyTwoFactorRequest.md | 13 +- .../src/types/generated/docs/LoggingApi.md | 43 +- .../types/generated/docs/MarketplaceApi.md | 276 +- .../src/types/generated/docs/PlaylistApi.md | 309 +- .../generated/docs/PlaylistsGet200Response.md | 17 +- .../docs/PlaylistsGet200ResponseAllOfData.md | 13 +- .../docs/PlaylistsIdTracksPostRequest.md | 9 +- .../docs/PlaylistsPost201Response.md | 17 +- .../docs/PlaylistsPost201ResponseAllOfData.md | 9 +- apps/web/src/types/generated/docs/TrackApi.md | 482 +- .../docs/TracksBatchDeletePost200Response.md | 17 +- ...acksBatchDeletePost200ResponseAllOfData.md | 13 +- .../docs/TracksChunkPost200Response.md | 17 +- .../TracksChunkPost200ResponseAllOfData.md | 21 +- .../docs/TracksCompletePost201Response.md | 17 +- .../TracksCompletePost201ResponseAllOfData.md | 17 +- .../generated/docs/TracksGet200Response.md | 17 +- .../docs/TracksGet200ResponseAllOfData.md | 13 +- .../TracksIdAnalyticsPlaysGet200Response.md | 17 +- ...IdAnalyticsPlaysGet200ResponseAllOfData.md | 9 +- .../docs/TracksIdCommentsGet200Response.md | 17 +- ...TracksIdCommentsGet200ResponseAllOfData.md | 13 +- .../docs/TracksIdDelete200Response.md | 17 +- .../docs/TracksIdStatusGet200Response.md | 17 +- .../TracksIdStatusGet200ResponseAllOfData.md | 9 +- .../docs/TracksInitiatePost200Response.md | 17 +- .../TracksInitiatePost200ResponseAllOfData.md | 13 +- .../generated/docs/TracksPost201Response.md | 17 +- .../docs/TracksPost201ResponseAllOfData.md | 9 +- .../docs/TracksQuotaIdGet200Response.md | 17 +- .../TracksQuotaIdGet200ResponseAllOfData.md | 9 +- .../TracksResumeUploadIdGet200Response.md | 17 +- ...ksResumeUploadIdGet200ResponseAllOfData.md | 13 +- apps/web/src/types/generated/docs/UserApi.md | 253 +- .../generated/docs/UsersGet200Response.md | 17 +- .../docs/UsersGet200ResponseAllOfData.md | 13 +- .../generated/docs/UsersIdGet200Response.md | 17 +- .../docs/UsersIdGet200ResponseAllOfData.md | 9 +- ...ndApiInternalCoreMarketplaceLicenseType.md | 7 +- ...aBackendApiInternalCoreMarketplaceOrder.md | 41 +- ...kendApiInternalCoreMarketplaceOrderItem.md | 21 +- ...ackendApiInternalCoreMarketplaceProduct.md | 53 +- ...ApiInternalCoreMarketplaceProductStatus.md | 7 +- .../VezaBackendApiInternalDtoLoginRequest.md | 17 +- .../VezaBackendApiInternalDtoLoginResponse.md | 17 +- ...VezaBackendApiInternalDtoRefreshRequest.md | 9 +- ...ezaBackendApiInternalDtoRegisterRequest.md | 21 +- ...zaBackendApiInternalDtoRegisterResponse.md | 13 +- ...ApiInternalDtoResendVerificationRequest.md | 9 +- .../VezaBackendApiInternalDtoTokenResponse.md | 17 +- .../VezaBackendApiInternalDtoUserResponse.md | 17 +- .../VezaBackendApiInternalModelsPlaylist.md | 53 +- ...ndApiInternalModelsPlaylistCollaborator.md | 33 +- ...kendApiInternalModelsPlaylistPermission.md | 7 +- ...zaBackendApiInternalModelsPlaylistTrack.md | 33 +- .../docs/VezaBackendApiInternalModelsTrack.md | 105 +- ...VezaBackendApiInternalModelsTrackStatus.md | 9 +- .../docs/VezaBackendApiInternalModelsUser.md | 105 +- ...zaBackendApiInternalResponseAPIResponse.md | 17 +- .../src/types/generated/docs/WebhookApi.md | 209 +- .../generated/docs/WebhooksGet200Response.md | 17 +- .../docs/WebhooksGet200ResponseAllOfData.md | 9 +- .../WebhooksIdRegenerateKeyPost200Response.md | 17 +- ...IdRegenerateKeyPost200ResponseAllOfData.md | 13 +- .../generated/docs/WebhooksPost201Response.md | 17 +- .../docs/WebhooksPost201ResponseAllOfData.md | 9 +- apps/web/src/types/index.ts | 20 +- apps/web/src/types/marketplace.ts | 7 +- apps/web/src/types/queryParams.ts | 64 +- apps/web/src/types/routes.ts | 17 +- apps/web/src/types/v2-v3-types.ts | 27 +- apps/web/src/types/webhook.ts | 30 +- apps/web/src/types/websocket.ts | 10 +- apps/web/src/utils/apiErrorHandler.test.ts | 12 +- apps/web/src/utils/apiErrorHandler.ts | 102 +- apps/web/src/utils/apiToastHelper.test.ts | 27 +- apps/web/src/utils/apiToastHelper.ts | 1 - apps/web/src/utils/broadcastSync.ts | 36 +- apps/web/src/utils/date.test.ts | 1 - apps/web/src/utils/errorMessages.test.ts | 35 +- apps/web/src/utils/errorMessages.ts | 132 +- apps/web/src/utils/formValidation.ts | 28 +- apps/web/src/utils/format.test.ts | 5 +- apps/web/src/utils/idNormalization.test.ts | 5 +- apps/web/src/utils/idNormalization.ts | 78 +- apps/web/src/utils/logger.test.ts | 1 - apps/web/src/utils/logger.ts | 76 +- apps/web/src/utils/networkErrorTracker.ts | 8 +- apps/web/src/utils/offlineDetection.ts | 5 +- apps/web/src/utils/optimisticStoreUpdates.ts | 125 +- apps/web/src/utils/optimisticUpdates.ts | 121 +- apps/web/src/utils/reportIssue.ts | 74 +- apps/web/src/utils/sanitize.test.ts | 15 +- apps/web/src/utils/sanitize.ts | 3 +- .../web/src/utils/serviceErrorHandler.test.ts | 1 - apps/web/src/utils/serviceErrorHandler.ts | 25 +- apps/web/src/utils/stateHydration.ts | 64 +- apps/web/src/utils/stateInvalidation.ts | 57 +- apps/web/src/utils/stateMiddleware.test.ts | 37 +- apps/web/src/utils/stateMiddleware.ts | 91 +- apps/web/src/utils/stateNormalization.ts | 9 +- apps/web/src/utils/storeSelectors.ts | 240 +- apps/web/src/utils/timeoutHandler.test.ts | 1 - apps/web/src/utils/timeoutHandler.ts | 34 +- apps/web/src/utils/typeGuards.test.ts | 1 - apps/web/src/utils/typeGuards.ts | 16 +- apps/web/src/utils/undoRedo.ts | 75 +- apps/web/src/utils/url.test.ts | 58 +- apps/web/src/utils/validation.ts | 57 +- config/incus/DEPLOYMENT_FEEDBACK.md | 300 + config/incus/README.md | 226 +- config/incus/apache/veza-web.conf | 62 + config/incus/build-native.sh | 161 + config/incus/deploy-service-native.sh | 300 + config/incus/env/backend-api.env | 27 + config/incus/env/chat-server.env | 32 + config/incus/env/stream-server.env | 26 + config/incus/haproxy.cfg | 85 + config/incus/systemd/veza-backend-api.service | 27 + config/incus/systemd/veza-chat-server.service | 27 + .../incus/systemd/veza-stream-server.service | 27 + config/incus/verify-deployment.sh | 142 + veza-backend-api/cmd/api/main.go | 4 +- veza-backend-api/cmd/backup/main.go | 1 - .../api/handlers/rbac_handlers_test.go | 1 - veza-backend-api/internal/api/user/handler.go | 2 +- veza-backend-api/internal/api/versioning.go | 11 +- .../internal/api/versioning_test.go | 1 - veza-backend-api/internal/config/config.go | 68 +- .../internal/core/track/handler.go | 2 +- .../core/track/handler_additional_test.go | 19 +- .../internal/core/track/handler_test.go | 1 - .../internal/core/track/service.go | 8 +- .../track/track_upload_integration_test.go | 19 +- .../database/migration_rollback_test.go | 10 +- .../internal/database/performance_monitor.go | 5 +- .../internal/handlers/analytics_handler.go | 46 +- .../handlers/auth_integration_test.go | 23 +- .../internal/handlers/avatar_handler_test.go | 1 - .../internal/handlers/comment_handler_test.go | 9 +- veza-backend-api/internal/handlers/common.go | 18 +- .../internal/handlers/config_reload_test.go | 1 - .../internal/handlers/csrf_test.go | 1 - .../internal/handlers/frontend_log_handler.go | 8 +- .../internal/handlers/marketplace_test.go | 13 +- .../internal/handlers/oauth_handlers_test.go | 2 - .../handlers/password_reset_handler_test.go | 1 - .../handlers/playback_websocket_handler.go | 2 +- .../playback_websocket_handler_test.go | 25 +- .../internal/handlers/role_handler_test.go | 1 - .../internal/handlers/search_handlers_test.go | 1 - veza-backend-api/internal/handlers/session.go | 2 +- .../internal/handlers/session_test.go | 3 +- .../handlers/settings_handler_test.go | 3 +- .../internal/handlers/system_metrics_test.go | 2 - .../handlers/two_factor_handler_test.go | 2 - .../internal/logging/logger_aggregation.go | 15 +- .../logging/logger_aggregation_test.go | 2 - .../internal/logging/secret_filter.go | 15 +- .../internal/logging/secret_filter_test.go | 9 +- veza-backend-api/internal/middleware/auth.go | 12 +- .../middleware/context_propagation.go | 7 +- .../middleware/csrf_integration_test.go | 1 - .../internal/middleware/endpoint_limiter.go | 8 +- .../internal/middleware/error_handler.go | 6 +- .../internal/middleware/monitoring.go | 1 - .../middleware/ownership_integration_test.go | 1 - .../internal/middleware/rate_limiter.go | 2 +- .../rate_limiting_integration_test.go | 23 +- .../internal/middleware/ratelimit.go | 2 +- .../internal/middleware/user_rate_limiter.go | 1 - .../internal/middleware/validation.go | 12 +- .../internal/middleware/validation_test.go | 1 - .../internal/middleware/webhook_api_key.go | 1 - .../internal/models/notification.go | 1 - veza-backend-api/internal/models/webhook.go | 2 +- .../internal/recovery/error_recovery.go | 1 - .../internal/recovery/error_recovery_test.go | 1 - veza-backend-api/internal/recovery/retry.go | 17 +- .../internal/recovery/retry_test.go | 11 +- .../services/account_lockout_service.go | 9 +- .../services/account_lockout_service_test.go | 1 - .../services/analytics_aggregation_service.go | 55 +- .../analytics_aggregation_service_test.go | 1 - .../services/audio_transcode_service.go | 31 +- .../services/audio_transcode_service_test.go | 13 +- .../internal/services/audit_service_test.go | 17 +- .../internal/services/backup_service.go | 33 +- .../internal/services/backup_service_test.go | 1 - .../internal/services/cache_service_test.go | 9 +- .../internal/services/cdn_service.go | 25 +- .../internal/services/cdn_service_test.go | 15 +- .../internal/services/data_export_service.go | 151 +- .../services/data_export_service_test.go | 3 +- .../internal/services/email_service_test.go | 1 - .../services/fulltext_search_service.go | 29 +- .../services/fulltext_search_service_test.go | 1 - .../hls_streaming_service_enhanced.go | 29 +- .../hls_streaming_service_enhanced_test.go | 7 +- .../services/image_service_enhanced.go | 31 +- .../services/image_service_enhanced_test.go | 1 - .../internal/services/image_service_test.go | 6 +- .../internal/services/job_service.go | 2 +- .../internal/services/job_service_test.go | 5 +- .../services/metadata_service_test.go | 1 - .../services/monitoring_alerting_service.go | 13 +- .../monitoring_alerting_service_test.go | 1 - .../services/notification_service_enhanced.go | 13 +- .../notification_service_enhanced_test.go | 1 - .../services/notification_service_test.go | 1 - .../internal/services/password_service.go | 4 +- .../password_service_integration_test.go | 3 +- .../internal/services/role_service_test.go | 1 - .../internal/services/s3_storage_service.go | 31 +- .../services/s3_storage_service_test.go | 1 - .../internal/services/social_service_test.go | 1 - .../internal/services/stream_service.go | 6 +- .../services/track_recommendation_service.go | 17 +- .../track_recommendation_service_test.go | 17 +- .../internal/services/user_service_search.go | 6 +- .../internal/services/webhook_service.go | 2 +- .../internal/services/webhook_service_test.go | 1 - .../internal/shutdown/shutdown.go | 7 +- .../internal/shutdown/shutdown_test.go | 1 - .../internal/tracing/http_client.go | 3 +- .../internal/tracing/trace_context.go | 3 +- .../internal/tracing/trace_context_test.go | 1 - veza-backend-api/internal/utils/datetime.go | 1 - veza-backend-api/internal/utils/sanitizer.go | 1 - .../internal/validators/password_validator.go | 26 +- .../internal/validators/validator.go | 6 +- .../internal/websocket/message.go | 39 +- .../tests/contract/api_contract_test.go | 25 +- .../tests/integration/resume_upload_test.go | 1 - .../tests/integration/track_quota_test.go | 1 - 838 files changed, 46074 insertions(+), 30345 deletions(-) create mode 100644 config/incus/DEPLOYMENT_FEEDBACK.md create mode 100644 config/incus/apache/veza-web.conf create mode 100755 config/incus/build-native.sh create mode 100755 config/incus/deploy-service-native.sh create mode 100644 config/incus/env/backend-api.env create mode 100644 config/incus/env/chat-server.env create mode 100644 config/incus/env/stream-server.env create mode 100644 config/incus/haproxy.cfg create mode 100644 config/incus/systemd/veza-backend-api.service create mode 100644 config/incus/systemd/veza-chat-server.service create mode 100644 config/incus/systemd/veza-stream-server.service create mode 100755 config/incus/verify-deployment.sh diff --git a/Makefile b/Makefile index a3e0a7b94..055d76aa4 100644 --- a/Makefile +++ b/Makefile @@ -130,11 +130,19 @@ deploy-docker: build-all ## [HIGH] Deploy all services with Docker + HAProxy @$(MAKE) -s wait-for-services @$(ECHO_CMD) "${GREEN}✅ Deployment complete! Access via http://localhost:$(PORT_HAPROXY)${NC}" -deploy-incus: build-all ## [HIGH] Deploy all services with Incus containers - @$(ECHO_CMD) "${BOLD}${BLUE}📦 Deploying with Incus...${NC}" +deploy-incus: build-all-native ## [HIGH] Deploy all services with Incus containers (native, no Docker) + @$(ECHO_CMD) "${BOLD}${BLUE}📦 Deploying with Incus (native)...${NC}" @$(MAKE) -s incus-setup-network - @$(MAKE) -s incus-deploy-all + @$(MAKE) -s incus-deploy-infra + @$(MAKE) -s incus-deploy-all-native + @$(MAKE) -s incus-start-all @$(ECHO_CMD) "${GREEN}✅ Incus deployment complete!${NC}" + @$(ECHO_CMD) "${BLUE}Access services at:${NC}" + @$(ECHO_CMD) " Backend API: http://10.10.10.2:8080" + @$(ECHO_CMD) " Chat Server: http://10.10.10.3:8081" + @$(ECHO_CMD) " Stream Server: http://10.10.10.4:3002" + @$(ECHO_CMD) " Web Frontend: http://10.10.10.5:80" + @$(ECHO_CMD) " HAProxy: http://10.10.10.6:80" status-full: ## [HIGH] Show complete system status @$(ECHO_CMD) "${BOLD}${CYAN}📊 SYSTEM STATUS${NC}" @@ -196,7 +204,7 @@ build-service: ## [MID] Build a specific service (usage: make build-service SERV @$(MAKE) -s build-$(SERVICE) @$(ECHO_CMD) "${GREEN}✅ $(SERVICE) built.${NC}" -build-all: ## [MID] Build all services +build-all: ## [MID] Build all services (Docker images) @$(ECHO_CMD) "${BLUE}🔨 Building all services...${NC}" @$(MAKE) -s build-backend-api @$(MAKE) -s build-chat-server @@ -204,6 +212,11 @@ build-all: ## [MID] Build all services @$(MAKE) -s build-web @$(ECHO_CMD) "${GREEN}✅ All services built.${NC}" +build-all-native: ## [MID] Build all services natively (for Incus) + @$(ECHO_CMD) "${BLUE}🔨 Building all services natively...${NC}" + @$(PROJECT_ROOT)/config/incus/build-native.sh all + @$(ECHO_CMD) "${GREEN}✅ All services built natively.${NC}" + # ============================================================================== # LOW LEVEL / DEBUG COMMANDS # ============================================================================== @@ -216,6 +229,14 @@ check-tools: ## [LOW] Check required tools done @$(ECHO_CMD) "${GREEN}✅ All tools present.${NC}" +check-tools-incus: ## [LOW] Check required tools for Incus deployment + @$(ECHO_CMD) "${BLUE}Checking Incus deployment requirements...${NC}" + @command -v incus >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ incus is missing! Install with: sudo snap install incus${NC}"; exit 1; } + @command -v go >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ go is missing!${NC}"; exit 1; } + @command -v cargo >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ cargo is missing!${NC}"; exit 1; } + @command -v npm >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ npm is missing!${NC}"; exit 1; } + @$(ECHO_CMD) "${GREEN}✅ All Incus tools present.${NC}" + install-tools: ## [LOW] Install Power User tools (Hot Reload, Linters) @$(ECHO_CMD) "${BLUE}🛠️ Installing Dev Tools...${NC}" @command -v air >/dev/null 2>&1 || go install github.com/air-verse/air@latest @@ -378,7 +399,7 @@ build-web: ## [LOW] Build web frontend # ============================================================================== # INCUS / LXD DEPLOYMENT # ============================================================================== -.PHONY: incus-setup-network incus-deploy-all incus-deploy-service incus-stop-all incus-logs +.PHONY: incus-setup-network incus-deploy-all incus-deploy-all-native incus-deploy-service incus-deploy-service-native incus-deploy-infra incus-start-all incus-stop-all incus-logs incus-setup-network: ## [LOW] Setup Incus network profile @$(ECHO_CMD) "${BLUE}📦 Setting up Incus network...${NC}" @@ -389,8 +410,8 @@ incus-setup-network: ## [LOW] Setup Incus network profile incus profile device add $(INCUS_PROFILE) eth0 nic network=$(INCUS_NETWORK) @$(ECHO_CMD) "${GREEN}✅ Incus network ready.${NC}" -incus-deploy-all: incus-setup-network ## [MID] Deploy all services to Incus - @$(ECHO_CMD) "${BLUE}📦 Deploying all services to Incus...${NC}" +incus-deploy-all: incus-setup-network ## [MID] Deploy all services to Incus (legacy Docker method) + @$(ECHO_CMD) "${BLUE}📦 Deploying all services to Incus (Docker)...${NC}" @$(MAKE) -s incus-deploy-service SERVICE=backend-api @$(MAKE) -s incus-deploy-service SERVICE=chat-server @$(MAKE) -s incus-deploy-service SERVICE=stream-server @@ -398,12 +419,21 @@ incus-deploy-all: incus-setup-network ## [MID] Deploy all services to Incus @$(MAKE) -s incus-deploy-service SERVICE=haproxy @$(ECHO_CMD) "${GREEN}✅ All services deployed to Incus.${NC}" -incus-deploy-service: ## [LOW] Deploy a service to Incus (usage: make incus-deploy-service SERVICE=backend-api) +incus-deploy-all-native: incus-setup-network ## [MID] Deploy all services to Incus (native, no Docker) + @$(ECHO_CMD) "${BLUE}📦 Deploying all services to Incus (native)...${NC}" + @$(MAKE) -s incus-deploy-service-native SERVICE=backend-api + @$(MAKE) -s incus-deploy-service-native SERVICE=chat-server + @$(MAKE) -s incus-deploy-service-native SERVICE=stream-server + @$(MAKE) -s incus-deploy-service-native SERVICE=web + @$(MAKE) -s incus-deploy-service-native SERVICE=haproxy + @$(ECHO_CMD) "${GREEN}✅ All services deployed to Incus.${NC}" + +incus-deploy-service: ## [LOW] Deploy a service to Incus with Docker (usage: make incus-deploy-service SERVICE=backend-api) @if [ -z "$(SERVICE)" ]; then \ $(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \ exit 1; \ fi - @$(ECHO_CMD) "${BLUE}📦 Deploying $(SERVICE) to Incus...${NC}" + @$(ECHO_CMD) "${BLUE}📦 Deploying $(SERVICE) to Incus (Docker)...${NC}" @if incus list -c n --format csv | grep -q "^veza-$(SERVICE)$$"; then \ $(ECHO_CMD) "${YELLOW}Container exists, removing...${NC}"; \ incus delete veza-$(SERVICE) --force; \ @@ -414,6 +444,44 @@ incus-deploy-service: ## [LOW] Deploy a service to Incus (usage: make incus-depl @incus exec veza-$(SERVICE) -- bash -c "apt-get update && apt-get install -y docker.io docker-compose && systemctl enable docker && systemctl start docker" || true @$(ECHO_CMD) "${GREEN}✅ $(SERVICE) deployed.${NC}" +incus-deploy-service-native: ## [LOW] Deploy a service to Incus natively (usage: make incus-deploy-service-native SERVICE=backend-api) + @if [ -z "$(SERVICE)" ]; then \ + $(ECHO_CMD) "${RED}❌ Please specify SERVICE=name${NC}"; \ + exit 1; \ + fi + @$(ECHO_CMD) "${BLUE}📦 Deploying $(SERVICE) to Incus (native)...${NC}" + @$(shell pwd)/config/incus/deploy-service-native.sh $(SERVICE) + +incus-deploy-infra: incus-setup-network ## [LOW] Deploy infrastructure services (PostgreSQL, Redis) + @$(ECHO_CMD) "${BLUE}📦 Deploying infrastructure services...${NC}" + @$(MAKE) -s incus-deploy-service-native SERVICE=infra + @$(ECHO_CMD) "${BLUE}Waiting for infrastructure to be ready...${NC}" + @sleep 10 + @$(ECHO_CMD) "${GREEN}✅ Infrastructure deployed.${NC}" + +incus-start-all: ## [MID] Start all Incus services + @$(ECHO_CMD) "${BLUE}🚀 Starting all Incus services...${NC}" + @for service in backend-api chat-server stream-server; do \ + if incus list -c n --format csv | grep -q "^veza-$$service$$"; then \ + $(ECHO_CMD) "Starting veza-$$service..."; \ + incus exec veza-$$service -- systemctl start veza-$$service 2>/dev/null || true; \ + fi; \ + done + @if incus list -c n --format csv | grep -q "^veza-web$$"; then \ + $(ECHO_CMD) "Starting veza-web..."; \ + incus exec veza-web -- systemctl start apache2 2>/dev/null || true; \ + fi + @if incus list -c n --format csv | grep -q "^veza-haproxy$$"; then \ + $(ECHO_CMD) "Starting veza-haproxy..."; \ + incus exec veza-haproxy -- systemctl start haproxy 2>/dev/null || true; \ + fi + @if incus list -c n --format csv | grep -q "^veza-infra$$"; then \ + $(ECHO_CMD) "Starting infrastructure services..."; \ + incus exec veza-infra -- systemctl start postgresql 2>/dev/null || true; \ + incus exec veza-infra -- systemctl start redis-server 2>/dev/null || true; \ + fi + @$(ECHO_CMD) "${GREEN}✅ All services started.${NC}" + incus-stop-all: ## [MID] Stop all Incus containers @$(ECHO_CMD) "${YELLOW}🛑 Stopping all Incus containers...${NC}" @for container in $$(incus list -c n --format csv | grep veza-); do \ diff --git a/apps/web/src/__tests__/accessibility.test.tsx b/apps/web/src/__tests__/accessibility.test.tsx index 8c28ec221..c2a76f71b 100644 --- a/apps/web/src/__tests__/accessibility.test.tsx +++ b/apps/web/src/__tests__/accessibility.test.tsx @@ -1,7 +1,7 @@ /** * Accessibility Tests * FE-TEST-013: Test keyboard navigation, screen reader support - * + * * This test suite covers: * - Keyboard navigation (Tab, Shift+Tab, Enter, Space, Arrow keys) * - Screen reader support (ARIA labels, roles, states) @@ -20,7 +20,12 @@ const LoginForm = () => ( - + ); @@ -30,13 +35,31 @@ const RegisterForm = () => ( - + - + ); -const SimpleDialog = ({ open, onClose, children }: { open: boolean; onClose: () => void; children: React.ReactNode }) => { +const SimpleDialog = ({ + open, + onClose, + children, +}: { + open: boolean; + onClose: () => void; + children: React.ReactNode; +}) => { if (!open) return null; return (
@@ -55,7 +78,9 @@ describe('Accessibility Tests', () => { const emailInput = screen.getByLabelText(/email/i); const passwordInput = screen.getByLabelText(/mot de passe/i); - const submitButton = screen.getByRole('button', { name: /se connecter/i }); + const submitButton = screen.getByRole('button', { + name: /se connecter/i, + }); // Focus should start on email input emailInput.focus(); @@ -90,9 +115,7 @@ describe('Accessibility Tests', () => { const user = userEvent.setup(); const handleClick = vi.fn(); - render( - , - ); + render(); const button = screen.getByRole('button', { name: /test button/i }); button.focus(); @@ -107,9 +130,7 @@ describe('Accessibility Tests', () => { const user = userEvent.setup(); const handleClick = vi.fn(); - render( - , - ); + render(); const button = screen.getByRole('button', { name: /test button/i }); button.focus(); @@ -184,7 +205,9 @@ describe('Accessibility Tests', () => { const dialog = screen.getByRole('dialog'); const firstButton = screen.getByRole('button', { name: /first button/i }); - const secondButton = screen.getByRole('button', { name: /second button/i }); + const secondButton = screen.getByRole('button', { + name: /second button/i, + }); const closeButton = screen.getByRole('button', { name: /close/i }); // Verify dialog and buttons are present @@ -325,9 +348,7 @@ describe('Accessibility Tests', () => { describe('Focus Management', () => { it('should show visible focus indicators', () => { - render( - , - ); + render(); const button = screen.getByRole('button'); button.focus(); @@ -397,7 +418,9 @@ describe('Accessibility Tests', () => {
, ); - const skipLink = screen.getByRole('link', { name: /skip to main content/i }); + const skipLink = screen.getByRole('link', { + name: /skip to main content/i, + }); expect(skipLink).toBeInTheDocument(); expect(skipLink).toHaveAttribute('href', '#main-content'); }); @@ -453,4 +476,3 @@ describe('Accessibility Tests', () => { }); }); }); - diff --git a/apps/web/src/app/App.tsx b/apps/web/src/app/App.tsx index 983217b72..ac4b68847 100644 --- a/apps/web/src/app/App.tsx +++ b/apps/web/src/app/App.tsx @@ -50,7 +50,7 @@ export function App() { // (refreshUser() est asynchrone, donc on vérifie après un court délai) const checkAndFetchCSRF = async () => { // Attendre un peu pour que refreshUser() se termine - await new Promise(resolve => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, 100)); const { isAuthenticated } = useAuthStore.getState(); if (isAuthenticated) { csrfService.refreshToken().catch((error) => { @@ -67,7 +67,10 @@ export function App() { // Forcer dark mode par défaut si pas encore défini if (!theme || theme === 'system') { const root = document.documentElement; - if (!root.classList.contains('dark') && !root.classList.contains('light')) { + if ( + !root.classList.contains('dark') && + !root.classList.contains('light') + ) { setTheme('dark'); } else { setTheme(theme); diff --git a/apps/web/src/components/ErrorBoundary.tsx b/apps/web/src/components/ErrorBoundary.tsx index 39f4ecefc..77bf84d06 100644 --- a/apps/web/src/components/ErrorBoundary.tsx +++ b/apps/web/src/components/ErrorBoundary.tsx @@ -32,7 +32,7 @@ export class ErrorBoundary extends Component { // Action 3.3.1.4: Enhanced error boundary logging for monitoring const logContext = getLogContext(); - + // Gather additional context for monitoring const monitoringContext = { ...logContext, @@ -42,7 +42,8 @@ export class ErrorBoundary extends Component { stack: error.stack, componentStack: errorInfo.componentStack, url: typeof window !== 'undefined' ? window.location.href : undefined, - userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined, + userAgent: + typeof navigator !== 'undefined' ? navigator.userAgent : undefined, timestamp: new Date().toISOString(), }; @@ -65,7 +66,9 @@ export class ErrorBoundary extends Component { tags: { error_boundary: true, error_type: error.name || 'Error', - ...(logContext.request_id ? { request_id: String(logContext.request_id) } : {}), + ...(logContext.request_id + ? { request_id: String(logContext.request_id) } + : {}), }, level: 'error', }); @@ -87,7 +90,10 @@ export class ErrorBoundary extends Component {
{ onRetry={this.handleReset} actions={[ { - label: 'Retour à l\'accueil', + label: "Retour à l'accueil", onClick: () => { window.location.href = '/'; }, diff --git a/apps/web/src/components/OfflineIndicator.tsx b/apps/web/src/components/OfflineIndicator.tsx index 0af27b43d..c6197d6cb 100644 --- a/apps/web/src/components/OfflineIndicator.tsx +++ b/apps/web/src/components/OfflineIndicator.tsx @@ -76,7 +76,8 @@ export function OfflineIndicator() { Mode hors ligne {queueSize > 0 && ( - - {queueSize} {queueSize === 1 ? 'requête' : 'requêtes'} en attente + - {queueSize} {queueSize === 1 ? 'requête' : 'requêtes'} en + attente )} @@ -93,7 +94,8 @@ export function OfflineIndicator() { Synchronisation en cours {queueSize > 0 && ( - - {queueSize} {queueSize === 1 ? 'requête' : 'requêtes'} restante{queueSize > 1 ? 's' : ''} + - {queueSize} {queueSize === 1 ? 'requête' : 'requêtes'} restante + {queueSize > 1 ? 's' : ''} )} diff --git a/apps/web/src/components/admin/AdminDashboardView.tsx b/apps/web/src/components/admin/AdminDashboardView.tsx index 4772935cc..086af559f 100644 --- a/apps/web/src/components/admin/AdminDashboardView.tsx +++ b/apps/web/src/components/admin/AdminDashboardView.tsx @@ -1,9 +1,18 @@ - import React, { useState, useEffect } from 'react'; import { Card } from '../ui/card'; import { Button } from '../ui/button'; import { StatCard } from '../dashboard/StatCard'; -import { Users, DollarSign, Activity, AlertTriangle, HardDrive, ShoppingBag, ShieldAlert, CheckCircle, Loader2 } from 'lucide-react'; +import { + Users, + DollarSign, + Activity, + AlertTriangle, + HardDrive, + ShoppingBag, + ShieldAlert, + CheckCircle, + Loader2, +} from 'lucide-react'; import { adminService } from '../../services/adminService'; import { Report } from '../../types'; import { useToast } from '../../context/ToastContext'; @@ -17,148 +26,272 @@ export const AdminDashboardView: React.FC = () => { const [loading, setLoading] = useState(true); useEffect(() => { - const fetchData = async () => { - setLoading(true); - try { - const [statsData, reportsData, uploadsData] = await Promise.all([ - adminService.getDashboardStats(), - adminService.getModerationQueue('pending'), - adminService.getRecentUploads() - ]); - setStats(statsData); - setReports(reportsData); - setUploads(uploadsData); - } catch (e) { - logger.error('Error loading admin dashboard data', { - error: e instanceof Error ? e.message : String(e), - stack: e instanceof Error ? e.stack : undefined, - }); - } finally { - setLoading(false); - } - }; - fetchData(); + const fetchData = async () => { + setLoading(true); + try { + const [statsData, reportsData, uploadsData] = await Promise.all([ + adminService.getDashboardStats(), + adminService.getModerationQueue('pending'), + adminService.getRecentUploads(), + ]); + setStats(statsData); + setReports(reportsData); + setUploads(uploadsData); + } catch (e) { + logger.error('Error loading admin dashboard data', { + error: e instanceof Error ? e.message : String(e), + stack: e instanceof Error ? e.stack : undefined, + }); + } finally { + setLoading(false); + } + }; + fetchData(); }, []); const handleAction = async (id: string, action: string) => { - await adminService.resolveReport(id, action); - setReports(reports.filter(r => r.id !== id)); - addToast(`Report ${action}`, 'success'); + await adminService.resolveReport(id, action); + setReports(reports.filter((r) => r.id !== id)); + addToast(`Report ${action}`, 'success'); }; - if (loading) return
; + if (loading) + return ( +
+ +
+ ); return (
-

SYSTEM OVERVIEW

+

+ SYSTEM OVERVIEW +

- {/* Stats Grid */} -
- } trend={stats.trends?.users} color="cyan" /> - } trend={stats.trends?.revenue} color="gold" /> - } trend={stats.trends?.sessions} color="lime" /> - } trend={stats.trends?.reports} color="red" /> -
+ {/* Stats Grid */} +
+ } + trend={stats.trends?.users} + color="cyan" + /> + } + trend={stats.trends?.revenue} + color="gold" + /> + } + trend={stats.trends?.sessions} + color="lime" + /> + } + trend={stats.trends?.reports} + color="red" + /> +
-
- - {/* Main Chart Area (Mock) */} - -
-

Traffic & Server Load

-
-
Traffic
-
CPU
-
-
-
- {Array.from({length: 40}).map((_, i) => ( -
-
-
-
- ))} -
-
- - {/* Quick Actions */} -
- -

Quick Actions

-
- - - - -
-
- - -

System Health

-
-
- Database - Healthy -
-
- Storage - 65% Used -
-
- API Latency - 45ms -
-
-
+
+ {/* Main Chart Area (Mock) */} + +
+

Traffic & Server Load

+
+ +
{' '} + Traffic +
+ +
CPU +
-
+
+
+ {Array.from({ length: 40 }).map((_, i) => ( +
+
+
+
+ ))} +
+ -
- {/* Recent Reports */} - -
-

Recent Reports

- -
-
- {reports.map(report => ( -
-
-
{report.targetName}
-
{report.targetType} • {report.reason}
-
-
- - -
-
- ))} - {reports.length === 0 &&
No pending reports.
} -
-
+ {/* Quick Actions */} +
+ +

+ Quick Actions +

+
+ + + + +
+
- {/* Recent Uploads */} - -
-

Moderation Queue

- -
-
- {uploads.map(upload => ( -
-
-
{upload.name}
-
{upload.user} • {upload.size}
-
-
- - -
-
- ))} -
-
+ +

+ System Health +

+
+
+ Database + Healthy +
+
+ Storage + 65% Used +
+
+ API Latency + 45ms +
+
+
+
+ +
+ {/* Recent Reports */} + +
+

+ Recent Reports +

+ +
+
+ {reports.map((report) => ( +
+
+
+ {report.targetName} +
+
+ {report.targetType} • {report.reason} +
+
+
+ + +
+
+ ))} + {reports.length === 0 && ( +
+ No pending reports. +
+ )} +
+
+ + {/* Recent Uploads */} + +
+

+ Moderation Queue +

+ +
+
+ {uploads.map((upload) => ( +
+
+
+ {upload.name} +
+
+ {upload.user} • {upload.size} +
+
+
+ + +
+
+ ))} +
+
+
); }; diff --git a/apps/web/src/components/admin/AdminModerationView.tsx b/apps/web/src/components/admin/AdminModerationView.tsx index 2b1b07e31..1e9d14be5 100644 --- a/apps/web/src/components/admin/AdminModerationView.tsx +++ b/apps/web/src/components/admin/AdminModerationView.tsx @@ -1,10 +1,16 @@ - import React, { useState, useEffect } from 'react'; import { Card } from '../ui/card'; import { Button } from '../ui/button'; import { Badge } from '../ui/badge'; import { Report } from '../../types'; -import { ShieldAlert, CheckCircle, Ban, MessageSquare, Clock, Loader2 } from 'lucide-react'; +import { + ShieldAlert, + CheckCircle, + Ban, + MessageSquare, + Clock, + Loader2, +} from 'lucide-react'; import { useToast } from '../../context/ToastContext'; import { adminService } from '../../services/adminService'; import { logger } from '@/utils/logger'; @@ -12,105 +18,169 @@ import { logger } from '@/utils/logger'; export const AdminModerationView: React.FC = () => { const { addToast } = useToast(); const [queue, setQueue] = useState([]); - const [activeTab, setActiveTab] = useState<'pending' | 'reviewed' | 'resolved'>('pending'); + const [activeTab, setActiveTab] = useState< + 'pending' | 'reviewed' | 'resolved' + >('pending'); const [loading, setLoading] = useState(true); useEffect(() => { - const loadQueue = async () => { - setLoading(true); - try { - const data = await adminService.getModerationQueue('all'); - setQueue(data); - } catch (e) { - logger.error('Error loading moderation queue', { - error: e instanceof Error ? e.message : String(e), - stack: e instanceof Error ? e.stack : undefined, - }); - } finally { - setLoading(false); - } - }; - loadQueue(); + const loadQueue = async () => { + setLoading(true); + try { + const data = await adminService.getModerationQueue('all'); + setQueue(data); + } catch (e) { + logger.error('Error loading moderation queue', { + error: e instanceof Error ? e.message : String(e), + stack: e instanceof Error ? e.stack : undefined, + }); + } finally { + setLoading(false); + } + }; + loadQueue(); }, []); - const filteredQueue = queue.filter(r => - activeTab === 'pending' ? r.status === 'pending' : - activeTab === 'reviewed' ? r.status === 'reviewed' : - r.status === 'resolved' || r.status === 'dismissed' + const filteredQueue = queue.filter((r) => + activeTab === 'pending' + ? r.status === 'pending' + : activeTab === 'reviewed' + ? r.status === 'reviewed' + : r.status === 'resolved' || r.status === 'dismissed', ); const handleAction = async (id: string, action: string) => { - try { - await adminService.resolveReport(id, action); - addToast(`Report ${action}`, 'success'); - setQueue(queue.map(r => r.id === id ? { ...r, status: action === 'dismissed' ? 'dismissed' : 'resolved' } as any : r)); - } catch (e) { - addToast("Action failed", "error"); - } + try { + await adminService.resolveReport(id, action); + addToast(`Report ${action}`, 'success'); + setQueue( + queue.map((r) => + r.id === id + ? ({ + ...r, + status: action === 'dismissed' ? 'dismissed' : 'resolved', + } as any) + : r, + ), + ); + } catch (e) { + addToast('Action failed', 'error'); + } }; return (
-

MODERATION QUEUE

+

+ MODERATION QUEUE +

-
- {['pending', 'reviewed', 'resolved'].map(tab => ( - - ))} -
+
+ {['pending', 'reviewed', 'resolved'].map((tab) => ( + + ))} +
-
- {loading &&
} - - {!loading && filteredQueue.length === 0 && ( -
- -

All caught up! No reports in this queue.

-
- )} +
+ {loading && ( +
+ +
+ )} - {!loading && filteredQueue.map(report => ( - -
-
-
- - {report.targetName} - - {report.timestamp} - -
-
-
Reason: {report.reason}
-

{report.description}

-
-
Reported by: {report.reportedBy}
-
+ {!loading && filteredQueue.length === 0 && ( +
+ +

All caught up! No reports in this queue.

+
+ )} -
- - - - -
+ {!loading && + filteredQueue.map((report) => ( + +
+
+
+ + + {report.targetName} + + + {report.timestamp} + +
+
+
+ Reason: {report.reason}
- - ))} -
+

+ {report.description} +

+
+
+ Reported by:{' '} + {report.reportedBy} +
+
+ +
+ + + + +
+
+
+ ))} +
); }; diff --git a/apps/web/src/components/admin/AdminSettingsView.tsx b/apps/web/src/components/admin/AdminSettingsView.tsx index 5a80e731d..c4aed2567 100644 --- a/apps/web/src/components/admin/AdminSettingsView.tsx +++ b/apps/web/src/components/admin/AdminSettingsView.tsx @@ -1,4 +1,3 @@ - import React, { useState } from 'react'; import { Card } from '../ui/card'; import { Button } from '../ui/button'; @@ -12,94 +11,121 @@ export const AdminSettingsView: React.FC = () => { const [announcement, setAnnouncement] = useState(''); const handleSave = () => { - addToast("System settings updated", "success"); + addToast('System settings updated', 'success'); }; return (
-
-

SYSTEM SETTINGS

- +
+

+ SYSTEM SETTINGS +

+ +
+ + {/* General Config */} + +

+ General Configuration +

+ +
+
+ + setUploadLimit(Number(e.target.value))} + /> +

+ Maximum file size for standard users. +

+
+
+ + +
+
- {/* General Config */} - -

- General Configuration -

- -
-
- - setUploadLimit(Number(e.target.value))} - /> -

Maximum file size for standard users.

-
-
- - -
+ {/* Feature Flags */} + +

+ Feature Flags +

+
+ {[ + 'Live Streaming', + 'Marketplace Transactions', + 'AI Mastering', + 'Public Registrations', + ].map((feature) => ( +
+ {feature} +
+
+
- + ))} +
+
- {/* Feature Flags */} - -

- Feature Flags -

-
- {['Live Streaming', 'Marketplace Transactions', 'AI Mastering', 'Public Registrations'].map(feature => ( -
- {feature} -
-
-
-
- ))} + {/* Maintenance */} + +

+ Emergency & + Maintenance +

+ +
+
+
+
Maintenance Mode
+
+ Disable access for non-admin users +
- - - {/* Maintenance */} - -

- Emergency & Maintenance -

- -
-
-
-
Maintenance Mode
-
Disable access for non-admin users
-
-
setMaintenance(!maintenance)} - className={`w-12 h-6 rounded-full relative cursor-pointer transition-colors ${maintenance ? 'bg-kodo-red' : 'bg-gray-600'}`} - > -
-
-
- -
- -