Story 3 verplaatst alle UI-consumers van de oude vier stores
(useBacklogStore/usePlannerStore/useSelectionStore/useProductStore) naar de
nieuwe product-workspace-store. De oude stores blijven nog bestaan voor
hydration-wrapper en realtime-hook (dual-dispatch); Story 8 ruimt ze op.
- T-848 backlog-split-pane.tsx: leest activePbiId/activeStoryId uit
context-slice (primitives, geen useShallow nodig).
- T-849 pbi-list.tsx: selectVisiblePbis(useShallow); DnD via
applyOptimisticMutation('pbi-order' + optionele 'entity-patch' bij
cross-priority drag), met settle/rollback per server-result.
- T-850 story-panel.tsx: selectStoriesForActivePbi(useShallow); DnD via
applyOptimisticMutation('story-order' + entity-patch bij priority change).
- T-851 task-panel.tsx: selectTasksForActiveStory(useShallow); DnD via
applyOptimisticMutation('task-order'); detail-view (ensureTaskLoaded +
isDetail) zit in de task-dialog (apart component, niet in deze lijst).
- T-852 start-sprint-button.tsx: selectActivePbi + selectStoriesForActivePbi
voor free-story count.
- T-853 set-current-product.tsx: alleen workspace-store.setActiveProduct
(oude useProductStore-import verwijderd).
- T-854 G1/G2-audit: alle nieuwe selectors gebruiken module-level EMPTY
refs (G1) en useShallow voor lijsten (G2). Geen 'Maximum update depth'-
warnings tijdens npm test.
- T-855 tests bijgewerkt: backlog-split-pane.test, task-panel.test,
integration.test gebruiken nu setState op workspace-store (helpers
resetWorkspace/setActiveStoryAndTasks/selectPbi/selectStory).
Verify: lint+typecheck clean, 636/636 tests groen. UI-consumers van
oude stores zijn nu nul (uitgezonderd dual-dispatch in hydration-wrapper en
realtime-hook + dev-fingerprint-helper, die in Story 8/T-873/T-878 verdwijnen).
Refs: PBI-74, ST-1320, T-848..T-855
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useProductWorkspaceStore } from '@/stores/product-workspace/store'
|
|
import { SplitPane, type SplitPaneProps } from '@/components/split-pane/split-pane'
|
|
|
|
type Props = Omit<SplitPaneProps, 'activeTab' | 'onActiveTabChange'>
|
|
|
|
// PBI-74 / T-848: leest active PBI/story-ids uit workspace-store. Primitives,
|
|
// dus geen useShallow nodig.
|
|
export function BacklogSplitPane(props: Props) {
|
|
const selectedPbiId = useProductWorkspaceStore((s) => s.context.activePbiId)
|
|
const selectedStoryId = useProductWorkspaceStore((s) => s.context.activeStoryId)
|
|
const [activeTab, setActiveTab] = useState(0)
|
|
|
|
// React-recommended "derived state from props" pattern: update state during render
|
|
// instead of useEffect to avoid cascading renders.
|
|
const [prevPbiId, setPrevPbiId] = useState(selectedPbiId)
|
|
const [prevStoryId, setPrevStoryId] = useState(selectedStoryId)
|
|
|
|
if (selectedStoryId !== prevStoryId) {
|
|
setPrevStoryId(selectedStoryId)
|
|
if (selectedStoryId) setActiveTab(2)
|
|
}
|
|
if (selectedPbiId !== prevPbiId) {
|
|
setPrevPbiId(selectedPbiId)
|
|
if (selectedPbiId && !selectedStoryId) setActiveTab(1)
|
|
}
|
|
|
|
return (
|
|
<SplitPane
|
|
{...props}
|
|
activeTab={activeTab}
|
|
onActiveTabChange={setActiveTab}
|
|
/>
|
|
)
|
|
}
|