import React, { useState, useRef, useEffect } from 'react'; import { Bell } from 'lucide-react'; import { useNotifications } from '../hooks/useNotifications'; import { useNavigate } from 'react-router-dom'; import { FaCheck, FaTimes, FaBell } from 'react-icons/fa'; const stripHtml = (html: string): string => { if (!html) return ''; const doc = new DOMParser().parseFromString(html, 'text/html'); return (doc.body.textContent || '').replace(/\uFEFF/g, '').replace(/\s+/g, ' ').trim(); }; const NotificationBell: React.FC = () => { const { notifications, unreadCount, markAsRead, markAllAsRead, loading } = useNotifications(); const [isOpen, setIsOpen] = useState(false); const [markingAll, setMarkingAll] = useState(false); const panelRef = useRef(null); const navigate = useNavigate(); // If notifications are not available (empty array and not loading), // the bell will still show but with 0 count - this is fine useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (panelRef.current && !panelRef.current.contains(event.target as Node)) { setIsOpen(false); } }; if (isOpen) { document.addEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [isOpen]); const handleMarkAllAsRead = async () => { setMarkingAll(true); try { await markAllAsRead(); } catch (error) { console.warn('[NotificationBell] Could not mark all as read:', error); } finally { setMarkingAll(false); } }; const handleNotificationClick = async (notification: any) => { console.log('[NotificationBell] Clicked notification:', notification); console.log('[NotificationBell] document_type:', notification.document_type); console.log('[NotificationBell] document_name:', notification.document_name); // Try to mark as read, but don't block navigation if it fails if (!notification.read) { try { await markAsRead(notification.name); } catch (error) { console.warn('[NotificationBell] Could not mark as read (permission issue):', error); // Continue anyway - navigate to document } } // Navigate based on document type if (notification.document_type && notification.document_name) { const docType = notification.document_type; const docName = notification.document_name; // Normalize document type (handle both spaces and underscores) const normalizedType = docType.replace(/_/g, ' ').trim(); console.log('[NotificationBell] Normalized type:', normalizedType); console.log('[NotificationBell] Document name:', docName); // Map document types to routes if (normalizedType === 'Asset Maintenance Log' || normalizedType === 'Asset Maintenance') { console.log('[NotificationBell] Navigating to maintenance:', `/maintenance/${docName}`); navigate(`/maintenance/${docName}`); } else if (normalizedType === 'Work Order' || normalizedType === 'Asset Repair') { console.log('[NotificationBell] Navigating to work order:', `/work-orders/${docName}`); navigate(`/work-orders/${docName}`); } else if (normalizedType === 'Asset') { console.log('[NotificationBell] Navigating to asset:', `/assets/${docName}`); navigate(`/assets/${docName}`); } else if (normalizedType === 'PM Schedule Generator' || normalizedType === 'PM Schedule') { console.log('[NotificationBell] Navigating to PPM planner:', `/ppm-planner/${docName}`); navigate(`/ppm-planner/${docName}`); } else if (normalizedType === 'PPM') { console.log('[NotificationBell] Navigating to PPM:', `/ppm/${docName}`); navigate(`/ppm/${docName}`); } else if (normalizedType === 'Item') { console.log('[NotificationBell] Navigating to inventory:', `/inventory/${docName}`); navigate(`/inventory/${docName}`); } else if (normalizedType === 'Inspection') { console.log('[NotificationBell] Navigating to inspection:', `/inspections/${docName}`); navigate(`/inspections/${docName}`); } else if (normalizedType === 'Issue') { console.log('[NotificationBell] Navigating to issue', `/issues/${docName}`); navigate(`/support/${docName}`); }else if (normalizedType === 'SFDA Entries') { console.log('[NotificationBell] Navigating to SFDA Entries', `/sfda-entries/${docName}`); navigate(`/sfda-entries/${docName}`); } else { // Fallback: Try to open in Frappe if route not found console.warn(`[NotificationBell] Unknown document type: ${docType}, opening in Frappe`); const frappeRoute = docType.toLowerCase().replace(/\s+/g, '-').replace(/_/g, '-'); window.open(`/app/${frappeRoute}/${docName}`, '_blank'); } } else { console.warn('[NotificationBell] No document_type or document_name found:', { document_type: notification.document_type, document_name: notification.document_name, notification }); } setIsOpen(false); }; const formatDate = (dateString: string) => { const date = new Date(dateString); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMs / 3600000); const diffDays = Math.floor(diffMs / 86400000); if (diffMins < 1) return 'Just now'; if (diffMins < 60) return `${diffMins}m ago`; if (diffHours < 24) return `${diffHours}h ago`; if (diffDays < 7) return `${diffDays}d ago`; return date.toLocaleDateString(); }; const unreadNotifications = notifications.filter(n => !n.read); const readNotifications = notifications.filter(n => n.read).slice(0, 10); return (
{isOpen && (
{/* Header */}

Notifications {unreadCount > 0 && ( {unreadCount} new )}

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

No notifications

) : ( <> {unreadNotifications.length > 0 && (
NEW
{unreadNotifications.map(notif => (
handleNotificationClick(notif)} className="p-3 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer border-l-4 border-blue-500 bg-blue-50 dark:bg-blue-900/20" >

{stripHtml((notif as any).subject || '') || notif.document_type || 'Notification'}

{(notif as any).email_content && (

{stripHtml((notif as any).email_content || '')}

)} {/*

{(notif as any).subject || notif.document_type || 'Notification'}

{(notif as any).email_content && (

{(notif as any).email_content}

)} */}

{formatDate(notif.creation)}

))}
)} {readNotifications.length > 0 && (
{unreadNotifications.length > 0 && (
EARLIER
)} {readNotifications.map(notif => (
handleNotificationClick(notif)} className="p-3 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer" >

{stripHtml((notif as any).subject || '') || notif.document_type || 'Notification'}

{(notif as any).email_content && (

{stripHtml((notif as any).email_content || '')}

)} {/*

{(notif as any).subject || notif.document_type || 'Notification'}

{(notif as any).email_content && (

{(notif as any).email_content}

)} */}

{formatDate(notif.creation)}

))}
)} )}
)}
); }; export default NotificationBell;