// Usuarios Module function Usuarios() { const [users, setUsers] = React.useState([]); const [loading, setLoading] = React.useState(true); const [showModal, setShowModal] = React.useState(false); const [form, setForm] = React.useState({ name: '', email: '', password: '', role: 'usuario', department: '' }); const [creating, setCreating] = React.useState(false); const [showPass, setShowPass] = React.useState(false); const [editTarget, setEditTarget] = React.useState(null); const [editForm, setEditForm] = React.useState({ name: '', role: 'usuario', department: '' }); const [editSaving, setEditSaving] = React.useState(false); const [resetTarget, setResetTarget] = React.useState(null); const [resetForm, setResetForm] = React.useState({ password: '', show: false }); const [resetSaving, setResetSaving] = React.useState(false); const [toast, setToast] = React.useState(null); const showToast = (msg, type = 'success') => { setToast({ msg, type }); setTimeout(() => setToast(null), 3500); }; const fetchUsers = () => { sb.from('app_users').select('*').order('created_at', { ascending: false }).then(({ data }) => { setUsers(data || []); setLoading(false); }); }; React.useEffect(() => { fetchUsers(); }, []); const handleCreate = async () => { if (!form.email.trim() || !form.password.trim()) { showToast('Preencha e-mail e senha.', 'error'); return; } if (form.password.length < 6) { showToast('Senha precisa ter pelo menos 6 caracteres.', 'error'); return; } setCreating(true); const tempClient = supabase.createClient(window.SUPA_URL, window.SUPA_KEY, { auth: { persistSession: false, autoRefreshToken: false }, }); const { data: authData, error: authErr } = await tempClient.auth.signUp({ email: form.email.trim().toLowerCase(), password: form.password, }); if (authErr) { const msg = authErr.message.includes('already') ? 'E-mail já cadastrado.' : 'Erro ao criar usuário: ' + authErr.message; showToast(msg, 'error'); setCreating(false); return; } // Upsert porque o trigger handle_new_auth_user pode ter inserido a linha // primeiro (com role default 'usuario' e department NULL) — aqui sobrescrevemos // com os valores que o admin escolheu na tela. await sb.from('app_users').upsert({ id: authData.user?.id, email: form.email.trim().toLowerCase(), name: form.name.trim() || form.email.split('@')[0], role: form.role, department: form.department || null, }, { onConflict: 'id' }); showToast('Usuário criado com sucesso!'); setForm({ name: '', email: '', password: '', role: 'usuario', department: '' }); setShowModal(false); fetchUsers(); setCreating(false); }; const openEdit = (user) => { setEditTarget(user); setEditForm({ name: user.name || '', role: user.role || 'usuario', department: user.department || '' }); }; const handleEditSave = async () => { if (!editTarget) return; setEditSaving(true); const { error } = await sb.from('app_users').update({ name: editForm.name.trim() || editTarget.email.split('@')[0], role: editForm.role, department: editForm.department || null, }).eq('id', editTarget.id); setEditSaving(false); if (error) { showToast('Erro ao salvar: ' + (error.message || 'tente novamente.'), 'error'); return; } showToast('Usuário atualizado!'); setEditTarget(null); fetchUsers(); }; const openReset = (user) => { setResetTarget(user); setResetForm({ password: '', show: false }); }; const handleSetPassword = async () => { if (!resetTarget) return; if (resetForm.password.length < 6) { showToast('Senha precisa ter pelo menos 6 caracteres.', 'error'); return; } setResetSaving(true); const { error } = await sb.rpc('admin_set_user_password', { p_user_id: resetTarget.id, p_new_password: resetForm.password, }); setResetSaving(false); if (error) { showToast('Erro ao redefinir senha: ' + (error.message || 'tente novamente.'), 'error'); return; } showToast(`Senha de ${resetTarget.name || resetTarget.email} redefinida!`); setResetTarget(null); setResetForm({ password: '', show: false }); }; const handleDelete = async (user) => { if (!window.confirm(`Remover ${user.name || user.email} do sistema?`)) return; await sb.from('app_users').delete().eq('id', user.id); showToast('Usuário removido da lista.'); fetchUsers(); }; const roleLabel = { admin: 'Administrador', usuario: 'Usuário', visualizador: 'Visualizador' }; const roleColor = { admin: 'danger', usuario: 'primary', visualizador: 'default' }; const fmtDate = (iso) => iso ? new Date(iso).toLocaleDateString('pt-BR') : '—'; const inputStyle = { width: '100%', boxSizing: 'border-box', padding: '10px 13px', fontSize: 13, border: `1.5px solid ${DS.colors.border}`, borderRadius: DS.radius.sm, outline: 'none', fontFamily: 'Inter, sans-serif', color: DS.colors.text, background: '#F8FAFC', }; if (loading) { return (

Usuários

); } return (

Usuários

Gerencie quem tem acesso ao sistema

setShowModal(true)}>Novo usuário
{users.length === 0 ? (
Nenhum usuário cadastrado
Clique em "Novo usuário" para adicionar alguém.
) : ( <>
NomeE-mailPerfilSetorCriado emAções
{users.map((u, i) => (
{u.name || '—'}
{u.email} {roleLabel[u.role] || u.role} {deptLabel(u.department)} {fmtDate(u.created_at)}
openEdit(u)}>Editar openReset(u)}>Senha
))} )}
{showModal && ( { setShowModal(false); setForm({ name: '', email: '', password: '', role: 'usuario', department: '' }); }} title="Novo usuário" width={480}>
setForm(f => ({ ...f, name: e.target.value }))} placeholder="Ex: João Silva" style={inputStyle} />
setForm(f => ({ ...f, email: e.target.value }))} placeholder="usuario@email.com" style={inputStyle} />
setForm(f => ({ ...f, password: e.target.value }))} placeholder="Mínimo 6 caracteres" style={{ ...inputStyle, paddingRight: 44 }} />
Admin / Financeiro veem todos os módulos e valores. Demais setores não veem o módulo Financeiro nem valores em R$.
{ setShowModal(false); setForm({ name: '', email: '', password: '', role: 'usuario', department: '' }); }}>Cancelar {creating ? 'Criando…' : 'Criar usuário'}
)} {editTarget && ( setEditTarget(null)} title="Editar usuário" width={460}>
Editando
{editTarget.email}
setEditForm(f => ({ ...f, name: e.target.value }))} style={inputStyle} />
setEditTarget(null)}>Cancelar {editSaving ? 'Salvando…' : 'Salvar'}
)} {resetTarget && ( { setResetTarget(null); setResetForm({ password: '', show: false }); }} title="Definir nova senha" width={440}>
Usuário
{resetTarget.name || resetTarget.email}
{resetTarget.email}
setResetForm(f => ({ ...f, password: e.target.value }))} placeholder="Mínimo 6 caracteres" style={{ ...inputStyle, paddingRight: 44 }} autoFocus />
A senha atual será substituída. Informe a nova senha ao usuário pessoalmente.
{ setResetTarget(null); setResetForm({ password: '', show: false }); }}>Cancelar {resetSaving ? 'Salvando…' : 'Definir senha'}
)} {toast && setToast(null)} />}
); } Object.assign(window, { Usuarios });