diff --git a/client/src/components/media-upload.tsx b/client/src/components/media-upload.tsx index 78e818e..c33e865 100644 --- a/client/src/components/media-upload.tsx +++ b/client/src/components/media-upload.tsx @@ -19,6 +19,8 @@ export default function MediaUpload() { queryKey: ["/api/media"], }); + const [uploadingCount, setUploadingCount] = useState(0); + const uploadMutation = useMutation({ mutationFn: async (file: File) => { const formData = new FormData(); @@ -33,25 +35,61 @@ export default function MediaUpload() { onSuccess: (data) => { queryClient.invalidateQueries({ queryKey: ["/api/media"] }); setSelectedFile(data); - toast({ - title: "Succès", - description: "Média téléchargé et traité avec succès", - }); - }, - onError: () => { - toast({ - title: "Erreur", - description: "Impossible de télécharger le média", - variant: "destructive", - }); }, }); - const onDrop = useCallback((acceptedFiles: File[]) => { - if (acceptedFiles.length > 0) { - uploadMutation.mutate(acceptedFiles[0]); + const onDrop = useCallback(async (acceptedFiles: File[]) => { + if (acceptedFiles.length === 0) return; + + setUploadingCount(acceptedFiles.length); + let successCount = 0; + let errorCount = 0; + + // Upload tous les fichiers en parallèle + const uploadPromises = acceptedFiles.map(async (file) => { + try { + const formData = new FormData(); + formData.append("file", file); + const response = await fetch("/api/media/upload", { + method: "POST", + body: formData, + }); + if (!response.ok) throw new Error("Upload failed"); + successCount++; + return response.json(); + } catch (error) { + errorCount++; + throw error; + } + }); + + try { + await Promise.all(uploadPromises); + queryClient.invalidateQueries({ queryKey: ["/api/media"] }); + + toast({ + title: "Succès", + description: `${successCount} média(s) téléchargé(s) avec succès`, + }); + } catch (error) { + if (successCount > 0) { + queryClient.invalidateQueries({ queryKey: ["/api/media"] }); + toast({ + title: "Partiellement réussi", + description: `${successCount} média(s) téléchargé(s), ${errorCount} échec(s)`, + variant: "destructive", + }); + } else { + toast({ + title: "Erreur", + description: "Impossible de télécharger les médias", + variant: "destructive", + }); + } + } finally { + setUploadingCount(0); } - }, []); + }, [toast]); const { getRootProps, getInputProps, isDragActive, open } = useDropzone({ onDrop, @@ -60,6 +98,7 @@ export default function MediaUpload() { "video/*": [".mp4", ".mov"], }, maxSize: 52428800, + multiple: true, }); const deleteMutation = useMutation({ @@ -126,18 +165,36 @@ export default function MediaUpload() { className={` border-2 border-dashed rounded-2xl p-12 text-center cursor-pointer transition-all ${isDragActive ? "border-primary bg-primary/5 shadow-lg" : "border-border/50 hover:border-primary hover:bg-accent/30"} + ${uploadingCount > 0 ? "pointer-events-none opacity-50" : ""} `} data-testid="dropzone-upload" >
- + {uploadingCount > 0 ? ( + + ) : ( + + )}
-

- {isDragActive ? "Déposez vos fichiers ici" : "Glissez-déposez vos fichiers"} -

-

ou cliquez pour parcourir

-

PNG, JPG, MP4 jusqu'à 50MB

+ {uploadingCount > 0 ? ( + <> +

+ Téléchargement en cours... +

+

+ {uploadingCount} fichier(s) en cours de traitement +

+ + ) : ( + <> +

+ {isDragActive ? "Déposez vos fichiers ici" : "Glissez-déposez vos fichiers"} +

+

ou cliquez pour parcourir

+

PNG, JPG, MP4 jusqu'à 50MB

+ + )}