'use client'; import { createContext, useContext, useEffect, useState } from 'react'; import { RealtimeEvent, RealtimeMessage, REALTIME_EVENTS } from '@/lib/realtime/events'; interface RealtimeContextValue { isConnected: boolean; subscribe: (event: RealtimeEvent, handler: (data: T) => void) => () => void; lastEvent: RealtimeMessage | null; } const RealtimeContext = createContext(null); export function RealtimeProvider({ children }: { children: React.ReactNode }) { const [isConnected, setIsConnected] = useState(false); const [lastEvent, setLastEvent] = useState(null); const [handlers, setHandlers] = useState void>>>(new Map()); useEffect(() => { const eventSource = new EventSource('/api/v1/realtime/events'); eventSource.onopen = () => { setIsConnected(true); }; eventSource.onmessage = (event) => { try { const message = JSON.parse(event.data); if (message.type === 'connected') return; setLastEvent(message); const eventHandlers = handlers.get(message.event); if (eventHandlers) { eventHandlers.forEach(handler => handler(message.data)); } } catch (e) { console.error('Parse error:', e); } }; eventSource.onerror = () => { setIsConnected(false); }; return () => eventSource.close(); }, [handlers]); const subscribe = (event: RealtimeEvent, handler: (data: T) => void) => { setHandlers(prev => { const newHandlers = new Map(prev); if (!newHandlers.has(event)) { newHandlers.set(event, new Set()); } newHandlers.get(event)!.add(handler); return newHandlers; }); return () => { setHandlers(prev => { const newHandlers = new Map(prev); newHandlers.get(event)?.delete(handler); return newHandlers; }); }; }; return ( {children} ); } export function useRealtimeContext() { const context = useContext(RealtimeContext); if (!context) { throw new Error('useRealtimeContext must be used within RealtimeProvider'); } return context; }