riseup-squad18/src/services/appointments/appointmentService.ts
guisilvagomes 3a3e4c1f55 fix: corrige exibição de nomes de médicos em laudos e relatórios
- Adiciona resolução de IDs para nomes nos laudos do painel do paciente
- Implementa dropdown de médicos nos formulários de relatórios
- Corrige API PATCH para retornar dados atualizados (header Prefer)
- Adiciona fallback para buscar relatório após update
- Limpa cache de nomes ao atualizar relatórios
- Trata dados legados (nomes diretos vs UUIDs)
- Exibe 'Médico não cadastrado' para IDs inexistentes
2025-11-05 18:25:13 -03:00

184 lines
4.7 KiB
TypeScript

/**
* Serviço de Agendamentos
*/
import { apiClient } from "../api/client";
import type {
Appointment,
CreateAppointmentInput,
UpdateAppointmentInput,
AppointmentFilters,
GetAvailableSlotsInput,
GetAvailableSlotsResponse,
} from "./types";
class AppointmentService {
private readonly basePath = "/appointments";
/**
* Busca horários disponíveis de um médico
* POST /functions/v1/get-available-slots
*/
async getAvailableSlots(
data: GetAvailableSlotsInput
): Promise<GetAvailableSlotsResponse> {
try {
console.log("[AppointmentService] Chamando get-available-slots:", data);
// Usa callFunction para chamar a Edge Function
const response = await apiClient.callFunction<GetAvailableSlotsResponse>(
"get-available-slots",
data
);
console.log(
"[AppointmentService] Resposta get-available-slots:",
response.data
);
return response.data;
} catch (error: any) {
console.error("[AppointmentService] ❌ Erro ao buscar slots:");
console.error("[AppointmentService] Status:", error?.response?.status);
console.error(
"[AppointmentService] Response Data:",
JSON.stringify(error?.response?.data, null, 2)
);
console.error("[AppointmentService] Message:", error?.message);
console.error(
"[AppointmentService] Input enviado:",
JSON.stringify(data, null, 2)
);
throw new Error(
error?.response?.data?.message ||
error?.message ||
"Erro ao buscar horários disponíveis"
);
}
}
/**
* Lista agendamentos com filtros opcionais
*/
async list(filters?: AppointmentFilters): Promise<Appointment[]> {
const params: Record<string, string> = {};
if (filters?.doctor_id) {
params["doctor_id"] = `eq.${filters.doctor_id}`;
}
if (filters?.patient_id) {
params["patient_id"] = `eq.${filters.patient_id}`;
}
if (filters?.status) {
params["status"] = `eq.${filters.status}`;
}
if (filters?.scheduled_at) {
params["scheduled_at"] = filters.scheduled_at;
}
if (filters?.limit) {
params["limit"] = filters.limit.toString();
}
if (filters?.offset) {
params["offset"] = filters.offset.toString();
}
if (filters?.order) {
params["order"] = filters.order;
}
const response = await apiClient.get<Appointment[]>(this.basePath, {
params,
});
return response.data;
}
/**
* Busca agendamento por ID
*/
async getById(id: string): Promise<Appointment> {
const response = await apiClient.get<Appointment[]>(
`${this.basePath}?id=eq.${id}`
);
if (response.data && response.data.length > 0) {
return response.data[0];
}
throw new Error("Agendamento não encontrado");
}
/**
* Cria novo agendamento
* POST /rest/v1/appointments
* Nota: order_number é gerado automaticamente (APT-YYYY-NNNN)
*/
async create(data: CreateAppointmentInput): Promise<Appointment> {
try {
console.log("[AppointmentService] Criando agendamento:", data);
// Adiciona created_by se não estiver presente
const payload = {
...data,
duration_minutes: data.duration_minutes || 30,
appointment_type: data.appointment_type || "presencial",
status: "requested",
};
console.log("[AppointmentService] Payload final:", payload);
const response = await apiClient.post<Appointment[]>(
this.basePath,
payload,
{
headers: {
Prefer: "return=representation",
},
}
);
console.log("[AppointmentService] Resposta da API:", response.data);
if (response.data && response.data.length > 0) {
return response.data[0];
}
throw new Error("Erro ao criar agendamento");
} catch (error: any) {
console.error("[AppointmentService] Erro ao criar agendamento:", {
error,
message: error?.message,
response: error?.response,
data: error?.response?.data,
status: error?.response?.status,
});
throw error;
}
}
/**
* Atualiza agendamento existente
*/
async update(id: string, data: UpdateAppointmentInput): Promise<Appointment> {
const response = await apiClient.patch<Appointment[]>(
`${this.basePath}?id=eq.${id}`,
data
);
if (response.data && response.data.length > 0) {
return response.data[0];
}
throw new Error("Agendamento não encontrado");
}
/**
* Deleta agendamento
*/
async delete(id: string): Promise<void> {
await apiClient.delete(`${this.basePath}?id=eq.${id}`);
}
}
export const appointmentService = new AppointmentService();