import { type NotificationItem, parseNotificationEvent } from '$lib/utils/notifications'; export type { NotificationItem }; export function createNotificationStream() { let notifications = $state([]); let unreadCount = $state(0); let eventSource: EventSource | null = null; async function fetchNotifications(): Promise { try { const res = await fetch('/api/notifications?size=10'); if (res.ok) { const data = await res.json(); notifications = data.content ?? []; } } catch (e) { console.error('Failed to fetch notifications', e); } } async function fetchUnreadCount(): Promise { try { const res = await fetch('/api/notifications/unread-count'); if (res.ok) { const data = await res.json(); unreadCount = data.count; } } catch (e) { console.error('Failed to fetch unread count', e); } } async function markRead(notification: NotificationItem): Promise { if (!notification.read) { try { await fetch(`/api/notifications/${notification.id}/read`, { method: 'PATCH' }); notification.read = true; unreadCount = Math.max(0, unreadCount - 1); } catch (e) { console.error('Failed to mark notification as read', e); } } } async function markAllRead(): Promise { try { await fetch('/api/notifications/read-all', { method: 'POST' }); for (const n of notifications) { n.read = true; } unreadCount = 0; } catch (e) { console.error('Failed to mark all notifications as read', e); } } function init(): void { fetchUnreadCount(); eventSource = new EventSource('/api/notifications/stream'); eventSource.addEventListener('notification', (e) => { const notification = parseNotificationEvent(e.data); if (!notification) return; notifications = [notification, ...notifications]; if (!notification.read) unreadCount += 1; }); eventSource.onopen = () => { fetchUnreadCount(); }; eventSource.onerror = () => { // Close on error to avoid repeated reconnect noise eventSource?.close(); }; } function destroy(): void { eventSource?.close(); eventSource = null; } return { get notifications() { return notifications; }, get unreadCount() { return unreadCount; }, fetchNotifications, fetchUnreadCount, markRead, markAllRead, init, destroy }; }