/** * useNotifications * * Source unique des notifications : la cloche, la page et tout futur écran * lisent le même état. */ 'use client'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { getUnreadNotificationCount, listNotifications, markAllNotificationsAsRead, markNotificationAsRead, } from '@/lib/api'; import type { NotificationResponse } from '@/types/api'; interface UseNotificationsOptions { /** Ne remonter que les non-lues. Par défaut, tout, du plus récent au plus ancien. */ unreadOnly?: boolean; /** Nombre maximum de notifications chargées. */ limit?: number; /** Intervalle de rafraîchissement, en millisecondes. */ refetchInterval?: number; } export function useNotifications(options: UseNotificationsOptions = {}) { const { unreadOnly = false, limit = 10, refetchInterval = 30000 } = options; const queryClient = useQueryClient(); const list = useQuery({ queryKey: ['notifications', { unreadOnly, limit }], queryFn: () => listNotifications(unreadOnly ? { isRead: false, limit } : { limit }), refetchInterval, refetchOnWindowFocus: true, }); /** * Le compteur vient du serveur. * * Il etait auparavant calcule sur la page chargee — dix elements — et ne * pouvait donc jamais depasser dix, quel que soit le nombre reel de non-lues. */ const count = useQuery({ queryKey: ['notifications', 'unread-count'], queryFn: getUnreadNotificationCount, refetchInterval, refetchOnWindowFocus: true, }); const invalidate = () => queryClient.invalidateQueries({ queryKey: ['notifications'] }); const markAsReadMutation = useMutation({ mutationFn: markNotificationAsRead, onSuccess: invalidate, }); const markAllAsReadMutation = useMutation({ mutationFn: markAllNotificationsAsRead, onSuccess: invalidate, }); const notifications: NotificationResponse[] = list.data?.notifications ?? []; return { notifications, total: list.data?.total ?? notifications.length, unreadCount: count.data?.count ?? 0, isLoading: list.isPending, isError: list.isError, refetch: list.refetch, markAsRead: markAsReadMutation.mutate, markAllAsRead: markAllAsReadMutation.mutate, isMarkingAll: markAllAsReadMutation.isPending, }; }