feat: Implement real-time unread support chat count in the sidebar using WebSockets.

This commit is contained in:
pradeepkumar
2026-03-19 04:20:33 +05:30
parent dbc2501d4c
commit 9036e9f32f
5 changed files with 226 additions and 4 deletions

View File

@@ -0,0 +1,88 @@
import { io, Socket } from 'socket.io-client';
class AdminSocketService {
private socket: Socket | null = null;
private listeners = new Map<string, Set<(data: unknown) => void>>();
connect() {
if (this.socket?.connected) return;
const token = localStorage.getItem('accessToken');
if (!token) return;
// Strip /api/v1 from API URL to get the socket server URL
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api/v1';
const socketUrl = apiUrl.replace(/\/api\/v1\/?$/, '');
this.socket = io(socketUrl, {
auth: { token },
transports: ['websocket', 'polling'],
reconnection: true,
reconnectionDelay: 2000,
reconnectionAttempts: 10,
});
this.socket.on('connect', () => {
console.log('[AdminSocket] Connected');
});
this.socket.on('disconnect', (reason) => {
console.log('[AdminSocket] Disconnected:', reason);
});
this.socket.on('connect_error', (err) => {
console.error('[AdminSocket] Connection error:', err.message);
});
// Re-attach all registered listeners
this.listeners.forEach((callbacks, event) => {
callbacks.forEach((cb) => {
this.socket?.on(event, cb as (...args: unknown[]) => void);
});
});
}
disconnect() {
if (this.socket) {
this.socket.disconnect();
this.socket = null;
}
}
on(event: string, callback: (data: unknown) => void) {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(callback);
if (this.socket) {
this.socket.on(event, callback as (...args: unknown[]) => void);
}
}
off(event: string, callback: (data: unknown) => void) {
const callbacks = this.listeners.get(event);
if (callbacks) {
callbacks.delete(callback);
if (callbacks.size === 0) {
this.listeners.delete(event);
}
}
if (this.socket) {
this.socket.off(event, callback as (...args: unknown[]) => void);
}
}
emit(event: string, data: unknown) {
if (this.socket?.connected) {
this.socket.emit(event, data);
}
}
get isConnected(): boolean {
return this.socket?.connected ?? false;
}
}
export const adminSocketService = new AdminSocketService();

View File

@@ -58,6 +58,11 @@ class SupportChatService {
const response = await api.patch<ApiResponse<SupportChat>>(`/support-chat/admin/${chatId}/close`);
return response.data.data;
}
async getUnreadTotal(): Promise<number> {
const response = await api.get<ApiResponse<number>>('/support-chat/admin/unread-total');
return response.data.data;
}
}
export const supportChatService = new SupportChatService();