import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { usuariosApi } from '@/api/usuarios'; import { rolesApi } from '@/api/roles'; import type { ActualizarUsuarioBody, Usuario } from '@/types'; import { PageHeader } from '@/components/PageHeader'; import { DataTable, type Column } from '@/components/DataTable'; import { Modal } from '@/components/Modal'; import { ConfirmDialog } from '@/components/ConfirmDialog'; import { ErrorAlert } from '@/components/ErrorAlert'; import { Field, Input, Select, Checkbox, btnPrimary, btnSecondary, btnDanger, } from '@/components/form/Field'; export function UsersPage() { const qc = useQueryClient(); const [editUser, setEditUser] = useState(null); const [deleteId, setDeleteId] = useState(null); const [formError, setFormError] = useState(''); const usuarios = useQuery({ queryKey: ['usuarios'], queryFn: usuariosApi.list }); const pendientes = useQuery({ queryKey: ['usuarios-pendientes'], queryFn: usuariosApi.pendientes, }); const roles = useQuery({ queryKey: ['roles'], queryFn: rolesApi.list }); const aceptar = useMutation({ mutationFn: (id: number) => usuariosApi.aceptar(id), onSuccess: () => { qc.invalidateQueries({ queryKey: ['usuarios'] }); qc.invalidateQueries({ queryKey: ['usuarios-pendientes'] }); qc.invalidateQueries({ queryKey: ['dashboard-stats'] }); }, }); const update = useMutation({ mutationFn: ({ id, body }: { id: number; body: ActualizarUsuarioBody }) => usuariosApi.update(id, body), onSuccess: () => { qc.invalidateQueries({ queryKey: ['usuarios'] }); qc.invalidateQueries({ queryKey: ['usuarios-pendientes'] }); setEditUser(null); }, onError: (e: Error) => setFormError(e.message), }); const remove = useMutation({ mutationFn: (id: number) => usuariosApi.delete(id), onSuccess: () => { qc.invalidateQueries({ queryKey: ['usuarios'] }); setDeleteId(null); }, }); const columns: Column[] = [ { key: 'id', header: 'ID', render: (u) => u.id }, { key: 'email', header: 'Email', render: (u) => u.username }, { key: 'nombre', header: 'Nombre', render: (u) => u.nombre }, { key: 'rol', header: 'Rol', render: (u) => u.rol?.name ?? u.roles ?? '—', }, { key: 'aprobado', header: 'Aprobado', render: (u) => (u.aprobado ? 'Sí' : 'No'), }, { key: 'visible', header: 'Visible', render: (u) => (u.visible ? 'Sí' : 'No'), }, { key: 'actions', header: '', render: (u) => (
), }, ]; return (
{pendientes.data && pendientes.data.length > 0 && (

Pendientes de aprobación ({pendientes.data.length})

    {pendientes.data.map((u) => (
  • {u.nombre} — {u.username}
  • ))}
)} u.id} loading={usuarios.isLoading} /> {editUser && ( { setEditUser(null); setFormError(''); }} onSave={(body) => update.mutate({ id: editUser.id, body })} /> )} deleteId != null && remove.mutate(deleteId)} onCancel={() => setDeleteId(null)} loading={remove.isPending} />
); } function UserFormModal({ user, roles, error, loading, onClose, onSave, }: { user: Usuario; roles: { id: number; name: string }[]; error: string; loading: boolean; onClose: () => void; onSave: (body: ActualizarUsuarioBody) => void; }) { const [nombre, setNombre] = useState(user.nombre); const [ci, setCi] = useState(String(user.ci)); const [celular, setCelular] = useState(String(user.celular)); const [aprobado, setAprobado] = useState(user.aprobado); const [visible, setVisible] = useState(user.visible); const [rolId, setRolId] = useState(String(user.rol?.id ?? '')); const [password, setPassword] = useState(''); return ( {error &&
}
{ e.preventDefault(); const body: ActualizarUsuarioBody = { nombre, ci: Number(ci), celular: Number(celular), aprobado, visible, rol: rolId ? Number(rolId) : undefined, }; if (password) body.password = password; onSave(body); }} > setNombre(e.target.value)} required /> setCi(e.target.value)} required /> setCelular(e.target.value)} required /> setPassword(e.target.value)} autoComplete="new-password" /> setAprobado(e.target.checked)} /> setVisible(e.target.checked)} />
); }