import { createContext, useState, useContext, useCallback, useEffect } from 'react' import { useLocation } from 'react-router-dom' import { notification, Drawer } from 'antd' import PropTypes from 'prop-types' import { AuthContext } from './AuthContext' import { ApiServerContext } from './ApiServerContext' import NotificationCenter from '../common/NotificationCenter' import Notification from '../common/Notification' import { useMediaQuery } from 'react-responsive' const NotificationContext = createContext() const NotificationProvider = ({ children }) => { const [api, contextHolder] = notification.useNotification() const location = useLocation() const { authenticated } = useContext(AuthContext) const { showError, fetchNotificationsApi, markNotificationAsReadApi, markAllNotificationsAsReadApi, deleteNotificationApi, deleteAllNotificationsApi, registerNotificationListener } = useContext(ApiServerContext) const [notificationCenterVisible, setNotificationCenterVisible] = useState(false) const [notifications, setNotifications] = useState([]) const [notificationsLoading, setNotificationsLoading] = useState(false) const isMobile = useMediaQuery({ maxWidth: 768 }) const fetchNotifications = useCallback(async () => { if (!authenticated) return [] setNotificationsLoading(true) try { const data = await fetchNotificationsApi() setNotifications(data) return data } catch (err) { console.error(err) const is404 = err?.response?.status === 404 if (is404) { setNotifications([]) } else { showError(err, () => fetchNotifications()) } return [] } finally { setNotificationsLoading(false) } }, [authenticated, fetchNotificationsApi, showError]) const markNotificationAsRead = useCallback( async (notificationId) => { try { await markNotificationAsReadApi(notificationId) setNotifications((prev) => prev.map((n) => (n._id === notificationId ? { ...n, read: true } : n)) ) } catch (err) { console.error(err) showError(err, () => markNotificationAsRead(notificationId)) } }, [markNotificationAsReadApi, showError] ) const markAllNotificationsAsRead = useCallback(async () => { try { await markAllNotificationsAsReadApi() setNotifications((prev) => prev.map((n) => ({ ...n, read: true }))) } catch (err) { console.error(err) showError(err, () => markAllNotificationsAsRead()) } }, [markAllNotificationsAsReadApi, showError]) const deleteNotification = useCallback( async (notificationId) => { try { await deleteNotificationApi(notificationId) setNotifications((prev) => prev.filter((n) => n._id !== notificationId)) } catch (err) { console.error(err) showError(err, () => deleteNotification(notificationId)) } }, [deleteNotificationApi, showError] ) const deleteAllNotifications = useCallback(async () => { try { await deleteAllNotificationsApi() setNotifications([]) } catch (err) { console.error(err) showError(err, () => deleteAllNotifications()) } }, [deleteAllNotificationsApi, showError]) const toggleNotificationCenter = useCallback(() => { setNotificationCenterVisible((prev) => !prev) }, []) const unreadCount = notifications.filter((n) => !n.read).length useEffect(() => { if (authenticated && notificationCenterVisible) { fetchNotifications() } }, [authenticated, notificationCenterVisible, fetchNotifications]) useEffect(() => { if (authenticated) { fetchNotifications() } }, [authenticated, fetchNotifications]) useEffect(() => { setNotificationCenterVisible(false) }, [location.pathname]) useEffect(() => { if (!authenticated || !registerNotificationListener) return const handleNotification = (notif) => { setNotifications((prev) => { const exists = prev.some((n) => n._id === notif._id) if (exists) return prev return [{ ...notif, read: false }, ...prev] }) const show = api.open show({ message: ( ), icon: null, duration: 3, key: notif._id }) } const unregister = registerNotificationListener(handleNotification) return unregister }, [authenticated, registerNotificationListener, api, deleteNotification]) return ( {contextHolder} {children} setNotificationCenterVisible(false)} open={notificationCenterVisible} > setNotificationCenterVisible(false)} /> ) } NotificationProvider.propTypes = { children: PropTypes.node.isRequired } export { NotificationContext, NotificationProvider }