Closed ndyudev closed 2 weeks ago
import Box from '@mui/material/Box'; import ListColumns from './ListColumns/ListColumns'; import { mapOrder } from '~/utils/sorts'; import { DndContext, useSensor, useSensors, MouseSensor, TouchSensor, DragOverlay, defaultDropAnimationSideEffects } from '@dnd-kit/core'; import { arrayMove } from '@dnd-kit/sortable'; import { useEffect, useState } from 'react'; import { cloneDeep } from 'lodash';
import Column from './ListColumns/Column/Column'; import Card from './ListColumns/Column/ListCards/Card/Card';
const ACTIVE_DRAG_ITEM_TYPE = { COLUMN: 'ACTIVE_DRAG_ITEM_TYPE_COLUMN', CARD: 'ACTIVE_DRAG_ITEM_TYPE_CARD', };
function BoardContent({ board }) { // Thiết lập các sensor cho việc kéo thả const mouseSensor = useSensor(MouseSensor, { activationConstraint: { distance: 10 } }); const touchSensor = useSensor(TouchSensor, { activationConstraint: { delay: 250, tolerance: 500 } }); const sensors = useSensors(mouseSensor, touchSensor);
const [orderedColumns, setOrderedColumns] = useState([]); const [activeDragItemId, setActiveDragItemID] = useState(null); const [activeDragItemType, setActiveDragItemType] = useState(null); const [activeDragItemData, setActiveDragItemData] = useState(null); const [oldColumnWhenDraggingCard, setOldColumnWhenDraggingCard] = useState(null);
useEffect(() => {
// Sắp xếp các columns theo thứ tự được chỉ định trong board.columnOrderIds
setOrderedColumns(mapOrder(board?.columns, board?.columnOrderIds, '_id'));
}, [board]);
// Tìm column chứa một card dựa trên cardId const findColumnByCardId = (cardId) => { return orderedColumns.find(column => column?.cards?.some(card => card._id === cardId)); };
// Xử lý di chuyển card giữa các columns khác nhau const moveCardBetweenDifferentColumns = ( overColumn, overCardId, active, over, activeColumn, activeDraggingCardId, activeDraggingCardData ) => { setOrderedColumns(prevColumns => { const nextColumns = cloneDeep(prevColumns); // Sao chép lại mảng để đảm bảo tính bất biến
const nextActiveColumn = nextColumns.find(column => column._id === activeColumn._id);
const nextOverColumn = nextColumns.find(column => column._id === overColumn._id);
if (nextActiveColumn) {
nextActiveColumn.cards = nextActiveColumn.cards.filter(card => card._id !== activeDraggingCardId);
nextActiveColumn.cardOrderIds = nextActiveColumn.cards.map(card => card._id);
}
if (nextOverColumn) {
const overCardIndex = nextOverColumn.cards.findIndex(card => card._id === overCardId);
const newCardIndex = overCardIndex >= 0 ? overCardIndex : nextOverColumn.cards.length;
const updatedCardData = { ...activeDraggingCardData, column: nextOverColumn._id };
nextOverColumn.cards.splice(newCardIndex, 0, updatedCardData);
nextOverColumn.cardOrderIds = nextOverColumn.cards.map(card => card._id);
}
return nextColumns;
});
};
// Xử lý khi bắt đầu kéo const handleDragStart = (event) => { const { active } = event; setActiveDragItemID(active?.id); setActiveDragItemType(active?.data?.current?.columnId ? ACTIVE_DRAG_ITEM_TYPE.CARD : ACTIVE_DRAG_ITEM_TYPE.COLUMN); setActiveDragItemData(active?.data?.current);
if (active?.data?.current?.columnId) {
setOldColumnWhenDraggingCard(findColumnByCardId(active?.id));
}
};
// Xử lý khi đang kéo qua một vị trí khác const handleDragOver = (event) => { if (activeDragItemType === ACTIVE_DRAG_ITEM_TYPE.COLUMN) return;
const { active, over } = event;
if (!active || !over) return;
const activeDraggingCardId = active.id;
const overCardId = over.id;
const activeColumn = findColumnByCardId(activeDraggingCardId);
const overColumn = findColumnByCardId(overCardId);
if (!activeColumn || !overColumn) return;
if (activeColumn._id !== overColumn._id) {
moveCardBetweenDifferentColumns(overColumn, overCardId, active, over, activeColumn, activeDraggingCardId, active?.data?.current);
}
};
// Xử lý khi kết thúc kéo const handleDragEnd = (event) => { const { active, over } = event; if (!active || !over) return;
if (activeDragItemType === ACTIVE_DRAG_ITEM_TYPE.CARD) {
const activeDraggingCardId = active.id;
const overCardId = over.id;
const activeColumn = findColumnByCardId(activeDraggingCardId);
const overColumn = findColumnByCardId(overCardId);
if (!activeColumn || !overColumn) return;
if (oldColumnWhenDraggingCard._id !== overColumn._id) {
moveCardBetweenDifferentColumns(overColumn, overCardId, active, over, activeColumn, activeDraggingCardId, active?.data?.current);
} else {
const oldCardIndex = oldColumnWhenDraggingCard.cards.findIndex(card => card._id === activeDragItemId);
const newCardIndex = overColumn.cards.findIndex(card => card._id === overCardId);
const updatedCards = arrayMove(oldColumnWhenDraggingCard.cards, oldCardIndex, newCardIndex);
setOrderedColumns(prevColumns => {
const nextColumns = cloneDeep(prevColumns);
const targetColumn = nextColumns.find(column => column._id === overColumn._id);
if (targetColumn) {
targetColumn.cards = updatedCards;
targetColumn.cardOrderIds = updatedCards.map(card => card._id);
}
return nextColumns;
});
}
}
if (activeDragItemType === ACTIVE_DRAG_ITEM_TYPE.COLUMN) {
if (active.id !== over.id) {
const oldColumnIndex = orderedColumns.findIndex(c => c._id === active.id);
const newColumnIndex = orderedColumns.findIndex(c => c._id === over.id);
const updatedColumns = arrayMove(orderedColumns, oldColumnIndex, newColumnIndex);
setOrderedColumns(updatedColumns);
}
}
setActiveDragItemID(null);
setActiveDragItemData(null);
setActiveDragItemType(null);
setOldColumnWhenDraggingCard(null);
};
// Thiết lập animation khi kết thúc thả const customDropAnimation = { sideEffects: defaultDropAnimationSideEffects({ styles: { active: { opacity: '0.5', }, }, }), };
return ( <DndContext onDragStart={handleDragStart} onDragOver={handleDragOver} onDragEnd={handleDragEnd} sensors={sensors}
<Box sx={{ backgroundColor: (theme) => theme.palette.mode === 'dark' ? '#34495e' : '#1976d2', width: '100%', height: (theme) => theme.trello.BoardContentHeight, p: '10px 0', }}
{!activeDragItemType && null} {activeDragItemType === ACTIVE_DRAG_ITEM_TYPE.COLUMN && } {activeDragItemType === ACTIVE_DRAG_ITEM_TYPE.CARD && } ); }
export default BoardContent;