diff --git a/components/notification-badge.tsx b/components/notification-badge.tsx index 61969dcc..7a180260 100644 --- a/components/notification-badge.tsx +++ b/components/notification-badge.tsx @@ -1,9 +1,10 @@ import React, { memo, useState, useEffect } from 'react'; import Link from 'next/link'; -import { Bell, Check, ExternalLink, AlertCircle } from 'lucide-react'; +import { Bell, Check, ExternalLink, AlertCircle, LogIn } 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, @@ -19,22 +20,53 @@ interface NotificationBadgeProps { // 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) { + if (isOpen && status === 'authenticated') { console.log('[NOTIFICATION_BADGE] Dropdown opened, fetching notifications'); - fetchNotifications(1, 10); + manualFetch(); } - }, [isOpen, fetchNotifications]); + }, [isOpen, status]); const handleMarkAsRead = async (notificationId: string) => { await markAsRead(notificationId); @@ -47,22 +79,27 @@ export const NotificationBadge = memo(function NotificationBadge({ className }: // Force fetch when component mounts useEffect(() => { - console.log('[NOTIFICATION_BADGE] Component mounted, fetching initial notifications'); - fetchNotifications(1, 10); - }, [fetchNotifications]); + 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) { + if (open && status === 'authenticated') { // Fetch fresh notifications when dropdown opens console.log('[NOTIFICATION_BADGE] Dropdown opened via handleOpenChange, fetching notifications'); - fetchNotifications(1, 10); + manualFetch(); } }; + // Special case for auth error + const isAuthError = error?.includes('Not authenticated') || error?.includes('401'); + return (
@@ -98,14 +135,29 @@ export const NotificationBadge = memo(function NotificationBadge({ className }:

Loading notifications...

+ ) : isAuthError ? ( +
+ +

Authentication required

+ +
) : error ? (

{error}

-
+ ) : notifications.length === 0 && manualFetchAttempted ? ( +
+

No notifications found

+ +
) : notifications.length === 0 ? (

No notifications

diff --git a/hooks/use-notifications.ts b/hooks/use-notifications.ts index 7cc93f02..a5900265 100644 --- a/hooks/use-notifications.ts +++ b/hooks/use-notifications.ts @@ -51,12 +51,18 @@ export function useNotifications() { setError(null); lastFetchTimeRef.current = now; - const response = await fetch('/api/notifications/count'); + console.log('[useNotifications] Fetching notification count'); + const response = await fetch('/api/notifications/count', { + credentials: 'include' // Ensure cookies are sent with the request + }); if (!response.ok) { - const errorData = await response.json(); - console.error('Failed to fetch notification count:', errorData); - setError(errorData.error || 'Failed to fetch notification count'); + const errorText = await response.text(); + console.error('Failed to fetch notification count:', { + status: response.status, + body: errorText + }); + setError(errorText || 'Failed to fetch notification count'); return; } @@ -91,12 +97,18 @@ export function useNotifications() { lastFetchTimeRef.current = now; try { - const response = await fetch(`/api/notifications?page=${page}&limit=${limit}`); + console.log('[useNotifications] Fetching notifications', { page, limit }); + const response = await fetch(`/api/notifications?page=${page}&limit=${limit}`, { + credentials: 'include' // Ensure cookies are sent with the request + }); if (!response.ok) { - const errorData = await response.json(); - console.error('Failed to fetch notifications:', errorData); - setError(errorData.error || 'Failed to fetch notifications'); + const errorText = await response.text(); + console.error('Failed to fetch notifications:', { + status: response.status, + body: errorText + }); + setError(errorText || 'Failed to fetch notifications'); return; } @@ -119,16 +131,21 @@ export function useNotifications() { if (!session?.user) return false; try { + console.log('[useNotifications] Marking notification as read:', notificationId); const response = await fetch(`/api/notifications/${notificationId}/read`, { method: 'POST', headers: { 'Content-Type': 'application/json' - } + }, + credentials: 'include' // Ensure cookies are sent with the request }); if (!response.ok) { - const errorData = await response.json(); - console.error('Failed to mark notification as read:', errorData); + const errorText = await response.text(); + console.error('Failed to mark notification as read:', { + status: response.status, + body: errorText + }); return false; } @@ -156,16 +173,21 @@ export function useNotifications() { if (!session?.user) return false; try { + console.log('[useNotifications] Marking all notifications as read'); const response = await fetch('/api/notifications/read-all', { method: 'POST', headers: { 'Content-Type': 'application/json' - } + }, + credentials: 'include' // Ensure cookies are sent with the request }); if (!response.ok) { - const errorData = await response.json(); - console.error('Failed to mark all notifications as read:', errorData); + const errorText = await response.text(); + console.error('Failed to mark all notifications as read:', { + status: response.status, + body: errorText + }); return false; }