From 697075eea2ccf3d715e4d90c8a293a15d49ae825 Mon Sep 17 00:00:00 2001 From: matthieu Date: Sun, 15 Mar 2026 19:47:33 +0100 Subject: [PATCH] feat(frontend) : add useNotifications composable with polling --- frontend/composables/useNotifications.ts | 69 ++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 frontend/composables/useNotifications.ts 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, + } +}