feat: Add an admin endpoint to retrieve the total count of unread support messages.
This commit is contained in:
@@ -82,7 +82,13 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
|
|||||||
}
|
}
|
||||||
this.userSocketMap.get(userId)!.add(client.id);
|
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)
|
// Update user online status in background (don't await)
|
||||||
this.messagesService.updateOnlineStatus(userId, true)
|
this.messagesService.updateOnlineStatus(userId, true)
|
||||||
@@ -337,6 +343,12 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
|
|||||||
// Broadcast to all clients in the support chat room
|
// Broadcast to all clients in the support chat room
|
||||||
this.server.to(`support:${data.chatId}`).emit('support_new_message', message);
|
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 };
|
return { success: true, message };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error.message };
|
return { error: error.message };
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
UseGuards,
|
UseGuards,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
|
Inject,
|
||||||
|
forwardRef,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
ApiTags,
|
ApiTags,
|
||||||
@@ -24,13 +26,18 @@ import { JwtAuthGuard } from '../auth/guards';
|
|||||||
import { CurrentUser } from '../auth/decorators';
|
import { CurrentUser } from '../auth/decorators';
|
||||||
import { Roles } from '../auth/decorators/roles.decorator';
|
import { Roles } from '../auth/decorators/roles.decorator';
|
||||||
import { UserRole, SupportChatStatus } from '@prisma/client';
|
import { UserRole, SupportChatStatus } from '@prisma/client';
|
||||||
|
import { MessagesGateway } from '../messages/messages.gateway';
|
||||||
|
|
||||||
@ApiTags('Support Chat')
|
@ApiTags('Support Chat')
|
||||||
@Controller('support-chat')
|
@Controller('support-chat')
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('JWT-auth')
|
||||||
export class SupportChatController {
|
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)
|
// GET OR CREATE SUPPORT CHAT (User/Agent)
|
||||||
@@ -95,7 +102,24 @@ export class SupportChatController {
|
|||||||
await this.supportChatService.getChat(chatId, userId, isAdmin);
|
await this.supportChatService.getChat(chatId, userId, isAdmin);
|
||||||
|
|
||||||
const senderRole = role === UserRole.ADMIN ? 'ADMIN' : 'USER';
|
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,
|
@Param('id') chatId: string,
|
||||||
@CurrentUser('role') role: UserRole,
|
@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();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
import { SupportChatController } from './support-chat.controller';
|
import { SupportChatController } from './support-chat.controller';
|
||||||
import { SupportChatService } from './support-chat.service';
|
import { SupportChatService } from './support-chat.service';
|
||||||
import { PrismaModule } from '../prisma/prisma.module';
|
import { PrismaModule } from '../prisma/prisma.module';
|
||||||
|
import { MessagesModule } from '../messages/messages.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PrismaModule],
|
imports: [PrismaModule, forwardRef(() => MessagesModule)],
|
||||||
controllers: [SupportChatController],
|
controllers: [SupportChatController],
|
||||||
providers: [SupportChatService],
|
providers: [SupportChatService],
|
||||||
exports: [SupportChatService],
|
exports: [SupportChatService],
|
||||||
|
|||||||
@@ -162,6 +162,17 @@ export class SupportChatService {
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin: get total unread message count across all open chats
|
||||||
|
*/
|
||||||
|
async getAdminUnreadTotal(): Promise<number> {
|
||||||
|
const result = await this.prisma.supportChat.aggregate({
|
||||||
|
where: { status: SupportChatStatus.OPEN },
|
||||||
|
_sum: { adminUnreadCount: true },
|
||||||
|
});
|
||||||
|
return result._sum.adminUnreadCount || 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Admin: get all support chats
|
* Admin: get all support chats
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user