# 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.