From 535f400f2d67efe8e9cee566eb408600b4a99802 Mon Sep 17 00:00:00 2001 From: M-Gabrielly Date: Sat, 11 Oct 2025 00:35:52 -0300 Subject: [PATCH] feat(auth):refaz fluxo de cadastro --- susconecta/Documentação API.md | 247 ++++++++++++++++++ susconecta/ERRO_BACKEND_EDGE_FUNCTION.md | 182 +++++++++++++ susconecta/app/api/assign-role/route.ts | 158 +++++++++++ .../forms/doctor-registration-form.tsx | 145 ++++++---- .../forms/patient-registration-form.tsx | 101 ++++--- 5 files changed, 729 insertions(+), 104 deletions(-) create mode 100644 susconecta/ERRO_BACKEND_EDGE_FUNCTION.md create mode 100644 susconecta/app/api/assign-role/route.ts diff --git a/susconecta/Documentação API.md b/susconecta/Documentação API.md index 1758ac0..b9138c8 100644 --- a/susconecta/Documentação API.md +++ b/susconecta/Documentação API.md @@ -940,4 +940,251 @@ security: - bearer: [] ``` +# Fazer login e obter token JWT + +## OpenAPI Specification + +```yaml +openapi: 3.0.1 +info: + title: '' + description: '' + version: 1.0.0 +paths: + /auth/v1/token: + post: + summary: Fazer login e obter token JWT + deprecated: false + description: >- + Autentica o usuário e retorna um token JWT para usar em outras + requisições. + tags: + - Authentication + parameters: + - name: grant_type + in: query + description: '' + required: true + schema: + type: string + enum: + - password + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LoginRequest' + examples: {} + responses: + '200': + description: Login realizado com sucesso + content: + application/json: + schema: + $ref: '#/components/schemas/LoginResponse' + headers: {} + x-apidog-name: OK + '400': + description: Credenciais inválidas + content: + application/json: + schema: &ref_0 + $ref: '#/components/schemas/Error' + headers: {} + x-apidog-name: Bad Request + '401': + description: Email ou senha incorretos + content: + application/json: + schema: *ref_0 + headers: {} + x-apidog-name: Unauthorized + security: + - bearer: [] + x-apidog-folder: Authentication + x-apidog-status: released + x-run-in-apidog: https://app.apidog.com/web/project/1053378/apis/api-21940510-run +components: + schemas: + LoginRequest: + type: object + required: + - email + - password + properties: + email: + type: string + format: email + examples: + - usuario@exemplo.com + password: + type: string + minLength: 6 + examples: + - senha123 + x-apidog-orders: + - email + - password + x-apidog-ignore-properties: [] + x-apidog-folder: '' + LoginResponse: + type: object + properties: + access_token: + type: string + description: Token JWT para autenticação + examples: + - eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + token_type: + type: string + examples: + - bearer + expires_in: + type: integer + description: Tempo de expiração do token em segundos + examples: + - 3600 + refresh_token: + type: string + description: Token para renovar o access_token + user: + $ref: '#/components/schemas/AuthUser' + x-apidog-orders: + - access_token + - token_type + - expires_in + - refresh_token + - user + x-apidog-ignore-properties: [] + x-apidog-folder: '' + AuthUser: + type: object + properties: + id: + type: string + format: uuid + email: + type: string + format: email + email_confirmed_at: + type: string + format: date-time + nullable: true + created_at: + type: string + format: date-time + x-apidog-orders: + - id + - email + - email_confirmed_at + - created_at + x-apidog-ignore-properties: [] + x-apidog-folder: '' + Error: + type: object + properties: + error: + type: string + message: + type: string + code: + type: string + x-apidog-orders: + - error + - message + - code + x-apidog-ignore-properties: [] + x-apidog-folder: '' + securitySchemes: + bearerAuth: + type: jwt + scheme: bearer + bearerFormat: JWT + description: Token JWT obtido no login + bearer: + type: http + scheme: bearer +servers: + - url: https://yuanqfswhberkoevtmfr.supabase.co + description: Prod Env + - url: '' + description: Cloud Mock +security: + - bearer: [] + +``` + +# Logout do usuário + +## OpenAPI Specification + +```yaml +openapi: 3.0.1 +info: + title: '' + description: '' + version: 1.0.0 +paths: + /auth/v1/logout: + post: + summary: Logout do usuário + deprecated: false + description: Encerrar sessão do usuário + tags: + - Authentication + - Authentication + parameters: [] + responses: + '204': + description: Logout realizado com sucesso + headers: {} + x-apidog-name: No Content + '401': + description: Token inválido + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + headers: {} + x-apidog-name: Unauthorized + security: + - bearer: [] + x-apidog-folder: Authentication + x-apidog-status: released + x-run-in-apidog: https://app.apidog.com/web/project/1053378/apis/api-21940511-run +components: + schemas: + Error: + type: object + properties: + error: + type: string + message: + type: string + code: + type: string + x-apidog-orders: + - error + - message + - code + x-apidog-ignore-properties: [] + x-apidog-folder: '' + securitySchemes: + bearerAuth: + type: jwt + scheme: bearer + bearerFormat: JWT + description: Token JWT obtido no login + bearer: + type: http + scheme: bearer +servers: + - url: https://yuanqfswhberkoevtmfr.supabase.co + description: Prod Env + - url: '' + description: Cloud Mock +security: + - bearer: [] + +``` diff --git a/susconecta/ERRO_BACKEND_EDGE_FUNCTION.md b/susconecta/ERRO_BACKEND_EDGE_FUNCTION.md new file mode 100644 index 0000000..02c62d2 --- /dev/null +++ b/susconecta/ERRO_BACKEND_EDGE_FUNCTION.md @@ -0,0 +1,182 @@ +# 🚨 ERRO CRÍTICO NA EDGE FUNCTION - BACKEND + +## Resumo do Problema + +A Edge Function `/functions/v1/create-user` está retornando **erro 500** com mensagem: +```json +{ "error": "Failed to assign user role" } +``` + +## Evidências + +### Console do Frontend +``` +XHRPOST https://yuanqfswhberkoevtmfr.supabase.co/functions/v1/create-user +[HTTP/3 500 1065ms] + +[API ERROR] https://yuanqfswhberkoevtmfr.supabase.co/functions/v1/create-user 500 +Object { error: "Failed to assign user role" } +``` + +### Request Enviado (CORRETO) +```json +{ + "email": "dipar64745@fanlvr.com", + "password": "senha789!", + "full_name": "Jonas Francisco Nascimento Bonfim", + "phone": "(79) 99649-8907", + "role": "medico" +} +``` + +### Response Recebido (ERRO) +```json +{ + "error": "Failed to assign user role" +} +``` + +## Fluxo Atual (Correto segundo documentação) + +1. ✅ Frontend cria perfil na tabela `doctors` +2. ✅ Frontend gera senha aleatória +3. ✅ Frontend chama `/functions/v1/create-user` com dados corretos +4. ❌ **Edge Function falha ao atribuir role na tabela `user_roles`** + +## O Que a Edge Function DEVE Fazer + +Segundo a documentação da API (`Documentação API.md`), a Edge Function `/functions/v1/create-user` deve: + +1. ✅ Criar usuário no Supabase Auth (isso está funcionando) +2. ❌ **Inserir registro na tabela `user_roles`** (isso está falhando) +3. ✅ Retornar `{ success: true, user: {...} }` + +## Possíveis Causas do Erro + +### 1. SUPABASE_SERVICE_ROLE_KEY não configurada +A Edge Function precisa da `SUPABASE_SERVICE_ROLE_KEY` para ter permissão de: +- Inserir na tabela `user_roles` +- Fazer operações administrativas + +**Como verificar:** +1. Acesse o Supabase Dashboard +2. Vá em **Edge Functions** > `create-user` +3. Verifique se a variável de ambiente `SUPABASE_SERVICE_ROLE_KEY` está configurada +4. Copie a chave de: **Settings** > **API** > **service_role key (secret)** + +### 2. Tabela `user_roles` sem permissões corretas +A tabela pode estar bloqueando inserções da Edge Function. + +**Como verificar:** +1. Acesse o Supabase Dashboard +2. Vá em **Database** > **user_roles** +3. Clique em **RLS Policies** +4. Verifique se existe uma policy permitindo: + - Service role pode inserir + - OU Edge Function pode inserir usando service key + +**Policy esperada:** +```sql +-- Permitir que service role insira roles +CREATE POLICY "service_role_insert_user_roles" +ON user_roles FOR INSERT +TO service_role +WITH CHECK (true); +``` + +### 3. Código da Edge Function com bug +O código da Edge Function pode ter erro de lógica ao tentar inserir na tabela. + +**Onde encontrar:** +- Supabase Dashboard > **Edge Functions** > `create-user` > **Editor** + +**O que verificar:** +```typescript +// A Edge Function deve ter algo assim: +const { data, error } = await supabaseAdmin + .from('user_roles') + .insert({ + user_id: newUser.id, + role: role + }); + +if (error) { + console.error('Erro ao inserir role:', error); + return new Response( + JSON.stringify({ error: 'Failed to assign user role' }), + { status: 500 } + ); +} +``` + +## Como Testar Cada Possibilidade + +### Teste 1: Verificar se service key está funcionando +Execute no SQL Editor do Supabase: +```sql +-- Teste de inserção manual +INSERT INTO user_roles (user_id, role) +VALUES ('00000000-0000-0000-0000-000000000000', 'medico'); + +-- Se der erro, mostrará a mensagem de permissão +``` + +### Teste 2: Verificar logs da Edge Function +1. Acesse **Edge Functions** > `create-user` +2. Clique em **Logs** +3. Procure por erros detalhados quando o frontend faz a chamada + +### Teste 3: Verificar estrutura da tabela +```sql +-- Verificar estrutura da tabela user_roles +SELECT column_name, data_type, is_nullable +FROM information_schema.columns +WHERE table_name = 'user_roles'; +``` + +Campos esperados: +- `id` (uuid, primary key) +- `user_id` (uuid, not null, foreign key para auth.users) +- `role` (text ou enum, not null) +- `created_at` (timestamp, default now()) + +## Solução Esperada do Backend + +A equipe de backend precisa: + +1. **URGENTE**: Configurar `SUPABASE_SERVICE_ROLE_KEY` na Edge Function +2. **URGENTE**: Adicionar RLS policy para permitir inserções via service role +3. **Recomendado**: Adicionar logs detalhados na Edge Function para debug +4. **Recomendado**: Retornar erro mais específico (ex: "Permission denied to insert into user_roles") + +## Status do Frontend + +✅ **O código do frontend está 100% correto e seguindo a documentação!** + +Não há nada a fazer no frontend. O erro está exclusivamente no backend. + +## Workaround Temporário (NÃO RECOMENDADO) + +Se o backend não puder resolver urgentemente, podemos: +1. Criar usuários sem role (ou role padrão) +2. Administrador atribui roles manualmente depois + +Mas isso **NÃO É RECOMENDADO** porque: +- Usuários não terão permissões corretas +- Aumenta trabalho manual +- Pode gerar problemas de segurança + +## Contato + +Frontend: ✅ Implementação completa e correta +Backend: ❌ Precisa corrigir Edge Function `create-user` + +**Prioridade:** 🔴 CRÍTICA - Sistema não consegue criar novos usuários + +--- + +**Data do erro:** 10/10/2025 +**Ambiente:** https://yuanqfswhberkoevtmfr.supabase.co +**Edge Function:** `/functions/v1/create-user` +**Status Code:** 500 +**Mensagem:** "Failed to assign user role" diff --git a/susconecta/app/api/assign-role/route.ts b/susconecta/app/api/assign-role/route.ts new file mode 100644 index 0000000..3363262 --- /dev/null +++ b/susconecta/app/api/assign-role/route.ts @@ -0,0 +1,158 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { createClient } from '@supabase/supabase-js'; + +/** + * Endpoint server-side para atribuir roles aos usuários + * Usa SUPABASE_SERVICE_ROLE_KEY para realizar operações administrativas + * + * POST /api/assign-role + * Body: { user_id: string, role: string } + */ +export async function POST(request: NextRequest) { + try { + // 1. Verificar autenticação do requisitante + const authHeader = request.headers.get('authorization'); + if (!authHeader) { + return NextResponse.json( + { error: 'Unauthorized', message: 'Token de autenticação não fornecido' }, + { status: 401 } + ); + } + + // 2. Extrair dados do body + const body = await request.json(); + const { user_id, role } = body; + + if (!user_id || !role) { + return NextResponse.json( + { error: 'Bad Request', message: 'user_id e role são obrigatórios' }, + { status: 400 } + ); + } + + // 3. Validar role + const validRoles = ['admin', 'gestor', 'medico', 'secretaria', 'user']; + if (!validRoles.includes(role)) { + return NextResponse.json( + { error: 'Bad Request', message: `Role inválido. Valores aceitos: ${validRoles.join(', ')}` }, + { status: 400 } + ); + } + + // 4. Obter service role key do ambiente + const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; + const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY; + + if (!supabaseUrl || !serviceRoleKey) { + console.error('❌ [ASSIGN-ROLE] SUPABASE_SERVICE_ROLE_KEY não configurada'); + return NextResponse.json( + { + error: 'Server Configuration Error', + message: 'Service role key não configurada no servidor. Entre em contato com o administrador do sistema.', + hint: 'Configure SUPABASE_SERVICE_ROLE_KEY nas variáveis de ambiente do servidor' + }, + { status: 500 } + ); + } + + // 5. Criar cliente Supabase com service role key + const supabaseAdmin = createClient(supabaseUrl, serviceRoleKey, { + auth: { + autoRefreshToken: false, + persistSession: false, + }, + }); + + // 6. Verificar se o usuário existe + const { data: userData, error: userError } = await supabaseAdmin.auth.admin.getUserById(user_id); + + if (userError || !userData) { + console.error('❌ [ASSIGN-ROLE] Usuário não encontrado:', userError); + return NextResponse.json( + { error: 'Not Found', message: 'Usuário não encontrado no sistema de autenticação' }, + { status: 404 } + ); + } + + console.log(`🔐 [ASSIGN-ROLE] Atribuindo role "${role}" ao usuário ${user_id}`); + + // 7. Inserir role na tabela user_roles + const { data: roleData, error: roleError } = await supabaseAdmin + .from('user_roles') + .insert({ + user_id: user_id, + role: role, + created_at: new Date().toISOString(), + }) + .select() + .single(); + + if (roleError) { + // Verificar se é erro de duplicação (usuário já tem esse role) + if (roleError.code === '23505') { + console.log(`⚠️ [ASSIGN-ROLE] Usuário já possui o role "${role}"`); + return NextResponse.json( + { + success: true, + message: `Usuário já possui o role "${role}"`, + user_id, + role, + already_exists: true + }, + { status: 200 } + ); + } + + console.error('❌ [ASSIGN-ROLE] Erro ao inserir role:', roleError); + return NextResponse.json( + { + error: 'Database Error', + message: `Erro ao atribuir role: ${roleError.message}`, + code: roleError.code, + details: roleError.details + }, + { status: 500 } + ); + } + + console.log(`✅ [ASSIGN-ROLE] Role "${role}" atribuído com sucesso ao usuário ${user_id}`); + + // 8. Retornar sucesso + return NextResponse.json( + { + success: true, + message: `Role "${role}" atribuído com sucesso`, + data: roleData, + user_id, + role, + }, + { status: 200 } + ); + + } catch (error: any) { + console.error('❌ [ASSIGN-ROLE] Erro inesperado:', error); + return NextResponse.json( + { + error: 'Internal Server Error', + message: 'Erro inesperado ao atribuir role', + details: error?.message || String(error) + }, + { status: 500 } + ); + } +} + +// Método OPTIONS para CORS (se necessário) +export async function OPTIONS(request: NextRequest) { + return NextResponse.json( + {}, + { + status: 200, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + }, + } + ); +} diff --git a/susconecta/components/forms/doctor-registration-form.tsx b/susconecta/components/forms/doctor-registration-form.tsx index 17fd7d5..da4bff9 100644 --- a/susconecta/components/forms/doctor-registration-form.tsx +++ b/susconecta/components/forms/doctor-registration-form.tsx @@ -24,9 +24,7 @@ import { removerAnexoMedico, MedicoInput, Medico, - criarUsuario, - criarUsuarioDirectAuth, - assignRoleServerSide, + criarUsuarioMedico, gerarSenhaAleatoria, } from "@/lib/api"; ; @@ -157,8 +155,13 @@ export function DoctorRegistrationForm({ const [serverAnexos, setServerAnexos] = useState([]); // Estados para o dialog de credenciais - const [dialogOpen, setDialogOpen] = useState(false); - const [tempCredentials, setTempCredentials] = useState<{ email: string; password: string } | null>(null); + const [showCredentialsDialog, setShowCredentialsDialog] = useState(false); + const [credentials, setCredentials] = useState<{ + email: string; + password: string; + userName: string; + userType: 'médico' | 'paciente'; + } | null>(null); const title = useMemo(() => (mode === "create" ? "Cadastro de Médico" : "Editar Médico"), [mode]); @@ -395,38 +398,84 @@ async function handleSubmit(ev: React.FormEvent) { else onOpenChange?.(false); } else { - // --- NOVA LÓGICA DE CRIAÇÃO --- + // --- FLUXO DE CRIAÇÃO DE MÉDICO --- + console.log('🏥 [CRIAR MÉDICO] Iniciando processo completo...'); + const medicoPayload = toPayload(); + console.log("Enviando os dados para a API:", medicoPayload); + + // 1. Cria o perfil do médico na tabela doctors const savedDoctorProfile = await criarMedico(medicoPayload); console.log("✅ Perfil do médico criado:", savedDoctorProfile); - // ⚠️ IMPORTANTE: A criação de usuário de autenticação foi DESABILITADA temporariamente - // porque a Edge Function /functions/v1/create-user está retornando erro 500 ao - // tentar atribuir o role "medico" ao usuário. - // - // Para habilitar novamente, o backend precisa corrigir a Edge Function ou - // configurar as permissões corretas na tabela user_roles. - // - // Por ora, apenas o perfil do médico será salvo na tabela "doctors". - // O acesso ao sistema precisa ser criado manualmente pelo administrador. + // 2. Cria usuário no Supabase Auth (direto via /auth/v1/signup) + console.log('🔐 Criando usuário de autenticação...'); - console.log("⚠️ Criação de usuário Auth desabilitada - salvando apenas perfil do médico"); - - alert( - `✅ Médico cadastrado com sucesso!\n\n` + - `📋 Perfil salvo na base de dados.\n\n` + - `⚠️ IMPORTANTE: O acesso ao sistema (login) precisa ser criado manualmente.\n\n` + - `Motivo: A função de criação automática de usuários está com problema no backend.\n` + - `Entre em contato com o administrador do sistema para criar o acesso.` - ); - - // Limpa formulário e fecha - setForm(initial); - setPhotoPreview(null); - setServerAnexos([]); - onSaved?.(savedDoctorProfile); - if (inline) onClose?.(); - else onOpenChange?.(false); + try { + const authResponse = await criarUsuarioMedico({ + email: form.email, + full_name: form.full_name, + phone_mobile: form.celular || '', + }); + + if (authResponse.success && authResponse.user) { + console.log('✅ Usuário Auth criado:', authResponse.user.id); + + // 3. Exibe popup com credenciais + setCredentials({ + email: authResponse.email, + password: authResponse.password, + userName: form.full_name, + userType: 'médico', + }); + setShowCredentialsDialog(true); + + // 4. Limpa formulário + setForm(initial); + setPhotoPreview(null); + setServerAnexos([]); + + // 5. Notifica componente pai + onSaved?.(savedDoctorProfile); + } else { + throw new Error('Falha ao criar usuário de autenticação'); + } + + } catch (authError: any) { + console.error('❌ Erro ao criar usuário Auth:', authError); + + const errorMsg = authError?.message || String(authError); + + // Mensagens específicas de erro + if (errorMsg.toLowerCase().includes('already registered') || + errorMsg.toLowerCase().includes('already been registered') || + errorMsg.toLowerCase().includes('já está cadastrado')) { + alert( + `⚠️ EMAIL JÁ CADASTRADO\n\n` + + `O email "${form.email}" já possui uma conta no sistema.\n\n` + + `✅ O perfil do médico "${form.full_name}" foi salvo com sucesso.\n\n` + + `❌ Porém, não foi possível criar o login porque este email já está em uso.\n\n` + + `SOLUÇÃO:\n` + + `• Use um email diferente para este médico, OU\n` + + `• Se o médico já tem conta, edite o perfil e vincule ao usuário existente` + ); + } else { + alert( + `⚠️ Médico cadastrado com sucesso, mas houve um problema ao criar o acesso ao sistema.\n\n` + + `✅ Perfil do médico salvo: ${form.full_name}\n\n` + + `❌ Erro ao criar login: ${errorMsg}\n\n` + + `Por favor, entre em contato com o administrador para criar o acesso manualmente.` + ); + } + + // Limpa formulário mesmo com erro + setForm(initial); + setPhotoPreview(null); + setServerAnexos([]); + onSaved?.(savedDoctorProfile); + if (inline) onClose?.(); + else onOpenChange?.(false); + } } } catch (err: any) { console.error("❌ Erro no handleSubmit:", err); @@ -990,14 +1039,14 @@ async function handleSubmit(ev: React.FormEvent) {
{content}
{/* Dialog de credenciais */} - {tempCredentials && ( + {credentials && ( { - setDialogOpen(open); + setShowCredentialsDialog(open); if (!open) { // Quando o dialog de credenciais fecha, fecha o formulário também - setTempCredentials(null); + setCredentials(null); if (inline) { onClose?.(); } else { @@ -1005,10 +1054,10 @@ async function handleSubmit(ev: React.FormEvent) { } } }} - email={tempCredentials.email} - password={tempCredentials.password} - userName={form.full_name} - userType="médico" + email={credentials.email} + password={credentials.password} + userName={credentials.userName} + userType={credentials.userType} /> )} @@ -1029,20 +1078,20 @@ async function handleSubmit(ev: React.FormEvent) { {/* Dialog de credenciais */} - {tempCredentials && ( + {credentials && ( { - setDialogOpen(open); + setShowCredentialsDialog(open); if (!open) { - setTempCredentials(null); + setCredentials(null); onOpenChange?.(false); } }} - email={tempCredentials.email} - password={tempCredentials.password} - userName={form.full_name} - userType="médico" + email={credentials.email} + password={credentials.password} + userName={credentials.userName} + userType={credentials.userType} /> )} diff --git a/susconecta/components/forms/patient-registration-form.tsx b/susconecta/components/forms/patient-registration-form.tsx index 1fe7b8f..5400b59 100644 --- a/susconecta/components/forms/patient-registration-form.tsx +++ b/susconecta/components/forms/patient-registration-form.tsx @@ -24,9 +24,7 @@ import { listarAnexos, removerAnexo, buscarPacientePorId, - criarUsuario, - gerarSenhaAleatoria, - CreateUserResponse, + criarUsuarioPaciente, criarPaciente, } from "@/lib/api"; @@ -106,8 +104,13 @@ export function PatientRegistrationForm({ const [serverAnexos, setServerAnexos] = useState([]); // Estados para o dialog de credenciais - const [dialogOpen, setDialogOpen] = useState(false); - const [tempCredentials, setTempCredentials] = useState<{ email: string; password: string } | null>(null); + const [showCredentialsDialog, setShowCredentialsDialog] = useState(false); + const [credentials, setCredentials] = useState<{ + email: string; + password: string; + userName: string; + userType: 'médico' | 'paciente'; + } | null>(null); const title = useMemo(() => (mode === "create" ? "Cadastro de Paciente" : "Editar Paciente"), [mode]); @@ -273,43 +276,41 @@ export function PatientRegistrationForm({ console.log("✅ Perfil do paciente criado:", savedPatientProfile); if (form.email && form.email.includes('@')) { - const tempPassword = gerarSenhaAleatoria(); - const userInput = { - email: form.email, - password: tempPassword, - full_name: form.nome, - phone: form.telefone, - role: 'user' as const, - }; - - console.log("🔐 Criando usuário de autenticação com payload:", userInput); - + console.log("🔐 Criando usuário de autenticação (paciente)..."); try { - const userResponse = await criarUsuario(userInput); + const userResponse = await criarUsuarioPaciente({ + email: form.email, + full_name: form.nome, + phone_mobile: form.telefone, + }); if (userResponse.success && userResponse.user) { console.log("✅ Usuário de autenticação criado:", userResponse.user); - - // Mostra credenciais (NÃO fecha o formulário ainda) - setTempCredentials({ email: form.email, password: tempPassword }); - setDialogOpen(true); - + + // Mostra credenciais no dialog usando as credenciais retornadas + setCredentials({ + email: userResponse.email ?? form.email, + password: userResponse.password ?? '', + userName: form.nome, + userType: 'paciente', + }); + setShowCredentialsDialog(true); + // Limpa formulário mas NÃO fecha ainda - fechará quando o dialog de credenciais fechar setForm(initial); setPhotoPreview(null); setServerAnexos([]); onSaved?.(savedPatientProfile); - // NÃO chama onClose ou onOpenChange aqui - deixa o dialog de credenciais fazer isso - return; + return; } else { throw new Error((userResponse as any).message || "Falhou ao criar o usuário de acesso."); } } catch (userError: any) { - console.error("❌ Erro ao criar usuário via função server-side:", userError); - + console.error("❌ Erro ao criar usuário via signup:", userError); + // Mensagem de erro específica para email duplicado const errorMsg = userError?.message || String(userError); - + if (errorMsg.toLowerCase().includes('already registered') || errorMsg.toLowerCase().includes('já está cadastrado') || errorMsg.toLowerCase().includes('já existe')) { @@ -318,18 +319,6 @@ export function PatientRegistrationForm({ `✅ O perfil do paciente foi salvo com sucesso.\n\n` + `Para criar acesso ao sistema, use um email diferente ou recupere a senha do email existente.` ); - } else if (errorMsg.toLowerCase().includes('failed to assign user role') || - errorMsg.toLowerCase().includes('atribuir permissões')) { - alert( - `⚠️ PROBLEMA NA CONFIGURAÇÃO DO SISTEMA\n\n` + - `✅ O perfil do paciente foi salvo com sucesso.\n\n` + - `❌ Porém, houve falha ao atribuir permissões de acesso.\n\n` + - `Esse erro indica que a Edge Function do Supabase não está configurada corretamente.\n\n` + - `Entre em contato com o administrador do sistema para:\n` + - `1. Verificar se a service role key está configurada\n` + - `2. Verificar as permissões da tabela user_roles\n` + - `3. Revisar o código da Edge Function create-user` - ); } else { alert( `✅ Paciente cadastrado com sucesso!\n\n` + @@ -337,7 +326,7 @@ export function PatientRegistrationForm({ `O cadastro do paciente foi salvo, mas será necessário criar o acesso manualmente.` ); } - + // Limpa formulário e fecha setForm(initial); setPhotoPreview(null); @@ -715,14 +704,14 @@ export function PatientRegistrationForm({
{content}
{/* Dialog de credenciais */} - {tempCredentials && ( + {credentials && ( { - setDialogOpen(open); + setShowCredentialsDialog(open); if (!open) { // Quando o dialog de credenciais fecha, fecha o formulário também - setTempCredentials(null); + setCredentials(null); if (inline) { onClose?.(); } else { @@ -730,10 +719,10 @@ export function PatientRegistrationForm({ } } }} - email={tempCredentials.email} - password={tempCredentials.password} - userName={form.nome} - userType="paciente" + email={credentials.email} + password={credentials.password} + userName={credentials.userName} + userType={credentials.userType} /> )} @@ -754,20 +743,20 @@ export function PatientRegistrationForm({ {/* Dialog de credenciais */} - {tempCredentials && ( + {credentials && ( { - setDialogOpen(open); + setShowCredentialsDialog(open); if (!open) { - setTempCredentials(null); + setCredentials(null); onOpenChange?.(false); } }} - email={tempCredentials.email} - password={tempCredentials.password} - userName={form.nome} - userType="paciente" + email={credentials.email} + password={credentials.password} + userName={credentials.userName} + userType={credentials.userType} /> )}