239 lines
6.7 KiB
TypeScript
239 lines
6.7 KiB
TypeScript
import api from "./api";
|
|
import ENDPOINTS from "./endpoints";
|
|
import { ApiResponse } from "./http";
|
|
|
|
export interface Consulta {
|
|
id: string;
|
|
pacienteId: string;
|
|
medicoId: string;
|
|
dataHora: string; // ISO
|
|
status: string; // agendada | confirmada | cancelada | realizada | faltou
|
|
tipo?: string;
|
|
motivo?: string;
|
|
observacoes?: string;
|
|
valorPago?: number;
|
|
formaPagamento?: string;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
export interface ConsultaCreate {
|
|
pacienteId: string;
|
|
medicoId: string;
|
|
dataHora: string;
|
|
tipo?: string;
|
|
motivo?: string;
|
|
observacoes?: string;
|
|
}
|
|
|
|
export interface ConsultaUpdate {
|
|
dataHora?: string;
|
|
status?: string;
|
|
tipo?: string;
|
|
motivo?: string;
|
|
observacoes?: string;
|
|
valorPago?: number;
|
|
formaPagamento?: string;
|
|
}
|
|
|
|
interface RawConsulta {
|
|
id?: string;
|
|
_id?: string;
|
|
Id?: string;
|
|
consultaId?: string;
|
|
pacienteId?: string;
|
|
patient_id?: string;
|
|
paciente?: string;
|
|
medicoId?: string;
|
|
doctor_id?: string;
|
|
medico?: string;
|
|
dataHora?: string;
|
|
data_hora?: string;
|
|
date?: string;
|
|
status?: string;
|
|
tipo?: string;
|
|
tipoConsulta?: string;
|
|
type?: string;
|
|
motivo?: string;
|
|
motivoConsulta?: string;
|
|
observacoes?: string;
|
|
notes?: string;
|
|
valorPago?: number;
|
|
valor_pago?: number;
|
|
formaPagamento?: string;
|
|
payment_method?: string;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
class ConsultasService {
|
|
async listarPorPaciente(
|
|
pacienteId: string,
|
|
params?: { futureOnly?: boolean; limit?: number; sort?: "asc" | "desc" }
|
|
): Promise<ApiResponse<Consulta[]>> {
|
|
try {
|
|
// Supabase PostgREST usa filtros específicos: patient_id=eq.valor
|
|
const queryParams: Record<string, string> = {
|
|
patient_id: `eq.${pacienteId}`,
|
|
};
|
|
|
|
if (params?.limit) {
|
|
queryParams.limit = String(params.limit);
|
|
}
|
|
|
|
if (params?.sort) {
|
|
queryParams.order = `dataHora.${params.sort}`;
|
|
}
|
|
|
|
const response = await api.get(ENDPOINTS.CONSULTATIONS, {
|
|
params: queryParams,
|
|
});
|
|
const data: RawConsulta[] = Array.isArray(response.data)
|
|
? response.data
|
|
: response.data?.data || [];
|
|
return {
|
|
success: true,
|
|
data: data.map(this.mapConsulta),
|
|
};
|
|
} catch (error) {
|
|
console.error("Erro ao listar consultas por paciente:", error);
|
|
return { success: false, error: "Erro ao listar consultas" };
|
|
}
|
|
}
|
|
|
|
async listarPorMedico(
|
|
medicoId: string,
|
|
params?: {
|
|
dateFrom?: string;
|
|
dateTo?: string;
|
|
status?: string;
|
|
limit?: number;
|
|
}
|
|
): Promise<ApiResponse<Consulta[]>> {
|
|
try {
|
|
const queryParams: Record<string, string> = {
|
|
doctor_id: `eq.${medicoId}`,
|
|
};
|
|
|
|
if (params?.status) {
|
|
queryParams.status = `eq.${params.status}`;
|
|
}
|
|
|
|
if (params?.dateFrom) {
|
|
queryParams.dataHora = `gte.${params.dateFrom}`;
|
|
}
|
|
|
|
if (params?.dateTo) {
|
|
queryParams.dataHora = `lte.${params.dateTo}`;
|
|
}
|
|
|
|
if (params?.limit) {
|
|
queryParams.limit = String(params.limit);
|
|
}
|
|
|
|
const response = await api.get(ENDPOINTS.CONSULTATIONS, {
|
|
params: queryParams,
|
|
});
|
|
const data: RawConsulta[] = Array.isArray(response.data)
|
|
? response.data
|
|
: response.data?.data || [];
|
|
return { success: true, data: data.map(this.mapConsulta) };
|
|
} catch (error) {
|
|
console.error("Erro ao listar consultas por médico:", error);
|
|
return { success: false, error: "Erro ao listar consultas" };
|
|
}
|
|
}
|
|
|
|
async criar(payload: ConsultaCreate): Promise<ApiResponse<Consulta>> {
|
|
try {
|
|
const response = await api.post(ENDPOINTS.CONSULTATIONS, payload);
|
|
return { success: true, data: this.mapConsulta(response.data) };
|
|
} catch (error) {
|
|
console.error("Erro ao criar consulta:", error);
|
|
return { success: false, error: "Erro ao criar consulta" };
|
|
}
|
|
}
|
|
|
|
async atualizar(
|
|
id: string,
|
|
updates: ConsultaUpdate
|
|
): Promise<ApiResponse<Consulta>> {
|
|
try {
|
|
const response = await api.patch(
|
|
`${ENDPOINTS.CONSULTATIONS}/${id}`,
|
|
updates
|
|
);
|
|
return { success: true, data: this.mapConsulta(response.data) };
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar consulta:", error);
|
|
return { success: false, error: "Erro ao atualizar consulta" };
|
|
}
|
|
}
|
|
|
|
async deletar(id: string): Promise<ApiResponse<void>> {
|
|
try {
|
|
await api.delete(`${ENDPOINTS.CONSULTATIONS}/${id}`);
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error("Erro ao deletar consulta:", error);
|
|
return { success: false, error: "Erro ao deletar consulta" };
|
|
}
|
|
}
|
|
|
|
async obterUltimaPorPaciente(
|
|
pacienteId: string
|
|
): Promise<ApiResponse<Consulta | null>> {
|
|
try {
|
|
const list = await this.listarPorPaciente(pacienteId, { limit: 10 });
|
|
if (!list.success || !list.data) return { success: true, data: null };
|
|
const sorted = [...list.data].sort((a, b) =>
|
|
b.dataHora.localeCompare(a.dataHora)
|
|
);
|
|
return { success: true, data: sorted[0] || null };
|
|
} catch {
|
|
return { success: false, error: "Erro ao obter última consulta" };
|
|
}
|
|
}
|
|
|
|
async obterProximaPorPaciente(
|
|
pacienteId: string
|
|
): Promise<ApiResponse<Consulta | null>> {
|
|
try {
|
|
const agora = new Date().toISOString();
|
|
const list = await this.listarPorPaciente(pacienteId, { limit: 50 });
|
|
if (!list.success || !list.data) return { success: true, data: null };
|
|
const futuras = list.data.filter((c) => c.dataHora >= agora);
|
|
futuras.sort((a, b) => a.dataHora.localeCompare(b.dataHora));
|
|
return { success: true, data: futuras[0] || null };
|
|
} catch {
|
|
return { success: false, error: "Erro ao obter próxima consulta" };
|
|
}
|
|
}
|
|
|
|
private mapConsulta(raw: RawConsulta): Consulta {
|
|
return {
|
|
id:
|
|
raw.id ||
|
|
raw._id ||
|
|
raw.Id ||
|
|
raw.consultaId ||
|
|
Math.random().toString(36).slice(2, 11),
|
|
pacienteId: raw.pacienteId || raw.patient_id || raw.paciente || "",
|
|
medicoId: raw.medicoId || raw.doctor_id || raw.medico || "",
|
|
dataHora:
|
|
raw.dataHora || raw.data_hora || raw.date || new Date().toISOString(),
|
|
status: raw.status || "agendada",
|
|
tipo: raw.tipo || raw.tipoConsulta || raw.type || undefined,
|
|
motivo: raw.motivo || raw.motivoConsulta || undefined,
|
|
observacoes: raw.observacoes || raw.notes || undefined,
|
|
valorPago: raw.valorPago ?? raw.valor_pago ?? undefined,
|
|
formaPagamento: raw.formaPagamento || raw.payment_method || undefined,
|
|
created_at: raw.created_at,
|
|
updated_at: raw.updated_at,
|
|
};
|
|
}
|
|
}
|
|
|
|
export const consultasService = new ConsultasService();
|
|
export default consultasService;
|