appointmnents.finishedAgendamento Finalizado/Cancelado
Evento WebSocket para notificar em tempo real quando um agendamento é finalizado ou cancelado. Este evento é emitido automaticamente pelo servidor quando um agendamento muda de status para FINALIZADO ou CANCELADO, propagando a notificação para todos os clientes conectados da mesma conta. O servidor faz broadcast do evento para todos os clientes da mesma accountId, permitindo que todos removam o agendamento da lista de espera simultaneamente. Este evento não é iniciado pelo frontend; é um evento unidirecional (servidor → clientes) usado exclusivamente para sincronização de UI em tempo real.
Access Token
Para realizar requisições GET, POST, PUT, DELETE e PATCH nos endpoints da API você precisa de uma chave de autorização. Chamamos essa chave de accessToken.
Para ter acesso ao accessToken, é necessário que o usuário master da licença efetue a liberação deste pela interface do ImageMais Clinic. O accessToken tem validade de 1 hora.
Headers
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
Authorization | string | Sim | Token de autenticação no formato Bearer {accessToken}. O token deve ser enviado durante o handshake de conexão WebSocket. |
AuthorizationOBRIGATÓRIOParâmetros
Este método não possui parâmetros.
Fluxo passo a passo: appointmnents.finished
Listeners escutam mudança de status de agendamento
Dois listeners diferentes escutam o evento interno 'appointments.status.change' e processam quando o status muda para FINALIZADO ou CANCELADO:
// finish-appointment.ts
@OnEvent('appointments.status.change')
async handleAppointmentsStatusChange(event: AppointmentStatusChangeEvent) {
// Só processa se action === FINALIZADO
if (event.action !== AppointmentStatusEnum.FINALIZADO) return;
try {
// Marca médico como não ocupado
await this.prisma.doctors.update({
where: { id: event.doctorId ?? event.appointment.doctorId },
data: { isBusy: false },
});
// Emite evento interno para propagação via WebSocket
this.eventEmitter.emit('appointmnents.finished', {
appointment: event.appointment,
payload: event.payload,
});
} catch (error) {
// Trata erros
}
}
// cancel-appointment.ts
@OnEvent('appointments.status.change')
async handleAppointmentsStatusChange(event: AppointmentStatusChangeEvent) {
// Só processa se action === CANCELADO
if (event.action !== AppointmentStatusEnum.CANCELADO) return;
try {
// Emite evento interno para propagação via WebSocket
this.eventEmitter.emit('appointmnents.finished', {
appointment: event.appointment,
payload: event.payload,
});
} catch (error) {
// Trata erros
}
}Listener propaga evento via WebSocket
O appointments.listener.ts escuta o evento interno e propaga via WebSocket para todos os clientes da conta:
// appointments.listener.ts
@OnEvent('appointmnents.finished')
async handleAppointmentsFinished(data: {
appointment: AppointmentResponseDto;
payload: PayloadTokenDto;
}) {
try {
// Propaga via WebSocket para todos os clientes da conta
await this.gateway.notifyOnEvent(
'appointmnents.finished',
data.appointment,
data.payload,
);
this.logger.debug(
`Agendamento ${data.appointment.id} finalizado e propagado via WebSocket para a fila de espera ${data.payload.accountId}`,
);
} catch (error) {
this.logger.error(
`Erro ao propagar evento appointments.finished:`,
error,
);
}
}Gateway faz broadcast para todos da conta
O método `notifyOnEvent` envia o evento 'appointmnents.finished' para todos os sockets da mesma accountId:
// accounts.gateways.ts
async notifyOnEvent(
event: string,
data: any,
payload: PayloadTokenDto,
): Promise<any> {
if (this._events.includes(event)) {
// Envia para todos os clientes da mesma conta
this.server
.to(`${this.room}${payload.accountId}`)
.emit(event, data);
}
}
// this.room = 'orders.account.'
// Todos os clientes conectados da mesma accountId recebem o evento 'appointmnents.finished'Cliente recebe evento e remove da lista
Todos os clientes conectados da mesma conta recebem o evento 'appointmnents.finished' e removem o agendamento da lista:
// List.tsx
socket.on('appointmnents.finished', (appointment: Appointment) => {
// Remove o agendamento da lista de espera
setListAppointments((prev) =>
prev.filter((apt) => apt.id !== appointment.id)
);
});
// Remove listener ao desmontar componente
useEffect(() => {
return () => {
socket.off('doctors.busy');
socket.off('appointments.checkin');
socket.off('appointments.serving');
socket.off('appointmnents.finished');
};
}, []);Request URL
ws://api-dev.imagemais.com{
"message": "Este evento é emitido automaticamente pelo servidor (não requer request body)"
}{
"message": "Este evento é emitido automaticamente pelo servidor (não requer request body)"
}Respostas
{
"id": 123,
"date": "2025-01-23T00:00:00.000Z",
...{
"id": 123,
"date": "2025-01-23T00:00:00.000Z",
"startTime": "09:00",
"endTime": "09:15",
"notes": "Observações sobre o agendamento",
"accountId": 1,
"createdAt": "2025-01-22T10:00:00.000Z",
"updatedAt": "2025-01-23T09:15:00.000Z",
"deletedAt": null,
"doctor": {
"id": 1,
"name": "Dr. Victor"
},
"patient": {
"id": 456,
"name": "João Silva",
"contact": {
"phone": "(81) 99999-9999"
}
},
"status": {
"id": 5,
"name": "Finalizado",
"color": "#28a745"
},
"appointmentProcedures": {
"procedure": {
"id": 3699,
"name": "Ultrassom: Tireoide",
"price": "100"
}
}
}