Test of SSE-event → store → render-pipeline werkt buiten de Solo Paneel context. Mirrort het patroon van solo-store maar minimaal. - debug-store.ts: kleine Zustand-store met tasks + applyEvent + applyCount/skipCount-tellers - store-panel.tsx: rendert store-state in een tabel met statuskleuring - client.tsx: drie layer-toggles (dispatch / flushSync / startView- Transition) + lift dispatch in onmessage. Zo kunnen we elke combinatie isoleren Bevestigd: alle drie de toggles werken op het bare /debug-realtime endpoint. Volgende laag is Server Action revalidation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
// Mini Zustand-store voor de debug-pagina. Mirrort het patroon van
|
|
// stores/solo-store.ts maar dan minimaal: alleen tasks-record + applyEvent.
|
|
// Doel: testen of de SSE-event → store → component-render keten werkt
|
|
// zonder de complexiteit van de echte Solo Paneel.
|
|
|
|
import { create } from 'zustand'
|
|
|
|
export interface DebugTask {
|
|
id: string
|
|
status: string
|
|
title: string
|
|
story_id: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface DebugRealtimeEvent {
|
|
op: 'I' | 'U' | 'D'
|
|
entity: 'task' | 'story'
|
|
id: string
|
|
story_id?: string
|
|
task_status?: string
|
|
task_title?: string
|
|
debug?: boolean
|
|
emitted_at?: string
|
|
[key: string]: unknown
|
|
}
|
|
|
|
interface DebugStore {
|
|
tasks: Record<string, DebugTask>
|
|
applyCount: number
|
|
skipCount: number
|
|
applyEvent: (event: DebugRealtimeEvent) => void
|
|
reset: () => void
|
|
}
|
|
|
|
export const useDebugStore = create<DebugStore>((set, get) => ({
|
|
tasks: {},
|
|
applyCount: 0,
|
|
skipCount: 0,
|
|
|
|
applyEvent: (event) => {
|
|
if (event.entity !== 'task') {
|
|
set((s) => ({ skipCount: s.skipCount + 1 }))
|
|
return
|
|
}
|
|
if (event.op === 'D') {
|
|
set((s) => {
|
|
const next = { ...s.tasks }
|
|
delete next[event.id]
|
|
return { tasks: next, applyCount: s.applyCount + 1 }
|
|
})
|
|
return
|
|
}
|
|
// INSERT/UPDATE — schrijf altijd, ongeacht of de task al bestond
|
|
set((s) => ({
|
|
tasks: {
|
|
...s.tasks,
|
|
[event.id]: {
|
|
id: event.id,
|
|
status: event.task_status ?? get().tasks[event.id]?.status ?? '?',
|
|
title: event.task_title ?? get().tasks[event.id]?.title ?? '(no title)',
|
|
story_id: event.story_id ?? get().tasks[event.id]?.story_id ?? '?',
|
|
updated_at: new Date().toISOString(),
|
|
},
|
|
},
|
|
applyCount: s.applyCount + 1,
|
|
}))
|
|
},
|
|
|
|
reset: () => set({ tasks: {}, applyCount: 0, skipCount: 0 }),
|
|
}))
|