Moves the functions and types related to patients and physicians from the single file lib/api.ts to their own dedicated files in lib/api/pacientes.ts and lib/api/medicos.ts.
269 lines
7.6 KiB
TypeScript
269 lines
7.6 KiB
TypeScript
// lib/api.ts
|
|
|
|
// Re-exporta as funções e tipos dos módulos específicos
|
|
export * from "./api/pacientes";
|
|
export * from "./api/medicos";
|
|
|
|
// Mantenha aqui apenas o código base da API que é compartilhado
|
|
|
|
export type ApiOk<T = any> = {
|
|
success?: boolean;
|
|
data: T;
|
|
message?: string;
|
|
pagination?: {
|
|
current_page?: number;
|
|
per_page?: number;
|
|
total_pages?: number;
|
|
total?: number;
|
|
};
|
|
};
|
|
|
|
// ===== TIPOS COMUNS =====
|
|
export type Endereco = {
|
|
cep?: string;
|
|
logradouro?: string;
|
|
numero?: string;
|
|
complemento?: string;
|
|
bairro?: string;
|
|
cidade?: string;
|
|
estado?: string;
|
|
};
|
|
|
|
// ===== PACIENTES =====
|
|
export type Paciente = {
|
|
id: string;
|
|
nome?: string;
|
|
nome_social?: string | null;
|
|
cpf?: string;
|
|
rg?: string | null;
|
|
sexo?: string | null;
|
|
data_nascimento?: string | null;
|
|
telefone?: string;
|
|
email?: string;
|
|
endereco?: Endereco;
|
|
observacoes?: string | null;
|
|
foto_url?: string | null;
|
|
};
|
|
|
|
export type PacienteInput = {
|
|
nome: string;
|
|
nome_social?: string | null;
|
|
cpf: string;
|
|
rg?: string | null;
|
|
sexo?: string | null;
|
|
data_nascimento?: string | null;
|
|
telefone?: string | null;
|
|
email?: string | null;
|
|
endereco?: Endereco;
|
|
observacoes?: string | null;
|
|
};
|
|
|
|
// ===== MÉDICOS =====
|
|
export type FormacaoAcademica = {
|
|
instituicao: string;
|
|
curso: string;
|
|
ano_conclusao: string;
|
|
};
|
|
|
|
export type DadosBancarios = {
|
|
banco: string;
|
|
agencia: string;
|
|
conta: string;
|
|
tipo_conta: string;
|
|
};
|
|
|
|
export type Medico = {
|
|
id: string;
|
|
nome?: string;
|
|
nome_social?: string | null;
|
|
cpf?: string;
|
|
rg?: string | null;
|
|
sexo?: string | null;
|
|
data_nascimento?: string | null;
|
|
telefone?: string;
|
|
celular?: string;
|
|
contato_emergencia?: string;
|
|
email?: string;
|
|
crm?: string;
|
|
estado_crm?: string;
|
|
rqe?: string;
|
|
formacao_academica?: FormacaoAcademica[];
|
|
curriculo_url?: string | null;
|
|
especialidade?: string;
|
|
observacoes?: string | null;
|
|
foto_url?: string | null;
|
|
tipo_vinculo?: string;
|
|
dados_bancarios?: DadosBancarios;
|
|
agenda_horario?: string;
|
|
valor_consulta?: number | string;
|
|
};
|
|
|
|
export type MedicoInput = {
|
|
nome: string;
|
|
nome_social?: string | null;
|
|
cpf?: string | null;
|
|
rg?: string | null;
|
|
sexo?: string | null;
|
|
data_nascimento?: string | null;
|
|
telefone?: string | null;
|
|
celular?: string | null;
|
|
contato_emergencia?: string | null;
|
|
email?: string | null;
|
|
crm: string;
|
|
estado_crm?: string | null;
|
|
rqe?: string | null;
|
|
formacao_academica?: FormacaoAcademica[];
|
|
curriculo_url?: string | null;
|
|
especialidade: string;
|
|
observacoes?: string | null;
|
|
tipo_vinculo?: string | null;
|
|
dados_bancarios?: DadosBancarios | null;
|
|
agenda_horario?: string | null;
|
|
valor_consulta?: number | string | null;
|
|
};
|
|
|
|
//
|
|
// Perfis de Usuário (Profiles)
|
|
//
|
|
|
|
export type UserProfile = {
|
|
id: string;
|
|
full_name?: string;
|
|
email?: string;
|
|
phone?: string;
|
|
avatar_url?: string;
|
|
disabled?: boolean;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
};
|
|
|
|
export type UserProfileInput = {
|
|
full_name?: string;
|
|
email?: string;
|
|
phone?: string;
|
|
avatar_url?: string;
|
|
disabled?: boolean;
|
|
};
|
|
|
|
export async function listarPerfis(params?: { page?: number; limit?: number; q?: string }): Promise<UserProfile[]> {
|
|
const query = new URLSearchParams();
|
|
if (params?.page) query.set("page", String(params.page));
|
|
if (params?.limit) query.set("limit", String(params.limit));
|
|
if (params?.q) query.set("q", params.q);
|
|
const url = `${API_BASE}/rest/v1/profiles${query.toString() ? `?${query.toString()}` : ""}`;
|
|
|
|
const res = await fetch(url, { method: "GET", headers: headers("json") });
|
|
const data = await parse<ApiOk<UserProfile[]>>(res);
|
|
logAPI("listarPerfis", { url, result: data });
|
|
return data?.data ?? (data as any);
|
|
}
|
|
|
|
export async function buscarPerfilPorId(id: string | number): Promise<UserProfile> {
|
|
const url = `${API_BASE}/rest/v1/profiles?id=eq.${id}`;
|
|
const res = await fetch(url, { method: "GET", headers: headers("json") });
|
|
// A API da Supabase/PostgREST retorna um array mesmo pedindo um ID, então pegamos o primeiro.
|
|
const data = await parse<UserProfile[]>(res);
|
|
const profile = data[0];
|
|
logAPI("buscarPerfilPorId", { url, result: profile });
|
|
return profile;
|
|
}
|
|
|
|
export async function atualizarPerfil(id: string | number, input: UserProfileInput): Promise<UserProfile> {
|
|
const url = `${API_BASE}/rest/v1/profiles?id=eq.${id}`;
|
|
const res = await fetch(url, { method: "PATCH", headers: headers("json"), body: JSON.stringify(input) });
|
|
// O método PATCH no PostgREST retorna um array vazio por padrão. Para retornar os dados, precisa de um header `Prefer: return=representation`
|
|
// Por simplicidade, vamos assumir que se não deu erro, a operação foi um sucesso.
|
|
// Se a API estiver configurada para retornar o objeto, o parse vai funcionar.
|
|
const data = await parse<ApiOk<UserProfile>>(res);
|
|
logAPI("atualizarPerfil", { url, payload: input, result: data });
|
|
return data?.data ?? (data as any);
|
|
}
|
|
|
|
|
|
// ===== CONFIG =====
|
|
export const API_BASE =
|
|
process.env.NEXT_PUBLIC_API_BASE ?? "https://yuanqfswhberkoevtmfr.supabase.co";
|
|
export const REST = `${API_BASE}/rest/v1`;
|
|
|
|
// Token salvo no browser (aceita auth_token ou token)
|
|
function getAuthToken(): string | null {
|
|
if (typeof window === "undefined") return null;
|
|
return (
|
|
localStorage.getItem("auth_token") ||
|
|
localStorage.getItem("token") ||
|
|
sessionStorage.getItem("auth_token") ||
|
|
sessionStorage.getItem("token")
|
|
);
|
|
}
|
|
|
|
// Cabeçalhos base
|
|
export function baseHeaders(): Record<string, string> {
|
|
const h: Record<string, string> = {
|
|
apikey:
|
|
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl1YW5xZnN3aGJlcmtvZXZ0bWZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQ5NTQzNjksImV4cCI6MjA3MDUzMDM2OX0.g8Fm4XAvtX46zifBZnYVH4tVuQkqUH6Ia9CXQj4DztQ",
|
|
Accept: "application/json",
|
|
};
|
|
const jwt = getAuthToken();
|
|
if (jwt) h.Authorization = `Bearer ${jwt}`;
|
|
return h;
|
|
}
|
|
|
|
// Para POST/PATCH/DELETE e para GET com count
|
|
export function withPrefer(h: Record<string, string>, prefer: string) {
|
|
return { ...h, Prefer: prefer };
|
|
}
|
|
|
|
// Parse genérico
|
|
export async function parse<T>(res: Response): Promise<T> {
|
|
let json: any = null;
|
|
try {
|
|
json = await res.json();
|
|
} catch {}
|
|
if (!res.ok) {
|
|
console.error("[API ERROR]", res.url, res.status, json);
|
|
const code = (json && (json.error?.code || json.code)) ?? res.status;
|
|
const msg = (json && (json.error?.message || json.message)) ?? res.statusText;
|
|
throw new Error(`${code}: ${msg}`);
|
|
}
|
|
return (json?.data ?? json) as T;
|
|
}
|
|
|
|
// Helper de paginação (Range/Range-Unit)
|
|
export function rangeHeaders(page?: number, limit?: number): Record<string, string> {
|
|
if (!page || !limit) return {};
|
|
const start = (page - 1) * limit;
|
|
const end = start + limit - 1;
|
|
return { Range: `${start}-${end}`, "Range-Unit": "items" };
|
|
}
|
|
|
|
// ===== CEP (usado nos formulários) =====
|
|
export async function buscarCepAPI(cep: string): Promise<{
|
|
logradouro?: string;
|
|
bairro?: string;
|
|
localidade?: string;
|
|
uf?: string;
|
|
erro?: boolean;
|
|
}> {
|
|
const clean = (cep || "").replace(/\D/g, "");
|
|
try {
|
|
const res = await fetch(`https://viacep.com.br/ws/${clean}/json/`);
|
|
const json = await res.json();
|
|
if (json?.erro) return { erro: true };
|
|
return {
|
|
logradouro: json.logradouro ?? "",
|
|
bairro: json.bairro ?? "",
|
|
localidade: json.localidade ?? "",
|
|
uf: json.uf ?? "",
|
|
erro: false,
|
|
};
|
|
} catch {
|
|
return { erro: true };
|
|
}
|
|
}
|
|
|
|
// Funções de log e outras utilidades podem ser mantidas aqui se necessário
|
|
export const logAPI = (name: string, details: any) => {
|
|
if (process.env.NODE_ENV === 'development') {
|
|
console.log(`[API Call: ${name}]`, details);
|
|
}
|
|
}; |