refactor(notifications): fetch from backend API instead of local generation
Rewrite store/notifications.ts to fetch via listNotifications API and remove local generateId-based notification creation. The store now acts as a simple cache with fetch/invalidate methods. Header unread count reads from this API-backed cache.
This commit is contained in:
@@ -10,6 +10,7 @@ import { toApiError } from "@/lib/errors"
|
||||
import { notifyInfo } from "@/lib/toast"
|
||||
import type { Notification } from "@/lib/types"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useNotificationStore } from "@/store/notifications"
|
||||
import { Bell, CheckCheck, Loader2, MessageSquare, ShoppingBag } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
@@ -100,31 +101,37 @@ export default function NotificationsPage() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [loadingError, setLoadingError] = useState<string | null>(null)
|
||||
const [markingAll, setMarkingAll] = useState(false)
|
||||
const setStoreNotifications = useNotificationStore((state) => state.setNotifications)
|
||||
const markStoreAllRead = useNotificationStore((state) => state.markAllRead)
|
||||
|
||||
const loadNotifications = useCallback(async function loadNotifications() {
|
||||
setLoading(true)
|
||||
setLoadingError(null)
|
||||
const loadNotifications = useCallback(
|
||||
async function loadNotifications() {
|
||||
setLoading(true)
|
||||
setLoadingError(null)
|
||||
|
||||
try {
|
||||
const res = await requestWithAuth(() => listNotifications({ offset: 0, limit: 50 }), {
|
||||
onUnauthorized: () => loadNotifications(),
|
||||
})
|
||||
try {
|
||||
const res = await requestWithAuth(() => listNotifications({ offset: 0, limit: 50 }), {
|
||||
onUnauthorized: () => loadNotifications(),
|
||||
})
|
||||
|
||||
if (!mountedRef.current) return
|
||||
if (!mountedRef.current) return
|
||||
|
||||
if (res === null) {
|
||||
if (res === null) {
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
setNotifications(res)
|
||||
setStoreNotifications(res)
|
||||
setLoading(false)
|
||||
return
|
||||
} catch (err: unknown) {
|
||||
if (!mountedRef.current) return
|
||||
setLoading(false)
|
||||
setLoadingError(toApiError(err).msg)
|
||||
}
|
||||
|
||||
setNotifications(res)
|
||||
setLoading(false)
|
||||
} catch (err: unknown) {
|
||||
if (!mountedRef.current) return
|
||||
setLoading(false)
|
||||
setLoadingError(toApiError(err).msg)
|
||||
}
|
||||
}, [])
|
||||
},
|
||||
[setStoreNotifications],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
mountedRef.current = true
|
||||
@@ -134,32 +141,36 @@ export default function NotificationsPage() {
|
||||
}
|
||||
}, [loadNotifications])
|
||||
|
||||
const markAllAsRead = useCallback(async function markAllAsRead() {
|
||||
if (markAllPendingRef.current) return
|
||||
const markAllAsRead = useCallback(
|
||||
async function markAllAsRead() {
|
||||
if (markAllPendingRef.current) return
|
||||
|
||||
markAllPendingRef.current = true
|
||||
setMarkingAll(true)
|
||||
markAllPendingRef.current = true
|
||||
setMarkingAll(true)
|
||||
|
||||
try {
|
||||
const res = await requestWithAuth(() => markAllNotificationsAsRead(), {
|
||||
onUnauthorized: () => markAllAsRead(),
|
||||
})
|
||||
try {
|
||||
const res = await requestWithAuth(() => markAllNotificationsAsRead(), {
|
||||
onUnauthorized: () => markAllAsRead(),
|
||||
})
|
||||
|
||||
if (!mountedRef.current) return
|
||||
if (!mountedRef.current) return
|
||||
|
||||
if (res === null) {
|
||||
return
|
||||
if (res === null) {
|
||||
return
|
||||
}
|
||||
|
||||
setNotifications((prev) => prev.map((n) => (n.read ? n : { ...n, read: true })))
|
||||
markStoreAllRead()
|
||||
} catch (err: unknown) {
|
||||
if (!mountedRef.current) return
|
||||
notifyInfo(toApiError(err).msg)
|
||||
} finally {
|
||||
markAllPendingRef.current = false
|
||||
if (mountedRef.current) setMarkingAll(false)
|
||||
}
|
||||
|
||||
setNotifications((prev) => prev.map((n) => (n.read ? n : { ...n, read: true })))
|
||||
} catch (err: unknown) {
|
||||
if (!mountedRef.current) return
|
||||
notifyInfo(toApiError(err).msg)
|
||||
} finally {
|
||||
markAllPendingRef.current = false
|
||||
if (mountedRef.current) setMarkingAll(false)
|
||||
}
|
||||
}, [])
|
||||
},
|
||||
[markStoreAllRead],
|
||||
)
|
||||
|
||||
const unreadCount = useMemo(
|
||||
() => notifications.filter((notification) => !notification.read).length,
|
||||
|
||||
Reference in New Issue
Block a user