import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody, ConnectedSocket, } from '@nestjs/websockets'; import { Logger, Inject, forwardRef } from '@nestjs/common'; import { Server, Socket } from 'socket.io'; import type { EnrichedCallEvent, DispositionPayload } from './call-events.types'; import { CallEventsService } from './call-events.service'; @WebSocketGateway({ cors: { origin: process.env.CORS_ORIGIN ?? 'http://localhost:5173', credentials: true, }, namespace: '/call-events', }) export class CallEventsGateway { @WebSocketServer() server: Server; private readonly logger = new Logger(CallEventsGateway.name); constructor( @Inject(forwardRef(() => CallEventsService)) private readonly callEventsService: CallEventsService, ) {} // Push enriched call event to a specific agent's room pushCallEvent(agentName: string, event: EnrichedCallEvent) { const room = `agent:${agentName}`; this.logger.log(`Pushing ${event.eventType} event to room ${room}`); this.server.to(room).emit('call:incoming', event); } // Broadcast to supervisors when a new call record is created broadcastCallCreated(callData: any) { this.logger.log('Broadcasting call:created to supervisor room'); this.server.to('supervisor').emit('call:created', callData); } // Supervisor registers to receive real-time updates @SubscribeMessage('supervisor:register') handleSupervisorRegister(@ConnectedSocket() client: Socket) { client.join('supervisor'); this.logger.log(`Supervisor registered (socket: ${client.id})`); client.emit('supervisor:registered', { room: 'supervisor' }); } // Agent registers when they open the Call Desk page @SubscribeMessage('agent:register') handleAgentRegister( @ConnectedSocket() client: Socket, @MessageBody() agentName: string, ) { const room = `agent:${agentName}`; client.join(room); this.logger.log( `Agent ${agentName} registered in room ${room} (socket: ${client.id})`, ); client.emit('agent:registered', { agentName, room }); } // Agent sends disposition after a call @SubscribeMessage('call:disposition') async handleDisposition( @ConnectedSocket() client: Socket, @MessageBody() payload: DispositionPayload, ) { this.logger.log( `Disposition received from ${payload.agentName}: ${payload.disposition}`, ); await this.callEventsService.handleDisposition(payload); client.emit('call:disposition:ack', { status: 'saved', callSid: payload.callSid, }); return payload; } handleConnection(client: Socket) { this.logger.log(`Client connected: ${client.id}`); } handleDisconnect(client: Socket) { this.logger.log(`Client disconnected: ${client.id}`); } }