feat(ST-355): add /solo route, cookie helper, product picker, and solo product page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-26 16:29:31 +02:00
parent 802aa58157
commit ca631e71ec
7 changed files with 230 additions and 1 deletions

View file

@ -0,0 +1,25 @@
import Link from 'next/link'
interface NoActiveSprintProps {
productId: string
productName: string
}
export function NoActiveSprint({ productId, productName }: NoActiveSprintProps) {
return (
<div className="flex flex-col items-center justify-center h-full gap-4 text-center px-6">
<div className="text-4xl text-muted-foreground">🏃</div>
<h2 className="text-lg font-medium text-foreground">Geen actieve sprint</h2>
<p className="text-sm text-muted-foreground max-w-sm">
Er is nog geen actieve sprint voor <span className="font-medium text-foreground">{productName}</span>.
Start een sprint in het Sprint Board om hier je taken te zien.
</p>
<Link
href={`/products/${productId}/sprint`}
className="text-sm text-primary hover:underline"
>
Naar Sprint Board
</Link>
</div>
)
}

View file

@ -0,0 +1,46 @@
import Link from 'next/link'
interface Product {
id: string
name: string
description: string | null
}
interface ProductPickerProps {
products: Product[]
}
export function ProductPicker({ products }: ProductPickerProps) {
return (
<div className="p-6 max-w-2xl mx-auto w-full">
<h1 className="text-xl font-medium text-foreground mb-2">Solo bord</h1>
<p className="text-sm text-muted-foreground mb-6">
Kies een product om je persoonlijke Kanban-bord te openen.
</p>
{products.length === 0 ? (
<div className="text-center py-12">
<p className="text-sm text-muted-foreground mb-3">Je hebt nog geen producten.</p>
<Link href="/products/new" className="text-sm text-primary hover:underline">
+ Nieuw product aanmaken
</Link>
</div>
) : (
<div className="grid gap-2">
{products.map(product => (
<Link
key={product.id}
href={`/products/${product.id}/solo`}
className="flex flex-col gap-0.5 px-4 py-3 rounded-lg border border-border bg-surface-container hover:bg-surface-container-high transition-colors"
>
<span className="text-sm font-medium text-foreground">{product.name}</span>
{product.description && (
<span className="text-xs text-muted-foreground line-clamp-1">{product.description}</span>
)}
</Link>
))}
</div>
)}
</div>
)
}

View file

@ -0,0 +1,32 @@
'use client'
export interface SoloTask {
id: string
title: string
description: string | null
implementation_plan: string | null
priority: number
sort_order: number
status: 'TO_DO' | 'IN_PROGRESS' | 'REVIEW' | 'DONE'
story_id: string
story_title: string
}
export interface SoloBoardProps {
productId: string
productName: string
sprintGoal: string
tasks: SoloTask[]
unassignedCount: number
isDemo: boolean
currentUserId: string
}
// Full implementation in ST-356
export function SoloBoard(_props: SoloBoardProps) {
return (
<div className="flex items-center justify-center h-full">
<p className="text-sm text-muted-foreground">Solo bord wordt geladen in ST-356</p>
</div>
)
}