From c74d1337cec734f4ce054668328b58432567decf Mon Sep 17 00:00:00 2001 From: janpeter visser Date: Mon, 27 Apr 2026 18:10:05 +0200 Subject: [PATCH] feat(backlog): sorteer PBI's en stories op prio/code/datum, onthoud keuze in localStorage; vergroot sprint-afronden dialoog Co-Authored-By: Claude Sonnet 4.6 --- app/(app)/products/[id]/page.tsx | 3 +- components/backlog/pbi-list.tsx | 104 ++++++++++++++-------------- components/backlog/story-panel.tsx | 91 +++++++++++------------- components/sprint/sprint-header.tsx | 2 +- 4 files changed, 94 insertions(+), 106 deletions(-) diff --git a/app/(app)/products/[id]/page.tsx b/app/(app)/products/[id]/page.tsx index 92a0e87..77cfe1d 100644 --- a/app/(app)/products/[id]/page.tsx +++ b/app/(app)/products/[id]/page.tsx @@ -42,6 +42,7 @@ export default async function ProductBacklogPage({ params }: Props) { priority: true, status: true, pbi_id: true, + created_at: true, }, }) @@ -88,7 +89,7 @@ export default async function ProductBacklogPage({ params }: Props) { left={ ({ id: p.id, code: p.code, title: p.title, priority: p.priority, description: p.description }))} + pbis={pbis.map((p: (typeof pbis)[number]) => ({ id: p.id, code: p.code, title: p.title, priority: p.priority, description: p.description, created_at: p.created_at }))} isDemo={isDemo} /> } diff --git a/components/backlog/pbi-list.tsx b/components/backlog/pbi-list.tsx index 7e7cb20..eaec7ae 100644 --- a/components/backlog/pbi-list.tsx +++ b/components/backlog/pbi-list.tsx @@ -40,12 +40,8 @@ const PRIORITY_LABELS: Record = { 4: 'Laag', } -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', -} + +type SortMode = 'priority' | 'code' | 'date' interface Pbi { id: string @@ -53,6 +49,7 @@ interface Pbi { title: string priority: number description?: string | null + created_at: Date } interface PbiListProps { @@ -129,10 +126,16 @@ export function PbiList({ productId, pbis, isDemo }: PbiListProps) { const { selectedPbiId, selectPbi } = useSelectionStore() const { pbiOrder, pbiPriority, initPbis, reorderPbis, rollbackPbis, updatePbiPriority } = usePlannerStore() const [filterPriority, setFilterPriority] = useState(null) + const [sortMode, setSortMode] = useState(() => { + const saved = typeof window !== 'undefined' ? localStorage.getItem('scrum4me:pbi_sort') : null + return (saved === 'priority' || saved === 'code' || saved === 'date') ? saved : 'priority' + }) const [dialogState, setDialogState] = useState(null) const [activeDragId, setActiveDragId] = useState(null) const [, startTransition] = useTransition() + useEffect(() => { localStorage.setItem('scrum4me:pbi_sort', sortMode) }, [sortMode]) + // Sync server data into store — use stable string dep to avoid infinite loop const pbiIdKey = pbis.map(p => p.id).join(',') useEffect(() => { @@ -150,14 +153,18 @@ export function PbiList({ productId, pbis, isDemo }: PbiListProps) { .filter(Boolean) .map(p => ({ ...p, priority: pbiPriority[p.id] ?? p.priority })) - const filtered = filterPriority ? orderedPbis.filter(p => p.priority === filterPriority) : orderedPbis + const base = filterPriority ? orderedPbis.filter(p => p.priority === filterPriority) : orderedPbis - const grouped = [1, 2, 3, 4].reduce>((acc, p) => { - acc[p] = filtered.filter(pbi => pbi.priority === p) - return acc - }, {} as Record) - - const visiblePriorities = [1, 2, 3, 4].filter(p => grouped[p].length > 0) + const filtered = [...base].sort((a, b) => { + if (sortMode === 'code') { + return (a.code ?? '').localeCompare(b.code ?? '', 'nl', { numeric: true }) + } + if (sortMode === 'date') { + return new Date(b.created_at).getTime() - new Date(a.created_at).getTime() + } + // priority: sort by priority asc, then drag-and-drop sort_order within group + return a.priority !== b.priority ? a.priority - b.priority : 0 + }) const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 5 } }), @@ -231,6 +238,19 @@ export function PbiList({ productId, pbis, isDemo }: PbiListProps) { × )} + setSortMode(v as SortMode)}> + + + + + Prioriteit + Code + Datum + +