Skip to content

Add balance section and addon credits section to billing and usage page#10773

Open
tylerlam-warp wants to merge 7 commits into
masterfrom
tyler/billing-page-v2-credits-modal
Open

Add balance section and addon credits section to billing and usage page#10773
tylerlam-warp wants to merge 7 commits into
masterfrom
tyler/billing-page-v2-credits-modal

Conversation

@tylerlam-warp
Copy link
Copy Markdown
Contributor

@tylerlam-warp tylerlam-warp commented May 12, 2026

Description

Populated the new billing and usage page to align with the Figma mocks. It populates the Plan, Balance, and Add On credits section. The usage section is still pending.

Note that this is still a feature gated until the new page is complete.

Testing

I ran the client locally and tested a number of different scenarios:

  1. The UI for a free, non-paid user with just base limits
  2. A self-serve user that has base limits and addon credits
  3. A enterprise users with no base limits who is on pay-as-you-go.
  • I have manually tested my changes locally with ./script/run

Screenshots / Videos

Loom: https://www.loom.com/share/db5b395b10f54fdd93cc2513be0ecba2

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

@cla-bot cla-bot Bot added the cla-signed label May 12, 2026
Comment on lines +187 to +224
struct ClassifiedGrants {
personal: GrantBucket,
team: GrantBucket,
cloud: GrantBucket,
}

impl ClassifiedGrants {
fn new(grants: &[BonusGrant], workspace_uid: Option<WorkspaceUid>) -> Self {
let now = chrono::Utc::now();
let mut personal = Vec::new();
let mut team = Vec::new();
let mut cloud = Vec::new();

for grant in grants {
if grant.expiration.is_some_and(|exp| now >= exp) {
continue;
}
if grant.request_credits_remaining <= 0 {
continue;
}
let in_user_scope = grant.scope == BonusGrantScope::User;
let in_workspace_scope =
workspace_uid.is_some_and(|uid| grant.scope == BonusGrantScope::Workspace(uid));
if grant.grant_type == BonusGrantType::AmbientOnly {
if in_user_scope || in_workspace_scope {
cloud.push(grant.clone());
}
} else if in_user_scope {
personal.push(grant.clone());
} else if in_workspace_scope {
team.push(grant.clone());
}
}

Self {
personal: GrantBucket { grants: personal },
team: GrantBucket { grants: team },
cloud: GrantBucket { grants: cloud },
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debating if I should move this all to a new file since the current file is long and quite dense, but didn't see a great use case right now so left it here. Open to thoughts

@tylerlam-warp tylerlam-warp marked this pull request as ready for review May 12, 2026 23:41
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 12, 2026

@tylerlam-warp

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment on lines +312 to +335
let mut me = Self {
auth_state,
addon_credit_modal_state: ModalViewState::new(addon_credit_modal_view),
selected_tab: BillingUsageTab::Overview,
usage_history: UsageHistoryState {
model: usage_history_model,
expanded_entries: HashMap::new(),
entry_mouse_states: RefCell::new(HashMap::new()),
tooltip_mouse_states: RefCell::new(HashMap::new()),
load_more_button,
},
addon_credits: AddonCreditsState {
selected_denomination: 0,
options: Default::default(),
denomination_buttons: Default::default(),
purchase_loading: false,
},
tab_mouse_states: Default::default(),
plan_mouse_states: Default::default(),
buy_credits_mouse_states: Default::default(),
};
me.update_addon_credits_options(ctx);
me.refresh_addon_credits_settings(ctx);
me
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this is copied over from the old usage and billing page. Group some of the args here to make it more grokkable

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR fills out the feature-gated billing and usage V2 page with plan, balance, add-on credit purchase, auto-reload, and usage history UI.

Concerns

  • The auto-reload action can enable the setting without a selected pricing denomination when pricing options are not available.
  • The auto-reload toggle shows a success toast before the workspace settings mutation succeeds, so users can receive contradictory success/failure feedback.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

},
ctx
);
let auto_reload_denomination_credits = if *enabled {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] Enabling auto-reload while pricing options are still empty sends selected_auto_reload_credit_denomination: None and later displays a "your selected" success message; guard this action until auto_reload_denomination_credits is Some or disable the switch until an option is available.

} else {
"Auto-reload disabled.".to_string()
};
self.show_toast(&toast_message, ToastFlavor::Success, ctx);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] This success toast fires before update_addon_credits_settings completes, so a rejected mutation first tells users auto-reload changed and only later shows failure; move the success toast to the success event path or keep the UI in a pending state until the update succeeds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant