diff --git a/frontend/composables/useNotifications.ts b/frontend/composables/useNotifications.ts new file mode 100644 index 0000000..e081b67 --- /dev/null +++ b/frontend/composables/useNotifications.ts @@ -0,0 +1,69 @@ +import type { Notification } from '~/services/dto/notification' +import { useNotificationService } from '~/services/notifications' + +const POLL_INTERVAL = 2 * 60 * 1000 // 2 minutes + +export function useNotifications() { + const unreadCount = useState('notification-unread-count', () => 0) + const notifications = useState('notification-list', () => []) + const isLoading = useState('notification-loading', () => false) + + const service = useNotificationService() + let pollTimer: ReturnType | null = null + + async function fetchUnreadCount(): Promise { + try { + unreadCount.value = await service.getUnreadCount() + } catch { + // Silently ignore polling errors + } + } + + async function fetchNotifications(): Promise { + isLoading.value = true + try { + notifications.value = await service.getAll() + } finally { + isLoading.value = false + } + } + + async function markAsRead(id: number): Promise { + await service.markAsRead(id) + const notif = notifications.value.find(n => n.id === id) + if (notif && !notif.isRead) { + notif.isRead = true + unreadCount.value = Math.max(0, unreadCount.value - 1) + } + } + + async function markAllAsRead(): Promise { + await service.markAllAsRead() + notifications.value.forEach(n => n.isRead = true) + unreadCount.value = 0 + } + + function startPolling(): void { + fetchUnreadCount() + pollTimer = setInterval(fetchUnreadCount, POLL_INTERVAL) + } + + function stopPolling(): void { + if (pollTimer) { + clearInterval(pollTimer) + pollTimer = null + } + } + + return { + unreadCount, + notifications, + isLoading, + fetchNotifications, + fetchUnreadCount, + markAsRead, + markAllAsRead, + startPolling, + stopPolling, + } +}