import { useState } from 'react'
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
DragEndEvent,
} from '@dnd-kit/core'
import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
verticalListSortingStrategy,
useSortable,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { Post } from '@/types'
function SortablePost({ post }: { post: Post }) {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
id: post.id,
})
const style = {
transform: CSS.Transform.toString(transform),
transition,
}
return (
<div ref={setNodeRef} style={style} {...attributes} {...listeners} className="bg-white p-4 rounded shadow mb-2 cursor-move">
<h3 className="font-bold">{post.title}</h3>
<p className="text-gray-600 text-sm">{post.excerpt}</p>
</div>
)
}
export function SortablePosts({ initialPosts }: { initialPosts: Post[] }) {
const [posts, setPosts] = useState(initialPosts)
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
)
const handleDragEnd = async (event: DragEndEvent) => {
const { active, over } = event
if (over && active.id !== over.id) {
setPosts((items) => {
const oldIndex = items.findIndex((item) => item.id === active.id)
const newIndex = items.findIndex((item) => item.id === over.id)
const newOrder = arrayMove(items, oldIndex, newIndex)
// Persist to backend
updatePostOrder(newOrder.map((p) => p.id))
return newOrder
})
}
}
return (
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<SortableContext items={posts.map((p) => p.id)} strategy={verticalListSortingStrategy}>
{posts.map((post) => (
<SortablePost key={post.id} post={post} />
))}
</SortableContext>
</DndContext>
)
}
async function updatePostOrder(postIds: string[]) {
// API call to persist order
}