/** * @file dashboard/KanbanColumn.tsx * @description Client component rendering a single kanban column container supporting drag-and-drop drop targets and status updates. */ "use client"; import { useState, useTransition } from "react"; import { Plus } from "lucide-react"; import { useRouter } from "next/navigation"; import KanbanCard from "./KanbanCard"; import { KanbanColumnProps, TaskStatus } from "@/types/tasks"; /** * Renders a kanban column with title indicators, task counters, drag-and-drop event handlers, * and lists of nested KanbanCard items. * * @param {KanbanColumnProps} props - The component props including column ID, title, count, tasks, and color configuration. * @returns {JSX.Element} The rendered kanban column component. */ export default function KanbanColumn(props: KanbanColumnProps) { const router = useRouter(); const [isPending, startTransition] = useTransition(); const [isDraggingOver, setIsDraggingOver] = useState(false); const indicatorColor = props.color ?? "bg-primary"; /** * Updates the status of a specific task via a PATCH API request and refreshes the router state. * * @async * @param {string} taskId - The unique identifier of the task to update. * @param {TaskStatus} targetStatus - The destination status to apply to the task. */ const updateTaskStatus = (taskId: string, targetStatus: TaskStatus) => { startTransition(async () => { try { const response = await fetch(`/api/tasks/${taskId}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ status: targetStatus }), }); if (!response.ok) { throw new Error("Failed to update task status"); } router.refresh(); } catch (error) { console.error("Error during task status update:", error); } }); }; /** * Handles the drag-over event to allow dropping items onto the column. * * @param {React.DragEvent} e - The drag event object. */ const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); e.dataTransfer.dropEffect = "move"; setIsDraggingOver(true); }; /** * Handles the drag-leave event when a dragged item leaves the column bounds. */ const handleDragLeave = () => { setIsDraggingOver(false); }; /** * Handles dropping a task card onto the column, triggering status updates if valid. * * @param {React.DragEvent} e - The drop event object. */ const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setIsDraggingOver(false); const taskId = e.dataTransfer.getData("text/plain"); const sourceStatus = e.dataTransfer.getData("sourceStatus") as TaskStatus; if (!taskId || sourceStatus === props.id) return; updateTaskStatus(taskId, props.id); }; return (
{/* Column Header */}

{props.title}

{props.count}
{/* Card List */}
{props.tasks.length === 0 ? (
No tasks
) : ( props.tasks.map((task) => ( )) )}
); }