From bb875a5395ec99d1b4c66f46daeb10a7d77470d8 Mon Sep 17 00:00:00 2001 From: joshna jojo Date: Sat, 30 May 2026 19:26:23 +0530 Subject: [PATCH] fix(notification-bell): improve error handling for notification requests --- src/components/NotificationBell.tsx | 46 +++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/components/NotificationBell.tsx b/src/components/NotificationBell.tsx index b93f53534..79f7a8719 100644 --- a/src/components/NotificationBell.tsx +++ b/src/components/NotificationBell.tsx @@ -14,14 +14,26 @@ export default function NotificationBell() { const [notifications, setNotifications] = useState([]); const [unreadCount, setUnreadCount] = useState(0); const [open, setOpen] = useState(false); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); const dropdownRef = useRef(null); const fetchNotifications = useCallback(async () => { + setLoading(true); + setError(null); + try { const res = await fetch("/api/notifications"); - if (!res.ok) return; + if (!res.ok) { + throw new Error("Failed to load notifications"); + } const data = await res.json(); + + if (!data || !Array.isArray(data.notifications)) { + throw new Error("Invalid notifications response"); + } + setNotifications(data.notifications ?? []); const count = data.unreadCount ?? 0; setUnreadCount(count); @@ -29,7 +41,9 @@ export default function NotificationBell() { localStorage.setItem("devtrack:unread-notification-count", count.toString()); } } catch { - // silent fail + setError("Failed to load notifications. Please try again later."); + } finally { + setLoading(false); } }, []); @@ -74,7 +88,9 @@ export default function NotificationBell() { const next = !prev; if (!prev && unreadCount > 0) { - fetch("/api/notifications", { method: "PATCH" }).catch(() => {}); + const previousUnreadCount = unreadCount; + const previousNotifications = notifications; + setUnreadCount(0); if (typeof window !== "undefined") { localStorage.setItem("devtrack:unread-notification-count", "0"); @@ -82,11 +98,23 @@ export default function NotificationBell() { setNotifications((prev) => prev.map((n) => ({ ...n, read: true })) ); + + fetch("/api/notifications", { method: "PATCH" }).catch(() => { + setUnreadCount(previousUnreadCount); + setNotifications(previousNotifications); + setError("Failed to update notifications. Please try again later."); + if (typeof window !== "undefined") { + localStorage.setItem( + "devtrack:unread-notification-count", + previousUnreadCount.toString() + ); + } + }); } return next; }); - }, [unreadCount]); + }, [notifications, unreadCount]); function timeAgo(iso: string): string { const mins = Math.floor( @@ -172,7 +200,15 @@ export default function NotificationBell() {
    - {notifications.length === 0 ? ( + {loading ? ( +
  • + Loading notifications… +
  • + ) : error ? ( +
  • + {error} +
  • + ) : notifications.length === 0 ? (
  • No notifications yet