feat(todos): dropdown filters visible todos; 'Alles' toont alles

De product-dropdown fungeert nu als filter voor de lijst:
- 'Alles' (default) toont alle todo's
- 'Geen product' toont alleen ongelinkte todo's
- Een specifiek product toont alleen todo's van dat product

Nieuw aangemaakte todo's krijgen het geselecteerde product mee.
'Alles' en 'Geen product' resulteren in een todo zonder productlink.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-25 19:23:54 +02:00
parent ca6510c98e
commit 2dfd01e421
2 changed files with 36 additions and 7 deletions

View file

@ -40,7 +40,17 @@ interface TodoListProps {
isDemo: boolean
}
function QuickInput({ products, isDemo }: { products: Product[]; isDemo: boolean }) {
function QuickInput({
products,
isDemo,
selectedProductId,
onProductChange,
}: {
products: Product[]
isDemo: boolean
selectedProductId: string
onProductChange: (id: string) => void
}) {
const [state, formAction] = useActionState(createTodoAction, undefined)
const titleRef = useRef<HTMLInputElement>(null)
@ -53,9 +63,12 @@ function QuickInput({ products, isDemo }: { products: Product[]; isDemo: boolean
<form action={formAction} className="flex gap-2">
<select
name="productId"
value={selectedProductId}
onChange={e => onProductChange(e.target.value)}
disabled={isDemo}
className="border border-border rounded-lg px-3 py-1.5 text-sm bg-input-background shrink-0"
>
<option value="all">Alles</option>
<option value="">Geen product</option>
{products.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
</select>
@ -239,9 +252,17 @@ export function TodoList({ todos, products, isDemo }: TodoListProps) {
const [, startTransition] = useTransition()
const [promotePbi, setPromotePbi] = useState<Todo | null>(null)
const [promoteStory, setPromoteStory] = useState<Todo | null>(null)
const [selectedProductId, setSelectedProductId] = useState('all')
const open = todos.filter(t => !t.done)
const done = todos.filter(t => t.done)
const filtered =
selectedProductId === 'all'
? todos
: selectedProductId === ''
? todos.filter(t => t.product_id === null)
: todos.filter(t => t.product_id === selectedProductId)
const open = filtered.filter(t => !t.done)
const done = filtered.filter(t => t.done)
function handleToggle(id: string, current: boolean) {
startTransition(async () => {
@ -259,11 +280,18 @@ export function TodoList({ todos, products, isDemo }: TodoListProps) {
return (
<div className="space-y-4">
<QuickInput products={products} isDemo={isDemo} />
<QuickInput
products={products}
isDemo={isDemo}
selectedProductId={selectedProductId}
onProductChange={setSelectedProductId}
/>
{todos.length === 0 ? (
{filtered.length === 0 ? (
<div className="bg-surface-container-low border border-border rounded-xl p-12 text-center">
<p className="text-muted-foreground text-sm">Geen todo&apos;s. Voeg er een toe hierboven.</p>
<p className="text-muted-foreground text-sm">
{todos.length === 0 ? 'Geen todos. Voeg er een toe hierboven.' : 'Geen todos voor deze selectie.'}
</p>
</div>
) : (
<>