import React, { memo, useState, useEffect, useMemo } from 'react'; import Link from 'next/link'; import { Bell, ExternalLink, AlertCircle, LogIn, Kanban, MessageSquare, Mail, Calendar, Check, X, Filter, ChevronDown, ChevronUp, RefreshCw } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { useNotifications } from '@/hooks/use-notifications'; import { Button } from '@/components/ui/button'; import { useSession, signIn } from 'next-auth/react'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, DropdownMenuSeparator, DropdownMenuLabel, } from '@/components/ui/dropdown-menu'; import { formatDistanceToNow } from 'date-fns'; import { SafeHTML } from '@/components/safe-html'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; interface NotificationBadgeProps { className?: string; } type SortOption = 'newest' | 'oldest'; type FilterOption = 'all' | 'email' | 'rocketchat' | 'leantime' | 'calendar'; // Use React.memo to prevent unnecessary re-renders export const NotificationBadge = memo(function NotificationBadge({ className }: NotificationBadgeProps) { const { data: session, status } = useSession(); const { notifications, notificationCount, fetchNotifications, markAsRead, markAllAsRead, loading, error } = useNotifications(); const hasUnread = notificationCount.unread > 0; const [isOpen, setIsOpen] = useState(false); const [sortBy, setSortBy] = useState('newest'); const [filterBy, setFilterBy] = useState('all'); const [displayLimit, setDisplayLimit] = useState(10); const [hasMarkedAsRead, setHasMarkedAsRead] = useState(false); // When dropdown opens, mark all as read and fetch notifications useEffect(() => { if (isOpen && status === 'authenticated') { // Mark all as read when opening (only once per open) if (!hasMarkedAsRead) { markAllAsRead(); setHasMarkedAsRead(true); } fetchNotifications(1, 50, filterBy === 'all' ? undefined : filterBy); } else if (!isOpen) { // Reset flag when dropdown closes setHasMarkedAsRead(false); } }, [isOpen, status, filterBy, fetchNotifications, markAllAsRead, hasMarkedAsRead]); // Sort and filter notifications const sortedAndFilteredNotifications = useMemo(() => { let filtered = notifications; // Filter by source if (filterBy !== 'all') { filtered = filtered.filter(n => n.source === filterBy); } // Sort const sorted = [...filtered].sort((a, b) => { const dateA = new Date(a.timestamp).getTime(); const dateB = new Date(b.timestamp).getTime(); return sortBy === 'newest' ? dateB - dateA : dateA - dateB; }); return sorted.slice(0, displayLimit); }, [notifications, filterBy, sortBy, displayLimit]); const handleMarkAsRead = async (notificationId: string, e: React.MouseEvent) => { e.stopPropagation(); await markAsRead(notificationId); }; const handleOpenChange = (open: boolean) => { setIsOpen(open); }; const handleLoadMore = () => { setDisplayLimit(prev => prev + 10); }; const hasMore = notifications.length > displayLimit; // Special case for auth error const isAuthError = error?.includes('Not authenticated') || error?.includes('401'); return (
{/* Header */}

Notifications

{/* Filters and Sort */}
{/* Notifications List */}
{loading ? (

Chargement...

) : isAuthError ? (

Authentification requise

) : error ? (

{error}

) : sortedAndFilteredNotifications.length === 0 ? (

Aucune notification

) : ( <> {sortedAndFilteredNotifications.map((notification) => ( { e.preventDefault(); // Si on clique sur la notification elle-même et qu'elle a un lien, ouvrir et marquer comme lu if (notification.link && !notification.isRead) { await markAsRead(notification.id); window.location.href = notification.link; setIsOpen(false); } }} >
{!notification.isRead && notification.source === 'rocketchat' && ( )} {notification.title} {!notification.isRead && notification.source !== 'rocketchat' && ( New )} {notification.source === 'leantime' && ( Agilité )} {notification.source === 'rocketchat' && ( Parole )} {notification.source === 'email' && ( Courrier )} {notification.source === 'calendar' && ( Agenda )}
{formatDistanceToNow(new Date(notification.timestamp), { addSuffix: true })}
{!notification.isRead && ( )} {notification.link && ( { // Marquer comme lu automatiquement quand on ouvre if (!notification.isRead) { await markAsRead(notification.id); } setIsOpen(false); }} > )}
))} {hasMore && (
)} )}
); });