From 77ffdefba4d28967bf442ad58359a00bad7c1780 Mon Sep 17 00:00:00 2001 From: alma Date: Tue, 6 Jan 2026 16:31:39 +0100 Subject: [PATCH] Refactor Notification --- hooks/use-notifications.ts | 55 ++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/hooks/use-notifications.ts b/hooks/use-notifications.ts index a5900265..1eb21fbe 100644 --- a/hooks/use-notifications.ts +++ b/hooks/use-notifications.ts @@ -51,9 +51,15 @@ export function useNotifications() { setError(null); lastFetchTimeRef.current = now; - console.log('[useNotifications] Fetching notification count'); - const response = await fetch('/api/notifications/count', { - credentials: 'include' // Ensure cookies are sent with the request + console.log('[useNotifications] Fetching notification count', { force }); + // Add cache-busting parameter when force is true to ensure fresh data + const url = force + ? `/api/notifications/count?_t=${Date.now()}` + : '/api/notifications/count'; + + const response = await fetch(url, { + credentials: 'include', // Ensure cookies are sent with the request + cache: force ? 'no-store' : 'default', // Disable cache when forcing refresh }); if (!response.ok) { @@ -68,6 +74,7 @@ export function useNotifications() { const data = await response.json(); if (isMountedRef.current) { + console.log('[useNotifications] Received notification count:', data); setNotificationCount(data); } } catch (err) { @@ -149,7 +156,7 @@ export function useNotifications() { return false; } - // Update local state + // Update local state optimistically setNotifications(prev => prev.map(notification => notification.id === notificationId @@ -158,15 +165,25 @@ export function useNotifications() { ) ); - // Refresh notification count - debouncedFetchCount(true); + // Update count optimistically (decrement unread count) + setNotificationCount(prev => ({ + ...prev, + unread: Math.max(0, prev.unread - 1), // Ensure it doesn't go below 0 + total: prev.total, // Keep total the same + })); + + // Immediately refresh notification count (not debounced) to get accurate data + // Use a small delay to ensure server cache is invalidated + setTimeout(() => { + fetchNotificationCount(true); + }, 100); return true; } catch (err) { console.error('Error marking notification as read:', err); return false; } - }, [session?.user, debouncedFetchCount]); + }, [session?.user, fetchNotificationCount]); // Mark all notifications as read const markAllAsRead = useCallback(async () => { @@ -191,20 +208,36 @@ export function useNotifications() { return false; } - // Update local state + // Update local state optimistically setNotifications(prev => prev.map(notification => ({ ...notification, isRead: true })) ); - // Refresh notification count - debouncedFetchCount(true); + // Update count optimistically (set unread to 0 immediately for instant UI feedback) + setNotificationCount(prev => ({ + ...prev, + unread: 0, + total: prev.total, // Keep total the same + sources: Object.fromEntries( + Object.entries(prev.sources).map(([key, value]) => [ + key, + { ...value, unread: 0 } + ]) + ), + })); + + // Immediately refresh notification count (not debounced) to get accurate data from server + // Use a small delay to ensure server cache is invalidated + setTimeout(() => { + fetchNotificationCount(true); + }, 200); return true; } catch (err) { console.error('Error marking all notifications as read:', err); return false; } - }, [session?.user, debouncedFetchCount]); + }, [session?.user, fetchNotificationCount]); // Start polling for notification count const startPolling = useCallback(() => {