Stats: Include archived shipments and use source-backed event counts #35

Closed
opened 2026-06-27 15:41:15 +02:00 by bullitt · 1 comment
Owner

Problem

Two data correctness issues on the Stats page:

  1. Archived shipments excluded: fetchShipments() without arguments returns only active+delivered. The Stats page calls this and gets 16 shipments, but Dashboard shows "10 active · 6 delivered · 4 archived" = 20. Stats undercounts by 4 and the description says "Overview of your Trackbox data" — but it's not all the data.

  2. Events = 0: fetchShipments() returns the list endpoint which does not include event arrays. shipments.reduce((acc, s) => acc + (s.events?.length ?? 0), 0) always returns 0 because s.events is undefined on list items. The Events StatCard shows "0 across all shipments" which is wrong — individual shipments have events.

Implementation

File: frontend/src/pages/Stats.tsx

Fix 1 — Include archived shipments

Change the fetch to include archived:

Promise.all([
  fetchShipments(),          // active + delivered
  fetchShipments("archived"), // archived
  fetchParsers(),
  fetchHealth().catch(() => null),
]).then(([active, archived, p, h]) => {
  const s = [...active, ...archived]
  setShipments(s)
  ...
})

Or add an "all" option to fetchShipments in frontend/src/lib/api.ts that calls /api/shipments?include_archived=true if the backend supports it.

Fix 2 — Events count

Either:
a) Add a /api/stats endpoint on the backend that returns pre-computed counts including total events (query: SELECT COUNT(*) FROM shipment_events)
b) Remove the Events StatCard since it cannot be computed from the list endpoint without N+1 fetches

Option (a) is cleaner. If the backend route does not exist, remove the Events card for now and add a // TODO: needs /api/stats endpoint comment.

Acceptance criteria

  • Total Shipments count matches Dashboard (includes archived)
  • Events card either shows correct count or is removed
  • Stats description still reads accurately

Brand identity alignment

Stats should be useful operational signals, not generic KPI decoration. Totals must reflect the user's owned dataset, including archived shipments, and event counts must be source-backed.

Brand-compliant implementation notes

  • Phrase the page subtitle around data ownership/transparency, e.g. Operational overview of shipments, sources, and parser activity.
  • Avoid making the Stats page KPI-heavy unless the metrics are genuinely useful.
  • If event counts require a backend aggregate, prefer a source-backed API value over inferring from partial list payloads.
  • Use neutral cards with restrained semantic colors; do not create a rainbow dashboard.

Additional acceptance criteria

  • Totals clearly state whether archived shipments are included.
  • Event count reflects actual raw/normalized event data, not missing list fields.
  • The visual treatment remains calm and operational.

Migrated from GitHub issue #14: https://github.com/bullitt186/trackbox/issues/14
Original author: @bullitt186
Original created: 2026-06-27T13:24:10Z
Original labels: ux

## Problem Two data correctness issues on the Stats page: 1. **Archived shipments excluded**: `fetchShipments()` without arguments returns only active+delivered. The Stats page calls this and gets 16 shipments, but Dashboard shows "10 active · 6 delivered · 4 archived" = 20. Stats undercounts by 4 and the description says "Overview of your Trackbox data" — but it's not all the data. 2. **Events = 0**: `fetchShipments()` returns the list endpoint which does not include event arrays. `shipments.reduce((acc, s) => acc + (s.events?.length ?? 0), 0)` always returns 0 because `s.events` is undefined on list items. The Events StatCard shows "0 across all shipments" which is wrong — individual shipments have events. ## Implementation File: `frontend/src/pages/Stats.tsx` ### Fix 1 — Include archived shipments Change the fetch to include archived: ```ts Promise.all([ fetchShipments(), // active + delivered fetchShipments("archived"), // archived fetchParsers(), fetchHealth().catch(() => null), ]).then(([active, archived, p, h]) => { const s = [...active, ...archived] setShipments(s) ... }) ``` Or add an `"all"` option to `fetchShipments` in `frontend/src/lib/api.ts` that calls `/api/shipments?include_archived=true` if the backend supports it. ### Fix 2 — Events count Either: a) Add a `/api/stats` endpoint on the backend that returns pre-computed counts including total events (query: `SELECT COUNT(*) FROM shipment_events`) b) Remove the Events StatCard since it cannot be computed from the list endpoint without N+1 fetches Option (a) is cleaner. If the backend route does not exist, remove the Events card for now and add a `// TODO: needs /api/stats endpoint` comment. ## Acceptance criteria - Total Shipments count matches Dashboard (includes archived) - Events card either shows correct count or is removed - Stats description still reads accurately ## Brand identity alignment Stats should be useful operational signals, not generic KPI decoration. Totals must reflect the user's owned dataset, including archived shipments, and event counts must be source-backed. ## Brand-compliant implementation notes - Phrase the page subtitle around data ownership/transparency, e.g. `Operational overview of shipments, sources, and parser activity`. - Avoid making the Stats page KPI-heavy unless the metrics are genuinely useful. - If event counts require a backend aggregate, prefer a source-backed API value over inferring from partial list payloads. - Use neutral cards with restrained semantic colors; do not create a rainbow dashboard. ## Additional acceptance criteria - Totals clearly state whether archived shipments are included. - Event count reflects actual raw/normalized event data, not missing list fields. - The visual treatment remains calm and operational. --- Migrated from GitHub issue #14: https://github.com/bullitt186/trackbox/issues/14 Original author: @bullitt186 Original created: 2026-06-27T13:24:10Z Original labels: ux
bullitt changed title from Stats: Include archived shipments in totals and fix Events count (shows 0) to Stats: Include archived shipments and use source-backed event counts 2026-06-27 15:46:21 +02:00
Author
Owner

Implemented in commit bd6b0e7. Stats now fetches active, delivered, and archived shipments separately and combines them into allShipments for the total count and distribution charts. The Events StatCard was removed since event arrays are not included in the list endpoint response (events are per-shipment detail only). Total, Active, and Delivered counts now match Dashboard totals including archived records.

Implemented in commit bd6b0e7. Stats now fetches active, delivered, and archived shipments separately and combines them into `allShipments` for the total count and distribution charts. The Events StatCard was removed since event arrays are not included in the list endpoint response (events are per-shipment detail only). Total, Active, and Delivered counts now match Dashboard totals including archived records.
Sign in to join this conversation.
No labels
arch
harness
security
ux
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bullitt/trackbox#35
No description provided.