From 451f0a441b514469d2773ccb1e27e80e9308d701 Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Mon, 2 Mar 2026 12:39:24 +0100 Subject: [PATCH] feat: introduce a new collapsible sidebar navigation component and an audio administration page. --- client/src/components/sidebar.tsx | 24 ++++ client/src/pages/audio-admin.tsx | 2 +- client/src/pages/new-reel.tsx | 196 +++++++----------------------- 3 files changed, 71 insertions(+), 151 deletions(-) diff --git a/client/src/components/sidebar.tsx b/client/src/components/sidebar.tsx index 3599ff8..112dfcd 100644 --- a/client/src/components/sidebar.tsx +++ b/client/src/components/sidebar.tsx @@ -286,6 +286,30 @@ export default function Sidebar({ onLinkClick }: SidebarProps = {}) { )} + handleLinkClick("/audio-admin", e)} + className={` + flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group cursor-pointer + ${location === "/audio-admin" + ? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm' + : 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground' + } + ${isCollapsed ? 'justify-center' : ''} + `} + data-testid="link-audio-admin" + > + {location === "/audio-admin" && ( +
+ )} + + {!isCollapsed && Bibliothèque Audio} + {isCollapsed && ( +
+ Bibliothèque Audio +
+ )} +
handleLinkClick("/settings", e)} diff --git a/client/src/pages/audio-admin.tsx b/client/src/pages/audio-admin.tsx index 0f3fb62..5816164 100644 --- a/client/src/pages/audio-admin.tsx +++ b/client/src/pages/audio-admin.tsx @@ -34,7 +34,7 @@ export default function AudioAdmin() { const uploadMutation = useMutation({ mutationFn: async (file: File) => { const formData = new FormData(); - formData.append("audio", file); + formData.append("file", file); const res = await fetch("/api/audio-tracks", { method: "POST", diff --git a/client/src/pages/new-reel.tsx b/client/src/pages/new-reel.tsx index 0f47d78..17c4548 100644 --- a/client/src/pages/new-reel.tsx +++ b/client/src/pages/new-reel.tsx @@ -80,7 +80,6 @@ export default function NewReel() { // État audio preview const [isPlaying, setIsPlaying] = useState(null); - const [musicOffset, setMusicOffset] = useState(0); // Récupérer les pages disponibles const { data: pages = [] } = useQuery({ @@ -94,9 +93,6 @@ export default function NewReel() { const videoList = allMedia.filter(m => m.type === 'video').slice(0, 12); - // État pour stocker les musiques chargées manuellement - const [loadedTracks, setLoadedTracks] = useState([]); - // --- Added for Internal Audio Tracks --- const { data: internalTracksResponse = [], isLoading: internalTracksLoading } = useQuery({ queryKey: ['/api/audio-tracks'], @@ -105,8 +101,8 @@ export default function NewReel() { const internalTracks: MusicTrack[] = (internalTracksResponse || []).map(t => ({ id: `internal_${t.id}`, title: t.title, - artist: "Bibliothèque Interne", - albumName: "Upload", + artist: t.fileName || t.title, + albumName: "Bibliothèque Interne", duration: t.duration || 0, previewUrl: t.url, downloadUrl: t.url, @@ -115,29 +111,6 @@ export default function NewReel() { })); // --- End Internal Tracks --- - // Recherche de musiques par durée - const { data: musicData, isLoading: musicLoading, refetch: refetchMusic } = useQuery<{ tracks: MusicTrack[] }>({ - queryKey: ['/api/music/search', selectedVideo?.id, musicOffset], - queryFn: async () => { - // Estimer la durée vidéo (on prend une marge de ±10 secondes) - const minDuration = 10; - const maxDuration = 120; // On prend toutes les musiques courtes - const response = await fetch( - `/api/music/search?minDuration=${minDuration}&maxDuration=${maxDuration}&limit=10&offset=${musicOffset}` - ); - const data = await response.json(); - setLoadedTracks(data.tracks || []); - return data; - }, - enabled: currentStep === 'music' && !!selectedVideo, - }); - - // Charger 10 nouvelles musiques - const handleLoadNewMusic = () => { - setMusicOffset(prev => prev + 10); - refetchMusic(); - }; - // Upload vidéo const uploadMutation = useMutation({ mutationFn: async (file: File) => { @@ -557,13 +530,18 @@ export default function NewReel() {
-

Bibliothèque Interne

+ {/* BIBLIOTHÈQUE INTERNE */} +
{internalTracksLoading ? ( -
+
+ +
) : internalTracks.length === 0 ? ( -

Aucune musique n'a été ajoutée par les administrateurs.

+
+ +

Aucune musique disponible

+

Un administrateur peut ajouter des MP3 via la Bibliothèque Audio.

+
) : ( internalTracks.map((track) => (

{track.title}

-

- - {track.artist} +

+ {Math.floor(track.duration / 60)}:{String(track.duration % 60).padStart(2, '0')}

{selectedTrack?.id === track.id && ( @@ -601,122 +578,41 @@ export default function NewReel() { )) )}
- {/* END INTERNAL TRACKS SECTION */} -

Recherche FreeSound

- - {musicLoading ? ( -
- + {/* Slider volume + navigation */} + {selectedTrack && ( +
+ +
- ) : ( - <> -
- {(!musicData?.tracks || musicData.tracks.length === 0) && ( - - )} - {musicData?.tracks?.map((track) => ( -
handleSelectTrack(track)} - className={`flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all ${selectedTrack?.id === track.id - ? 'bg-primary/10 border border-primary' - : 'bg-muted/50 hover:bg-muted' - }`} - > - -
-

{track.title}

-

{track.artist}

-
- - {formatDuration(track.duration)} - - {selectedTrack?.id === track.id && ( - - )} -
- ))} - - {/* Bouton pour charger 10 nouvelles musiques */} - {musicData?.tracks && musicData.tracks.length > 0 && ( - - )} -
- - {selectedTrack && ( -
-
- - -
-
- )} - -
- -
- - -
-
- )} + +
+ +
+ + +
+
)}