diff --git a/src/components/card/subtask-list.tsx b/src/components/card/subtask-list.tsx new file mode 100644 index 0000000..f1d53ce --- /dev/null +++ b/src/components/card/subtask-list.tsx @@ -0,0 +1,139 @@ +"use client"; + +import { useState, useTransition } from "react"; +import { Plus, X } from "lucide-react"; + +import { addSubtask, deleteSubtask, toggleSubtask } from "@/app/actions/subtasks"; +import { cn } from "@/lib/cn"; +import type { SubtaskRecord } from "@/lib/pb/types"; + +export function SubtaskList({ + cardId, + subtasks, + editable, + clientSlug, + projectSlug, +}: { + cardId: string; + subtasks: SubtaskRecord[]; + editable: boolean; + clientSlug: string; + projectSlug: string; +}) { + const [pending, startTransition] = useTransition(); + const [draft, setDraft] = useState(""); + + const done = subtasks.filter((s) => s.done).length; + const percent = subtasks.length + ? Math.round((done / subtasks.length) * 100) + : 0; + + function submit(event: React.FormEvent) { + event.preventDefault(); + const title = draft.trim(); + if (!title) return; + setDraft(""); + startTransition(() => + addSubtask({ cardId, title, clientSlug, projectSlug }).then(() => undefined) + ); + } + + return ( +
+
+

+ Checklist +

+ {subtasks.length > 0 && ( + <> + + {done}/{subtasks.length} + +
+
+
+ + )} +
+ + {subtasks.length === 0 && !editable && ( +

No checklist items yet.

+ )} + + + + {editable && ( +
+ + setDraft(event.target.value)} + placeholder="Add an item" + disabled={pending} + className="flex-1 bg-transparent text-sm text-text-primary outline-none placeholder:text-text-muted" + /> + + )} +
+ ); +} \ No newline at end of file