import { useState } from "react"; import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, type DragStartEvent, type DragEndEvent, } from "@dnd-kit/core"; import { arrayMove, sortableKeyboardCoordinates } from "@dnd-kit/sortable"; export interface DragAndDropItem { [key: string]: any; } export interface UseDragAndDropProps { items: T[]; onReorder: (reorderedItems: Array<{ id: string; sortOrder: number }>) => Promise; getItemId: (item: T) => string; } export function useDragAndDrop({ items, onReorder, getItemId }: UseDragAndDropProps) { const [activeId, setActiveId] = useState(null); // 드래그 센서 설정 const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 8, // 8px 이동 후 드래그 시작 }, }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, }), ); // 드래그 시작 핸들러 const handleDragStart = (event: DragStartEvent) => { setActiveId(event.active.id as string); }; // 드래그 종료 핸들러 const handleDragEnd = async (event: DragEndEvent) => { setActiveId(null); const { active, over } = event; if (over && active.id !== over.id) { const oldIndex = items.findIndex((item) => getItemId(item) === active.id); const newIndex = items.findIndex((item) => getItemId(item) === over.id); if (oldIndex !== -1 && newIndex !== -1) { const newOrder = arrayMove(items, oldIndex, newIndex); // 순서 업데이트를 위한 데이터 준비 const reorderedItems = newOrder.map((item, index) => ({ id: getItemId(item), sortOrder: index + 1, })); try { await onReorder(reorderedItems); } catch (error) { console.error("순서 변경 실패:", error); } } } }; // 현재 드래그 중인 아이템 찾기 const activeItem = activeId ? items.find((item) => getItemId(item) === activeId) : null; return { // 상태 activeId, activeItem, // 센서 및 핸들러 sensors, handleDragStart, handleDragEnd, // DndContext props dndContextProps: { sensors, collisionDetection: closestCenter, onDragStart: handleDragStart, onDragEnd: handleDragEnd, }, }; }