From 26f549c34044f37e075a3ae9dce76d9ddf6f1fae Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Wed, 8 Oct 2025 20:14:12 +0000 Subject: [PATCH] Add drag-and-drop functionality to reorder selected media in posts Integrates @dnd-kit for drag-and-drop reordering of media items within the new post creation interface, enabling carousel slide order customization. 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/WzkpF6q --- client/src/pages/new-post.tsx | 225 +++++++++++++++++++++++++++------- 1 file changed, 182 insertions(+), 43 deletions(-) diff --git a/client/src/pages/new-post.tsx b/client/src/pages/new-post.tsx index 92969f2..b165cdf 100644 --- a/client/src/pages/new-post.tsx +++ b/client/src/pages/new-post.tsx @@ -1,8 +1,25 @@ import { useState, useCallback, useRef } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { useLocation } from "wouter"; -import { Send, Sparkles, Image as ImageIcon, Calendar, Upload, Camera } from "lucide-react"; +import { Send, Sparkles, Image as ImageIcon, Calendar, Upload, Camera, GripVertical } from "lucide-react"; import { useDropzone } from "react-dropzone"; +import { + DndContext, + closestCenter, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, + DragEndEvent, +} from "@dnd-kit/core"; +import { + arrayMove, + SortableContext, + sortableKeyboardCoordinates, + rectSortingStrategy, + useSortable, +} from "@dnd-kit/sortable"; +import { CSS } from "@dnd-kit/utilities"; import Sidebar from "@/components/sidebar"; import TopBar from "@/components/topbar"; import { Button } from "@/components/ui/button"; @@ -16,6 +33,69 @@ import { useToast } from "@/hooks/use-toast"; import { apiRequest, queryClient } from "@/lib/queryClient"; import type { SocialPage, Media } from "@shared/schema"; +function SortableMediaItem({ + media, + index, + isSelected, + onToggle +}: { + media: Media; + index: number; + isSelected: boolean; + onToggle: () => void; +}) { + const { + attributes, + listeners, + setNodeRef, + transform, + transition, + } = useSortable({ id: media.id }); + + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; + + return ( +
+ + {isSelected && ( + <> +
+ {index + 1} +
+
+ +
+ + )} +
+ ); +} + export default function NewPost() { const [sidebarOpen, setSidebarOpen] = useState(false); const [, navigate] = useLocation(); @@ -208,6 +288,25 @@ export default function NewPost() { } }; + const sensors = useSensors( + useSensor(PointerSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + + const handleDragEnd = (event: DragEndEvent) => { + const { active, over } = event; + + if (over && active.id !== over.id) { + setSelectedMedia((items) => { + const oldIndex = items.indexOf(active.id as string); + const newIndex = items.indexOf(over.id as string); + return arrayMove(items, oldIndex, newIndex); + }); + } + }; + return (
{sidebarOpen && ( @@ -309,50 +408,90 @@ export default function NewPost() {
) : ( -
- {mediaList.map((media) => { - const isSelected = selectedMedia.includes(media.id); - const selectionIndex = selectedMedia.indexOf(media.id); - - return ( - - ); - })} -
+ + + + )} +
+ Toutes les photos +
+
+ {mediaList.map((media) => { + const isSelected = selectedMedia.includes(media.id); + + return ( + + ); + })} +
+ )}