feat(tasks): Normalize task statuses and enhance UI for task management
This commit is contained in:
@@ -24,12 +24,34 @@ type TaskBoardProps = {
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ title: "Inbox", status: "inbox" },
|
||||
{ title: "Assigned", status: "assigned" },
|
||||
{ title: "In Progress", status: "in_progress" },
|
||||
{ title: "Testing", status: "testing" },
|
||||
{ title: "Review", status: "review" },
|
||||
{ title: "Done", status: "done" },
|
||||
{
|
||||
title: "Inbox",
|
||||
status: "inbox",
|
||||
dot: "bg-slate-400",
|
||||
accent: "hover:border-slate-400 hover:bg-slate-50",
|
||||
text: "group-hover:text-slate-700 text-slate-500",
|
||||
},
|
||||
{
|
||||
title: "In Progress",
|
||||
status: "in_progress",
|
||||
dot: "bg-purple-500",
|
||||
accent: "hover:border-purple-400 hover:bg-purple-50",
|
||||
text: "group-hover:text-purple-600 text-slate-500",
|
||||
},
|
||||
{
|
||||
title: "Review",
|
||||
status: "review",
|
||||
dot: "bg-indigo-500",
|
||||
accent: "hover:border-indigo-400 hover:bg-indigo-50",
|
||||
text: "group-hover:text-indigo-600 text-slate-500",
|
||||
},
|
||||
{
|
||||
title: "Done",
|
||||
status: "done",
|
||||
dot: "bg-green-500",
|
||||
accent: "hover:border-green-400 hover:bg-green-50",
|
||||
text: "group-hover:text-green-600 text-slate-500",
|
||||
},
|
||||
];
|
||||
|
||||
const formatDueDate = (value?: string | null) => {
|
||||
@@ -61,41 +83,53 @@ export function TaskBoard({
|
||||
}, [tasks]);
|
||||
|
||||
return (
|
||||
<div className="grid grid-flow-col auto-cols-[minmax(260px,320px)] gap-6 overflow-x-auto pb-4">
|
||||
<div className="grid grid-flow-col auto-cols-[minmax(260px,320px)] gap-4 overflow-x-auto pb-6">
|
||||
{columns.map((column) => {
|
||||
const columnTasks = grouped[column.status] ?? [];
|
||||
return (
|
||||
<div key={column.title} className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-sm font-semibold text-strong">
|
||||
{column.title}
|
||||
</h3>
|
||||
<span className="text-xs text-quiet">{columnTasks.length}</span>
|
||||
<div key={column.title} className="kanban-column min-h-[calc(100vh-260px)]">
|
||||
<div className="column-header sticky top-0 z-10 rounded-t-xl border border-b-0 border-slate-200 bg-white/80 px-4 py-3 backdrop-blur">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={cn("h-2 w-2 rounded-full", column.dot)} />
|
||||
<h3 className="text-sm font-semibold text-slate-900">
|
||||
{column.title}
|
||||
</h3>
|
||||
</div>
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-slate-100 text-xs font-semibold text-slate-600">
|
||||
{columnTasks.length}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="rounded-b-xl border border-t-0 border-slate-200 bg-white p-3">
|
||||
{column.status === "inbox" ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCreateTask}
|
||||
disabled={isCreateDisabled}
|
||||
className={cn(
|
||||
"flex w-full items-center justify-center rounded-2xl border border-dashed border-[color:var(--border)] bg-[color:var(--surface-muted)] px-4 py-6 text-[11px] font-semibold uppercase tracking-[0.2em] text-quiet transition hover:border-[color:var(--border-strong)] hover:bg-[color:var(--surface)]",
|
||||
"group mb-3 flex w-full items-center justify-center rounded-lg border-2 border-dashed border-slate-300 px-4 py-4 text-sm font-medium transition",
|
||||
column.accent,
|
||||
isCreateDisabled && "cursor-not-allowed opacity-60"
|
||||
)}
|
||||
>
|
||||
New task
|
||||
<div className={cn("flex items-center gap-2", column.text)}>
|
||||
<span className="text-sm font-medium">New task</span>
|
||||
</div>
|
||||
</button>
|
||||
) : null}
|
||||
{columnTasks.map((task) => (
|
||||
<TaskCard
|
||||
key={task.id}
|
||||
title={task.title}
|
||||
status={column.status}
|
||||
assignee={task.assignee}
|
||||
due={formatDueDate(task.due_at)}
|
||||
onClick={() => onTaskSelect?.(task)}
|
||||
/>
|
||||
))}
|
||||
<div className="space-y-3">
|
||||
{columnTasks.map((task) => (
|
||||
<TaskCard
|
||||
key={task.id}
|
||||
title={task.title}
|
||||
status={column.status}
|
||||
assignee={task.assignee}
|
||||
due={formatDueDate(task.due_at)}
|
||||
onClick={() => onTaskSelect?.(task)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user