diff --git a/susconecta/components/forms/patient-registration-form.tsx b/susconecta/components/forms/patient-registration-form.tsx index 3c6247c..81a5a62 100644 --- a/susconecta/components/forms/patient-registration-form.tsx +++ b/susconecta/components/forms/patient-registration-form.tsx @@ -26,8 +26,9 @@ import { listarAnexos, removerAnexo, buscarPacientePorId, - listarPerfis, } from "@/lib/api"; +import { listarPerfis } from "@/lib/api/perfis"; +import { criarUsuario } from "@/lib/api/usuarios"; type Mode = "create" | "edit"; @@ -231,23 +232,21 @@ export function PatientRegistrationForm({ let saved: Paciente; if (mode === "create") { saved = await criarPaciente(payload); - - console.log("--- INÍCIO DO TESTE DE API ---"); - console.log("Paciente recém-criado:", saved); - try { - console.log("Buscando lista de perfis para verificar a criação..."); - const perfis = await listarPerfis(); - console.log("Lista de Perfis encontrada:", perfis); - const perfilCorrespondente = perfis.find(p => p.email === saved.email); - if (perfilCorrespondente) { - console.log("SUCESSO: Perfil correspondente foi encontrado!", perfilCorrespondente); - } else { - console.log("FALHA: Nenhum perfil correspondente ao email do paciente foi encontrado na lista de perfis."); + + if (saved.email && saved.nome) { + try { + await criarUsuario({ + email: saved.email, + full_name: saved.nome, + phone: saved.telefone || undefined, + role: 'paciente', + }); + } catch (userError) { + console.error("Falha ao criar usuário para o paciente:", userError); + // TODO: O que fazer se a criação do usuário falhar? + // Por enquanto, apenas logamos o erro. } - } catch (error) { - console.error("ERRO AO BUSCAR PERFIS:", error); } - console.log("--- FIM DO TESTE DE API ---"); } else { if (patientId == null) throw new Error("Paciente inexistente para edição"); diff --git a/susconecta/lib/api.ts b/susconecta/lib/api.ts index 8efdb88..d441645 100644 --- a/susconecta/lib/api.ts +++ b/susconecta/lib/api.ts @@ -60,7 +60,7 @@ export type PacienteInput = { -const API_BASE = process.env.NEXT_PUBLIC_API_BASE ?? "https://mock.apidog.com/m1/1053378-0-default"; +export const API_BASE = process.env.NEXT_PUBLIC_API_BASE ?? "https://mock.apidog.com/m1/1053378-0-default"; const MEDICOS_BASE = process.env.NEXT_PUBLIC_MEDICOS_BASE_PATH ?? "/medicos"; export const PATHS = { @@ -88,7 +88,7 @@ function getAuthToken(): string | null { return localStorage.getItem('auth_token'); } -function headers(kind: "json" | "form" = "json"): Record { +export function headers(kind: "json" | "form" = "json"): Record { const h: Record = {}; // API Key da Supabase sempre necessária @@ -104,7 +104,7 @@ function headers(kind: "json" | "form" = "json"): Record { return h; } -function logAPI(title: string, info: { url?: string; payload?: any; result?: any } = {}) { +export function logAPI(title: string, info: { url?: string; payload?: any; result?: any } = {}) { try { console.group(`[API] ${title}`); if (info.url) console.log("url:", info.url); @@ -114,7 +114,7 @@ function logAPI(title: string, info: { url?: string; payload?: any; result?: any } catch {} } -async function parse(res: Response): Promise { +export async function parse(res: Response): Promise { let json: any = null; try { json = await res.json(); @@ -344,135 +344,6 @@ export type MedicoInput = { 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 { - 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>(res); - logAPI("listarPerfis", { url, result: data }); - return data?.data ?? (data as any); -} - -export async function buscarPerfilPorId(id: string | number): Promise { - 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(res); - const profile = data[0]; - logAPI("buscarPerfilPorId", { url, result: profile }); - return profile; -} - -export async function atualizarPerfil(id: string | number, input: UserProfileInput): Promise { - 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>(res); - logAPI("atualizarPerfil", { url, payload: input, result: data }); - return data?.data ?? (data as any); -} - - -// -// User Management APIs -// - -export type UserRole = { - id: string; - user_id: string; - role: 'admin' | 'medico' | 'paciente'; - created_at: string; -}; - -export type CreateUserInput = { - email: string; - password?: string; - full_name: string; - phone?: string; - role: 'admin' | 'medico' | 'paciente'; -}; - -export type CreatedUser = { - id: string; - email: string; - full_name: string; - phone?: string; - role: string; -}; - -export type CompleteUserInfo = { - user: { - id: string; - email: string; - email_confirmed_at: string; - created_at: string; - last_sign_in_at: string; - }; - profile: UserProfile; - roles: string[]; - permissions: { - isAdmin: boolean; - isManager: boolean; - isDoctor: boolean; - isSecretary: boolean; - isAdminOrManager: boolean; - }; -}; - -export async function criarUsuario(input: CreateUserInput): Promise<{ success: boolean; user: CreatedUser }> { - const url = `${API_BASE}/functions/v1/create-user`; - const res = await fetch(url, { method: "POST", headers: headers("json"), body: JSON.stringify(input) }); - const data = await parse(res); - logAPI("criarUsuario", { url, payload: input, result: data }); - return data; -} - -export async function listarUserRoles(): Promise { - const url = `${API_BASE}/rest/v1/user_roles`; - const res = await fetch(url, { method: "GET", headers: headers("json") }); - const data = await parse(res); - logAPI("listarUserRoles", { url, result: data }); - return data ?? []; -} - -export async function getCompleteUserInfo(userId: string): Promise { - const url = `${API_BASE}/functions/v1/user-info`; - // Assuming the function takes the user ID in the body of a POST request - const res = await fetch(url, { method: "POST", headers: headers("json"), body: JSON.stringify({ id: userId }) }); - const data = await parse(res); - logAPI("getCompleteUserInfo", { url, payload: { id: userId }, result: data }); - return data; -} - // // MÉDICOS (CRUD) diff --git a/susconecta/lib/api/medicos.ts b/susconecta/lib/api/medicos.ts new file mode 100644 index 0000000..3ae4724 --- /dev/null +++ b/susconecta/lib/api/medicos.ts @@ -0,0 +1 @@ +// Arquivo reservado para as APIs de Médicos diff --git a/susconecta/lib/api/pacientes.ts b/susconecta/lib/api/pacientes.ts new file mode 100644 index 0000000..461e86a --- /dev/null +++ b/susconecta/lib/api/pacientes.ts @@ -0,0 +1 @@ +// Arquivo reservado para as APIs de Pacientes diff --git a/susconecta/lib/api/perfis.ts b/susconecta/lib/api/perfis.ts new file mode 100644 index 0000000..6234253 --- /dev/null +++ b/susconecta/lib/api/perfis.ts @@ -0,0 +1,64 @@ +import { + API_BASE, + headers, + logAPI, + parse, +} from "../api"; +import type { ApiOk } from "../api"; + +// +// 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 { + 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>(res); + logAPI("listarPerfis", { url, result: data }); + return data?.data ?? (data as any); +} + +export async function buscarPerfilPorId(id: string | number): Promise { + 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(res); + const profile = data[0]; + logAPI("buscarPerfilPorId", { url, result: profile }); + return profile; +} + +export async function atualizarPerfil(id: string | number, input: UserProfileInput): Promise { + 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>(res); + logAPI("atualizarPerfil", { url, payload: input, result: data }); + return data?.data ?? (data as any); +} \ No newline at end of file diff --git a/susconecta/lib/api/usuarios.ts b/susconecta/lib/api/usuarios.ts new file mode 100644 index 0000000..b7485e5 --- /dev/null +++ b/susconecta/lib/api/usuarios.ts @@ -0,0 +1,79 @@ +import { + API_BASE, + headers, + logAPI, + parse, +} from "../api"; +import type { ApiOk } from "../api"; +import type { UserProfile } from "./perfis"; + +// +// User Management APIs +// + +export type UserRole = { + id: string; + user_id: string; + role: 'admin' | 'medico' | 'paciente'; + created_at: string; +}; + +export type CreateUserInput = { + email: string; + password?: string; + full_name: string; + phone?: string; + role: 'admin' | 'medico' | 'paciente'; +}; + +export type CreatedUser = { + id: string; + email: string; + full_name: string; + phone?: string; + role: string; +}; + +export type CompleteUserInfo = { + user: { + id: string; + email: string; + email_confirmed_at: string; + created_at: string; + last_sign_in_at: string; + }; + profile: UserProfile; + roles: string[]; + permissions: { + isAdmin: boolean; + isManager: boolean; + isDoctor: boolean; + isSecretary: boolean; + isAdminOrManager: boolean; + }; +}; + +export async function criarUsuario(input: CreateUserInput): Promise<{ success: boolean; user: CreatedUser }> { + const url = `${API_BASE}/functions/v1/create-user`; + const res = await fetch(url, { method: "POST", headers: headers("json"), body: JSON.stringify(input) }); + const data = await parse(res); + logAPI("criarUsuario", { url, payload: input, result: data }); + return data; +} + +export async function listarUserRoles(): Promise { + const url = `${API_BASE}/rest/v1/user_roles`; + const res = await fetch(url, { method: "GET", headers: headers("json") }); + const data = await parse(res); + logAPI("listarUserRoles", { url, result: data }); + return data ?? []; +} + +export async function getCompleteUserInfo(userId: string): Promise { + const url = `${API_BASE}/functions/v1/user-info`; + // Assuming the function takes the user ID in the body of a POST request + const res = await fetch(url, { method: "POST", headers: headers("json"), body: JSON.stringify({ id: userId }) }); + const data = await parse(res); + logAPI("getCompleteUserInfo", { url, payload: { id: userId }, result: data }); + return data; +} \ No newline at end of file