From 7f57f2b36f7908a831f852b28e4ae9cfc4fb91a8 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Sat, 25 Apr 2026 20:00:57 +0200 Subject: [PATCH] =?UTF-8?q?feat(ST-510):=20add=20TodoCard=20=E2=80=94=20aa?= =?UTF-8?q?nmaken,=20bewerken=20en=20promoveren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Aanmaken (+ knop): product-dropdown erft huidige filter, autoFocus op titel - Bewerken (rij-klik): laadt todo in kaart; velden: product, titel, done-toggle - Promoveren: → PBI en → Story knoppen openen bestaande dialogs - key op TodoCard dwingt remount bij ander geselecteerde rij zodat defaultValue-velden altijd de juiste todo tonen - SaveButton via useFormStatus voor pending-state op submit Co-Authored-By: Claude Sonnet 4.6 --- components/todos/todo-list.tsx | 180 +++++++++++++++++++++++++++++++-- 1 file changed, 169 insertions(+), 11 deletions(-) diff --git a/components/todos/todo-list.tsx b/components/todos/todo-list.tsx index 398f5b0..2eb7497 100644 --- a/components/todos/todo-list.tsx +++ b/components/todos/todo-list.tsx @@ -1,6 +1,8 @@ 'use client' import { useState, useTransition, useMemo, useEffect, useRef, useCallback } from 'react' +import { useActionState } from 'react' +import { useFormStatus } from 'react-dom' import { useReactTable, getCoreRowModel, @@ -18,11 +20,12 @@ import { Input } from '@/components/ui/input' import { DemoTooltip } from '@/components/shared/demo-tooltip' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' import { + createTodoAction, + updateTodoAction, archiveSelectedTodosAction, promoteTodoToPbiAction, promoteTodoToStoryAction, } from '@/actions/todos' -import { useActionState } from 'react' interface Todo { id: string @@ -70,6 +73,15 @@ function IndeterminateCheckbox({ ) } +function SaveButton() { + const { pending } = useFormStatus() + return ( + + ) +} + // --- Promote to PBI dialog --- function PromotePbiDialog({ todo, @@ -217,6 +229,141 @@ function PromoteStoryDialog({ ) } +// --- Detail card --- +function TodoCard({ + mode, + activeTodo, + products, + isDemo, + defaultProductId, + onSuccess, + onPromotePbi, + onPromoteStory, +}: { + mode: 'idle' | 'create' | 'edit' + activeTodo: Todo | null + products: Product[] + isDemo: boolean + defaultProductId: string + onSuccess: () => void + onPromotePbi: (todo: Todo) => void + onPromoteStory: (todo: Todo) => void +}) { + const [createState, createFormAction] = useActionState(createTodoAction, undefined) + const [editState, editFormAction] = useActionState(updateTodoAction, undefined) + + useEffect(() => { + if (createState?.success) onSuccess() + }, [createState, onSuccess]) + + useEffect(() => { + if (editState?.success) onSuccess() + }, [editState, onSuccess]) + + if (mode === 'idle') { + return ( +
+

Selecteer een rij of klik op + om te beginnen.

+
+ ) + } + + if (mode === 'create') { + return ( +
+

Nieuwe todo

+
+
+ + +
+ {typeof createState?.error === 'string' && ( +

{createState.error}

+ )} +
+ + +
+
+
+ ) + } + + // Edit mode + if (!activeTodo) return null + + return ( +
+

Todo bewerken

+
+ +
+ + +
+ + {typeof editState?.error === 'string' && ( +

{editState.error}

+ )} +
+ {!isDemo && ( + <> + + + + )} +
+ + +
+ +
+ ) +} + // --- Main component --- export function TodoList({ todos, products, isDemo }: TodoListProps) { const [isPending, startTransition] = useTransition() @@ -307,7 +454,15 @@ export function TodoList({ todos, products, isDemo }: TodoListProps) { const totalRows = filtered.length const start = totalRows === 0 ? 0 : pageIndex * pageSize + 1 const end = Math.min((pageIndex + 1) * pageSize, totalRows) + const activeTodo = todos.find(t => t.id === activeRowId) ?? null + const cardMode = mode === 'create' ? 'create' : activeTodo ? 'edit' : 'idle' + const defaultProductId = selectedProductId !== 'all' ? selectedProductId : '' + + const handleCancel = useCallback(() => { + setActiveRowId(null) + setMode('idle') + }, []) function handleRowClick(todo: Todo) { setActiveRowId(prev => prev === todo.id ? null : todo.id) @@ -331,6 +486,7 @@ export function TodoList({ todos, products, isDemo }: TodoListProps) { toast.success(`${n} todo${n === 1 ? '' : "'s"} gearchiveerd`) setRowSelection({}) setActiveRowId(null) + setMode('idle') } }) } @@ -422,16 +578,18 @@ export function TodoList({ todos, products, isDemo }: TodoListProps) {
)} - {/* Detail card — ST-510 */} -
-

- {mode === 'create' - ? 'Nieuwe todo aanmaken — kaart wordt gebouwd in ST-510.' - : activeTodo - ? `Geselecteerd: ${activeTodo.title}` - : 'Selecteer een rij of klik op + om te beginnen.'} -

-
+ {/* Detail card */} + {promotePbi && ( setPromotePbi(null)} />