Skip to content

feat(billing): split add-credits sheet into purchase and coupon tabs#3403

Merged
baktun14 merged 5 commits into
mainfrom
feat/billing-add-credits-coupon-tab
Jul 10, 2026
Merged

feat(billing): split add-credits sheet into purchase and coupon tabs#3403
baktun14 merged 5 commits into
mainfrom
feat/billing-add-credits-coupon-tab

Conversation

@baktun14

@baktun14 baktun14 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Why

With coupons now being fixed-amount Stripe credits, the redesigned Add credits sheet needs a clear split between buying credit and redeeming a coupon. Today the new sheet only has a purchase flow; coupon redemption lives only in the legacy PaymentPopup.

Ref CON-368

image image image

What

Reorganizes the redesigned Add Credits sheet into two tabs — Purchase credits and Redeem coupon — reusing the existing coupon mutation and error handling. No backend changes (coupon apply already exists end-to-end).

  • RedeemCouponForm (new): reuses usePaymentMutations().applyCoupon, usePaymentPolling().pollForPayment, and handleCouponError. Feedback is inline (success/destructive Alert); on success it polls to refresh the balance, shows a confirmation, and resets the field — the sheet stays open so the user closes it via the X. The redeem button is gated on wallet readiness with a "Setting up your account…" hint.
  • AddCreditsTabs (new): controlled Radix tabs wrapper. Only the active tab's content is mounted (so the purchase tab's Stripe SetupIntent lazy-mounts and the coupon form resets on switch). Aggregates processing state from both children for the sheet's close-guard and disables the inactive trigger mid-transaction.
  • AddCreditsSheet (edit): renders AddCreditsTabs, threads a new initialTab prop, and uses the generic free-plan header copy. Close-guard behavior preserved.

The legacy PaymentPopup is left untouched.

Follow-up (PR 2, out of scope here): hackathon entry points behind a hackathons feature flag that open the sheet with initialTab="coupon".

Tests

Colocated *.spec.tsx for all three components (18 tests): coupon success/error/empty/wallet-gating/processing, tab default/initial/aggregated-processing/inactive-disable, and sheet render/thread/close-guard.

Summary by CodeRabbit

  • New Features
    • Added a two-tab credits flow to purchase credits or redeem a coupon.
    • The credits sheet can now open on a specified tab (Purchase or Coupon).
    • Coupon redemption now supports a completion flow that can trigger sheet closure.
  • Bug Fixes
    • Improved credits sheet close behavior to stay open during purchase/coupon processing.
    • Tab switching is disabled while the active tab’s action is in progress.
    • Coupon polling now uses coupon-specific snackbar loading and success messages.
    • Fixed invoice-based coupon top-up trial-ending behavior.
  • Tests
    • Expanded coverage for tabs, processing-state behavior, coupon redemption outcomes, and polling/snackbar messaging.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6fe5b6ee-2176-4d45-96be-9e30b94ebba3

📥 Commits

Reviewing files that changed from the base of the PR and between c655c62 and b6806e9.

📒 Files selected for processing (1)
  • apps/deploy-web/src/components/auth/AddCreditsSheet/AddCreditsSheet.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/deploy-web/src/components/auth/AddCreditsSheet/AddCreditsSheet.tsx

📝 Walkthrough

Walkthrough

Adds coupon redemption, tabbed credit purchasing, coupon-aware payment polling, sheet/onboarding callbacks, and updated invoice webhook top-up behavior.

Changes

Coupon redemption and tabbed credits UI

Layer / File(s) Summary
RedeemCouponForm implementation and tests
apps/deploy-web/src/components/billing-usage/RedeemCouponForm/*
Validates coupon codes, submits applyCoupon, polls after positive credit additions, reports processing state, renders result messages, and triggers redemption completion callbacks.
AddCreditsTabs container and tests
apps/deploy-web/src/components/billing-usage/AddCreditsTabs/*
Combines purchase and coupon forms, supports initialTab, aggregates processing state, disables the inactive tab during processing, and forwards completion callbacks.
AddCreditsSheet and onboarding integration
apps/deploy-web/src/components/auth/AddCreditsSheet/*, apps/deploy-web/src/components/onboarding-picker/*
Renders AddCreditsTabs, forwards redemption and processing callbacks, updates sheet copy, and clears the onboarding sheet reason after redemption.

Coupon-aware polling and invoice top-ups

Layer / File(s) Summary
Payment polling variants
apps/deploy-web/src/context/PaymentPollingProvider/*
Extends pollForPayment with payment and coupon variants and displays variant-specific loading and success snackbar copy.
Invoice webhook top-up handling
apps/api/src/billing/services/stripe-webhook/*
Stops deriving an endTrial argument for invoice top-ups and updates integration test expectations.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: ygrishajev, stalniy

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/billing-add-credits-coupon-tab

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

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.17476% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.01%. Comparing base (81dadb7) to head (b6806e9).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ts/billing-usage/AddCreditsTabs/AddCreditsTabs.tsx 84.21% 3 Missing ⚠️
...illing-usage/RedeemCouponForm/RedeemCouponForm.tsx 95.77% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3403      +/-   ##
==========================================
- Coverage   71.98%   71.01%   -0.97%     
==========================================
  Files        1153     1065      -88     
  Lines       29228    26991    -2237     
  Branches     7207     6779     -428     
==========================================
- Hits        21041    19169    -1872     
+ Misses       7191     6858     -333     
+ Partials      996      964      -32     
Flag Coverage Δ *Carryforward flag
api 85.59% <ø> (+0.02%) ⬆️
deploy-web 60.81% <94.17%> (+0.19%) ⬆️
log-collector ?
notifications 91.44% <ø> (ø) Carriedforward from c655c62
provider-console 81.38% <ø> (ø) Carriedforward from c655c62
provider-inventory ?
provider-proxy 86.42% <ø> (ø) Carriedforward from c655c62
tx-signer ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
.../services/stripe-webhook/stripe-webhook.service.ts 77.19% <ø> (-0.14%) ⬇️
...omponents/auth/AddCreditsSheet/AddCreditsSheet.tsx 100.00% <100.00%> (ø)
...ponents/onboarding-picker/OnboardingPickerPage.tsx 94.11% <100.00%> (+0.17%) ⬆️
.../PaymentPollingProvider/PaymentPollingProvider.tsx 89.18% <100.00%> (+0.50%) ⬆️
...ts/billing-usage/AddCreditsTabs/AddCreditsTabs.tsx 84.21% <84.21%> (ø)
...illing-usage/RedeemCouponForm/RedeemCouponForm.tsx 95.77% <95.77%> (ø)

... and 91 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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/deploy-web/src/components/billing-usage/RedeemCouponForm/RedeemCouponForm.tsx`:
- Around line 90-106: The redeem flow in RedeemCouponForm’s coupon submit
handler only shows feedback when applyCoupon returns an error or a positive
amountAdded, so successful zero-credit responses leave the user with no message.
Update the branch in RedeemCouponForm’s submit logic to add a fallback
success/info alert when response.error is absent and amountAdded is missing or
0, while keeping the existing pollForPayment, setSuccessAmount, and form.reset
behavior only for positive credits.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 66c53710-8e95-4647-8269-6e6aa19ace32

📥 Commits

Reviewing files that changed from the base of the PR and between d5809c1 and 6face37.

📒 Files selected for processing (6)
  • apps/deploy-web/src/components/auth/AddCreditsSheet/AddCreditsSheet.spec.tsx
  • apps/deploy-web/src/components/auth/AddCreditsSheet/AddCreditsSheet.tsx
  • apps/deploy-web/src/components/billing-usage/AddCreditsTabs/AddCreditsTabs.spec.tsx
  • apps/deploy-web/src/components/billing-usage/AddCreditsTabs/AddCreditsTabs.tsx
  • apps/deploy-web/src/components/billing-usage/RedeemCouponForm/RedeemCouponForm.spec.tsx
  • apps/deploy-web/src/components/billing-usage/RedeemCouponForm/RedeemCouponForm.tsx

baktun14 added 4 commits July 10, 2026 11:12
Reorganize the redesigned Add Credits sheet into two tabs: "Purchase
credits" (the existing purchase flow, unchanged) and "Redeem coupon" (a
new inline coupon-redemption flow). Adds:

- RedeemCouponForm: reuses usePaymentMutations().applyCoupon,
  usePaymentPolling().pollForPayment and handleCouponError; feedback is
  inline (success/destructive Alert), the sheet stays open, and the
  redeem button is gated on wallet readiness.
- AddCreditsTabs: controlled Radix tabs wrapper that lazy-mounts each
  flow, aggregates processing state from both children for the sheet's
  close-guard, and disables the inactive trigger mid-transaction.
- AddCreditsSheet: renders the tabs, threads an initialTab prop, and
  uses the generic free-plan header copy.

No backend changes — coupon apply already exists end-to-end.

Ref CON-368
Coupon-claim invoice top-ups now end the user's trial like a card
purchase does, so redeeming a coupon unlocks GPU access and the full
plan. Reverses the coupon carve-out added in #2780.
…dback

- Show the redeemed coupon amount as a dollar value instead of "N credits"
- Auto-close the add-credits sheet shortly after a successful redeem and
  return to the onboarding picker (no auto-deploy)
- Use coupon-specific snackbar copy ("Applying coupon..." / "Coupon
  applied!") instead of the payment wording during the balance poll
@baktun14 baktun14 force-pushed the feat/billing-add-credits-coupon-tab branch from 2a6b26e to c655c62 Compare July 10, 2026 15:15
The split-tabs refactor changed the sheet copy to generic free-plan
wording; restore the template-specific description that main uses.
@baktun14 baktun14 added this pull request to the merge queue Jul 10, 2026
Merged via the queue into main with commit a72c94b Jul 10, 2026
57 checks passed
@baktun14 baktun14 deleted the feat/billing-add-credits-coupon-tab branch July 10, 2026 19:09
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.

2 participants