# F-147 — Architect

## Feature
Admin: reporting shell and global filters.

## Background
F-143/F-146 implementaron los endpoints de reporting backend (filters schema, summary, sales). F-147 expone esta funcionalidad en el frontend admin con navegación, shell de dashboard, filtros globales reusables y estados de datos explícitos.

## Objetivo
- Añadir navegación "Reporting" al sidebar del admin
- Crear `GET /reporting` (shell + filtro global de canal/día)
- Componentes reusables: `DateRangePicker`, `ReportingFilters`, `AvailabilityBadge`, `KpiCard`
- Persistencia de filtros en URL (Next.js searchParams)
- Estados explícitos: loading skeleton, empty state, error state

## Diseño

### Navegación
Añadir a `NAV_ITEMS`:
```typescript
{ href: '/reporting', label: 'Reporting', icon: '📊', permission: 'reporting.read' }
```
Y añadir `reporting.read` a `Permission` type + `can()`.

### Página principal `/reporting`
- Layout de 2 paneles: filtros (sidebar izquierdo, colapsable) + contenido (gráficos/resumen)
- Por defecto muestra `GET /reporting/summary` con rango de los últimos 30 días
- Filtros: canal (ecommerce/pos/todos), rango de fechas, tienda, comparador

### Componentes
- `DateRangePicker`: selector de rango de fechas con presets (7d, 30d, 90d, mes actual, mes anterior)
- `ReportingFilters`: formulario con todos los filtros del schema de F-143
- `AvailabilityBadge`: muestra "✅ disponible" / "❌ no disponible" para cada métrica
- `KpiCard`: tarjeta con KPI (número, label, comparación con período anterior, badge de disponibilidad)

### API calls
`lib/reporting-client.ts` con:
- `fetchFilterSchema()` → GET /api/reporting/filters/schema
- `fetchSummary(params)` → GET /api/reporting/summary
- `fetchSales(params)` → GET /api/reporting/sales

### Estados de datos
- `loading`: skeleton spinner centrado
- `empty`: mensaje "No hay datos para este período" con icono
- `error`: mensaje de error con botón reintentar
- `dataAvailability`: badge junto a cada métrica

### URL persistence
Los filtros se serializan en searchParams de Next.js: `?from=&to=&channel=&storeId=&compare=&groupBy=`. Al recargar la página se mantienen.

## Acceptance Criteria
AC1: Navegación "Reporting" visible en sidebar para admin/editor.
AC2: Página `/reporting` carga con filtro de rango de fechas y canal por defecto (últimos 30 días, todos los canales).
AC3: Filtros se persisten en URL (al recargar mantienen los valores).
AC4: Estado loading: spinner/skeleton mientras carga.
AC5: Estado empty: mensaje cuando no hay datos.
AC6: Estado error: mensaje con botón reintentar.
AC7: Cada métrica muestra AvailabilityBadge (disponible/no disponible).
AC8: tsc 0, verify.sh verde.
