Files
fusion/packages/dashboard/app/components/Column.tsx

70 lines
2.1 KiB
TypeScript

import { useState, useCallback } from "react";
import type { Task, TaskDetail, Column as ColumnType } from "@hai/core";
import { COLUMN_LABELS, COLUMN_DESCRIPTIONS } from "@hai/core";
import { TaskCard } from "./TaskCard";
import type { ToastType } from "../hooks/useToast";
interface ColumnProps {
column: ColumnType;
tasks: Task[];
onMoveTask: (id: string, column: ColumnType) => Promise<Task>;
onOpenDetail: (task: TaskDetail) => void;
addToast: (message: string, type?: ToastType) => void;
}
export function Column({ column, tasks, onMoveTask, onOpenDetail, addToast }: ColumnProps) {
const [dragOver, setDragOver] = useState(false);
const handleDragOver = useCallback((e: React.DragEvent) => {
e.preventDefault();
e.dataTransfer.dropEffect = "move";
setDragOver(true);
}, []);
const handleDragLeave = useCallback((e: React.DragEvent) => {
const el = e.currentTarget as HTMLElement;
if (!el.contains(e.relatedTarget as Node)) {
setDragOver(false);
}
}, []);
const handleDrop = useCallback(async (e: React.DragEvent) => {
e.preventDefault();
setDragOver(false);
const taskId = e.dataTransfer.getData("text/plain");
if (!taskId) return;
try {
await onMoveTask(taskId, column);
} catch (err: any) {
addToast(err.message, "error");
}
}, [column, onMoveTask, addToast]);
return (
<div
className={`column${dragOver ? " drag-over" : ""}`}
data-column={column}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
<div className="column-header">
<div className={`column-dot dot-${column}`} />
<h2>{COLUMN_LABELS[column]}</h2>
<span className="column-count">{tasks.length}</span>
</div>
<p className="column-desc">{COLUMN_DESCRIPTIONS[column]}</p>
<div className="column-body">
{tasks.length === 0 ? (
<div className="empty-column">No tasks</div>
) : (
tasks.map((task) => (
<TaskCard key={task.id} task={task} onOpenDetail={onOpenDetail} addToast={addToast} />
))
)}
</div>
</div>
);
}