From 4d5a3fc36d6956ff302559653d86fa972e584731 Mon Sep 17 00:00:00 2001 From: pradeepkumar Date: Thu, 19 Mar 2026 04:19:55 +0530 Subject: [PATCH] feat: Add an admin endpoint to retrieve the total count of unread support messages. --- src/messages/messages.gateway.ts | 14 +++++- src/support-chat/support-chat.controller.ts | 49 +++++++++++++++++++-- src/support-chat/support-chat.module.ts | 5 ++- src/support-chat/support-chat.service.ts | 11 +++++ 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/messages/messages.gateway.ts b/src/messages/messages.gateway.ts index 830cf08..b7d9c30 100644 --- a/src/messages/messages.gateway.ts +++ b/src/messages/messages.gateway.ts @@ -82,7 +82,13 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect } this.userSocketMap.get(userId)!.add(client.id); - this.logger.log(`Client connected successfully: ${client.id} (User: ${userId})`); + this.logger.log(`Client connected successfully: ${client.id} (User: ${userId}, Role: ${payload.role})`); + + // Auto-join admin users to admin_room for support chat notifications + if (payload.role === 'ADMIN') { + client.join('admin_room'); + this.logger.log(`Admin ${userId} joined admin_room`); + } // Update user online status in background (don't await) this.messagesService.updateOnlineStatus(userId, true) @@ -337,6 +343,12 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect // Broadcast to all clients in the support chat room this.server.to(`support:${data.chatId}`).emit('support_new_message', message); + // Notify admins about new unread count (for sidebar badge) + if (senderRole !== 'ADMIN') { + const unreadTotal = await this.supportChatService.getAdminUnreadTotal(); + this.server.to('admin_room').emit('support_unread_update', { unreadTotal }); + } + return { success: true, message }; } catch (error) { return { error: error.message }; diff --git a/src/support-chat/support-chat.controller.ts b/src/support-chat/support-chat.controller.ts index cb75e2c..9a888ad 100644 --- a/src/support-chat/support-chat.controller.ts +++ b/src/support-chat/support-chat.controller.ts @@ -9,6 +9,8 @@ import { UseGuards, HttpCode, HttpStatus, + Inject, + forwardRef, } from '@nestjs/common'; import { ApiTags, @@ -24,13 +26,18 @@ import { JwtAuthGuard } from '../auth/guards'; import { CurrentUser } from '../auth/decorators'; import { Roles } from '../auth/decorators/roles.decorator'; import { UserRole, SupportChatStatus } from '@prisma/client'; +import { MessagesGateway } from '../messages/messages.gateway'; @ApiTags('Support Chat') @Controller('support-chat') @UseGuards(JwtAuthGuard) @ApiBearerAuth('JWT-auth') export class SupportChatController { - constructor(private readonly supportChatService: SupportChatService) {} + constructor( + private readonly supportChatService: SupportChatService, + @Inject(forwardRef(() => MessagesGateway)) + private readonly messagesGateway: MessagesGateway, + ) {} // ========================================== // GET OR CREATE SUPPORT CHAT (User/Agent) @@ -95,7 +102,24 @@ export class SupportChatController { await this.supportChatService.getChat(chatId, userId, isAdmin); const senderRole = role === UserRole.ADMIN ? 'ADMIN' : 'USER'; - return this.supportChatService.sendMessage(chatId, userId, senderRole, dto.content); + const message = await this.supportChatService.sendMessage(chatId, userId, senderRole, dto.content); + + // Emit WebSocket events for real-time updates + this.messagesGateway.server.to(`support:${chatId}`).emit('support_new_message', message); + + // If user/agent sent the message, notify admins about unread count + if (senderRole !== 'ADMIN') { + const unreadTotal = await this.supportChatService.getAdminUnreadTotal(); + this.messagesGateway.server.to('admin_room').emit('support_unread_update', { unreadTotal }); + } + + // If admin sent the message, notify the user directly + if (senderRole === 'ADMIN') { + const chat = await this.supportChatService.getChat(chatId, userId, true); + this.messagesGateway.sendToUser(chat.userId, 'support_new_message', message); + } + + return message; } // ========================================== @@ -109,7 +133,26 @@ export class SupportChatController { @Param('id') chatId: string, @CurrentUser('role') role: UserRole, ) { - return this.supportChatService.markAsRead(chatId, role); + const result = await this.supportChatService.markAsRead(chatId, role); + + // If admin marked as read, update sidebar badge for all admins + if (role === UserRole.ADMIN) { + const unreadTotal = await this.supportChatService.getAdminUnreadTotal(); + this.messagesGateway.server.to('admin_room').emit('support_unread_update', { unreadTotal }); + } + + return result; + } + + // ========================================== + // ADMIN: GET TOTAL UNREAD COUNT + // ========================================== + @Get('admin/unread-total') + @Roles(UserRole.ADMIN) + @ApiOperation({ summary: 'Admin: Get total unread support message count' }) + @ApiResponse({ status: 200, description: 'Total unread count returned' }) + async getUnreadTotal() { + return this.supportChatService.getAdminUnreadTotal(); } // ========================================== diff --git a/src/support-chat/support-chat.module.ts b/src/support-chat/support-chat.module.ts index e0efe48..7637aa5 100644 --- a/src/support-chat/support-chat.module.ts +++ b/src/support-chat/support-chat.module.ts @@ -1,10 +1,11 @@ -import { Module } from '@nestjs/common'; +import { Module, forwardRef } from '@nestjs/common'; import { SupportChatController } from './support-chat.controller'; import { SupportChatService } from './support-chat.service'; import { PrismaModule } from '../prisma/prisma.module'; +import { MessagesModule } from '../messages/messages.module'; @Module({ - imports: [PrismaModule], + imports: [PrismaModule, forwardRef(() => MessagesModule)], controllers: [SupportChatController], providers: [SupportChatService], exports: [SupportChatService], diff --git a/src/support-chat/support-chat.service.ts b/src/support-chat/support-chat.service.ts index ce6df65..e243e45 100644 --- a/src/support-chat/support-chat.service.ts +++ b/src/support-chat/support-chat.service.ts @@ -162,6 +162,17 @@ export class SupportChatService { return { success: true }; } + /** + * Admin: get total unread message count across all open chats + */ + async getAdminUnreadTotal(): Promise { + const result = await this.prisma.supportChat.aggregate({ + where: { status: SupportChatStatus.OPEN }, + _sum: { adminUnreadCount: true }, + }); + return result._sum.adminUnreadCount || 0; + } + /** * Admin: get all support chats */