fix-dialog-modal
This commit is contained in:
parent
9adf479e90
commit
5d78e9f066
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState, useRef } from "react";
|
||||
import { parse, parseISO, format } from 'date-fns';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@ -167,6 +167,7 @@ export function DoctorRegistrationForm({
|
||||
userName: string;
|
||||
userType: 'médico' | 'paciente';
|
||||
} | null>(null);
|
||||
const savedDoctorRef = useRef<any>(null);
|
||||
|
||||
const title = useMemo(() => (mode === "create" ? "Cadastro de Médico" : "Editar Médico"), [mode]);
|
||||
|
||||
@ -504,6 +505,11 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
// 1. Cria o perfil do médico na tabela doctors
|
||||
let savedDoctorProfile: any = await criarMedico(medicoPayload);
|
||||
console.log("✅ Perfil do médico criado:", savedDoctorProfile);
|
||||
console.log("🔑 Senha no objeto retornado:", savedDoctorProfile?.password);
|
||||
|
||||
// Salvar a senha ANTES de qualquer operação que possa sobrescrever o objeto
|
||||
const senhaGerada = savedDoctorProfile?.password;
|
||||
console.log("💾 Senha salva em variável:", senhaGerada);
|
||||
|
||||
// Fallback: some create flows don't persist optional fields like birth_date/cep/sexo.
|
||||
// If the returned object is missing those but our payload included them,
|
||||
@ -531,7 +537,9 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
const patched = await atualizarMedico(String(createdDoctorId), medicoPayload).catch((e) => { console.warn('[DoctorForm] fallback PATCH failed:', e); return null; });
|
||||
if (patched) {
|
||||
console.debug('[DoctorForm] fallback PATCH result:', patched);
|
||||
savedDoctorProfile = patched;
|
||||
// Preservar a senha ao atualizar o objeto
|
||||
savedDoctorProfile = { ...patched, password: senhaGerada };
|
||||
console.log("🔄 Senha preservada após PATCH:", savedDoctorProfile?.password);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@ -547,6 +555,7 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
// { doctor, doctor_id, email, password, user_id } or similar shapes.
|
||||
const result = savedDoctorProfile as any;
|
||||
console.log('✅ Resultado de criarMedico:', result);
|
||||
console.log('🔑 Senha no resultado final:', result?.password);
|
||||
|
||||
// Determine the doctor id if available
|
||||
let createdDoctorId: string | null = null;
|
||||
@ -559,13 +568,36 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
|
||||
// If the function returned credentials, show them in the credentials dialog
|
||||
if (result && (result.password || result.email || result.user)) {
|
||||
setCredentials({
|
||||
console.log('📧 Credenciais recebidas - configurando dialog...');
|
||||
console.log('📧 Email:', result.email || form.email);
|
||||
console.log('🔑 Senha extraída:', result.password);
|
||||
console.log('👤 Nome do usuário:', form.full_name);
|
||||
|
||||
const credenciaisParaExibir = {
|
||||
email: result.email || form.email,
|
||||
password: result.password || "",
|
||||
password: result.password || senhaGerada || "",
|
||||
userName: form.full_name,
|
||||
userType: 'médico',
|
||||
});
|
||||
userType: 'médico' as const,
|
||||
};
|
||||
|
||||
console.log('📋 Credenciais a serem definidas:', credenciaisParaExibir);
|
||||
|
||||
// Salvar o médico no ref ANTES de abrir o dialog
|
||||
savedDoctorRef.current = savedDoctorProfile;
|
||||
|
||||
setCredentials(credenciaisParaExibir);
|
||||
setShowCredentialsDialog(true);
|
||||
console.log('✅ Dialog de credenciais configurado e aberto');
|
||||
|
||||
// Verificar estados após 100ms
|
||||
setTimeout(() => {
|
||||
console.log('🔍 Verificando estados após 100ms:');
|
||||
console.log('- showCredentialsDialog:', showCredentialsDialog);
|
||||
console.log('- credentials:', credentials);
|
||||
}, 100);
|
||||
|
||||
// NÃO fechar o formulário aqui - será fechado quando o usuário fechar o dialog de credenciais
|
||||
return; // Sair da função para não executar o cleanup abaixo
|
||||
}
|
||||
|
||||
// Upload photo if provided and we have an id
|
||||
@ -800,8 +832,8 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
<PopoverContent className="w-auto p-0">
|
||||
<Calendar
|
||||
mode="single"
|
||||
selected={form.data_nascimento}
|
||||
onSelect={(date) => setField("data_nascimento", date || null)}
|
||||
selected={form.data_nascimento ?? undefined}
|
||||
onSelect={(date) => setField("data_nascimento", date ?? null)}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
@ -1061,28 +1093,37 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
<>
|
||||
<div className="space-y-6">{content}</div>
|
||||
|
||||
{/* Dialog de credenciais */}
|
||||
{credentials && (
|
||||
<CredentialsDialog
|
||||
open={showCredentialsDialog}
|
||||
onOpenChange={(open) => {
|
||||
console.log('🔄 CredentialsDialog (inline) onOpenChange chamado com:', open);
|
||||
setShowCredentialsDialog(open);
|
||||
if (!open) {
|
||||
// Quando o dialog de credenciais fecha, fecha o formulário também
|
||||
// Dialog foi fechado - limpar estados e fechar formulário
|
||||
console.log('✅ Dialog fechado - limpando formulário...');
|
||||
setCredentials(null);
|
||||
if (inline) {
|
||||
onClose?.();
|
||||
} else {
|
||||
onOpenChange?.(false);
|
||||
|
||||
// Chamar onSaved se houver médico salvo
|
||||
if (savedDoctorRef.current) {
|
||||
onSaved?.(savedDoctorRef.current);
|
||||
savedDoctorRef.current = null;
|
||||
}
|
||||
|
||||
// Limpar formulário
|
||||
setForm(initial);
|
||||
setPhotoPreview(null);
|
||||
setServerAnexos([]);
|
||||
|
||||
// Fechar formulário
|
||||
if (inline) onClose?.();
|
||||
else onOpenChange?.(false);
|
||||
}
|
||||
}}
|
||||
email={credentials.email}
|
||||
password={credentials.password}
|
||||
userName={credentials.userName}
|
||||
userType={credentials.userType}
|
||||
email={credentials?.email || ''}
|
||||
password={credentials?.password || ''}
|
||||
userName={credentials?.userName || ''}
|
||||
userType={credentials?.userType || 'médico'}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -1100,23 +1141,36 @@ async function handleSubmit(ev: React.FormEvent) {
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Dialog de credenciais */}
|
||||
{credentials && (
|
||||
<CredentialsDialog
|
||||
open={showCredentialsDialog}
|
||||
onOpenChange={(open) => {
|
||||
console.log('🔄 CredentialsDialog (dialog) onOpenChange chamado com:', open);
|
||||
setShowCredentialsDialog(open);
|
||||
if (!open) {
|
||||
// Dialog foi fechado - limpar estados e fechar formulário
|
||||
console.log('✅ Dialog fechado - limpando formulário...');
|
||||
setCredentials(null);
|
||||
|
||||
// Chamar onSaved se houver médico salvo
|
||||
if (savedDoctorRef.current) {
|
||||
onSaved?.(savedDoctorRef.current);
|
||||
savedDoctorRef.current = null;
|
||||
}
|
||||
|
||||
// Limpar formulário
|
||||
setForm(initial);
|
||||
setPhotoPreview(null);
|
||||
setServerAnexos([]);
|
||||
|
||||
// Fechar formulário principal
|
||||
onOpenChange?.(false);
|
||||
}
|
||||
}}
|
||||
email={credentials.email}
|
||||
password={credentials.password}
|
||||
userName={credentials.userName}
|
||||
userType={credentials.userType}
|
||||
email={credentials?.email || ''}
|
||||
password={credentials?.password || ''}
|
||||
userName={credentials?.userName || ''}
|
||||
userType={credentials?.userType || 'médico'}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState, useRef } from "react";
|
||||
import { format, parseISO, parse } from "date-fns";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@ -139,6 +139,9 @@ export function PatientRegistrationForm({
|
||||
userType: 'médico' | 'paciente';
|
||||
} | null>(null);
|
||||
|
||||
// Ref para guardar o paciente salvo para chamar onSaved quando o dialog fechar
|
||||
const savedPatientRef = useRef<any>(null);
|
||||
|
||||
const title = useMemo(() => (mode === "create" ? "Cadastro de Paciente" : "Editar Paciente"), [mode]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -276,7 +279,11 @@ export function PatientRegistrationForm({
|
||||
setErrors((e) => ({ ...e, telefone: 'Telefone é obrigatório quando email é informado (fluxo de criação único).' })); setSubmitting(false); return;
|
||||
}
|
||||
let savedPatientProfile: any = await criarPaciente(patientPayload);
|
||||
console.log('Perfil do paciente criado (via Function):', savedPatientProfile);
|
||||
console.log('🎯 Paciente criado! Resposta completa:', savedPatientProfile);
|
||||
console.log('🔑 Senha no objeto:', savedPatientProfile?.password);
|
||||
|
||||
// Guardar a senha ANTES de qualquer operação que possa sobrescrever o objeto
|
||||
const senhaGerada = savedPatientProfile?.password;
|
||||
|
||||
// Fallback: some backend create flows (create-user-with-password) do not
|
||||
// persist optional patient fields like sex/cep/birth_date. The edit flow
|
||||
@ -295,17 +302,56 @@ export function PatientRegistrationForm({
|
||||
const patched = await atualizarPaciente(String(pacienteId), patientPayload).catch((e) => { console.warn('[PatientForm] fallback PATCH falhou:', e); return null; });
|
||||
if (patched) {
|
||||
console.debug('[PatientForm] fallback PATCH result:', patched);
|
||||
savedPatientProfile = patched;
|
||||
// Preserva a senha ao fazer merge do patch
|
||||
savedPatientProfile = { ...patched, password: senhaGerada };
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[PatientForm] erro ao tentar fallback PATCH:', e);
|
||||
}
|
||||
|
||||
const maybePassword = (savedPatientProfile as any)?.password || (savedPatientProfile as any)?.generated_password;
|
||||
if (maybePassword) {
|
||||
setCredentials({ email: (savedPatientProfile as any).email || form.email, password: String(maybePassword), userName: form.nome, userType: 'paciente' });
|
||||
// Usar a senha que foi guardada ANTES do PATCH
|
||||
const emailToDisplay = savedPatientProfile?.email || form.email;
|
||||
console.log('📧 Email para exibir:', emailToDisplay);
|
||||
console.log('🔐 Senha para exibir:', senhaGerada);
|
||||
|
||||
if (senhaGerada && emailToDisplay) {
|
||||
console.log('✅ Abrindo modal de credenciais...');
|
||||
const credentialsToShow = {
|
||||
email: emailToDisplay,
|
||||
password: String(senhaGerada),
|
||||
userName: form.nome,
|
||||
userType: 'paciente' as const
|
||||
};
|
||||
console.log('📝 Credenciais a serem definidas:', credentialsToShow);
|
||||
|
||||
// Guardar o paciente salvo no ref para usar quando o dialog fechar
|
||||
savedPatientRef.current = savedPatientProfile;
|
||||
|
||||
// Definir credenciais e abrir dialog
|
||||
setCredentials(credentialsToShow);
|
||||
setShowCredentialsDialog(true);
|
||||
|
||||
// NÃO limpar o formulário ou fechar ainda - aguardar o usuário fechar o dialog de credenciais
|
||||
// O dialog de credenciais vai chamar onSaved e fechar quando o usuário clicar em "Fechar"
|
||||
|
||||
// Verificar se foi setado
|
||||
setTimeout(() => {
|
||||
console.log('🔍 Verificando estados após 100ms:');
|
||||
console.log(' - showCredentialsDialog:', showCredentialsDialog);
|
||||
console.log(' - credentials:', credentials);
|
||||
}, 100);
|
||||
} else {
|
||||
console.error('❌ Não foi possível exibir credenciais:', { senhaGerada, emailToDisplay });
|
||||
alert(`Paciente criado!\n\nEmail: ${emailToDisplay}\n\nAVISO: A senha não pôde ser recuperada. Entre em contato com o suporte.`);
|
||||
|
||||
// Se não há senha, limpar e fechar normalmente
|
||||
onSaved?.(savedPatientProfile);
|
||||
setForm(initial);
|
||||
setPhotoPreview(null);
|
||||
setServerAnexos([]);
|
||||
if (inline) onClose?.();
|
||||
else onOpenChange?.(false);
|
||||
}
|
||||
|
||||
if (form.photo) {
|
||||
@ -313,8 +359,6 @@ export function PatientRegistrationForm({
|
||||
catch (upErr) { console.warn('[PatientForm] Falha ao enviar foto do paciente após criação:', upErr); alert('Paciente criado, mas falha ao enviar a foto. Você pode tentar novamente no perfil.'); }
|
||||
finally { setUploadingPhoto(false); }
|
||||
}
|
||||
|
||||
onSaved?.(savedPatientProfile); setForm(initial); setPhotoPreview(null); setServerAnexos([]); if (inline) onClose?.(); else onOpenChange?.(false);
|
||||
}
|
||||
} catch (err: any) { console.error("❌ Erro no handleSubmit:", err); const userMessage = err?.message?.includes("toPayload") || err?.message?.includes("is not defined") ? "Erro ao processar os dados do formulário. Por favor, verifique os campos e tente novamente." : err?.message || "Erro ao salvar paciente. Por favor, tente novamente."; setErrors({ submit: userMessage }); }
|
||||
finally { setSubmitting(false); }
|
||||
@ -519,8 +563,86 @@ export function PatientRegistrationForm({
|
||||
);
|
||||
|
||||
if (inline) {
|
||||
return (<><div className="space-y-6">{content}</div>{credentials && (<CredentialsDialog open={showCredentialsDialog} onOpenChange={(open) => { setShowCredentialsDialog(open); if (!open) { setCredentials(null); if (inline) onClose?.(); else onOpenChange?.(false); } }} email={credentials.email} password={credentials.password} userName={credentials.userName} userType={credentials.userType} />)}</>);
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-6">{content}</div>
|
||||
<CredentialsDialog
|
||||
open={showCredentialsDialog}
|
||||
onOpenChange={(open) => {
|
||||
console.log('🔄 CredentialsDialog onOpenChange chamado com:', open);
|
||||
setShowCredentialsDialog(open);
|
||||
if (!open) {
|
||||
// Dialog foi fechado - limpar estados e fechar formulário
|
||||
console.log('✅ Dialog fechado - limpando formulário...');
|
||||
setCredentials(null);
|
||||
|
||||
// Chamar onSaved se houver paciente salvo
|
||||
if (savedPatientRef.current) {
|
||||
onSaved?.(savedPatientRef.current);
|
||||
savedPatientRef.current = null;
|
||||
}
|
||||
|
||||
return (<><Dialog open={open} onOpenChange={onOpenChange}><DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto"><DialogHeader><DialogTitle className="flex items-center gap-2"><User className="h-5 w-5" /> {title}</DialogTitle></DialogHeader>{content}</DialogContent></Dialog>{credentials && (<CredentialsDialog open={showCredentialsDialog} onOpenChange={(open) => { setShowCredentialsDialog(open); if (!open) { setCredentials(null); onOpenChange?.(false); } }} email={credentials.email} password={credentials.password} userName={credentials.userName} userType={credentials.userType} />)}</>);
|
||||
// Limpar formulário
|
||||
setForm(initial);
|
||||
setPhotoPreview(null);
|
||||
setServerAnexos([]);
|
||||
|
||||
// Fechar formulário
|
||||
if (inline) onClose?.();
|
||||
else onOpenChange?.(false);
|
||||
}
|
||||
}}
|
||||
email={credentials?.email || ''}
|
||||
password={credentials?.password || ''}
|
||||
userName={credentials?.userName || ''}
|
||||
userType={credentials?.userType || 'paciente'}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<User className="h-5 w-5" /> {title}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
{content}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<CredentialsDialog
|
||||
open={showCredentialsDialog}
|
||||
onOpenChange={(open) => {
|
||||
console.log('🔄 CredentialsDialog onOpenChange chamado com:', open);
|
||||
setShowCredentialsDialog(open);
|
||||
if (!open) {
|
||||
// Dialog foi fechado - limpar estados e fechar formulário
|
||||
console.log('✅ Dialog fechado - limpando formulário...');
|
||||
setCredentials(null);
|
||||
|
||||
// Chamar onSaved se houver paciente salvo
|
||||
if (savedPatientRef.current) {
|
||||
onSaved?.(savedPatientRef.current);
|
||||
savedPatientRef.current = null;
|
||||
}
|
||||
|
||||
// Limpar formulário
|
||||
setForm(initial);
|
||||
setPhotoPreview(null);
|
||||
setServerAnexos([]);
|
||||
|
||||
// Fechar formulário principal
|
||||
onOpenChange?.(false);
|
||||
}
|
||||
}}
|
||||
email={credentials?.email || ''}
|
||||
password={credentials?.password || ''}
|
||||
userName={credentials?.userName || ''}
|
||||
userType={credentials?.userType || 'paciente'}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -2139,25 +2139,25 @@ export async function criarMedico(input: MedicoInput): Promise<Medico> {
|
||||
// If server returned doctor_id, fetch the doctor
|
||||
if (parsed && parsed.doctor_id) {
|
||||
const doc = await buscarMedicoPorId(String(parsed.doctor_id)).catch(() => null);
|
||||
if (doc) return Object.assign(doc, { password });
|
||||
if (parsed.doctor) return Object.assign(parsed.doctor, { password });
|
||||
return Object.assign({ id: parsed.doctor_id, full_name: input.full_name, cpf: cleanCpf, email: input.email } as Medico, { password });
|
||||
if (doc) return { ...doc, password } as any;
|
||||
if (parsed.doctor) return { ...parsed.doctor, password } as any;
|
||||
return { id: parsed.doctor_id, full_name: input.full_name, cpf: cleanCpf, email: input.email, password } as any;
|
||||
}
|
||||
|
||||
// If server returned doctor object directly
|
||||
if (parsed && (parsed.id || parsed.full_name || parsed.cpf)) {
|
||||
return Object.assign(parsed, { password }) as Medico;
|
||||
return { ...parsed, password } as any;
|
||||
}
|
||||
|
||||
// If server returned an envelope with user, try to locate doctor by email
|
||||
if (parsed && parsed.user && parsed.user.id) {
|
||||
const maybe = await fetch(`${REST}/doctors?email=eq.${encodeURIComponent(String(input.email))}&select=*`, { method: 'GET', headers: baseHeaders() }).then((r) => r.ok ? r.json().catch(() => []) : []);
|
||||
if (Array.isArray(maybe) && maybe.length) return Object.assign(maybe[0] as Medico, { password });
|
||||
return Object.assign({ id: parsed.user.id, full_name: input.full_name, email: input.email } as Medico, { password });
|
||||
if (Array.isArray(maybe) && maybe.length) return { ...maybe[0], password } as any;
|
||||
return { id: parsed.user.id, full_name: input.full_name, email: input.email, password } as any;
|
||||
}
|
||||
|
||||
// otherwise return parsed with password as best-effort
|
||||
return Object.assign(parsed || {}, { password });
|
||||
return { ...(parsed || {}), password } as any;
|
||||
} catch (err: any) {
|
||||
lastErr = err;
|
||||
const emsg = err && typeof err === 'object' && 'message' in err ? (err as any).message : String(err);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user