feat(billing): promote first-purchase bonus with dynamic preview in add-credits form - #3424
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe pull request adds first-purchase bonus support across transaction APIs, credit purchasing, onboarding messaging, billing history, and payment-success displays. It introduces feature gating, transaction-based bonus lookup, capped bonus previews, and updated callback and data contracts. ChangesFirst-purchase bonus flow
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
b28e26c to
075df0b
Compare
6a04475 to
e889b9f
Compare
e889b9f to
9e7c5a8
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3424 +/- ##
==========================================
- Coverage 72.33% 71.53% -0.80%
==========================================
Files 1158 1095 -63
Lines 29332 27460 -1872
Branches 7254 6883 -371
==========================================
- Hits 21216 19644 -1572
+ Misses 7136 6860 -276
+ Partials 980 956 -24
*This pull request uses carry forward flags. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsx (1)
58-66: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePromo copy hardcodes values that already exist as constants.
"$100 or more, up to $100" duplicates
MIN_QUALIFYING_AMOUNT/MAX_BONUS, and "10%" duplicatesBONUS_PERCENT. If the promo terms change, it's easy to update the constants (which the header comment says must stay in sync with the backend) but forget this string.♻️ Proposed refactor
- Get 10% bonus credits on your first purchase of $100 or more, up to $100. + Get {BONUS_PERCENT}% bonus credits on your first purchase of ${MIN_QUALIFYING_AMOUNT} or more, up to ${MAX_BONUS}.🤖 Prompt for 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. In `@apps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsx` around lines 58 - 66, Update the promo text in FirstPurchaseBonusAlert to render MIN_QUALIFYING_AMOUNT, MAX_BONUS, and BONUS_PERCENT instead of hardcoded 10%, $100, and $100 values. Preserve the existing wording and qualification behavior while formatting the interpolated values appropriately for users.
🤖 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/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsx`:
- Around line 34-38: Update the query state check in FirstPurchaseBonusAlert to
use isSuccess instead of isFetched, and gate the existing early return on that
success state. Preserve the hasPaidBefore check and avoid rendering the bonus
alert when the payment transactions request fails.
---
Nitpick comments:
In
`@apps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsx`:
- Around line 58-66: Update the promo text in FirstPurchaseBonusAlert to render
MIN_QUALIFYING_AMOUNT, MAX_BONUS, and BONUS_PERCENT instead of hardcoded 10%,
$100, and $100 values. Preserve the existing wording and qualification behavior
while formatting the interpolated values appropriately for users.
🪄 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: ed94b9bc-7c76-4f26-a443-425679a07000
📒 Files selected for processing (6)
apps/deploy-web/src/components/billing-usage/AddCreditsForm/AddCreditsForm.spec.tsxapps/deploy-web/src/components/billing-usage/AddCreditsForm/AddCreditsForm.tsxapps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.spec.tsxapps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsxapps/deploy-web/src/queries/usePaymentQueries.tsapps/deploy-web/src/types/feature-flags.ts
9e7c5a8 to
5d9c51f
Compare
6250080 to
3e5ff5c
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/api/src/billing/services/stripe/stripe.service.spec.ts (1)
134-137: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
mock()instead of anas unknown ascast in this spec.Create a
mock<Stripe.Response<Stripe.ApiList<Stripe.Charge>>>()and assigndataandhas_moreafter creation. As per coding guidelines,*.spec.tstests must usemock<T>()instead ofas unknown as <Type>.Suggested replacement
- const mockCharges = { - data: [bonusCharge, plainCharge], - has_more: false - } as unknown as Stripe.Response<Stripe.ApiList<Stripe.Charge>>; + const mockCharges = mock<Stripe.Response<Stripe.ApiList<Stripe.Charge>>>(); + mockCharges.data = [bonusCharge, plainCharge]; + mockCharges.has_more = false;🤖 Prompt for 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. In `@apps/api/src/billing/services/stripe/stripe.service.spec.ts` around lines 134 - 137, Replace the as unknown as cast in the mockCharges setup with mock<Stripe.Response<Stripe.ApiList<Stripe.Charge>>>(). After creating the mock, assign its data and has_more properties to the existing bonusCharge/plainCharge values and false.Source: Coding guidelines
🤖 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.
Nitpick comments:
In `@apps/api/src/billing/services/stripe/stripe.service.spec.ts`:
- Around line 134-137: Replace the as unknown as cast in the mockCharges setup
with mock<Stripe.Response<Stripe.ApiList<Stripe.Charge>>>(). After creating the
mock, assign its data and has_more properties to the existing
bonusCharge/plainCharge values and false.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e0d82d35-ff96-4d37-b900-2baefda07cf4
📒 Files selected for processing (21)
apps/api/src/billing/http-schemas/stripe.schema.tsapps/api/src/billing/repositories/stripe-transaction/stripe-transaction.repository.tsapps/api/src/billing/services/stripe/stripe.service.spec.tsapps/api/src/billing/services/stripe/stripe.service.tsapps/api/src/types/transactions.tsapps/api/test/seeders/stripe-transaction.seeder.tsapps/deploy-web/src/components/auth/AddCreditsSheet/AddCreditsSheet.tsxapps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.spec.tsxapps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsxapps/deploy-web/src/components/billing-usage/AddCreditsAmountFields/AddCreditsAmountFields.spec.tsxapps/deploy-web/src/components/billing-usage/AddCreditsAmountFields/AddCreditsAmountFields.tsxapps/deploy-web/src/components/billing-usage/AddCreditsForm/AddCreditsForm.spec.tsxapps/deploy-web/src/components/billing-usage/AddCreditsForm/AddCreditsForm.tsxapps/deploy-web/src/components/billing-usage/AddCreditsTabs/AddCreditsTabs.tsxapps/deploy-web/src/components/billing-usage/BillingView/BillingView.spec.tsxapps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsxapps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsxapps/deploy-web/src/components/billing-usage/PaymentSuccessAnimation/PaymentSuccessAnimation.spec.tsxapps/deploy-web/src/components/billing-usage/PaymentSuccessAnimation/PaymentSuccessAnimation.tsxapps/deploy-web/tests/ui/pages/AddCreditsSheetPage.tspackages/http-sdk/src/stripe/stripe.types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/deploy-web/src/components/billing-usage/FirstPurchaseBonusAlert/FirstPurchaseBonusAlert.tsx
Covers the new findByChargeIds method so codecov patch coverage for api passes.
Why
Part of CON-410
The Add Credits form still promises the stale "dollar-for-dollar match" that was never implemented. CON-410 finalizes the offer as a one-time 10% bonus (min $100 purchase, capped at $100) — the backend grant ships in #3423; this PR updates the purchase UI to promote and preview it. Hidden behind the same
first_purchase_bonusUnleash flag, so nothing changes until both sides are deployed and the flag is flipped.Stacked on #3412 (base =
refactor/billing-unify-add-credits-sheet) because the unified tabbed sheet makesAddCreditsFormthe single purchase surface (it deletesPaymentPopup); retarget tomainwhen #3412 merges (#3404 already landed).Screen.Recording.2026-07-13.at.6.06.04.PM.mov
What
FirstPurchaseBonusAlert(blue gift alert, same visual as the old copy) rendered at the top ofAddCreditsForm, reacting to the entered amount:FirstPurchaseBonusService).succeededstatus → correctly treated as consumed). Not gated onisTrialing— coupon claims end the trial without producing a charge, so coupon users (non-trialing) still see the offer, matching the backend rule that coupons don't consume eligibility. Replaces the{isTrialing && ...}wrapper from refactor(billing): unify add-credits and coupon on the shared tabbed sheet #3412.usePaymentTransactionsQuerygains an optionalqueryOptionssecond param (mirrorsusePaymentMethodsQuery) so the alert can gate fetching on the flag.first_purchase_bonusadded to the frontendFeatureFlagunion.BONUS_PERCENT/MAX_BONUSare now exported from the alert so the two copies can't drift).No UI when the flag is off (query disabled, renders null).
Summary by CodeRabbit
Summary