charts: dual-line popularity chart — views (red) + zaps (orange) over time (#47 §5.9)

The per-video Popularity modal now plots a second, orange zaps-over-time line
beside the red views line, with a legend and — new — VISIBLE x-axis date ticks
(the old chart only put the range in the aria-label).

- buildZapSatsTimeSeries: buckets cumulative SATS from 9735 receipts + verified
  bitvid tallies, deduped by payment_hash (same rule as the badge store) so the
  chart and badge agree.
- buildPopularityChartSvg: two token-colored cumulative lines on a shared time
  x-axis, each with its OWN y scale (independent per-series — D5), plus date-tick
  <text> labels. Views = .text-accent, zaps = .text-zap (new --color-zap
  utility). Legend is plain DOM in the modal; headline gains "· N sats zapped".
- js/zapEventsFacade.js: lists a pointer's [9735, ZAP_TALLY_KIND] events via the
  L1 SubscriptionManager for the chart; modal re-renders on onZapTotalsChanged.
- All flag-gated (FEATURE_ZAP_TALLY); the existing views-only chart + its test
  are untouched (buildViewCountChartSvg kept).

Verified live earlier that imports resolve (app builds/runs). Tests:
tests/zap-time-series-chart.test.mjs (5) + existing view-count-chart green.
Lint + build green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-07-05 00:27:00 -04:00
1 parent 68bdee8da5
commit 974fdc836d
5 files changed
+504 -8

No files matched your search

+8 -4
View File
@@ -471,12 +471,16 @@ tallies simply stop being counted. No data migration.
- [x] Tests: verify, schema, publisher, cross-source dedup, flag-off, e2e verify.
- [x] `lint` + `build` + suites green; pushed to `unstable`.
- [ ] **Remaining v1 work:**
- [ ] **Profile-zap counting:** the store queries `#a`/`#e` only — add
`#p` batches so a profile-only tally (no video pointer) is fetched,
and a channel-page total UI surface (D2 chose video+profile).
- [ ] **Profile-zap counting (remaining):** the store queries `#a`/`#e`
only — add `#p` batches so a profile-only tally (no video pointer) is
fetched, and a channel-page total UI surface (D2 chose video+profile).
- [x] **Retry path:** `zapController.executeRetry` fires `onZapSuccess`
so retried shares publish tallies too. (commit afed041f)
- [ ] **Popularity chart §5.9:** orange zaps line + legend + date axis.
- [x] **Popularity chart §5.9 DONE:** orange zaps-over-time line beside
the red views line, legend (Views/Zaps), visible date-axis ticks,
and a "· N sats zapped" headline. buildZapSatsTimeSeries (dedup by
payment_hash) + buildPopularityChartSvg + zapEventsFacade. Tests:
tests/zap-time-series-chart.test.mjs.
- [ ] Live end-to-end on unstable (real zap → tally on relay → second
browser counts it); rollout per §9.