import { useState, useEffect } from "react"; import axios from "axios"; import { Link, router, usePage } from "@inertiajs/react"; import { Bell, CheckCheck } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/Components/ui/dropdown-menu"; import { Button } from "@/Components/ui/button"; import { ScrollArea } from "@/Components/ui/scroll-area"; import { formatDate } from "@/lib/date"; import { cn } from "@/lib/utils"; interface NotificationData { message: string; link?: string; action?: string; [key: string]: any; } interface Notification { id: string; type: string; data: NotificationData; read_at: string | null; created_at: string; } interface NotificationsProp { latest: Notification[]; unread_count: number; } export default function NotificationDropdown() { const { notifications } = usePage<{ notifications?: NotificationsProp }>().props; if (!notifications) return null; // 使用整體的 notifications 物件作為初始狀態,方便後續更新 const [data, setData] = useState(notifications); const { latest, unread_count } = data; const [isOpen, setIsOpen] = useState(false); // 輪詢機制 useEffect(() => { const intervalId = setInterval(() => { axios.get(route('notifications.check')) .then(response => { setData(response.data); }) .catch(error => { console.error("Failed to fetch notifications:", error); }); }, 30000); // 30 秒 return () => clearInterval(intervalId); }, []); // 當 Inertia props 更新時(例如頁面跳轉),同步更新本地狀態 useEffect(() => { if (notifications) { setData(notifications); } }, [notifications]); const handleMarkAllAsRead = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); // 樂觀更新 (Optimistic Update) setData(prev => ({ ...prev, unread_count: 0, latest: prev.latest.map(n => ({ ...n, read_at: new Date().toISOString() })) })); router.post(route('notifications.read-all'), {}, { preserveScroll: true, preserveState: true, onSuccess: () => { // 成功後重新整理一次確保數據正確 (可選) } }); }; const handleNotificationClick = (notification: Notification) => { if (!notification.read_at) { // 樂觀更新 setData(prev => ({ ...prev, unread_count: Math.max(0, prev.unread_count - 1), latest: prev.latest.map(n => n.id === notification.id ? { ...n, read_at: new Date().toISOString() } : n ) })); router.post(route('notifications.read', { id: notification.id })); } if (notification.data.link) { router.visit(notification.data.link); } setIsOpen(false); }; return (

通知中心

{unread_count > 0 && ( )}
{latest.length === 0 ? (

目前沒有新通知

) : (
{latest.map((notification) => ( ))}
)}
查看所有通知
); }