added changes ready to ship

This commit is contained in:
tusuii
2026-02-21 12:06:16 +05:30
parent 1788e364f1
commit 82077d38e6
39 changed files with 694 additions and 5600 deletions

View File

@@ -0,0 +1,80 @@
import React, { createContext, useContext, useEffect, useState } from 'react';
import { io } from 'socket.io-client';
export interface Notification {
id: string;
type: 'assignment' | 'mention' | 'update';
title: string;
message: string;
link?: string;
is_read: boolean;
created_at: string;
}
interface NotificationContextType {
notifications: Notification[];
unreadCount: number;
markAsRead: (id: string) => Promise<void>;
}
const NotificationContext = createContext<NotificationContextType | undefined>(undefined);
export const NotificationProvider: React.FC<{ children: React.ReactNode, userId: string }> = ({ children, userId }) => {
const [notifications, setNotifications] = useState<Notification[]>([]);
useEffect(() => {
if (!userId) return;
const newSocket = io(window.location.protocol + '//' + window.location.hostname + ':3001');
newSocket.emit('join', userId);
newSocket.on('notification', (notif: Notification) => {
setNotifications(prev => [notif, ...prev]);
// Optional: Show browser toast here
});
fetchNotifications();
return () => {
newSocket.close();
};
}, [userId]);
const fetchNotifications = async () => {
try {
const res = await fetch(`/api/notifications/${userId}`);
if (res.ok) {
const data = await res.json();
setNotifications(data);
}
} catch (err) {
console.error('Fetch notifications failed', err);
}
};
const markAsRead = async (id: string) => {
try {
const res = await fetch(`/api/notifications/${id}/read`, { method: 'PUT' });
if (res.ok) {
setNotifications(prev => prev.map(n => n.id === id ? { ...n, is_read: true } : n));
}
} catch (err) {
console.error('Mark read failed', err);
}
};
const unreadCount = notifications.filter(n => !n.is_read).length;
return (
<NotificationContext.Provider value={{ notifications, unreadCount, markAsRead }}>
{children}
</NotificationContext.Provider>
);
};
export const useNotifications = () => {
const context = useContext(NotificationContext);
if (!context) throw new Error('useNotifications must be used within NotificationProvider');
return context;
};