Improved task structure

This commit is contained in:
2025-11-10 21:05:08 +01:00
parent 086f470ebe
commit 6bf91af1f8
2 changed files with 68 additions and 70 deletions
+40 -43
View File
@@ -18,19 +18,12 @@ const id = (prefix = "t") =>
`${prefix}_${Math.random().toString(36).slice(2, 9)}`; `${prefix}_${Math.random().toString(36).slice(2, 9)}`;
export default function BoardView() { export default function BoardView() {
const [columns, setColumns] = useState<Record<string, Task[]>>({ const [tasks, setTasks] = useState<Task[]>([]);
todo: [],
inprogress: [],
done: [],
});
useEffect(() => { useEffect(() => {
setColumns({ setTasks([
todo: [ { id: id(), title: "Buy groceries", status: "todo" },
{ id: id(), title: "Buy groceries" }, { id: id(), title: "Plan sprint", status: "todo" },
{ id: id(), title: "Plan sprint" },
],
inprogress: [
{ {
id: id(), id: id(),
title: "Build header", title: "Build header",
@@ -42,35 +35,36 @@ export default function BoardView() {
{ name: "App", color: "purple" }, { name: "App", color: "purple" },
{ name: "Rust", color: "orange" }, { name: "Rust", color: "orange" },
], ],
status: "inprogress",
}, },
], ]);
done: [],
});
}, []); }, []);
function onDragEnd(result: any) { function onDragEnd(result: any) {
const { source, destination } = result; const { draggableId, source, destination } = result;
if (!destination) return; if (!destination) return;
const sourceCol = source.droppableId; setTasks((tasks) => {
const destCol = destination.droppableId; const taskIndex = tasks.findIndex((task) => task.id === draggableId);
const task = tasks[taskIndex];
tasks.splice(taskIndex, 1);
if (sourceCol === destCol) { const destinationGroupStartIndex = tasks.findIndex(
const items = Array.from(columns[sourceCol]); (t) => t.status === destination.droppableId
const [moved] = items.splice(source.index, 1); );
items.splice(destination.index, 0, moved);
setColumns({ ...columns, [sourceCol]: items }); const insertIndex =
} else { destinationGroupStartIndex === -1
const sourceItems = Array.from(columns[sourceCol]); ? tasks.length
const destItems = Array.from(columns[destCol]); : destinationGroupStartIndex + destination.index;
const [moved] = sourceItems.splice(source.index, 1);
destItems.splice(destination.index, 0, moved); tasks.splice(insertIndex, 0, {
setColumns({ ...task,
...columns, status: destination.droppableId,
[sourceCol]: sourceItems, });
[destCol]: destItems,
return tasks;
}); });
}
} }
return ( return (
@@ -93,11 +87,12 @@ export default function BoardView() {
className="ml-auto" className="ml-auto"
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const t: Task = { id: id(), title: "New task" }; const t: Task = {
setColumns((c) => ({ id: id(),
...c, title: "New task",
[colKey]: [...c[colKey], t], status: colKey,
})); };
setTasks((c) => [...c, t]);
}} }}
> >
<PlusIcon /> <PlusIcon />
@@ -106,7 +101,9 @@ export default function BoardView() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
{columns[colKey].map((task, index) => ( {tasks
.filter((task) => task.status === colKey)
.map((task, index) => (
<Draggable <Draggable
key={task.id} key={task.id}
draggableId={task.id} draggableId={task.id}
@@ -115,10 +112,9 @@ export default function BoardView() {
{(provided) => ( {(provided) => (
<BoardTask <BoardTask
setTask={(t) => setTask={(t) =>
setColumns((cols) => { setTasks((cols) =>
cols[colKey][index] = t; cols.map((c) => (c.id === t.id ? t : c))
return cols; )
})
} }
provided={provided} provided={provided}
task={task} task={task}
@@ -127,7 +123,8 @@ export default function BoardView() {
</Draggable> </Draggable>
))} ))}
{provided.placeholder} {provided.placeholder}
{columns[colKey].length === 0 && ( {tasks.filter((task) => task.status === colKey).length ===
0 && (
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
No tasks No tasks
</p> </p>
+1
View File
@@ -3,6 +3,7 @@ import { Color } from "./ui/color";
export type Task = { export type Task = {
id: string; id: string;
title: string; title: string;
status: string;
description?: string; description?: string;
tags?: { name: string; color: Color }[]; tags?: { name: string; color: Color }[];
}; };