70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
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<number>('notification-unread-count', () => 0)
|
|
const notifications = useState<Notification[]>('notification-list', () => [])
|
|
const isLoading = useState<boolean>('notification-loading', () => false)
|
|
|
|
const service = useNotificationService()
|
|
let pollTimer: ReturnType<typeof setInterval> | null = null
|
|
|
|
async function fetchUnreadCount(): Promise<void> {
|
|
try {
|
|
unreadCount.value = await service.getUnreadCount()
|
|
} catch {
|
|
// Silently ignore polling errors
|
|
}
|
|
}
|
|
|
|
async function fetchNotifications(): Promise<void> {
|
|
isLoading.value = true
|
|
try {
|
|
notifications.value = await service.getAll()
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
async function markAsRead(id: number): Promise<void> {
|
|
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<void> {
|
|
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,
|
|
}
|
|
}
|