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 (
-