"use client"; import { useRef, useEffect } from "react"; import { useDraggable, useDroppable } from "@dnd-kit/core"; import { Badge } from "@/components/ui/badge"; import { cn } from "@/lib/utils"; import { TaskCard } from "./task-card"; import type { KanbanColumn as KanbanColumnType } from "@/lib/api/tasks"; const COLUMN_COLORS: Record = { overdue_tasks: "border-red-500/50 bg-red-50/50 dark:bg-red-950/20", due_soon_tasks: "border-yellow-500/50 bg-yellow-50/50 dark:bg-yellow-950/20", upcoming_tasks: "border-blue-500/50 bg-blue-50/50 dark:bg-blue-950/20", in_progress_tasks: "border-green-500/50 bg-green-50/50 dark:bg-green-950/20", completed_tasks: "border-gray-500/50 bg-gray-50/50 dark:bg-gray-950/20", cancelled_tasks: "border-slate-500/50 bg-slate-50/50 dark:bg-slate-950/20", }; const COLUMN_HEADER_COLORS: Record = { overdue_tasks: "text-red-700 dark:text-red-400", due_soon_tasks: "text-yellow-700 dark:text-yellow-400", upcoming_tasks: "text-blue-700 dark:text-blue-400", in_progress_tasks: "text-green-700 dark:text-green-400", completed_tasks: "text-gray-700 dark:text-gray-400", cancelled_tasks: "text-slate-700 dark:text-slate-400", }; const COUNT_BADGE_COLORS: Record = { overdue_tasks: "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200", due_soon_tasks: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200", upcoming_tasks: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200", in_progress_tasks: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200", completed_tasks: "bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200", cancelled_tasks: "bg-slate-100 text-slate-800 dark:bg-slate-900 dark:text-slate-200", }; interface KanbanColumnProps { column: KanbanColumnType; } function DraggableTask({ task }: { task: import("@/lib/api/tasks").TaskResponse }) { const { attributes, listeners, setNodeRef, transform, isDragging, } = useDraggable({ id: task.id }); const wasDragging = useRef(false); useEffect(() => { if (isDragging) { wasDragging.current = true; } }, [isDragging]); const style: React.CSSProperties = transform ? { transform: `translate(${transform.x}px, ${transform.y}px)`, opacity: isDragging ? 0.5 : 1, zIndex: isDragging ? 50 : undefined, position: isDragging ? "relative" : undefined, } : undefined as unknown as React.CSSProperties; // Block the click that fires after a drag ends so the Link doesn't navigate const handleClick = (e: React.MouseEvent) => { if (wasDragging.current) { e.preventDefault(); e.stopPropagation(); wasDragging.current = false; } }; return (
); } export function KanbanColumn({ column }: KanbanColumnProps) { const { setNodeRef, isOver } = useDroppable({ id: column.name, }); return (

{column.display_name}

{column.count}
{column.tasks.map((task) => ( ))} {column.tasks.length === 0 && (
No tasks
)}
); }