CreaRack-SL

Endpoint GET /api/sidebar-counts — Conteos en vivo para el Sidebar

Endpoint GET /api/sidebar-counts

Cloudflare Pages Function que devuelve los conteos en tiempo real de las entidades principales del workspace. Reemplaza los badges hardcoded que existían en Sidebar.tsx hasta la sesión s60 (2026-05-13).

Ubicación

functions/api/sidebar-counts/index.ts

Handler: onRequestGet: PagesFunction<Env>

Responsabilidad

Proporcionar 4 conteos ligeros a través de un único fetch que el componente Sidebar.tsx ejecuta al montarse. Antes de este endpoint, los valores Tareas=9, Noticias=2, Alertas=1 estaban hardcoded en el componente — Edu detectó la desincronización al crear la task #27 cuando la base ya tenía 22 pending.

Response schema

interface CountsResponse {
  tasks_pending: number;   // tasks WHERE status = 'pending'
  news_recent:   number;   // news WHERE created_at >= now() - 7 días
  alerts_active: number;   // alerts WHERE active = 1
  notes_total:   number;   // COUNT(*) de notes
}

Queries D1

CampoQuery
tasks_pendingSELECT COUNT(*) AS c FROM tasks WHERE status = 'pending'
news_recentSELECT COUNT(*) AS c FROM news WHERE datetime(created_at) >= datetime('now', '-7 days')
alerts_activeSELECT COUNT(*) AS c FROM alerts WHERE active = 1
notes_totalSELECT COUNT(*) AS c FROM notes

Las 4 queries se ejecutan en paralelo con Promise.all. Si alguna falla, el campo correspondiente devuelve 0 (via .catch(() => null)).

Cache

Cache-Control: private, max-age=60

60 segundos de caché privado. Suficiente para que el sidebar sea reactivo sin machacar D1 en cada cambio de página. El caché es private (por navegador, no CDN) para garantizar consistencia por usuario.

Integración con Sidebar.tsx

Sidebar.tsx consume el endpoint en un useEffect al montar el componente:

const [counts, setCounts] = useState<SidebarCounts | null>(null);
useEffect(() => {
  fetch('/api/sidebar-counts')
    .then((r) => (r.ok ? r.json<SidebarCounts>() : null))
    .then((c) => { if (!cancelled && c) setCounts(c); })
    .catch(() => { /* badges quedan ocultos */ });
}, []);

Cada item de navegación declara un countKey opcional que apunta al campo del response:

interface NavDef {
  title: string;
  icon?: string;
  href: string;
  countKey?: 'tasks_pending' | 'news_recent' | 'alerts_active' | 'notes_total';
}

Si badgeValue es 0 o undefined (fetch fallido), no se renderiza badge. Esto evita mostrar números incorrectos ante fallos de red.

Items y countKey actuales (v1.0.73)

ÍtemcountKey
Tareastasks_pending
Noticiasnews_recent
Alertasalerts_active
Notas— (sin badge; notes_total está cableado por si se activa)
Dashboard— (sin badge)

Activar badge de Notas en el futuro

El campo notes_total se calcula y se devuelve en el response, pero el item Notas en NAV no declara countKey. Para activarlo:

// src/components/shell/Sidebar.tsx — array NAV
{ title: 'Notas', icon: 'sticky', href: '/notes', countKey: 'notes_total' },

Historial

FechaVersiónCambio
2026-05-13v1.0.73Creación — reemplaza badges hardcoded (s60, commit 689023f)

Véase también

  • [[workspace—que-es-workspace]]
  • [[crearack—conceptos—interfaz-general]]
  • [[incident—20260513—shell-s60-regressions]]