feat(auth): Creates user in patient registration

- Adds automatic user creation in the new patient registration flow.              - To avoid merge conflicts, the user and profile APIs have been separated from the main lib/api.ts file.
This commit is contained in:
M-Gabrielly 2025-09-30 12:01:37 -03:00
parent cb70c0a45a
commit cde4c42309
5 changed files with 160 additions and 16 deletions

View File

@ -25,8 +25,9 @@ import {
listarAnexos, listarAnexos,
removerAnexo, removerAnexo,
buscarPacientePorId, buscarPacientePorId,
listarPerfis,
} from "@/lib/api"; } from "@/lib/api";
import { listarPerfis } from "@/lib/api/perfis";
import { criarUsuario } from "@/lib/api/usuarios";
import { validarCPFLocal } from "@/lib/utils"; import { validarCPFLocal } from "@/lib/utils";
import { verificarCpfDuplicado } from "@/lib/api"; import { verificarCpfDuplicado } from "@/lib/api";
@ -241,23 +242,21 @@ export function PatientRegistrationForm({
let saved: Paciente; let saved: Paciente;
if (mode === "create") { if (mode === "create") {
saved = await criarPaciente(payload); saved = await criarPaciente(payload);
console.log("--- INÍCIO DO TESTE DE API ---"); if (saved.email && saved.nome) {
console.log("Paciente recém-criado:", saved); try {
try { await criarUsuario({
console.log("Buscando lista de perfis para verificar a criação..."); email: saved.email,
const perfis = await listarPerfis(); full_name: saved.nome,
console.log("Lista de Perfis encontrada:", perfis); phone: saved.telefone || undefined,
const perfilCorrespondente = perfis.find(p => p.email === saved.email); role: 'paciente',
if (perfilCorrespondente) { });
console.log("SUCESSO: Perfil correspondente foi encontrado!", perfilCorrespondente); } catch (userError) {
} else { console.error("Falha ao criar usuário para o paciente:", userError);
console.log("FALHA: Nenhum perfil correspondente ao email do paciente foi encontrado na lista de perfis."); // 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 { } else {
if (patientId == null) throw new Error("Paciente inexistente para edição"); if (patientId == null) throw new Error("Paciente inexistente para edição");

View File

@ -0,0 +1 @@
// Arquivo reservado para as APIs de Médicos

View File

@ -0,0 +1 @@
// Arquivo reservado para as APIs de Pacientes

View File

@ -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<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);
}

View File

@ -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<any>(res);
logAPI("criarUsuario", { url, payload: input, result: data });
return data;
}
export async function listarUserRoles(): Promise<UserRole[]> {
const url = `${API_BASE}/rest/v1/user_roles`;
const res = await fetch(url, { method: "GET", headers: headers("json") });
const data = await parse<UserRole[]>(res);
logAPI("listarUserRoles", { url, result: data });
return data ?? [];
}
export async function getCompleteUserInfo(userId: string): Promise<CompleteUserInfo> {
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<CompleteUserInfo>(res);
logAPI("getCompleteUserInfo", { url, payload: { id: userId }, result: data });
return data;
}