Skip to content

Chart syncs per day over the last 30 days - #39

Merged
DimitriKwihangana merged 9 commits into
mainfrom
feat/daily-sync-trend
Sep 18, 2026
Merged

DimitriKwihangana merged 9 commits into
mainfrom
feat/daily-sync-trend

Conversation

@DimitriKwihangana

Copy link
Copy Markdown
Contributor

Closes #5.

What changes for the user

A new Trend page at /trend answers whether device activity is rising or falling. It shows the last 30 days: a bar per day for the number of syncs, a line for the resources those syncs carried (submissions, org units and entities added together), and three numbers above the chart — total syncs, total resources, and the change against the previous 30 days.

Days with no sync are drawn as zero rather than skipped, which is the point of the ticket: a line that jumps a silent day hides exactly the event the page exists to show.

The tooltip writes the day out in full, with how long ago it was: 4 September 2026 (14 days ago).

How it works

  • listDailyActivity builds the 30 days with Postgres generate_series and left-joins the syncs onto it, so a silent day arrives as a real row of zeros. Enforcing that in SQL is what makes it testable in one place.
  • getActivityTotals returns the current and previous window in one pass, split with count(...) filter (where ...).
  • now is set by the tRPC procedure and never sent by the client, so the window cannot be moved from the browser and a test can still choose its own date. Days are bucketed in UTC.
  • Every count and sum carries an ::int cast: Postgres returns bigint, which the pg driver hands back as a string.
  • The chart is Mantine's CompositeChart. Its stylesheet was missing from the root route — that is what lays out the chart tooltip and legend — so @mantine/charts/styles.css is now loaded next to the core one.

The dual axis, on purpose

The two series are about fifteen times apart, so the chart uses two y-axes. This goes against the usual advice: where the line sits against the bars is set by how the two scales are picked, not by the data, so the crossing point means nothing. Two stacked plots and a single shared axis were both mocked up and looked at; the single axis flattens the syncs series against the floor and cannot answer the ticket's question, and density won over the stacked plots because this page is read at a glance. There is a comment saying so in ActivityChart.tsx.

An ADR was drafted for this decision and deliberately left out at the author's request.

Tests

61 pass. Query tests on in-process Postgres cover the zero-filled days, the three counters, and both window boundaries. ActivitySummary and formatDay have their own tests — formatDay counts whole UTC days rather than elapsed hours, so a day does not become "yesterday" partway through the afternoon.

ActivityChart has no test: jsdom computes no layout, so a chart draws nothing there.

Worth a reviewer's eye

  • Today's bar is a partial day. The window includes today by choice, so the last bar is always low until the day is over. On the current seed it reads as zero.
  • A missing stylesheet is invisible to CI. Nothing in pnpm test or pnpm build could have caught the bug above — only looking at the page did. Fits issue Add an end-to-end smoke test #9.
  • relativeDays in SyncTable overlaps formatDay. Four duplicated lines, left alone so this branch does not edit another feature's file.

@vercel

vercel Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
wee-app Ready Ready Preview Sep 18, 2026 10:00am UTC

Request Review

@DimitriKwihangana DimitriKwihangana self-assigned this Sep 18, 2026
@DimitriKwihangana
DimitriKwihangana merged commit 2e452d3 into main Sep 18, 2026
2 checks passed

This branch was successfully deployed

1 active deployment
Preview — db2ae97c Deployed Sep 18, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chart syncs per day over the last 30 days

2 participants