feat(statistics-deck): Month view (Room, Desk, Laptop) #136

Closed
opened 2026-09-26 11:29:18 +00:00 by gabogg · 0 comments
Owner

Blocked by: #133

Part of the statistics deck UI (accepted RFC, #80). This issue is the Month view in its three profiles. The shell (#133) provides the frame, top bar, picker, keyboard and marker helpers. The view is about the month only; multi-month and yearly trends are out of scope.

Content (RFC §4)

KPIs, most important first:

  1. Visitors, vs the previous month, and also vs the same month last year when that data exists;
  2. daily average;
  3. best day;
  4. average visit (Mean Dwell);
  5. highest peak (people inside);
  6. weekend share.

Graphs, most important first:

  1. The month day by day;
  2. Running total vs the previous month;
  3. Peak people inside per day;
  4. Average by weekday;
  5. Entrance share vs the previous month.

Data

  • GET /api/statistics/periods/month/{first}/summary: the KPIs. previous_month_daily_average is always present, for the month view.
  • GET /api/statistics/timeseries/daily: for the month and for the previous month. It feeds the day-by-day graph, the running totals, the peak per day (peak_people_inside) and the average by weekday.
    • Compute the average by weekday on the client, over covered days that are not Closed Days.
    • Align the running totals by day of month. When the months differ in length, the shorter line simply ends.
  • GET /api/statistics/periods/month/{first}/entrances: entrance share, with its previous-month comparison.

Month-view marker

  • Per-day bars and points in the day-by-day and peak graphs: a dashed amber outline for Estimate days, grey hatching for Unreliable days.
  • The running total includes marked days (totals include them); mark the segments that come from marked days.
  • The average by weekday includes marked days, as all averages do.

Profiles

Room shows 6 KPIs and 4–5 graphs, Desk 4 KPIs and 3 graphs, Laptop 3 KPIs and 1 graph. Each smaller profile keeps the top of the ranking below (KPIs and graphs are listed most important first). Each profile is its own layout, not a crop (RFC §3.3), and follows the zero-scroll rule and row splits from the shell.

Rules that apply to every figure

  • Comparisons: the previous period first; last year only when it has data. A missing reference shows "—" with its reason, never 0%. Partial periods compare by daily average only when the route returns basis: DAILY_AVERAGE.
  • Data-quality marker (RFC §4.1): totals and averages include marked days. Records come from the route, which skips Unreliable days (#129). Mark graphs with the shell's shared Estimate / Unreliable styles. No per-KPI marks, and no confidence margins.
  • Holidays are marked on per-day graphs. Closed Days are shown as closed, not as missing.
  • All copy goes through i18n (es/en).

Acceptance

  • All three profiles render from live routes with no scroll at 1920×1080 and 1920×960.
  • A partial month (for example the month counting started) shows its covered days and compares by daily average above the coverage threshold, or shows "—".
  • Best day and highest peak never come from an excluded day.
  • Frontend tests cover the data mapping, the running-total alignment across month lengths, the weekday averages, and the marker cases.

Depends on #133 and #129. Refs #80.

🤖 Generated with Claude Code

Blocked by: #133 Part of the statistics deck UI (accepted RFC, #80). This issue is the **Month** view in its three profiles. The shell (#133) provides the frame, top bar, picker, keyboard and marker helpers. The view is about the month only; multi-month and yearly trends are out of scope. ## Content (RFC §4) **KPIs, most important first:** 1. Visitors, vs the previous month, and also vs the same month last year when that data exists; 2. daily average; 3. best day; 4. average visit (Mean Dwell); 5. highest peak (people inside); 6. weekend share. **Graphs, most important first:** 1. The month day by day; 2. Running total vs the previous month; 3. Peak people inside per day; 4. Average by weekday; 5. Entrance share vs the previous month. ## Data - `GET /api/statistics/periods/month/{first}/summary`: the KPIs. `previous_month_daily_average` is always present, for the month view. - `GET /api/statistics/timeseries/daily`: for the month and for the previous month. It feeds the day-by-day graph, the running totals, the peak per day (`peak_people_inside`) and the average by weekday. - Compute the average by weekday on the client, over covered days that are not Closed Days. - Align the running totals by day of month. When the months differ in length, the shorter line simply ends. - `GET /api/statistics/periods/month/{first}/entrances`: entrance share, with its previous-month comparison. ## Month-view marker - Per-day bars and points in the day-by-day and peak graphs: a dashed amber outline for Estimate days, grey hatching for Unreliable days. - The running total includes marked days (totals include them); mark the segments that come from marked days. - The average by weekday includes marked days, as all averages do. ## Profiles Room shows 6 KPIs and 4–5 graphs, Desk 4 KPIs and 3 graphs, Laptop 3 KPIs and 1 graph. Each smaller profile keeps the top of the ranking below (KPIs and graphs are listed most important first). Each profile is its own layout, not a crop (RFC §3.3), and follows the zero-scroll rule and row splits from the shell. ## Rules that apply to every figure - Comparisons: the previous period first; last year only when it has data. A missing reference shows "—" with its `reason`, never 0%. Partial periods compare by daily average only when the route returns `basis: DAILY_AVERAGE`. - Data-quality marker (RFC §4.1): totals and averages include marked days. Records come from the route, which skips Unreliable days (#129). Mark graphs with the shell's shared Estimate / Unreliable styles. No per-KPI marks, and no confidence margins. - Holidays are marked on per-day graphs. Closed Days are shown as closed, not as missing. - All copy goes through i18n (es/en). ## Acceptance - All three profiles render from live routes with no scroll at 1920×1080 and 1920×960. - A partial month (for example the month counting started) shows its covered days and compares by daily average above the coverage threshold, or shows "—". - Best day and highest peak never come from an excluded day. - Frontend tests cover the data mapping, the running-total alignment across month lengths, the weekday averages, and the marker cases. Depends on #133 and #129. Refs #80. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
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
gabogg/hikcentral#136
No description provided.