- 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
184 lines
4.7 KiB
TypeScript
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();
|