Total API-value donut card (SOU-265 pass 3b) - #58
Conversation
The aggregate card from SOU-265, consuming the pass-3a backend. Shows estimated API value across providers with a donut ring + ranked legend. - lib/apiValueCard.ts: pure, unit-tested model + ring geometry. buildApiValueCard omits providers with no data (never zero), computes per-provider shares and pricing coverage; ringSegments turns shares into stroke-dasharray donut segments. - components/TotalApiValueCard.tsx: period switcher (Today / Yesterday / 30 days) + metric switcher (API value / Tokens), an SVG donut coloured by provider brand colors, a ranked legend (share + value), and transparency copy - an estimate marker plus "N% of tokens priced (unpriced models in ...)" whenever coverage is below 100%. Empty periods show "No data"; a failed command shows an unavailable state. role=img on the ring carries an a11y summary of metric, period, total, and providers. - Mounted at the top of ChartsPanel; card styling is responsive and theme-aware, reusing existing design tokens. Tests: 8 pure-logic cases (single/multiple/tiny-share/missing-data/partial- pricing/all-unpriced + ring geometry) and 3 render cases (aggregate + legend + coverage, "No data" on period switch, unavailable on failure). Frontend 258 / tsc clean. Note: the donut was verified via the geometry unit tests and the standard stroke-dasharray technique; the in-app browser preview was unavailable for a live screenshot this session.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ceiling | 53359a6 | Commit Preview URL Branch Preview URL |
Jul 18 2026, 09:59 PM |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds an API value card that loads local provider totals, supports period and metric selection, renders aggregate and provider-level data, reports pricing coverage, handles empty/error states, and integrates above the existing charts panel. ChangesAPI value card
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant ChartsPanel
participant TotalApiValueCard
participant getLocalApiValueTotals
participant buildApiValueCard
ChartsPanel->>TotalApiValueCard: Render card
TotalApiValueCard->>getLocalApiValueTotals: Request local API value totals
getLocalApiValueTotals-->>TotalApiValueCard: Return provider totals
TotalApiValueCard->>buildApiValueCard: Build selected period and metric model
buildApiValueCard-->>TotalApiValueCard: Return slices, totals, and coverage
TotalApiValueCard-->>ChartsPanel: Render card UI
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/desktop-tauri/src/components/TotalApiValueCard.tsx`:
- Around line 114-143: Update the period and metric controls in the
TotalApiValueCard component to use native button-group semantics: remove
role="tablist"/role="tab" and replace aria-selected with aria-pressed on each
button, preserving the existing active-state comparisons and click handlers.
- Around line 94-96: Update the coverage visibility logic near coveragePercent
so showCoverage compares the raw model.coverage ratio against 1, rather than the
rounded percentage. Continue rounding coveragePercent only for display,
preserving null handling and showing partial coverage such as 99.6%.
In `@apps/desktop-tauri/src/surfaces/ChartsPanel.tsx`:
- Line 73: Update the unsupported-chart-provider early-return branch in
ChartsPanel so it still renders TotalApiValueCard alongside the existing
empty-state content. Keep the card mounted even when chart data is unavailable,
including snapshot errors and unsupported providers, while preserving the normal
chart rendering path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: cb115959-167e-49b5-8b4b-17fa3a19ac92
📒 Files selected for processing (6)
apps/desktop-tauri/src/components/TotalApiValueCard.test.tsxapps/desktop-tauri/src/components/TotalApiValueCard.tsxapps/desktop-tauri/src/lib/apiValueCard.test.tsapps/desktop-tauri/src/lib/apiValueCard.tsapps/desktop-tauri/src/styles.cssapps/desktop-tauri/src/surfaces/ChartsPanel.tsx
…Rabbit) - Coverage note: compare the raw ratio (model.coverage < 1) instead of the rounded percent, so 99.6% (rounds to 100) still shows "N% of tokens priced" when tokens are unpriced. - Switchers: use role="group" + aria-pressed native buttons instead of role="tab" without the full tablist keyboard pattern — accurate semantics for value toggles. - ChartsPanel: render TotalApiValueCard in the "no chart providers" empty branch too; it loads its own local totals, so API-value analytics should not be hidden when no provider reports chart series. Frontend 258 / tsc clean.
Version bump to **1.1.0** (build 95) and changelog for the local spend-analytics work shipped in #52-#58. ## Bumped - `version.env` (MARKETING_VERSION 1.1.0, BUILD_NUMBER 95) - `rust/Cargo.toml`, `apps/desktop-tauri/src-tauri/Cargo.toml` - `apps/desktop-tauri/package.json`, `apps/desktop-tauri/src-tauri/tauri.conf.json` - `Cargo.lock` (both workspace crates) ## Changelog highlights (1.1.0) - Total estimated API-value card (Codex + Claude) with Today / Yesterday / 30-day and API value / Tokens views, provider ring, and ranked legend. - Per-model and per-Codex-effort 30-day breakdowns with pricing-coverage transparency and "Not priced" rows. - Codex cost-integrity fixes: suppressed replayed child-session history (the ~20x inflation), archived-session scanning + rollout dedup, unknown-model unpricing, and real reasoning-effort tiers. `cargo check --workspace` compiles both crates at 1.1.0. After merge, tag `v1.1.0` to trigger the signed release build. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a local usage and API-value dashboard with Today, Yesterday, and 30-day views. * Added provider breakdowns and ranked usage details. * Added 30-day spend breakdowns by model and Codex reasoning effort. * Added pricing coverage indicators, including clearly labeled “Not priced” entries. * **Bug Fixes** * Improved usage accuracy by preventing duplicate or replayed session data from being counted. * Corrected Codex attribution and suppressed misleading dollar estimates for models without pricing. * **Release** * Updated the application to version 1.1.0. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: tsouth89 <tsouth89@users.noreply.github.com>
What
The aggregate "estimated API value" card from SOU-265, consuming the pass-3a backend (#57). Completes the SOU-262 dollar-analytics epic's UI.
Changes
buildApiValueCardomits providers with no data (never counts zero), computes per-provider shares and pricing coverage;ringSegmentsturns shares into stroke-dasharray donut segments.role="img"on the ring carries an a11y summary of metric, period, total, and providers.Terminology (per SOU-265)
Dollars are labelled Estimated API value, never a bill or subscription spend. Providers with no source data are omitted; coverage is surfaced whenever any tokens are unpriced.
Tests
Frontend 258 /
tscclean.Note: the donut was verified via the geometry unit tests and the standard stroke-dasharray technique - the in-app browser preview was unavailable for a live screenshot this session, so a visual pass on the rendered ring is worth a glance before release.
Summary by CodeRabbit