# Handoff frontend: solicitudes de registro

Implementar el módulo administrativo de React. Consultar `registration-requests-api.md` para los contratos exactos.

## Rutas y sidebar

| Ruta SPA sugerida | Acceso |
|---|---|
| `/admin/registration-requests` | `registration_requests.view_any` |
| `/admin/registration-requests/:id` | `registration_requests.view` |

Esperar el bootstrap de `/api/v1/auth/me` antes de evaluar guardas. Mostrar el ítem **Solicitudes de registro** solo si:

```ts
const can = (permission: string) => user?.permissions.includes(permission) ?? false;
const canList = can('registration_requests.view_any');
const canView = can('registration_requests.view');
const canApprove = can('registration_requests.approve');
const canReject = can('registration_requests.reject');
```

El frontend controla visibilidad, pero debe manejar `401`, `403` y `409` porque Laravel decide el acceso y estado final.

## Pantalla de listado

Agregar:

- Título, estado de carga, vacío, error y recarga.
- Buscador único y filtros de estado, farmacia, rango de fechas.
- Tabla: solicitante, username, cédula, WhatsApp, farmacia, ciudad, estado, fecha de solicitud y revisor.
- Ordenamiento permitido y paginación usando `meta`.
- Acción “Ver detalle” solo con `canView`.

Flujo:

1. Cargar `page=1&per_page=15` al entrar.
2. Guardar filtros, sort, direction y page en los query params de la URL.
3. Aplicar debounce al buscador y volver a página 1 al cambiar una consulta.
4. Preservar la URL del listado al navegar al detalle y volver.

No mostrar IP ni user agent aquí.

## Pantalla de detalle

Mostrar solicitante, contacto, farmacia, aceptación de términos, estado y fechas; revisor y motivo cuando existan; y el usuario creado tras aprobar. Ubicar IP y user agent en un bloque secundario de auditoría.

| Estado | Acciones visibles |
|---|---|
| `pending` | Aprobar con `canApprove`; rechazar con `canReject`. |
| `approved`, `rejected`, `cancelled` | Solo consulta. |

No renderizar acciones finales aunque el usuario tenga permiso. Si llega `409`, recargar los datos porque otro administrador pudo completar la operación.

## Diálogo de aprobación

1. Mostrar resumen de solicitante y farmacia, con Cancelar/Confirmar.
2. Explicar que creará un usuario activo `dependent`; no ofrecer selectores de rol ni farmacia.
3. Al confirmar, deshabilitar controles, pedir CSRF y enviar `POST .../approve` sin body.
4. Con `200`, cerrar, mostrar el mensaje y actualizar detalle/listado.
5. Con `409`, cerrar, informar y recargar.
6. Con `422 REGISTRATION_DATA_ALREADY_EXISTS`, mostrar mensaje y errores sin marcar la solicitud como aprobada.

## Diálogo de rechazo

1. Incluir textarea obligatoria `rejection_reason` y contador máximo 1000.
2. Validar que el texto recortado tenga al menos 3 caracteres.
3. Pedir CSRF y enviar únicamente `{ rejection_reason }`.
4. Con `200`, cerrar, notificar y actualizar los datos.
5. Con `422`, pintar `errors.rejection_reason`; con `409`, cerrar y recargar.

## Checklist

- Sidebar y guardas basados en `permissions`, no solo roles.
- Filtros, búsqueda, orden y paginación sincronizados con URL.
- UUIDs públicos en rutas y parámetros.
- Botones condicionados por permiso y estado.
- Aprobación sin payload; rechazo con motivo obligatorio.
- Manejo consistente de `401`, `403`, `404`, `409` y `422`.
- Información de auditoría limitada al detalle y nunca persistida en el navegador.
