From fa3e286dce2d7c7815b4bafebfabfbae3fce5d5f Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Wed, 8 Oct 2025 13:56:21 +0000 Subject: [PATCH] Add the ability to upload new photos directly from the new post page Integrates react-dropzone for image/video uploads on the new post page, including upload mutation and UI updates to the media card. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/TXBOLMj --- .replit | 4 + client/src/pages/new-post.tsx | 141 +++++++++++++++++++++++++--------- 2 files changed, 108 insertions(+), 37 deletions(-) diff --git a/.replit b/.replit index 518307b..dddb987 100644 --- a/.replit +++ b/.replit @@ -18,6 +18,10 @@ externalPort = 80 localPort = 35357 externalPort = 3002 +[[ports]] +localPort = 36673 +externalPort = 3003 + [[ports]] localPort = 37659 externalPort = 4200 diff --git a/client/src/pages/new-post.tsx b/client/src/pages/new-post.tsx index 19bab3f..107f6fc 100644 --- a/client/src/pages/new-post.tsx +++ b/client/src/pages/new-post.tsx @@ -1,7 +1,8 @@ -import { useState } from "react"; +import { useState, useCallback } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { useLocation } from "wouter"; -import { Send, Sparkles, Image as ImageIcon, Calendar } from "lucide-react"; +import { Send, Sparkles, Image as ImageIcon, Calendar, Upload } from "lucide-react"; +import { useDropzone } from "react-dropzone"; import Sidebar from "@/components/sidebar"; import TopBar from "@/components/topbar"; import { Button } from "@/components/ui/button"; @@ -36,6 +37,51 @@ export default function NewPost() { queryKey: ['/api/media'], }); + const uploadMutation = useMutation({ + mutationFn: async (file: File) => { + 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"); + return response.json(); + }, + onSuccess: (data) => { + queryClient.invalidateQueries({ queryKey: ["/api/media"] }); + setSelectedMedia(data.id); + toast({ + title: "Succès", + description: "Photo téléchargée avec succès", + }); + }, + onError: () => { + toast({ + title: "Erreur", + description: "Impossible de télécharger la photo", + variant: "destructive", + }); + }, + }); + + const onDrop = useCallback((acceptedFiles: File[]) => { + if (acceptedFiles.length > 0) { + uploadMutation.mutate(acceptedFiles[0]); + } + }, []); + + const { getRootProps, getInputProps, isDragActive, open } = useDropzone({ + onDrop, + accept: { + "image/*": [".png", ".jpg", ".jpeg", ".gif"], + "video/*": [".mp4", ".mov"], + }, + maxSize: 52428800, + noClick: true, + noKeyboard: true, + }); + const generateTextMutation = useMutation({ mutationFn: async (productInfoText: string) => { const productInfo = { @@ -254,44 +300,65 @@ export default function NewPost() { - Média - Sélectionnez une image ou vidéo +
+
+ Média + Sélectionnez ou uploadez une image/vidéo +
+ +
- {mediaList.length === 0 ? ( -
- -

Aucun média disponible

- -
- ) : ( -
- {mediaList.map((media) => ( - - ))} -
- )} + + Uploader une photo + + + ) : ( +
+ {mediaList.map((media) => ( + + ))} +
+ )} +