import React, { useState, useEffect } from 'react'; import axios from 'axios'; import { formatLocalTime } from './utils/timeUtils'; function Notifications() { const [notifications, setNotifications] = useState([]); const [unreadCount, setUnreadCount] = useState(0); const [filter, setFilter] = useState('all'); const [loading, setLoading] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [total, setTotal] = useState(0); const itemsPerPage = 50; useEffect(() => { loadNotifications(); const interval = setInterval(loadNotifications, 10000); // Connect to WebSocket for real-time updates connectWebSocket(); return () => { clearInterval(interval); if (window.notificationWebSocket) { window.notificationWebSocket.close(); } }; }, [filter, currentPage]); const connectWebSocket = () => { try { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const ws = new WebSocket(`${protocol}//${window.location.host}`); ws.onmessage = (event) => { try { const message = JSON.parse(event.data); if (message.type === 'notification') { loadNotifications(); } } catch (error) { console.error('Failed to parse WebSocket message:', error); } }; ws.onclose = () => { setTimeout(connectWebSocket, 5000); }; window.notificationWebSocket = ws; } catch (error) { console.error('Failed to connect WebSocket:', error); } }; const loadNotifications = async () => { setLoading(true); try { const params = { limit: itemsPerPage, offset: (currentPage - 1) * itemsPerPage }; if (filter === 'unread') params.read = 'unread'; if (filter === 'read') params.read = 'read'; const response = await axios.get('/api/notifications', { params }); setNotifications(response.data.notifications); setUnreadCount(response.data.unreadCount); setTotal(response.data.total); } catch (error) { console.error('Failed to load notifications:', error); } finally { setLoading(false); } }; const handleMarkAsRead = async (notificationId) => { try { await axios.put(`/api/notifications/${notificationId}/read`); loadNotifications(); } catch (error) { console.error('Failed to mark notification as read:', error); } }; const handleDelete = async (notificationId) => { try { await axios.delete(`/api/notifications/${notificationId}`); loadNotifications(); } catch (error) { console.error('Failed to delete notification:', error); } }; const handleClearAll = async () => { if (!window.confirm(`Clear all ${filter} notifications?`)) return; try { await axios.post('/api/notifications/clear', { type: filter }); setCurrentPage(1); loadNotifications(); } catch (error) { console.error('Failed to clear notifications:', error); } }; const totalPages = Math.ceil(total / itemsPerPage); return (

📬 Notifications

{notifications.length > 0 && ( )}
{loading ? (

Loading...

) : notifications.length === 0 ? (

No {filter === 'unread' ? 'unread ' : filter === 'read' ? 'read ' : ''}notifications

) : ( <>
{notifications.map((notification) => (

{notification.title}

{notification.message}

{notification.resource_name && ( 📌 {notification.resource_name} )} ⏰ {formatLocalTime(notification.created_at)}
{!notification.read && ( )}
))}
{/* Pagination */} {totalPages > 1 && (
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => ( ))}
)} )}
); } export default Notifications;