import React, { memo, useState, useEffect } from 'react'; import Link from 'next/link'; import { Bell, Check, ExternalLink, AlertCircle, LogIn, Kanban } 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, } from '@/components/ui/dropdown-menu'; import { formatDistanceToNow } from 'date-fns'; import { SafeHTML } from '@/components/safe-html'; interface NotificationBadgeProps { className?: string; } // Use React.memo to prevent unnecessary re-renders export const NotificationBadge = memo(function NotificationBadge({ className }: NotificationBadgeProps) { const { data: session, status } = useSession(); const { notifications, notificationCount, markAsRead, markAllAsRead, fetchNotifications, loading, error } = useNotifications(); const hasUnread = notificationCount.unread > 0; const [isOpen, setIsOpen] = useState(false); const [manualFetchAttempted, setManualFetchAttempted] = useState(false); console.log('[NOTIFICATION_BADGE] Auth status:', status); console.log('[NOTIFICATION_BADGE] Session:', session ? 'exists' : 'null'); console.log('[NOTIFICATION_BADGE] Current notification count:', notificationCount); console.log('[NOTIFICATION_BADGE] Current notifications:', notifications.length > 0 ? `${notifications.length} loaded` : 'none loaded'); console.log('[NOTIFICATION_BADGE] Loading state:', loading); console.log('[NOTIFICATION_BADGE] Error state:', error); // Manual fetch function with error handling const manualFetch = async () => { console.log('[NOTIFICATION_BADGE] Manual fetch initiated'); setManualFetchAttempted(true); try { // Direct fetch to debug const response = await fetch('/api/notifications', { credentials: 'include' }); console.log('[NOTIFICATION_BADGE] Manual fetch response:', response.status); if (!response.ok) { console.error('[NOTIFICATION_BADGE] Manual fetch failed:', response.status, await response.text()); } else { const data = await response.json(); console.log('[NOTIFICATION_BADGE] Manual fetch success:', data); } } catch (err) { console.error('[NOTIFICATION_BADGE] Manual fetch error:', err); } // Then try the normal way fetchNotifications(1, 10); }; // Fetch notifications when dropdown is opened useEffect(() => { if (isOpen && status === 'authenticated') { console.log('[NOTIFICATION_BADGE] Dropdown opened, fetching notifications'); manualFetch(); } }, [isOpen, status]); const handleMarkAsRead = async (notificationId: string) => { await markAsRead(notificationId); }; const handleMarkAllAsRead = async () => { await markAllAsRead(); setIsOpen(false); }; // Force fetch when component mounts useEffect(() => { if (status === 'authenticated') { console.log('[NOTIFICATION_BADGE] Component mounted and authenticated, fetching initial notifications'); manualFetch(); } }, [status]); // Take the latest 10 notifications for the dropdown const recentNotifications = notifications.slice(0, 10); const handleOpenChange = (open: boolean) => { setIsOpen(open); if (open && status === 'authenticated') { // Fetch fresh notifications when dropdown opens console.log('[NOTIFICATION_BADGE] Dropdown opened via handleOpenChange, fetching notifications'); manualFetch(); } }; // Special case for auth error const isAuthError = error?.includes('Not authenticated') || error?.includes('401'); return (
Loading notifications...
Authentication required
{error}
No notifications found
No notifications
{formatDistanceToNow(new Date(notification.timestamp), { addSuffix: true })} {notification.source && ( • {notification.source === 'leantime' ? 'Leantime' : notification.source} )}