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 1/3] 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() {
Aucun média disponible