feat: ST-201-ST-210 M2 stories, drag-and-drop en Zustand stores

- usePlannerStore met pbiOrder/storyOrder init/reorder/rollback (ST-201)
- useSelectionStore uitgebreid met selectedStoryId en clearSelection (ST-202)
- PBI drag-and-drop binnen prioriteitsgroep via dnd-kit (ST-203)
- PBI slepen over prioriteitsgrens wijzigt priority (ST-204)
- Stories als blokken met prioriteit- en statusbadge (ST-205/ST-206)
- Story drag-and-drop horizontaal binnen en tussen groepen (ST-207)
- Story detail slide-over met bewerkformulier (ST-208)
- Story verwijderen met bevestigingsstap (ST-209)
- Filter op status en prioriteit in rechterpaneel (ST-210)
- Fix: infinite loop in useEffect door stabiele string dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-24 11:46:18 +02:00
parent ffda65490f
commit 4dd62c199c
25 changed files with 1794 additions and 100 deletions

46
stores/planner-store.ts Normal file
View file

@ -0,0 +1,46 @@
import { create } from 'zustand'
interface PlannerStore {
// Order maps: productId → pbiId[]
pbiOrder: Record<string, string[]>
// Order maps: pbiId → storyId[]
storyOrder: Record<string, string[]>
// Priority maps: pbiId → priority
pbiPriority: Record<string, number>
initPbis: (productId: string, ids: string[]) => void
reorderPbis: (productId: string, ids: string[]) => void
rollbackPbis: (productId: string, ids: string[]) => void
updatePbiPriority: (pbiId: string, priority: number) => void
initStories: (pbiId: string, ids: string[]) => void
reorderStories: (pbiId: string, ids: string[]) => void
rollbackStories: (pbiId: string, ids: string[]) => void
}
export const usePlannerStore = create<PlannerStore>((set) => ({
pbiOrder: {},
storyOrder: {},
pbiPriority: {},
initPbis: (productId, ids) =>
set((state) => ({ pbiOrder: { ...state.pbiOrder, [productId]: ids } })),
reorderPbis: (productId, ids) =>
set((state) => ({ pbiOrder: { ...state.pbiOrder, [productId]: ids } })),
rollbackPbis: (productId, ids) =>
set((state) => ({ pbiOrder: { ...state.pbiOrder, [productId]: ids } })),
updatePbiPriority: (pbiId, priority) =>
set((state) => ({ pbiPriority: { ...state.pbiPriority, [pbiId]: priority } })),
initStories: (pbiId, ids) =>
set((state) => ({ storyOrder: { ...state.storyOrder, [pbiId]: ids } })),
reorderStories: (pbiId, ids) =>
set((state) => ({ storyOrder: { ...state.storyOrder, [pbiId]: ids } })),
rollbackStories: (pbiId, ids) =>
set((state) => ({ storyOrder: { ...state.storyOrder, [pbiId]: ids } })),
}))