11import { useEffect , useRef , useState , useCallback } from "react" ;
2+ import {
3+ DndContext ,
4+ closestCenter ,
5+ PointerSensor ,
6+ useSensor ,
7+ useSensors ,
8+ } from "@dnd-kit/core" ;
9+ import {
10+ SortableContext ,
11+ verticalListSortingStrategy ,
12+ arrayMove ,
13+ } from "@dnd-kit/sortable" ;
214import { CardType } from "@/types/task" ;
3- import Card from "./Card " ;
15+ import SortableCard from "@/components/columnCard/SortableCard " ;
416import { getCardsByColumn } from "@/api/card" ;
517
618type CardListProps = {
@@ -25,7 +37,14 @@ export default function CardList({
2537 const observerRef = useRef < HTMLDivElement | null > ( null ) ;
2638 const isFetchingRef = useRef ( false ) ;
2739
28- /* cursorId 업데이트 방식 변경 */
40+ const sensors = useSensors (
41+ useSensor ( PointerSensor , {
42+ activationConstraint : {
43+ distance : 5 ,
44+ } ,
45+ } )
46+ ) ;
47+
2948 const fetchMoreCards = useCallback ( async ( ) => {
3049 if ( isFetchingRef . current || ! hasMore ) return ;
3150
@@ -35,7 +54,7 @@ export default function CardList({
3554 const res = await getCardsByColumn ( {
3655 columnId,
3756 size : ITEMS_PER_PAGE ,
38- cursorId : cursorId ?? undefined , // 최신 cursorId 사용
57+ cursorId : cursorId ?? undefined ,
3958 } ) ;
4059
4160 const newCards = res . cards as CardType [ ] ;
@@ -49,7 +68,6 @@ export default function CardList({
4968 return [ ...prev , ...uniqueCards ] ;
5069 } ) ;
5170
52- // cursorId 안전하게 업데이트
5371 setCursorId ( ( prevCursorId ) => {
5472 const newCursor = newCards [ newCards . length - 1 ] ?. id ?? prevCursorId ;
5573 return newCursor ;
@@ -66,7 +84,6 @@ export default function CardList({
6684 }
6785 } , [ columnId , cursorId , hasMore ] ) ;
6886
69- /* 무한 스크롤 */
7087 useEffect ( ( ) => {
7188 if ( ! observerRef . current ) return ;
7289
@@ -84,17 +101,35 @@ export default function CardList({
84101 return ( ) => observer . disconnect ( ) ;
85102 } , [ fetchMoreCards , hasMore ] ) ;
86103
104+ const handleDragEnd = ( event : any ) => {
105+ const { active, over } = event ;
106+
107+ if ( ! over || active . id === over . id ) return ;
108+
109+ const oldIndex = cards . findIndex ( ( card ) => card . id === active . id ) ;
110+ const newIndex = cards . findIndex ( ( card ) => card . id === over . id ) ;
111+
112+ const newOrder = arrayMove ( cards , oldIndex , newIndex ) ;
113+ setCards ( newOrder ) ;
114+ } ;
115+
87116 return (
88- < div className = "grid gap-3 w-full grid-cols-1" >
89- { cards . map ( ( task ) => (
90- < Card
91- key = { task . id }
92- { ...task }
93- assignee = { task . assignee }
94- onClick = { ( ) => onCardClick ( task ) }
95- />
96- ) ) }
97- { hasMore && < div ref = { observerRef } className = "h-20" /> }
98- </ div >
117+ < DndContext
118+ sensors = { sensors }
119+ collisionDetection = { closestCenter }
120+ onDragEnd = { handleDragEnd }
121+ >
122+ < SortableContext
123+ items = { cards . map ( ( card ) => card . id ) }
124+ strategy = { verticalListSortingStrategy }
125+ >
126+ < div className = "grid gap-3 w-full grid-cols-1" >
127+ { cards . map ( ( card ) => (
128+ < SortableCard key = { card . id } card = { card } onClick = { onCardClick } />
129+ ) ) }
130+ { hasMore && < div ref = { observerRef } className = "h-20" /> }
131+ </ div >
132+ </ SortableContext >
133+ </ DndContext >
99134 ) ;
100135}
0 commit comments