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 69e04c46f9
commit 0904402a4b
5 changed files with 226 additions and 4 deletions

View File

@@ -2,6 +2,9 @@
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useState, useEffect, useCallback } from 'react';
import { supportChatService } from '@/services/support-chat.service';
import { adminSocketService } from '@/services/socket.service';
const menuItems = [
{
@@ -106,6 +109,41 @@ const menuItems = [
export default function Sidebar() {
const pathname = usePathname();
const [unreadCount, setUnreadCount] = useState(0);
const fetchUnreadCount = useCallback(async () => {
try {
const count = await supportChatService.getUnreadTotal();
setUnreadCount(count);
} catch {
// Silently fail
}
}, []);
useEffect(() => {
// Initial fetch
fetchUnreadCount();
// Connect WebSocket for real-time updates
adminSocketService.connect();
const handleUnreadUpdate = (data: unknown) => {
const payload = data as { unreadTotal: number };
if (typeof payload?.unreadTotal === 'number') {
setUnreadCount(payload.unreadTotal);
}
};
adminSocketService.on('support_unread_update', handleUnreadUpdate);
// Fallback polling every 30s (in case socket disconnects)
const interval = setInterval(fetchUnreadCount, 30000);
return () => {
clearInterval(interval);
adminSocketService.off('support_unread_update', handleUnreadUpdate);
};
}, [fetchUnreadCount]);
return (
<aside className="w-64 bg-[#00293d] min-h-screen fixed left-0 top-0">
@@ -140,6 +178,7 @@ export default function Sidebar() {
{menuItems.map((item) => {
const isActive = pathname === item.href ||
(item.href !== '/dashboard' && pathname.startsWith(item.href));
const showBadge = item.name === 'Support Chat' && unreadCount > 0;
return (
<li key={item.name}>
@@ -153,6 +192,11 @@ export default function Sidebar() {
>
{item.icon}
<span className="ml-3 font-medium font-serif text-sm">{item.name}</span>
{showBadge && (
<span className="ml-auto inline-flex items-center justify-center min-w-[20px] h-5 px-1.5 text-xs font-bold text-white bg-red-500 rounded-full">
{unreadCount > 99 ? '99+' : unreadCount}
</span>
)}
</Link>
</li>
);