import { useEffect, useRef, useState } from "react"; import { useSyncExternalStore } from "react"; import { Bell, Trash2 } from "lucide-react"; import { clearAll, dismiss, getNotifications, getUnreadCount, markAllRead, subscribe, } from "../lib/notifications"; import { LEVEL_STYLE } from "./Toaster"; function relTime(ts: number): string { const s = Math.round((Date.now() - ts) / 1000); if (s < 60) return "just now"; const m = Math.round(s / 60); if (m < 60) return `${m}m ago`; const h = Math.round(m / 60); if (h < 24) return `${h}h ago`; const d = Math.round(h / 24); return `${d}d ago`; } export default function NotificationCenter() { const notifications = useSyncExternalStore(subscribe, getNotifications, getNotifications); const unread = useSyncExternalStore(subscribe, getUnreadCount, getUnreadCount); const [open, setOpen] = useState(false); const wrap = useRef(null); // Opening the center marks everything read. useEffect(() => { if (open) markAllRead(); }, [open, notifications.length]); return (
{open && ( <>
setOpen(false)} />
Notifications
{notifications.length > 0 && ( )}
{notifications.length === 0 ? (
No notifications yet.
) : ( notifications.map((n) => { const { icon: Icon, color } = LEVEL_STYLE[n.level]; const needsAction = n.requiresInteraction && !n.dismissed; return (
{n.title &&
{n.title}
}
{n.message}
{relTime(n.ts)} {needsAction && ( Action needed )}
{n.action && !n.dismissed && ( )}
); }) )}
)}
); }