appointments.checkinAgendamento Check-in
Evento WebSocket para notificar em tempo real quando um agendamento faz check-in. Este evento é emitido automaticamente pelo servidor quando um agendamento muda de status para CHECKIN, 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 adicionem o agendamento à fila 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. O frontend valida se o agendamento já existe na lista e se o status é 'Check-in' antes de adicionar, prevenindo duplicatas.
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: appointments.checkin
Listener escuta mudança de status para CHECKIN
O CheckInAppointmentListener escuta o evento interno 'appointments.status.change' e processa quando o status muda para CHECKIN:
// check-in-appointment.ts
@OnEvent('appointments.status.change')
async handleAppointmentsStatusChange(event: AppointmentStatusChangeEvent) {
// Só processa se action === CHECKIN
if (event.action !== AppointmentStatusEnum.CHECKIN) return;
try {
// Emite evento interno para propagação via WebSocket
this.eventEmitter.emit('appointments.checkin', {
appointment: event.appointment,
payload: event.payload,
});
} catch (e) {
const error = e as Error;
this.logger.error(error.message, error.stack);
}
}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('appointments.checkin')
async handlePatientCheckin(data: {
appointment: AppointmentResponseDto;
payload: PayloadTokenDto;
}) {
try {
// Propaga via WebSocket para todos os clientes da conta
await this.gateway.notifyOnEvent(
'appointments.checkin',
data.appointment,
data.payload,
);
this.logger.debug(
`Agendamento ${data.appointment.id} propagado via WebSocket para a fila de espera ${data.payload.accountId}`,
);
} catch (error) {
this.logger.error(
`Erro ao propagar evento appointments.checkin:`,
error,
);
}
}Gateway faz broadcast para todos da conta
O método `notifyOnEvent` envia o evento 'appointments.checkin' 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 'appointments.checkin'Cliente recebe evento e adiciona à lista com validações
Todos os clientes conectados da mesma conta recebem o evento 'appointments.checkin' e adicionam o agendamento à lista com validações:
// List.tsx
socket.on('appointments.checkin', (appointment: Appointment) => {
setListAppointments((prev) => {
// Verifica se o agendamento já existe na lista
const exists = prev.some((apt) => apt.id === appointment.id);
// Valida se não existe e se o status é 'Check-in'
if (!exists && appointment.status?.name === 'Check-in') {
// Adiciona à lista
return [...prev, appointment];
}
// Se já existe ou status não é 'Check-in', mantém lista original
return prev;
});
});
// 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:00:00.000Z",
"deletedAt": null,
"doctor": {
"id": 1,
"name": "Dr. Victor"
},
"patient": {
"id": 456,
"name": "João Silva",
"contact": {
"phone": "(81) 99999-9999"
}
},
"status": {
"id": 2,
"name": "Check-in",
"color": "#17a2b8"
},
"appointmentProcedures": {
"procedure": {
"id": 3699,
"name": "Ultrassom: Tireoide",
"price": "100"
}
}
}