From 07b3cf6822862206469f5524cb766aba775bfb8b Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Fri, 15 May 2026 01:21:31 +0200 Subject: [PATCH] =?UTF-8?q?feat(ST-1369):=20screen-state=20module=20?= =?UTF-8?q?=E2=80=94=20ScreenState=20+=20deriveScreenState()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure afleidingslaag die de verspreide schermstaat-derivatie van de Product Backlog page consolideert tot één testbaar ScreenState-model. Nog geen consumers — die volgen in T-1035/T-1036. Co-Authored-By: Claude Opus 4.7 (1M context) --- stores/product-workspace/screen-state.ts | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 stores/product-workspace/screen-state.ts diff --git a/stores/product-workspace/screen-state.ts b/stores/product-workspace/screen-state.ts new file mode 100644 index 0000000..c32e58b --- /dev/null +++ b/stores/product-workspace/screen-state.ts @@ -0,0 +1,33 @@ +// Expliciete schermstaat voor de Product Backlog page. +// +// Consolideert de vandaag verspreide schermstaat-afleiding (page.tsx, +// sprint-switcher.tsx, new-sprint-trigger.tsx, save-sprint-button.tsx) tot één +// pure, testbare functie. Zie docs/architecture/product-backlog-workflow.md, +// sectie "To-be: expliciete state machine". +// +// PRODUCT_NOT_ACTIVE en DEMO_MODE blijven bewust BUITEN ScreenState — het zijn +// cross-cutting gates, geen knopen in de state machine. + +export type ScreenState = + | { kind: 'NO_SPRINT' } + | { kind: 'DRAFT' } + | { kind: 'ACTIVE'; building: boolean } + | { kind: 'EDITING'; building: boolean } + +export interface ScreenStateInput { + activeSprintItem: { id: string } | null // SSR-prop uit page.tsx + buildingSprintIds: string[] // SSR-prop uit page.tsx + hasPendingDraft: boolean // user-settings store + pendingAdds: string[] // product-workspace store: sprintMembership.pending.adds + pendingRemoves: string[] // product-workspace store: sprintMembership.pending.removes +} + +export function deriveScreenState(i: ScreenStateInput): ScreenState { + if (i.hasPendingDraft) return { kind: 'DRAFT' } // draft wint van alles + if (i.activeSprintItem) { + const building = i.buildingSprintIds.includes(i.activeSprintItem.id) + const dirty = i.pendingAdds.length > 0 || i.pendingRemoves.length > 0 + return dirty ? { kind: 'EDITING', building } : { kind: 'ACTIVE', building } + } + return { kind: 'NO_SPRINT' } +}