Files
GPI/src/client/contexts/NotificationContext.tsx

104 lines
3.3 KiB
TypeScript

import React, { useState, useEffect, useCallback } from 'react';
import { useAuth } from '../context/useAuth';
import api from '../services/api';
import type { INotification } from '../types';
import { NotificationContext } from './NotificationContextState';
export const NotificationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { isSignedIn } = useAuth();
const [notifications, setNotifications] = useState<INotification[]>([]);
const [loading, setLoading] = useState(false);
const fetchNotifications = useCallback(async () => {
if (!isSignedIn) return;
try {
if (notifications.length === 0) setLoading(true);
const response = await api.get('/notifications');
setNotifications(response.data);
} catch (error) {
console.error('Failed to fetch notifications', error);
} finally {
setLoading(false);
}
}, [isSignedIn, notifications.length]);
const markAsRead = async (id: string) => {
try {
await api.put(`/notifications/${id}/read`);
setNotifications(prev => prev.map(n => n._id === id ? { ...n, isRead: true } : n));
} catch (error) {
console.error('Failed to mark as read', error);
}
};
const markAllAsRead = async () => {
try {
await api.put('/notifications/read-all');
setNotifications(prev => prev.map(n => ({ ...n, isRead: true })));
} catch (error) {
console.error('Failed to mark all as read', error);
}
}
const clearAll = async () => {
try {
await api.delete('/notifications/clear-all');
setNotifications([]);
} catch (error) {
console.error('Failed to clear all notifications', error);
}
};
const archiveNotification = async (id: string) => {
try {
await api.patch(`/notifications/${id}/archive`);
setNotifications(prev => prev.filter(n => n._id !== id));
} catch (error) {
console.error('Failed to archive notification', error);
}
};
const deleteNotification = async (id: string) => {
try {
await api.delete(`/notifications/${id}`);
setNotifications(prev => prev.filter(n => n._id !== id));
} catch (error) {
console.error('Failed to delete notification', error);
}
};
// Polling effect
useEffect(() => {
if (isSignedIn) {
fetchNotifications(); // Initial fetch
const interval = setInterval(() => {
fetchNotifications();
}, 30000); // Poll every 30 seconds
return () => clearInterval(interval);
} else {
setNotifications([]);
}
}, [isSignedIn, fetchNotifications]);
const unreadCount = (notifications || []).filter(n => !n.isRead).length;
return (
<NotificationContext.Provider value={{
notifications,
unreadCount,
loading,
markAsRead,
markAllAsRead,
clearAll,
archiveNotification,
deleteNotification,
fetchNotifications
}}>
{children}
</NotificationContext.Provider>
);
};