Módulo: Usuarios¶
Este módulo implementa listado, edición y acciones de activación/eliminación de usuarios siguiendo el mismo patrón que roles/*
.
Columnas (SSOT)¶
id
(ordenable)name
(ordenable)email
(ordenable)roles_count
(ordenable)is_active
(ordenable)created_at
(ordenable)
Las columnas están definidas en resources/js/pages/users/columns.tsx
y son la fuente de verdad también para exportaciones (vía UserService::defaultExportColumns
).
Filtros¶
Implementados con FilterSheet
y FilterBadges
(mismo UX de Roles):
name
(texto, LIKE case-insensitive)email
(texto, LIKE case-insensitive)role_id
(select de roles disponibles)is_active
(select all/active/inactive)created_between
(rango de fechas)
Archivo: resources/js/pages/users/filters.tsx
.
Permisos¶
Definidos en config/permissions/users.php
y agregados por config/permissions.php
:
users.view
users.create
users.update
users.delete
users.restore
users.forceDelete
users.export
users.setActive
Policy: App\Policies\UserPolicy
(extiende BaseResourcePolicy
con prefijo users
).
Exportación¶
- Endpoint:
GET /users/export?format=csv|xlsx|json
- Permiso:
users.export
- Columns SSOT desde
UserService::defaultExportColumns()
Backend (resumen)¶
- Request:
App\Http\Requests\UserIndexRequest
(extiendeBaseIndexRequest
) - Repository:
App\Repositories\UserRepository
(extiendeBaseRepository
)searchable()
:name
,email
allowedSorts()
:id
,name
,email
,is_active
,created_at
withRelations()
:withCount('roles')
filterMap()
:name
,email
,role_id
,is_active
,created_between
- Service:
App\Services\UserService
(extiendeBaseService
)toRow()
:{ id, name, email, is_active, roles_count, created_at }
defaultExportColumns()
ydefaultExportFilename()
- Controller:
App\Http\Controllers\UsersController
(extiendeBaseIndexController
)view()
:users/index
indexRequestClass()
:UserIndexRequest
allowedExportFormats()
:csv
,xlsx
,json
- Extra:
availableRoles
para el filtro
-
Rutas:
routes/users.php
GET /users
→ indexGET /users/export
→ exportPOST /users/bulk
→ operaciones masivas (delete
,restore
,forceDelete
,setActive
)GET /users/selected
→ subset de IDsGET /users/{user}
→ showGET /users/{user}/edit
→ editPUT /users/{user}
→ updatePATCH /users/{user}/active
→ setActive (independiente de update)DELETE /users/{user}
→ destroy
En Laravel 12, las rutas están reforzadas con middleware de Spatie (
permission:*
) además de las Policies, p. ej.permission:users.view
,permission:users.export
,permission:users.setActive
. Asegúrate de registrar los aliases enbootstrap/app.php
(ver guía "Permisos (permission-first)").
Frontend (resumen)¶
- Vista:
resources/js/pages/users/index.tsx
- TanStack v8 en modo manual:
manualPagination
,manualSorting
,rowCount
- Inertia partial reloads:
only: ['rows', 'meta']
,preserveState
,preserveScroll
- Bulk actions: delete (si
auth.can['users.delete']
) - Export:
users.export
- Stats cards: tarjetas dinámicas con
stats.total
,stats.inactive
(backend las provee)
- TanStack v8 en modo manual:
- Columnas:
resources/js/pages/users/columns.tsx
- Filtros:
resources/js/pages/users/filters.tsx
- Vista Show:
resources/js/pages/users/show.tsx
- Botón Eliminar con
ConfirmAlert
→DELETE /users/{id}
(toasts y redirección) - Consistencia con Roles Show
- Botón Eliminar con
UX/Comportamiento clave¶
- Misma UI/estilos que Roles
- Controles visibles aunque no haya resultados
- Densidad de tabla persistida en
localStorage
bajousers_table_density
- Navegación lateral: ítem "Usuarios" visible sólo si
auth.can['users.view']
Reglas de negocio (configurables)¶
- Archivo:
config/permissions/users.php
users.activation.block_self_deactivate
(bool, default true): impide desactivar tu propio usuariousers.activation.block_deactivate_if_last_admin
(bool): impide desactivar al último administradorusers.activation.admin_role_name
(string): nombre del rol considerado adminusers.deletion.require_inactive
(bool): requiere inactivo antes de permitir eliminarusers.deletion.block_if_last_admin
(bool): impide eliminar al último administrador
Estas reglas se aplican en los FormRequest
:
SetUserActiveRequest
(PATCH/users/{id}/active
)DeleteUsersRequest
(DELETE/users/{id}
)