codenuk_frontend_mine/src/hooks/useNotificationSocket.ts
2025-09-17 17:13:22 +05:30

123 lines
3.8 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
import { io, Socket } from 'socket.io-client';
import { AdminNotification } from '@/types/admin.types';
import { SOCKET_URL } from '@/config/backend';
import { getAccessToken } from '@/components/apis/authApiClients';
interface NotificationCounts {
total: number;
unread: number;
read: number;
}
interface UseNotificationSocketReturn {
socket: Socket | null;
isConnected: boolean;
notificationCounts: NotificationCounts;
onNewNotification: (callback: (notification: AdminNotification) => void) => void;
onNotificationRead: (callback: (data: { id: string }) => void) => void;
onAllNotificationsRead: (callback: () => void) => void;
}
export function useNotificationSocket(): UseNotificationSocketReturn {
const [socket, setSocket] = useState<Socket | null>(null);
const [isConnected, setIsConnected] = useState(false);
const [notificationCounts, setNotificationCounts] = useState<NotificationCounts>({
total: 0,
unread: 0,
read: 0
});
const newNotificationCallbackRef = useRef<((notification: AdminNotification) => void) | null>(null);
const notificationReadCallbackRef = useRef<((data: { id: string }) => void) | null>(null);
const allNotificationsReadCallbackRef = useRef<(() => void) | null>(null);
useEffect(() => {
const templateManagerUrl = SOCKET_URL;
const token = getAccessToken();
console.log('[useNotificationSocket] Initializing socket', {
url: templateManagerUrl,
hasToken: !!token,
tokenPreview: token ? token.substring(0, 12) + '...' : null
});
const newSocket = io(templateManagerUrl, {
transports: ['websocket', 'polling'],
timeout: 20000,
path: '/socket.io/',
auth: token ? { token } : undefined,
});
newSocket.on('connect', () => {
console.log('🔌 Connected to notification socket');
setIsConnected(true);
});
newSocket.on('disconnect', () => {
console.log('🔌 Disconnected from notification socket');
setIsConnected(false);
});
newSocket.on('notification-count', (counts: NotificationCounts) => {
console.log('📊 Notification counts updated:', counts);
setNotificationCounts(counts);
});
newSocket.on('new-notification', (notification: AdminNotification) => {
console.log('🔔 New notification received:', notification);
if (newNotificationCallbackRef.current) {
newNotificationCallbackRef.current(notification);
}
});
newSocket.on('notification-read', (data: { id: string }) => {
console.log('✅ Notification marked as read:', data.id);
if (notificationReadCallbackRef.current) {
notificationReadCallbackRef.current(data);
}
});
newSocket.on('all-notifications-read', () => {
console.log('✅ All notifications marked as read');
if (allNotificationsReadCallbackRef.current) {
allNotificationsReadCallbackRef.current();
}
});
newSocket.on('connect_error', (error: any) => {
console.error('🔌 Socket connection error:', {
message: error?.message,
name: error?.name,
data: error?.data
});
setIsConnected(false);
});
setSocket(newSocket);
return () => {
newSocket.close();
};
}, []);
const onNewNotification = (callback: (notification: AdminNotification) => void) => {
newNotificationCallbackRef.current = callback;
};
const onNotificationRead = (callback: (data: { id: string }) => void) => {
notificationReadCallbackRef.current = callback;
};
const onAllNotificationsRead = (callback: () => void) => {
allNotificationsReadCallbackRef.current = callback;
};
return {
socket,
isConnected,
notificationCounts,
onNewNotification,
onNotificationRead,
onAllNotificationsRead,
};
}