'use client' import { useState } from 'react' import { useDroppable, useDraggable } from '@dnd-kit/core' import { SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' import { Badge } from '@/components/ui/badge' import { PanelNavBar } from '@/components/shared/panel-nav-bar' import { useSprintStore } from '@/stores/sprint-store' import { cn } from '@/lib/utils' const STATUS_COLORS: Record = { OPEN: 'bg-status-todo/15 text-status-todo border-status-todo/30', IN_SPRINT: 'bg-status-in-progress/15 text-status-in-progress border-status-in-progress/30', DONE: 'bg-status-done/15 text-status-done border-status-done/30', } const STATUS_LABELS: Record = { OPEN: 'Open', IN_SPRINT: 'In Sprint', DONE: 'Klaar' } const PRIORITY_COLORS: Record = { 1: 'bg-priority-critical/15 text-priority-critical border-priority-critical/30', 2: 'bg-priority-high/15 text-priority-high border-priority-high/30', 3: 'bg-priority-medium/15 text-priority-medium border-priority-medium/30', 4: 'bg-priority-low/15 text-priority-low border-priority-low/30', } const PRIORITY_LABELS: Record = { 1: 'Kritiek', 2: 'Hoog', 3: 'Gemiddeld', 4: 'Laag' } export interface SprintStory { id: string title: string priority: number status: string taskCount: number doneCount: number } export interface PbiWithStories { id: string title: string stories: SprintStory[] } // --- Left panel: Sprint Backlog --- function SortableSprintRow({ story, isDemo, onRemove, }: { story: SprintStory; isDemo: boolean; onRemove: () => void }) { const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: story.id }) const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.4 : 1 } return (
{!isDemo && ( )}

{story.title}

{PRIORITY_LABELS[story.priority]} {story.doneCount}/{story.taskCount} klaar
{!isDemo && ( )}
) } interface SprintBacklogLeftProps { sprintId: string stories: SprintStory[] isDemo: boolean onRemove: (storyId: string) => void } export function SprintBacklogLeft({ sprintId, stories, isDemo, onRemove }: SprintBacklogLeftProps) { const { sprintStoryOrder } = useSprintStore() const { setNodeRef, isOver } = useDroppable({ id: 'sprint-zone' }) const storyMap = Object.fromEntries(stories.map(s => [s.id, s])) const order = sprintStoryOrder[sprintId] ?? stories.map(s => s.id) const orderedStories = order.map(id => storyMap[id]).filter(Boolean) return (
{orderedStories.length === 0 ? (

{isOver ? 'Loslaten om toe te voegen aan Sprint' : 'Geen stories in de Sprint. Sleep stories vanuit het rechterpaneel.'}

) : ( s.id)} strategy={verticalListSortingStrategy}> {orderedStories.map(story => ( onRemove(story.id)} /> ))} )}
) } // --- Right panel: Product Backlog grouped by PBI --- function DraggablePbiStoryRow({ story, isDemo }: { story: SprintStory; isDemo: boolean }) { const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({ id: `pb:${story.id}` }) const style = transform ? { transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`, zIndex: 50, position: 'relative' as const } : undefined return (
{!isDemo && ( )}

{story.title}

{STATUS_LABELS[story.status]}
) } interface SprintBacklogRightProps { pbisWithStories: PbiWithStories[] sprintStoryIds: Set isDemo: boolean } export function SprintBacklogRight({ pbisWithStories, sprintStoryIds, isDemo }: SprintBacklogRightProps) { const [collapsed, setCollapsed] = useState>(new Set()) const { setNodeRef, isOver } = useDroppable({ id: 'backlog-zone' }) function toggle(pbiId: string) { setCollapsed(prev => { const next = new Set(prev) if (next.has(pbiId)) { next.delete(pbiId) } else { next.add(pbiId) } return next }) } return (
{pbisWithStories.map(pbi => (
{!collapsed.has(pbi.id) && pbi.stories.map(story => { const inSprint = sprintStoryIds.has(story.id) if (inSprint) { return (

{story.title}

{STATUS_LABELS[story.status]}
In Sprint
) } return })}
))}
) }