Scrum4Me/lib/realtime/use-sprint-workspace-resync.ts
Madhura68 307b998871 feat(PBI-74): sprint hydratie + realtime SSE (Story 9 / T-880)
- app/api/realtime/sprint/route.ts: SSE-stream LISTEN/NOTIFY op
  scrum4me_changes, filter entity ∈ {sprint, story, task} per product_id;
  ready-event, heartbeat 25s, hard-close 240s
- lib/realtime/use-sprint-realtime.ts: client-hook met backoff-reconnect;
  ready-cycle telt; geen close op hidden; setRealtimeStatus
- lib/realtime/use-sprint-workspace-resync.ts: visibility + online triggers
  resyncActiveScopes('visible' | 'reconnect')
- components/sprint/sprint-hydration-wrapper.tsx: hydrateSnapshot via
  useEffect met fingerprint-check; mount realtime + resync
- app/(app)/products/[id]/sprint/[sprintId]/page.tsx: wrap SprintBoardClient
  in SprintHydrationWrapper; bouw SprintWorkspaceTask-shape voor
  tasksByStoryWorkspace en SprintHydrationData voor de wrapper

Schaduw-fase: useSprintStore blijft parallel werken in board components
totdat T-881 die migreert en T-883 de oude store opruimt.
2026-05-10 06:37:59 +02:00

36 lines
1.1 KiB
TypeScript

'use client'
// PBI-74 / Story 9 / T-880: useSprintWorkspaceResync.
//
// Trigger resyncActiveScopes bij:
// - hidden→visible (browser-throttled events kunnen gemist zijn)
// - online (netwerk hersteld na disconnect)
//
// Hoort gemount te worden naast useSprintRealtime in SprintHydrationWrapper.
import { useEffect } from 'react'
import { useSprintWorkspaceStore } from '@/stores/sprint-workspace/store'
export function useSprintWorkspaceResync(): void {
useEffect(() => {
if (typeof document === 'undefined') return
const onVisibility = () => {
if (document.visibilityState === 'visible') {
void useSprintWorkspaceStore.getState().resyncActiveScopes('visible')
}
}
const onOnline = () => {
void useSprintWorkspaceStore.getState().resyncActiveScopes('reconnect')
}
document.addEventListener('visibilitychange', onVisibility)
window.addEventListener('online', onOnline)
return () => {
document.removeEventListener('visibilitychange', onVisibility)
window.removeEventListener('online', onOnline)
}
}, [])
}