/* JRN — Admin: Usuários, cadastro/edição e permissões */ /* ---------- Modal: credenciais do novo usuário ---------- */ function PasswordRevealModal({ nome, email, senha, onClose }) { const [copied, setCopied] = useState(false); const [showSenha, setShowSenha] = useState(true); const copy = () => { navigator.clipboard.writeText(senha).catch(() => {}); setCopied(true); setTimeout(() => setCopied(false), 2200); }; return ( Entendido}>
{/* Alerta */}
Anote ou copie a senha agora. Por segurança, ela não poderá ser recuperada após fechar este modal.
{/* Dados do usuário */}
Credenciais de acesso
Usuário (e-mail) {email}
Senha inicial
{showSenha ? senha : '•'.repeat(senha.length)}
{/* Botão de copiar */}

No primeiro acesso, {nome.split(' ')[0]} será solicitado(a) a definir uma nova senha.

); } /* ---------- Modal: cadastro / edição de usuário ---------- */ function UserFormModal({ user, onClose, onSave }) { const isEdit = !!user; const [f, setF] = useState(user ? { nome: user.nome, email: user.email, cargo: user.cargo, perfil: user.perfil, status: user.status, _dbId: user._dbId } : { nome: '', email: '', cargo: '', perfil: 'comum', status: 'ativo', senha: '' }); const [saving, setSaving] = useState(false); const [err, setErr] = useState(''); const [showSenha, setShowSenha] = useState(false); const set = (k, v) => setF(s => ({ ...s, [k]: v })); const valid = f.nome.trim() && /\S+@\S+\.\S+/.test(f.email); const handleSave = async () => { setSaving(true); setErr(''); try { await onSave(f); } catch (e) { setErr(e.message || 'Erro ao salvar.'); setSaving(false); } }; return ( Cancelar {saving ? : null} {isEdit ? 'Salvar alterações' : 'Cadastrar usuário'} }> {err &&
{err}
}
set('nome', e.target.value)} placeholder="Ex.: Maria Souza" /> set('email', e.target.value)} placeholder="nome@empresa.com.br" disabled={isEdit} /> set('cargo', e.target.value)} placeholder="Ex.: Controller" /> {!isEdit && (
set('senha', e.target.value)} placeholder="Gerar automaticamente" autoComplete="new-password" style={{ paddingRight: 40 }} />
)}
{f.perfil === 'admin' && (
Administradores acessam todas as empresas, dashboards e funções administrativas automaticamente.
)}
); } /* ---------- Modal: permissões (empresa + dashboard + funções) ---------- */ function PermissionsModal({ user, empresas, onClose, onSaved }) { const [allDashboards, setAllDashboards] = useState([]); const [emp, setEmp] = useState(new Set()); const [dash, setDash] = useState(new Set()); const [fns, setFns] = useState(new Set()); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [err, setErr] = useState(''); useEffect(() => { Promise.all([ apiDashboardsGet(), apiPermissoesGet(user.id, empresas), ]).then(([dashes, perms]) => { setAllDashboards(dashes); setEmp(new Set(perms.empresas)); setDash(new Set(perms.dashboards)); setFns(new Set(perms.funcoes)); }).catch(e => setErr(e.message || 'Erro ao carregar permissões.')) .finally(() => setLoading(false)); }, []); const dashByCompany = (companyId) => allDashboards.filter(d => d.companyId === companyId); const toggleEmp = (id) => { const ne = new Set(emp); const nd = new Set(dash); if (ne.has(id)) { ne.delete(id); dashByCompany(id).forEach(d => nd.delete(d.id)); } else { ne.add(id); } setEmp(ne); setDash(nd); }; const toggleDash = (d) => { const nd = new Set(dash); if (nd.has(d.id)) { nd.delete(d.id); } else { nd.add(d.id); } setDash(nd); if (!emp.has(d.companyId) && nd.has(d.id)) setEmp(new Set(emp).add(d.companyId)); }; const toggleFn = (id) => { const n = new Set(fns); n.has(id) ? n.delete(id) : n.add(id); setFns(n); }; const save = async () => { setSaving(true); setErr(''); try { await apiPermissoesSet(user.id, [...emp], [...dash], [...fns], empresas, allDashboards); onSaved(); } catch (e) { setErr(e.message || 'Erro ao salvar permissões.'); setSaving(false); } }; return ( {emp.size} empresas · {dash.size} painéis · {fns.size} funções Cancelar {saving ? : null} Salvar permissões }> {err &&
{err}
} {loading ? (
) : (
Empresas e painéis
{(empresas || []).map(c => { const ds = dashByCompany(c.id); const on = emp.has(c.id); return (
toggleEmp(c.id)} accent={c.cor} />
{c.nome}
{c.tipo} · {ds.length} painéis
{on && (
{ds.map(d => ( ))} {ds.length === 0 && Nenhum dashboard cadastrado.}
)}
); })}
Funções administrativas
{FUNCOES_ADMIN.map(fn => ( ))}
)}
); } /* ---------- Página: lista de usuários ---------- */ function UsersAdmin({ empresas, toast }) { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [q, setQ] = useState(''); const [perfil, setPerfil] = useState('todos'); const [modal, setModal] = useState(null); // {type:'form'|'perm', user} const [senhaModal, setSenhaModal] = useState(null); // {nome, email, senha} const loadUsers = () => { setLoading(true); apiUsuariosGet().then(setUsers).catch(() => toast('Erro ao carregar usuários.', 'danger')).finally(() => setLoading(false)); }; useEffect(loadUsers, []); const filtered = users.filter(u => (perfil === 'todos' || u.perfil === perfil) && (u.nome.toLowerCase().includes(q.toLowerCase()) || u.email.toLowerCase().includes(q.toLowerCase())) ); const saveUser = async (f) => { if (f._dbId) { await apiUsuariosUpdate(f); toast('Usuário atualizado com sucesso.'); setModal(null); loadUsers(); } else { const result = await apiUsuariosCreate(f); setModal(null); loadUsers(); // Exibe as credenciais para o admin compartilhar com o usuário if (result && result.senha_provisoria) { setSenhaModal({ nome: f.nome, email: f.email, senha: result.senha_provisoria }); } } }; const savePerm = () => { setModal(null); toast('Permissões atualizadas.'); }; const removeUser = async (u) => { if (!confirm(`Remover ${u.nome}?`)) return; try { await apiUsuariosDelete(u); toast('Usuário removido.', 'danger'); loadUsers(); } catch (e) { toast(e.message || 'Erro ao remover.', 'danger'); } }; return (
setModal({ type: 'form' })}>Novo usuário} />
setQ(e.target.value)} />
{loading ? (
) : (
{filtered.map(u => ( ))}
Usuário Cargo Perfil Status Último acesso
{u.avatar} {u.nome} {u.email}
{u.cargo} {u.perfil === 'admin' ? Admin : Comum} {u.ultimoAcesso}
{u.perfil !== 'admin' && ( )}
{filtered.length === 0 && }
)}
{modal?.type === 'form' && ( setModal(null)} onSave={saveUser} /> )} {modal?.type === 'perm' && ( setModal(null)} onSaved={savePerm} /> )} {senhaModal && ( setSenhaModal(null)} /> )}
); } Object.assign(window, { UsersAdmin, UserFormModal, PermissionsModal, PasswordRevealModal });