import React, { useState, useEffect } from "react"; import { Users, UserPlus, Stethoscope, UserCog, Plus, Edit, Trash2, Shield, Search, RefreshCw, UserCheck, UserX, } from "lucide-react"; import toast from "react-hot-toast"; import { useNavigate } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; import { ConfirmDialog } from "../components/ui/ConfirmDialog"; import { patientService, type Patient, doctorService, type Doctor, userService, type UserInfo, type UserRole, type CreateUserInput, profileService, } from "../services"; import type { CrmUF } from "../services/doctors/types"; // Type aliases para compatibilidade type Paciente = Patient; type FullUserInfo = UserInfo; type TabType = "pacientes" | "usuarios" | "medicos"; const PainelAdmin: React.FC = () => { const { roles: authUserRoles } = useAuth(); const navigate = useNavigate(); const [activeTab, setActiveTab] = useState("pacientes"); const [loading, setLoading] = useState(false); // Estados para pacientes const [pacientes, setPacientes] = useState([]); const [showPacienteModal, setShowPacienteModal] = useState(false); const [editingPaciente, setEditingPaciente] = useState(null); const [formPaciente, setFormPaciente] = useState({ full_name: "", cpf: "", email: "", phone_mobile: "", birth_date: "", social_name: "", sex: "", blood_type: "", weight_kg: "", height_m: "", street: "", number: "", complement: "", neighborhood: "", city: "", state: "", cep: "", }); // Estados para usuários const [usuarios, setUsuarios] = useState([]); const [searchTerm, setSearchTerm] = useState(""); const [showUserModal, setShowUserModal] = useState(false); const [editingUser, setEditingUser] = useState(null); const [editForm, setEditForm] = useState<{ full_name?: string; email?: string; phone?: string; disabled?: boolean; }>({}); const [managingRolesUser, setManagingRolesUser] = useState(null); const [userRoles, setUserRoles] = useState([]); const [newRole, setNewRole] = useState("user"); const [formUser, setFormUser] = useState({ email: "", full_name: "", phone: "", role: "user", }); const [userPassword, setUserPassword] = useState(""); // Senha opcional const [usePassword, setUsePassword] = useState(false); // Toggle para criar com senha // Estados para dialog de confirmação const [confirmDialog, setConfirmDialog] = useState<{ isOpen: boolean; title: string; message: string | React.ReactNode; confirmText?: string; cancelText?: string; onConfirm: () => void; requireTypedConfirmation: boolean; confirmationWord: string; isDangerous: boolean; }>({ isOpen: false, title: "", message: "", onConfirm: () => {}, requireTypedConfirmation: false, confirmationWord: "", isDangerous: false, }); // Estados para médicos const [medicos, setMedicos] = useState([]); const [showMedicoModal, setShowMedicoModal] = useState(false); const [editingMedico, setEditingMedico] = useState(null); const [formMedico, setFormMedico] = useState({ crm: "", crm_uf: "SP", specialty: "", full_name: "", cpf: "", email: "", phone_mobile: "", phone2: "", cep: "", street: "", number: "", complement: "", neighborhood: "", city: "", state: "", birth_date: "", rg: "", active: true, }); // Verificar permissão de admin useEffect(() => { const isAdmin = authUserRoles.includes("admin") || authUserRoles.includes("gestor"); if (!isAdmin) { toast.error("Acesso negado: apenas administradores"); navigate("/"); } }, [authUserRoles, navigate]); // Carregar dados conforme aba ativa useEffect(() => { // Só carrega se não estiver já carregando if (loading) return; if (activeTab === "pacientes") { loadPacientes(); } else if (activeTab === "usuarios") { loadUsuarios(); } else if (activeTab === "medicos") { loadMedicos(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeTab]); const loadUsuarios = async () => { setLoading(true); try { // Lista todos os perfis (usuários) do sistema const profiles = await profileService.list(); // Busca todas as roles de uma vez const allRoles = await userService.listRoles(); // Converte Profile para UserInfo (estrutura compatível com a interface esperada) const userInfoList: FullUserInfo[] = profiles.map((profile) => { // Filtra as roles deste usuário específico const userRoles = allRoles .filter((role) => role.user_id === profile.id) .map((role) => role.role); // Calcula permissões baseado nas roles const isAdmin = userRoles.includes("admin"); const isManager = userRoles.includes("gestor"); const isDoctor = userRoles.includes("medico"); const isSecretary = userRoles.includes("secretaria"); return { user: { id: profile.id || "", email: profile.email || "", email_confirmed_at: null, created_at: profile.created_at || new Date().toISOString(), last_sign_in_at: null, }, profile: { id: profile.id || "", full_name: profile.full_name, email: profile.email, phone: profile.phone || null, avatar_url: profile.avatar_url, disabled: profile.disabled || false, created_at: profile.created_at || new Date().toISOString(), updated_at: profile.updated_at || new Date().toISOString(), }, roles: userRoles, permissions: { isAdmin, isManager, isDoctor, isSecretary, isAdminOrManager: isAdmin || isManager, }, }; }); setUsuarios(userInfoList); } catch (error) { console.error("Erro ao carregar usuários:", error); toast.error("Erro ao carregar usuários"); setUsuarios([]); } finally { setLoading(false); } }; const loadPacientes = async () => { setLoading(true); try { const patients = await patientService.list(); setPacientes(patients); } catch (error) { console.error("Erro ao carregar pacientes:", error); toast.error("Erro ao carregar pacientes"); } finally { setLoading(false); } }; const loadMedicos = async () => { setLoading(true); try { const doctors = await doctorService.list(); setMedicos(doctors); } catch (error) { console.error("Erro ao carregar médicos:", error); toast.error("Erro ao carregar médicos"); } finally { setLoading(false); } }; const handleCreateUser = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { // Determina redirect_url baseado no role let redirectUrl = "https://mediconnectbrasil.netlify.app/"; if (formUser.role === "medico") { redirectUrl = "https://mediconnectbrasil.netlify.app/medico/painel"; } else if (formUser.role === "paciente") { redirectUrl = "https://mediconnectbrasil.netlify.app/paciente/agendamento"; } else if (formUser.role === "secretaria") { redirectUrl = "https://mediconnectbrasil.netlify.app/secretaria/painel"; } else if (formUser.role === "admin" || formUser.role === "gestor") { redirectUrl = "https://mediconnectbrasil.netlify.app/admin/painel"; } // Criar com senha OU magic link if (usePassword && userPassword.trim()) { // Criar com senha await userService.createUserWithPassword({ email: formUser.email, password: userPassword, full_name: formUser.full_name, phone: formUser.phone, role: formUser.role, }); toast.success( `Usuário ${formUser.full_name} criado com sucesso! Email de confirmação enviado.` ); } else { // Criar com magic link (padrão) await userService.createUser( { ...formUser, redirect_url: redirectUrl }, false ); toast.success( `Usuário ${formUser.full_name} criado com sucesso! Magic link enviado para o email.` ); } setShowUserModal(false); resetFormUser(); setUserPassword(""); setUsePassword(false); loadUsuarios(); } catch (error) { console.error("Erro ao criar usuário:", error); toast.error("Erro ao criar usuário"); } finally { setLoading(false); } }; // Funções de gerenciamento de usuários // TODO: Implement admin user endpoints (update, enable/disable, delete) const handleEditUser = (_user: FullUserInfo) => { toast.error("Função de edição de usuário ainda não implementada"); // setEditingUser(user); // setEditForm({ // full_name: user.profile?.full_name || "", // email: user.profile?.email || "", // phone: user.profile?.phone || "", // disabled: user.profile?.disabled || false, // }); }; const handleSaveEditUser = async () => { toast.error("Função de salvar usuário ainda não implementada"); // TODO: Implement adminUserService.updateUser endpoint // if (!editingUser) return; // try { // const result = await adminUserService.updateUser(editingUser.user.id, editForm); // if (result.success) { // toast.success("Usuário atualizado com sucesso!"); // setEditingUser(null); // loadUsuarios(); // } // } catch { // toast.error("Erro ao atualizar usuário"); // } }; const handleToggleStatusUser = async ( _userId: string, _currentStatus: boolean ) => { toast.error( "Função de habilitar/desabilitar usuário ainda não implementada" ); // TODO: Implement adminUserService.enableUser/disableUser endpoints // try { // const result = currentStatus // ? await adminUserService.enableUser(userId) // : await adminUserService.disableUser(userId); // if (result.success) { // toast.success(`Usuário ${currentStatus ? "habilitado" : "desabilitado"} com sucesso!`); // loadUsuarios(); // } // } catch { // toast.error("Erro ao alterar status do usuário"); // } }; const handleDeleteUser = async (userId: string, userName: string) => { // Abre o dialog customizado de confirmação setConfirmDialog({ isOpen: true, title: "ATENÇÃO: OPERAÇÃO IRREVERSÍVEL!", message: (

Deseja deletar permanentemente o usuário{" "} "{userName}"?

Isso irá deletar:

  • Conta de autenticação
  • Perfil do usuário
  • Todas as roles e permissões
  • Dados relacionados (cascata)

⚠️ Esta ação NÃO pode ser desfeita!

), confirmText: "Deletar Permanentemente", cancelText: "Cancelar", requireTypedConfirmation: true, confirmationWord: "DELETAR", isDangerous: true, onConfirm: async () => { setLoading(true); try { await userService.deleteUser(userId); toast.success(`Usuário "${userName}" deletado permanentemente!`); loadUsuarios(); } catch (error: unknown) { console.error("Erro ao deletar usuário:", error); const errorMessage = (error as { response?: { data?: { error?: string } } })?.response ?.data?.error || "Erro ao deletar usuário"; toast.error(errorMessage); } finally { setLoading(false); } }, }); }; // Funções de gerenciamento de roles const handleAddRole = async () => { if (!managingRolesUser) return; try { await userService.addUserRole(managingRolesUser.user.id, newRole); toast.success(`Role "${newRole}" adicionada com sucesso!`); setNewRole("user"); await loadUsuarios(); // Atualiza o estado local do modal const updatedUsers = usuarios.find( (u) => u.user.id === managingRolesUser.user.id ); if (updatedUsers) { setManagingRolesUser(updatedUsers); } } catch (error) { console.error("Erro ao adicionar role:", error); toast.error("Erro ao adicionar role"); } }; const handleRemoveRole = async (role: UserRole) => { if (!managingRolesUser) return; if (!confirm(`Tem certeza que deseja remover a role "${role}"?`)) return; try { await userService.removeUserRole(managingRolesUser.user.id, role); toast.success(`Role "${role}" removida com sucesso!`); await loadUsuarios(); // Atualiza o estado local do modal const updatedUsers = usuarios.find( (u) => u.user.id === managingRolesUser.user.id ); if (updatedUsers) { setManagingRolesUser(updatedUsers); } } catch (error) { console.error("Erro ao remover role:", error); toast.error("Erro ao remover role"); } }; // Funções de gerenciamento de pacientes const handleEditPaciente = (paciente: Paciente) => { setEditingPaciente(paciente); setFormPaciente({ full_name: paciente.full_name, cpf: paciente.cpf || "", email: paciente.email || "", phone_mobile: paciente.phone_mobile || "", birth_date: paciente.birth_date || "", social_name: paciente.social_name || "", sex: paciente.sex || "", blood_type: paciente.blood_type || "", weight_kg: paciente.weight_kg?.toString() || "", height_m: paciente.height_m?.toString() || "", street: paciente.street || "", number: paciente.number || "", complement: paciente.complement || "", neighborhood: paciente.neighborhood || "", city: paciente.city || "", state: paciente.state || "", cep: paciente.cep || "", }); setShowPacienteModal(true); }; const handleSavePaciente = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { const patientData = { full_name: formPaciente.full_name, cpf: formPaciente.cpf.replace(/\D/g, ""), // Remover máscara do CPF email: formPaciente.email, phone_mobile: formPaciente.phone_mobile, birth_date: formPaciente.birth_date, social_name: formPaciente.social_name, sex: formPaciente.sex, blood_type: formPaciente.blood_type, weight_kg: formPaciente.weight_kg ? parseFloat(formPaciente.weight_kg) : undefined, height_m: formPaciente.height_m ? parseFloat(formPaciente.height_m) : undefined, street: formPaciente.street, number: formPaciente.number, complement: formPaciente.complement, neighborhood: formPaciente.neighborhood, city: formPaciente.city, state: formPaciente.state, cep: formPaciente.cep, }; if (editingPaciente) { await patientService.update(editingPaciente.id, patientData); toast.success("Paciente atualizado com sucesso!"); setShowPacienteModal(false); setEditingPaciente(null); resetFormPaciente(); loadPacientes(); } else { // Usar create-user com create_patient_record=true (nova API 21/10) // isPublicRegistration = false porque é admin criando await userService.createUser( { email: patientData.email, full_name: patientData.full_name, phone: patientData.phone_mobile, role: "paciente", create_patient_record: true, cpf: patientData.cpf, phone_mobile: patientData.phone_mobile, redirect_url: "https://mediconnectbrasil.netlify.app/paciente/agendamento", }, false ); toast.success( "Paciente criado com sucesso! Magic link enviado para o email." ); setShowPacienteModal(false); resetFormPaciente(); loadPacientes(); } } catch (error) { console.error("Erro ao salvar paciente:", error); toast.error("Erro ao salvar paciente"); } finally { setLoading(false); } }; const handleDeletePaciente = async (id: string, nome: string) => { if ( !confirm( `Tem certeza que deseja deletar o paciente "${nome}"? Esta ação não pode ser desfeita.` ) ) { return; } try { console.log("[PainelAdmin] Deletando paciente:", { id, nome }); await patientService.delete(id); console.log("[PainelAdmin] Paciente deletado com sucesso"); toast.success("Paciente deletado com sucesso!"); loadPacientes(); } catch (error) { console.error("[PainelAdmin] Erro ao deletar paciente:", error); toast.error("Erro ao deletar paciente"); } }; // Funções de gerenciamento de médicos const handleEditMedico = (medico: Doctor) => { setEditingMedico(medico); setFormMedico({ crm: medico.crm || "", crm_uf: medico.crm_uf || "SP", specialty: medico.specialty || "", full_name: medico.full_name || "", cpf: medico.cpf || "", email: medico.email || "", phone_mobile: medico.phone_mobile || "", phone2: medico.phone2 || "", cep: medico.cep || "", street: medico.street || "", number: medico.number || "", complement: medico.complement || "", neighborhood: medico.neighborhood || "", city: medico.city || "", state: medico.state || "", birth_date: medico.birth_date || "", rg: medico.rg || "", active: medico.active ?? true, }); setShowMedicoModal(true); }; const handleSaveMedico = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { // Preparar dados com CPF sem máscara const medicoData = { ...formMedico, cpf: formMedico.cpf.replace(/\D/g, ""), // Remover máscara do CPF }; if (editingMedico) { await doctorService.update(editingMedico.id!, medicoData); toast.success("Médico atualizado com sucesso!"); setShowMedicoModal(false); setEditingMedico(null); resetFormMedico(); loadMedicos(); } else { // Usar create-user com role=medico (nova API 21/10 - create-doctor não cria auth user) // isPublicRegistration = false porque é admin criando await userService.createUser( { email: medicoData.email, full_name: medicoData.full_name, phone: medicoData.phone_mobile, role: "medico", redirect_url: "https://mediconnectbrasil.netlify.app/medico/painel", }, false ); // Depois criar registro na tabela doctors com createDoctor (sem password) await userService.createDoctor({ crm: medicoData.crm, crm_uf: medicoData.crm_uf, cpf: medicoData.cpf, full_name: medicoData.full_name, email: medicoData.email, specialty: medicoData.specialty, phone_mobile: medicoData.phone_mobile, }); toast.success( "Médico criado com sucesso! Magic link enviado para o email." ); setShowMedicoModal(false); resetFormMedico(); loadMedicos(); } } catch (error) { console.error("Erro ao salvar médico:", error); toast.error("Erro ao salvar médico"); } finally { setLoading(false); } }; const handleDeleteMedico = async (id: string, nome: string) => { if ( !confirm( `Tem certeza que deseja deletar o médico "${nome}"? Esta ação não pode ser desfeita.` ) ) { return; } try { await doctorService.delete(id); toast.success("Médico deletado com sucesso!"); loadMedicos(); } catch { toast.error("Erro ao deletar médico"); } }; const resetFormPaciente = () => { setFormPaciente({ full_name: "", cpf: "", email: "", phone_mobile: "", birth_date: "", social_name: "", sex: "", blood_type: "", weight_kg: "", height_m: "", street: "", number: "", complement: "", neighborhood: "", city: "", state: "", cep: "", }); }; const resetFormUser = () => { setFormUser({ email: "", full_name: "", phone: "", role: "user", }); }; const resetFormMedico = () => { setFormMedico({ crm: "", crm_uf: "SP", specialty: "", full_name: "", cpf: "", email: "", phone_mobile: "", phone2: "", cep: "", street: "", number: "", complement: "", neighborhood: "", city: "", state: "", birth_date: "", rg: "", active: true, }); }; const estadosBR = [ "AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO", ]; const availableRoles: UserRole[] = [ "admin", "gestor", "medico", "secretaria", "user", "paciente", ]; return (
{/* Header */}

Painel de Administração

Gerenciar pacientes, usuários e médicos do sistema

{/* Tabs */}
{/* Content */}
{activeTab === "pacientes" && (

Pacientes Cadastrados

{loading ? (
Carregando...
) : (
{pacientes.length === 0 ? (
Nenhum paciente cadastrado
) : ( pacientes.map((p, idx) => (

{p.full_name}

{p.email} | {p.phone_mobile}

CPF: {p.cpf} | Nascimento: {p.birth_date}

)) )}
)}
)} {activeTab === "usuarios" && (

Gerenciar Usuários

{/* Search Bar */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40 transition-colors" />
{loading ? (
Carregando usuários...
) : (
{usuarios.filter((user) => { const searchLower = searchTerm.toLowerCase(); return ( user.profile?.full_name ?.toLowerCase() .includes(searchLower) || user.profile?.email ?.toLowerCase() .includes(searchLower) || user.user.email.toLowerCase().includes(searchLower) ); }).length === 0 ? ( ) : ( usuarios .filter((user) => { const searchLower = searchTerm.toLowerCase(); return ( user.profile?.full_name ?.toLowerCase() .includes(searchLower) || user.profile?.email ?.toLowerCase() .includes(searchLower) || user.user.email .toLowerCase() .includes(searchLower) ); }) .map((user) => ( )) )}
Nome Email Telefone Roles Status Ações
{searchTerm ? "Nenhum usuário encontrado" : "Nenhum usuário cadastrado"}
{user.profile?.full_name || "Sem nome"}
{user.profile?.email || user.user.email} {user.profile?.phone || "-"}
{user.roles && user.roles.length > 0 ? ( user.roles.map((role, index) => ( {role} )) ) : ( Sem roles )}
{user.profile?.disabled ? "Desabilitado" : "Ativo"}
)}
)} {activeTab === "medicos" && (

Médicos Cadastrados

{loading ? (
Carregando...
) : (
{medicos.length === 0 ? (
Nenhum médico cadastrado
) : ( medicos.map((m, idx) => (

{m.full_name}

{m.specialty} | CRM: {m.crm}/{m.crm_uf}

{m.email} | {m.phone_mobile}

{m.active ? "Ativo" : "Inativo"}
)) )}
)}
)}
{/* Modal Paciente */} {showPacienteModal && (

Novo Paciente

setFormPaciente({ ...formPaciente, full_name: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" />
setFormPaciente({ ...formPaciente, social_name: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" />
setFormPaciente({ ...formPaciente, cpf: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" placeholder="00000000000" />
setFormPaciente({ ...formPaciente, email: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" />
setFormPaciente({ ...formPaciente, phone_mobile: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" placeholder="(00) 00000-0000" />
{!editingPaciente && (

🔐 Ativação de Conta: Um link mágico (magic link) será enviado automaticamente para o email do paciente para ativar a conta e definir senha.

)}
setFormPaciente({ ...formPaciente, birth_date: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" />
setFormPaciente({ ...formPaciente, blood_type: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-green-600/40" placeholder="A+" />
)} {/* Modal Usuário */} {showUserModal && (

Novo Usuário

setFormUser({ ...formUser, full_name: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" />
setFormUser({ ...formUser, email: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" />
setFormUser({ ...formUser, phone: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" placeholder="(00) 00000-0000" />
{/* Toggle para criar com senha */}
{/* Campo de senha (condicional) */} {usePassword && (
setUserPassword(e.target.value)} minLength={6} className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" placeholder="Mínimo 6 caracteres" />

O usuário precisará confirmar o email antes de fazer login

)} {!usePassword && (

ℹ️ Um Magic Link será enviado para o email do usuário para ativação da conta

)}
)} {/* Modal Médico */} {showMedicoModal && (

Novo Médico

setFormMedico({ ...formMedico, full_name: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" />
setFormMedico({ ...formMedico, specialty: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" placeholder="Cardiologia" />
setFormMedico({ ...formMedico, crm: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" placeholder="123456" />
setFormMedico({ ...formMedico, cpf: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" placeholder="000.000.000-00" />
setFormMedico({ ...formMedico, rg: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" />
setFormMedico({ ...formMedico, email: e.target.value }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" />
setFormMedico({ ...formMedico, phone_mobile: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" placeholder="(00) 00000-0000" />
{!editingMedico && (

🔐 Ativação de Conta: Um link mágico (magic link) será enviado automaticamente para o email do médico para ativar a conta e definir senha.

)}
setFormMedico({ ...formMedico, birth_date: e.target.value, }) } className="w-full border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-purple-600/40" />
)} {/* Modal de Edição de Usuário */} {editingUser && (

Editar Usuário

setEditForm({ ...editForm, full_name: e.target.value }) } className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" />
setEditForm({ ...editForm, email: e.target.value }) } className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" />
setEditForm({ ...editForm, phone: e.target.value }) } className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-blue-600/40" />
)} {/* Modal de Gerenciar Roles */} {managingRolesUser && (

Gerenciar Roles

{managingRolesUser.profile?.full_name || managingRolesUser.user.email}

{/* Lista de roles atuais */}

Roles Atuais:

{managingRolesUser && managingRolesUser.roles && managingRolesUser.roles.length > 0 ? ( managingRolesUser.roles.map((role, index) => (
{role}
)) ) : ( Nenhum role atribuído )}
{/* Adicionar novo role */}

Adicionar Role:

)} {/* Dialog de Confirmação Customizado */} setConfirmDialog((prev) => ({ ...prev, isOpen: false }))} onConfirm={confirmDialog.onConfirm} title={confirmDialog.title} message={confirmDialog.message} confirmText={confirmDialog.confirmText} cancelText={confirmDialog.cancelText} requireTypedConfirmation={confirmDialog.requireTypedConfirmation} confirmationWord={confirmDialog.confirmationWord} isDangerous={confirmDialog.isDangerous} />
); }; export default PainelAdmin;