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

+28
View File
@@ -2923,6 +2923,34 @@
font-variant-numeric: tabular-nums;
}
/* Zap orange as a currentColor source for the popularity chart's zaps line
+ legend swatch (mirrors how the views line uses .text-accent). */
.text-zap {
color: var(--color-zap);
}
.popularity-legend {
display: flex;
gap: var(--space-md);
align-items: center;
font-size: var(--font-size-2xs);
color: var(--color-text-muted);
margin-block-start: var(--space-2xs);
}
.popularity-legend__item {
display: inline-flex;
align-items: center;
gap: var(--space-3xs);
}
.popularity-legend__swatch {
inline-size: var(--space-sm);
block-size: var(--size-3px, 0.1875rem);
border-radius: var(--radius-full);
background-color: currentColor;
}
/* #43: always-visible active-identity pill. Rendered after the header in
flow and pulled up with a negative block-start margin so it sits half-on /
half-off the header divider — every pane shows who you're acting as. */