import { Add, AddCircle, CloseCircle } from "iconsax-react"; import { useRef, useState, type FC } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "react-toastify"; import ModalConfrim from "../../../components/ModalConfrim"; import { ErrorType } from "../../../helpers/types"; import { useDeleteTaskPhase } from "../task-phase/hooks/useTaskPhaseData"; import type { Column as ColumnType, Task as TaskType } from "../types"; import ColumnMenu from "./ColumnMenu"; import Task from "./Task"; type Props = { column: ColumnType; projectId: string; tasks: TaskType[]; draggedTaskId: string | null; draggedColumnId: string | null; onDragStart: (taskId: string) => void; onDragEnd: () => void; onDrop: (columnId: string, index: number) => void; onColumnDragStart: (columnId: string) => void; onColumnDragEnd: () => void; onColumnDrop: (overColumnId: string) => void; onTaskClick?: (task: TaskType) => void; onColumnDeleted?: (columnId: string) => void; }; const Column: FC = ({ column, projectId, tasks, draggedTaskId, draggedColumnId, onDragStart, onDragEnd, onDrop, onColumnDragStart, onColumnDragEnd, onColumnDrop, onTaskClick, onColumnDeleted, }) => { const { t } = useTranslation("global"); const deleteTaskPhase = useDeleteTaskPhase(); const [isAdding, setIsAdding] = useState(false); const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false); const [isDragOver, setIsDragOver] = useState(false); const [isColumnDragOver, setIsColumnDragOver] = useState(false); const columnRef = useRef(null); const dragImageRef = useRef(null); const isDraggingColumn = draggedColumnId === column.id; const handleColumnDragStart = (e: React.DragEvent) => { const columnEl = columnRef.current; if (columnEl) { const clone = columnEl.cloneNode(true) as HTMLElement; clone.style.position = "fixed"; clone.style.top = "-10000px"; clone.style.left = "-10000px"; clone.style.width = `${columnEl.offsetWidth}px`; clone.style.opacity = "0.95"; clone.style.boxShadow = "0 8px 24px rgba(0, 0, 0, 0.15)"; clone.style.pointerEvents = "none"; clone.style.zIndex = "9999"; document.body.appendChild(clone); dragImageRef.current = clone; const rect = columnEl.getBoundingClientRect(); e.dataTransfer.setDragImage( clone, e.clientX - rect.left, e.clientY - rect.top, ); e.dataTransfer.effectAllowed = "move"; } onColumnDragStart(column.id); }; const handleColumnDragEnd = () => { if (dragImageRef.current) { document.body.removeChild(dragImageRef.current); dragImageRef.current = null; } onColumnDragEnd(); }; const handleDragOver = (e: React.DragEvent) => { if (draggedColumnId) return; e.preventDefault(); e.dataTransfer.dropEffect = "move"; setIsDragOver(true); }; const handleDragLeave = (e: React.DragEvent) => { if (draggedColumnId) return; if (!e.currentTarget.contains(e.relatedTarget as Node)) { setIsDragOver(false); } }; const handleDrop = (e: React.DragEvent, index: number) => { if (draggedColumnId) return; e.preventDefault(); e.stopPropagation(); setIsDragOver(false); onDrop(column.id, index); }; const handleColumnDragOver = (e: React.DragEvent) => { if (!draggedColumnId || draggedColumnId === column.id) return; e.preventDefault(); e.dataTransfer.dropEffect = "move"; setIsColumnDragOver(true); }; const handleColumnDragLeave = (e: React.DragEvent) => { if (!draggedColumnId) return; if (!e.currentTarget.contains(e.relatedTarget as Node)) { setIsColumnDragOver(false); } }; const handleColumnDrop = (e: React.DragEvent) => { if (!draggedColumnId || draggedColumnId === column.id) return; e.preventDefault(); e.stopPropagation(); setIsColumnDragOver(false); onColumnDrop(column.id); }; const handleDeleteColumn = () => { deleteTaskPhase.mutate( { id: column.id, projectId }, { onSuccess: () => { onColumnDeleted?.(column.id); setIsDeleteConfirmOpen(false); toast.success(t("taskmanager.column_deleted")); }, onError: (error: ErrorType) => { toast.error(error.response?.data?.error.message[0]); }, }, ); }; return (
{ handleColumnDragOver(e); handleDragOver(e); }} onDragLeave={(e) => { handleColumnDragLeave(e); handleDragLeave(e); }} onDrop={(e) => { handleColumnDrop(e); if (!draggedColumnId) { handleDrop(e, tasks.length); } }} >
{column.title}
setIsDeleteConfirmOpen(true)} />
setIsDeleteConfirmOpen(false)} onConfrim={handleDeleteColumn} isLoading={deleteTaskPhase.isPending} label={t("taskmanager.delete_column_confirm")} />
{tasks.map((task, index) => (
{ if (draggedColumnId) return; e.preventDefault(); e.stopPropagation(); }} onDrop={(e) => handleDrop(e, index)} >
))}
{isAdding ? (
) : ( )}
); }; export default Column;