ndyudev / trello-web

1 stars 0 forks source link

Drag Drop Card P8 #47

Closed ndyudev closed 2 weeks ago

ndyudev commented 2 weeks ago
ndyudev commented 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;

ndyudev commented 2 weeks ago