Skip to content

Usage dashboard prototype: show every state on fixture data - #8192

Draft
talissoncosta wants to merge 20 commits into
mainfrom
spike/usage-billing-transparency
Draft

Usage dashboard prototype: show every state on fixture data#8192
talissoncosta wants to merge 20 commits into
mainfrom
spike/usage-billing-transparency

Conversation

@talissoncosta

@talissoncosta talissoncosta commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to #8184

Prototype, not for merge. It replaces the usage page on this branch so the v0.2 designs can be reviewed before we commit to building them. The production work is tracked under #8183.

The page runs on fixtures, so every designed state can be shown without depending on what an organisation has actually used:

  • healthy
  • approaching the limit
  • over limit, grace period covering this month
  • over limit, grace period used and charged
  • free plan, inside the 7 day countdown
  • free plan, restricted

A "Live data" option uses the real usage endpoints.

On the page: billing period with reset date and grace chip, "% of plan consumed" meter with notification markers, tiles that change per state, cumulative usage against the plan limit with a shaded overage zone and a dashed projection, request-type breakdown, and the notifications screen.

Reset date, grace state and cost are faked here. The API work that would make them real is in #8183.

Also included: the fix for #6099, current billing period ignoring terms longer than a year. One line and a test, no dependency on the prototype, and it can be split out to merge on its own.

How did you test this code?

Type checking and linting only. The page has not been rendered yet, I had no local API running to load it against.

To try it: check out the branch, run the frontend against an API, and open Organisation Settings, then Usage. The state switch at the top moves between the six fixtures, and the tabs move between the usage and notifications screens. Only "Live data" needs the API to return anything.

talissoncosta and others added 11 commits July 31, 2026 12:13
Reframes OrganisationUsagePage with a "usage vs plan limit" summary:
% of plan consumed, a meter, and a cumulative-vs-limit chart, all wired
to the existing usage-data + max_api_calls (no backend change).

Everything the API cannot feed yet is marked TODO(BE) and listed in the
component so the diff doubles as the backend ask: reset date / billing
period boundaries, the current-billing-period date-range bug, projection,
grace-period status, and cost in currency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expands the prototype to the full v0.2 layout for the global view:
billing-period strip, hero meter with Notify markers, stat tiles,
cumulative usage-vs-limit chart (Area + plan-limit ReferenceLine + today
dot), and the request-type breakdown. Global view now renders this in
place of the old totals + bar chart; By SDK view is unchanged.

Still wired only to existing data; reset date, projection and cost remain
TODO(BE).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Swaps the hardcoded hex (accent/danger/success/warning + panel/border/
text/track) for the --color-* semantic tokens via common/theme/tokens, so
the prototype flips correctly under .dark.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`_get_start_date_and_stop_date_for_subscribed_organisation` derived the
current period start from relativedelta(...).months only, dropping the
years component, so terms that started >12 months ago (annual plans)
resolved to the wrong year. Add years*12, mirroring the existing
PREVIOUS_BILLING_PERIOD branch, and cover the annual case with a test.

Note: api env (uv) not available locally; needs CI to run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The reframed design drops the left "By Endpoint / By SDK" sidebar (SDK
becomes a breakdown-dimension option instead), so remove the sidebar and
the global/user-agents toggle from the page.

Keep the Period/Project/Environment filters. Per the agreed behaviour, the
plan limit is org-level, so the meter + cumulative chart use an org-wide
query (period only) while Project/Environment filter a second query that
feeds only the request-type breakdown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Environment is a drill-down within a project and too granular for
org-level usage; project is the meaningful pivot. Remove the environment
select from UsageChartFilters and the page's filtered query.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the design: Usage title on the left, Period + Project selects on the
right of the page header (dropping the separate labelled filter row). Give
the surface a max-width and centre it instead of the left-aligned, narrow
app-container layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recharts auto-scaled the y-axis to usage, so with tiny usage against a
large limit the plan-limit ceiling fell off-screen and the "usage vs
limit" comparison was lost. Fix the domain to [0, max(limit, usage)] so
the ceiling is always visible (and over-limit usage still shows above it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The end marker's label was centred on the far-right point and half of it
overflowed the panel; right-align it so it stays within bounds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a scenario switch backed by fixtures so the over-limit, restricted and
grace states can be shown on demand, fills in the tiles that were printing
"needs BE", and adds the notifications screen.

Restores the existing usage page and puts the prototype behind the
usage_billing_prototype flag, so nothing changes until the flag is on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview Aug 3, 2026 2:07pm
flagsmith-frontend-staging Ready Ready Preview Aug 3, 2026 2:07pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Aug 3, 2026 2:07pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: aad02336-b801-4104-9b87-7e13675f017b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.71%. Comparing base (10a3bb7) to head (282cd65).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8192   +/-   ##
=======================================
  Coverage   98.71%   98.71%           
=======================================
  Files        1531     1531           
  Lines       61234    61272   +38     
=======================================
+ Hits        60446    60484   +38     
  Misses        788      788           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The branch is never merged, so gating it behind a flag only means creating
one in Flagsmith before anyone can look at it. Check the branch out and the
prototype is there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Swaps the hand-rolled pieces for what already exists: StatItem for the tiles,
Chip for the grace status, BareButton for the state and screen switches, and
Format.shortenNumber instead of a local copy. Adds progressbar semantics to
the meter and group labels to the switches.

The tile badges go with this: StatItem has no badge slot, so the state now
reads from the meter colour, the banner and the chart. Whether StatItem should
grow one is a question for #8185.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
StatItem and Chip pulled the page away from the design: the tiles lost their
badge and sub-label and grew icon blocks, and the grace chip read as a flat
pill. Both are back to the designed layout.

Badges now follow the dot-and-label pattern from experiments/StatusBadge,
which looks like where the app is heading. That component is typed to
experiment statuses, so this is a local copy with a tone prop rather than a
change to shared code. Generalising it is a question for #8185.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
StatItem was a label, a value and an icon block, so anything richer got
hand-rolled next to it: the admin metrics cards render their sub-line in a
<small> outside the component, and the usage prototype had its own tiles.

It now carries its own card: label and optional badge on one line, the value,
then an optional sub-line. The icon is optional, since dense rows of figures
read better without one.

Call sites: the admin metrics cards drop their external <small>, Billing loses
the panel that was wrapping the limit cards, and the usage prototype uses
StatItem instead of its own tiles. Stories cover the new slots.

Lives on the prototype branch by choice, so it needs porting when this becomes
real work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The plan, organisation id and management email were hand-rolled versions of
the same tile, inside a panel that boxed them in. They are StatItem cards now,
matching the subscription limits below.

Adds a small size to StatItem for text values: an email at 28px overflows the
card, which is why the old markup dropped to an h6 for it. Long values also
wrap rather than stretching the card.

The organisation id renders as a string, since numbers get thousands
separators and "7,528" is not an id.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds the inline note under the meter, which is the only line on the page that
draws a conclusion rather than stating a number: on track, over by how much,
what it costs, what happens next. Wording follows the state, so the restricted
and grace-countdown screens explain themselves.

Adds the breakdown dimension menu (request type, project, environment, SDK)
with obviously invented project and environment names, so nobody mistakes the
demo for their own data. Live data only has request type, and says so.

Labels the dashed projection on the chart, which was an unexplained line.

Two fixes the screenshots turned up:

- the period selector read "Last 90 days" while the strip underneath said
  "Billing period 18 Jul to 17 Aug". It follows the fixture now
- rolling windows claimed a reset date. They are "Usage window" now, with no
  reset, since a rolling window never resets

Also adds the "See docs" link the notifications design has.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The y-axis top was the projected value itself, so its label had nowhere to
render and got cut off by the edge of the chart. The axis now carries 8%
headroom above the highest value, and the label sits above the endpoint
rather than inside the corner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
You could add a notification but never get rid of one. Each row now has a
remove control next to its toggle, labelled for screen readers.

Rows above 100% claimed "You have reached your plan limit", which is wrong
once you are past it. They now read "You are over your plan limit", and only
the 100% row claims to be at it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The settings screen kept its own copy of the notifications, so removing 75%
left the "Notify 75%" marker sitting on the meter, and edits vanished on tab
switch. State lives on the page now and both screens read the same list.

Changing scenario drops the edits, so each fixture still shows its own
notifications.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant