// NotificationsView Component // Full page view displaying all notifications with filtering and management options const { useState, useEffect, useCallback } = React; function NotificationsView({ onViewChange, onViewProject }) { const { notifications, unreadCount, loading, fetchNotifications, markAsRead, markAllAsRead, deleteNotification } = useNotifications(); const [filter, setFilter] = useState('all'); // 'all', 'unread', 'read' const [loadingMore, setLoadingMore] = useState(false); const [limit, setLimit] = useState(50); // Fetch all notifications on mount useEffect(() => { fetchNotifications(limit); }, [fetchNotifications, limit]); const handleLoadMore = async () => { setLoadingMore(true); const newLimit = limit + 50; setLimit(newLimit); await fetchNotifications(newLimit); setLoadingMore(false); }; const handleNotificationClick = async (notification) => { // Mark as read if unread if (!notification.is_read) { await markAsRead(notification.id); } // Navigate to the relevant item if (notification.data?.project_id) { const notificationType = notification.type; const isCommentNotification = ['comment_added', 'project_comment_added', 'reaction_added'].includes(notificationType); if (isCommentNotification && notification.data?.comment_id && onViewProject) { // For comment notifications, go to project detail onViewProject(notification.data.project_id, notification.data.comment_id, notification.data.step_id); } else if (onViewChange) { // For other notifications, go to projects view onViewChange('projects'); } } }; const handleDelete = async (e, notificationId) => { e.stopPropagation(); await deleteNotification(notificationId); }; const handleMarkAsRead = async (e, notificationId) => { e.stopPropagation(); await markAsRead(notificationId); }; const formatTime = (dateString) => { if (!dateString) return ''; const date = new Date(dateString); const now = new Date(); const diffMs = now - date; const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMs / 3600000); const diffDays = Math.floor(diffMs / 86400000); if (diffMins < 1) return 'Adesso'; if (diffMins < 60) return `${diffMins} minuti fa`; if (diffHours < 24) return `${diffHours} ore fa`; if (diffDays < 7) return `${diffDays} giorni fa`; return date.toLocaleDateString('it-IT', { day: '2-digit', month: 'long', year: 'numeric' }); }; const getNotificationIcon = (type) => { switch (type) { case 'project_status_changed': return (
); case 'project_assigned': case 'project_unassigned': return (
); case 'comment_added': case 'project_comment_added': return (
); case 'reaction_added': return (
); case 'step_status_changed': return (
); default: return (
); } }; // Filter notifications based on selected filter const filteredNotifications = notifications.filter(n => { if (filter === 'unread') return !n.is_read; if (filter === 'read') return n.is_read; return true; }); return (
{/* Header */}

Notifiche

{unreadCount > 0 ? `${unreadCount} notifiche non lette` : 'Tutte le notifiche sono state lette' }

{unreadCount > 0 && ( )}
{/* Filter Tabs */}
{/* Notifications List */}
{loading && notifications.length === 0 ? (

Caricamento notifiche...

) : filteredNotifications.length === 0 ? (

{filter === 'unread' ? 'Nessuna notifica non letta' : filter === 'read' ? 'Nessuna notifica letta' : 'Nessuna notifica' }

) : (
{filteredNotifications.map((notification) => (
handleNotificationClick(notification)} className={`p-4 flex items-start gap-4 cursor-pointer hover:bg-slate-50 transition-colors ${ !notification.is_read ? 'bg-blue-50/30' : '' }`} > {/* Icon */} {getNotificationIcon(notification.type)} {/* Content */}

{notification.title}

{notification.message}

{formatTime(notification.created_at)}

{/* Actions */}
{!notification.is_read && ( )} {!notification.is_read && ( )}
))}
)} {/* Load More */} {filteredNotifications.length > 0 && filteredNotifications.length >= limit && (
)}
); } // Export to global scope window.NotificationsView = NotificationsView;