Skip to content

feat(redeem): funnel low-Points users from RC top-up to in-app Points purchase#3281

Merged
feruzm merged 3 commits into
developmentfrom
feature/rc-topup-buy-points-funnel
Jun 21, 2026
Merged

feat(redeem): funnel low-Points users from RC top-up to in-app Points purchase#3281
feruzm merged 3 commits into
developmentfrom
feature/rc-topup-buy-points-funnel

Conversation

@feruzm

@feruzm feruzm commented Jun 21, 2026

Copy link
Copy Markdown
Member

Mobile counterpart to the web buy-Points funnel. The RC top-up redeem screen used to just disable Next when the user lacked enough Points, with no message and no path forward.

Changes (src/screens/redeem/children/rcTopUp.tsx)

  • Shows an insufficient Points message when the selected duration's price exceeds the balance.
  • Adds an always-visible Buy Points action that opens the in-app Points purchase (native Apple/Google billing via the existing Boost/IAP screen, SKUs 099points...9999points). After the purchase credits Points, the user returns and the balance query refetches so they can finish the top-up.
  • Shown regardless of balance, so users can also stock up for later.

Mobile is the easiest conversion path here since the purchase is the OS payment sheet (no crypto, no QR). No SDK bump (uses existing navigation + the existing IAP screen), so it ships on the next app build. Strings added to en-US.json only.

Summary by CodeRabbit

  • New Features
    • Points balance automatically refreshes when you return to the RC top-up screen, ensuring you always see your most current available balance after making any in-app purchases
    • Added insufficient points notification with a convenient button to directly purchase additional points when your selected RC option exceeds your available balance, simplifying the top-up experience

… purchase

The RC top-up redeem screen previously just disabled Next when the price
exceeded the Points balance, with no message and no way to get more Points.

- Show an 'insufficient Points' message when price > balance.
- Add an always-visible 'Buy Points' action that opens the in-app Points
  purchase (native Apple/Google billing via the Boost/IAP screen), so a user
  with no Hive can buy Points and return to finish the top-up. Shown even with
  enough balance so users can stock up for later.

No SDK bump (uses existing navigation + the existing IAP screen).
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@feruzm, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 21 minutes and 57 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 687add38-e05e-495d-88ca-feadbcd0d17b

📥 Commits

Reviewing files that changed from the base of the PR and between dcb28a3 and 62f710f.

📒 Files selected for processing (1)
  • src/screens/redeem/children/rcTopUp.tsx
📝 Walkthrough

Walkthrough

The RC Top-Up screen gains a useFocusEffect hook that refetches the Points balance each time the screen is focused. When the selected RC price exceeds the current balance, an insufficient-Points message and a "buy Points" button are rendered, navigating to the Boost screen. Three new locale strings and three new stylesheet rules support this UI path.

Changes

RC Top-Up Insufficient Points Flow

Layer / File(s) Summary
Focus refetch, insufficient state, and locale strings
src/screens/redeem/children/rcTopUp.tsx, src/config/locales/en-US.json
Imports useFocusEffect, wraps pointsQuery.refetch() in a focus callback, derives insufficient from price > balance, adds _onBuyPoints navigation handler, and registers insufficient/buy_points locale keys under rc_topup.
Insufficient UI render and styles
src/screens/redeem/children/rcTopUp.tsx, src/screens/redeem/styles/boostPlus.styles.ts
Conditionally renders the insufficient message and buy-points button when the insufficient flag is true; adds insufficientText, buyPointsButton, and buyPointsText stylesheet entries.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! Points running low?
A red message says "Insufficient, oh no!"
With a click of a button, off to Boost we go,
The balance refetches each time screens glow.
No more guessing — the rabbit always knows! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: implementing a funnel for users with insufficient Points during RC top-up, directing them to in-app Points purchase, which matches the core objective of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/rc-topup-buy-points-funnel

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 and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a01951aa5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +107 to +111
const _onBuyPoints = () => {
RootNavigation.navigate({
name: ROUTES.SCREENS.BOOST,
params: { username: currentAccountName },
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh point balance after returning from purchase

When a low-Points user opens this purchase flow, completes an IAP, and backs out, the RC top-up screen is still mounted and its balance only changes when pointsQuery.data changes. BoostScreen only shows a toast on purchase success and does not pass fetchData or invalidate the points query, while the shared query client disables focus refetches, so the old balance can keep Next disabled and the insufficient warning visible even after the purchase credits. Add an explicit refetch/invalidation on return or purchase success before expecting the user to finish the top-up.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR improves the RC top-up flow by funneling users with insufficient Points directly to the in-app purchase screen, and ensures the balance refreshes when they return so the top-up can proceed immediately.

  • Adds a conditional insufficient banner and an always-visible Buy Points TouchableOpacity that navigates to ROUTES.SCREENS.BOOST using the same { username } param pattern already used by walletHeader and walletScreen.
  • Wires useFocusEffect + useCallback to call pointsQuery.refetch() whenever the screen regains focus, so a completed IAP purchase is reflected without the user needing to leave and re-enter the screen manually.
  • Extends en-US.json with two new keys (rc_topup.insufficient, rc_topup.buy_points) and adds three matching style entries to boostPlus.styles.ts.

Confidence Score: 5/5

Safe to merge — the changes are additive, touch only one screen, and the navigation + refetch patterns are consistent with the rest of the codebase.

The balance-refetch mechanism (previously missing) is now correctly implemented with useFocusEffect. The navigation call to the Boost screen uses the identical { name, params: { username } } shape already used in walletHeader.tsx and walletScreen.tsx. The insufficient guard is straightforward and the new styles are self-contained. No regressions introduced to existing paths.

No files require special attention.

Important Files Changed

Filename Overview
src/screens/redeem/children/rcTopUp.tsx Adds insufficient-Points banner and always-visible Buy Points button; wires useFocusEffect to refetch balance on return from Boost screen. Navigation params match existing codebase patterns.
src/screens/redeem/styles/boostPlus.styles.ts Adds three new style entries (insufficientText, buyPointsButton, buyPointsText) for the new UI elements; paddingHorizontal is included on the button.
src/config/locales/en-US.json Adds two new localisation keys (insufficient, buy_points) under rc_topup; no existing keys modified.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant U as User
    participant RC as RcTopUp screen
    participant TQ as TanStack Query
    participant SRV as Ecency API
    participant BS as Boost / IAP screen

    U->>RC: Opens RC Top-Up
    RC->>TQ: useQuery(getPointsQueryOptions)
    RC->>TQ: useFocusEffect → pointsQuery.refetch()
    TQ->>SRV: GET points balance
    SRV-->>TQ: "{ points }"
    TQ-->>RC: updates balance state

    alt "balance >= price"
        RC->>U: shows Next (enabled)
    else "balance < price"
        RC->>U: shows insufficient banner + Buy Points button
        U->>RC: taps Buy Points
        RC->>BS: "RootNavigation.navigate(BOOST, { username })"
        U->>BS: completes IAP purchase
        BS-->>RC: user navigates back (screen gains focus)
        RC->>TQ: useFocusEffect fires → pointsQuery.refetch()
        TQ->>SRV: GET points balance
        SRV-->>TQ: "updated { points }"
        TQ-->>RC: balance updated → Next becomes enabled
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant U as User
    participant RC as RcTopUp screen
    participant TQ as TanStack Query
    participant SRV as Ecency API
    participant BS as Boost / IAP screen

    U->>RC: Opens RC Top-Up
    RC->>TQ: useQuery(getPointsQueryOptions)
    RC->>TQ: useFocusEffect → pointsQuery.refetch()
    TQ->>SRV: GET points balance
    SRV-->>TQ: "{ points }"
    TQ-->>RC: updates balance state

    alt "balance >= price"
        RC->>U: shows Next (enabled)
    else "balance < price"
        RC->>U: shows insufficient banner + Buy Points button
        U->>RC: taps Buy Points
        RC->>BS: "RootNavigation.navigate(BOOST, { username })"
        U->>BS: completes IAP purchase
        BS-->>RC: user navigates back (screen gains focus)
        RC->>TQ: useFocusEffect fires → pointsQuery.refetch()
        TQ->>SRV: GET points balance
        SRV-->>TQ: "updated { points }"
        TQ-->>RC: balance updated → Next becomes enabled
    end
Loading

Reviews (3): Last reviewed commit: "fix(redeem): order @react-navigation/nat..." | Re-trigger Greptile

Comment thread src/screens/redeem/styles/boostPlus.styles.ts
- Refetch the Points balance with useFocusEffect when the RC top-up screen
  regains focus, so Points bought via the IAP show up on return (RN
  refetch-on-focus is AppState-based, not navigation-based) and the user can
  finish the top-up without leaving the screen.
- Add paddingHorizontal to the Buy Points button for a comfortable tap target.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@src/screens/redeem/children/rcTopUp.tsx`:
- Around line 1-11: The import order violates ESLint's import/order rule. The
useFocusEffect import from `@react-navigation/native` on line 11 is an external
third-party import that must be grouped with the other external imports at the
top of the file, before the relative imports. Move the useFocusEffect import
line to be positioned after the other external imports (such as after the import
from `@ecency/sdk`) and before the relative imports (such as before the
ScaleSlider import).
🪄 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: 99801269-4fb4-4ba2-8bc7-75f258a10bbf

📥 Commits

Reviewing files that changed from the base of the PR and between ff8d1da and dcb28a3.

📒 Files selected for processing (3)
  • src/config/locales/en-US.json
  • src/screens/redeem/children/rcTopUp.tsx
  • src/screens/redeem/styles/boostPlus.styles.ts

Comment thread src/screens/redeem/children/rcTopUp.tsx Outdated
@feruzm feruzm merged commit b6421bd into development Jun 21, 2026
10 of 12 checks passed
@feruzm feruzm deleted the feature/rc-topup-buy-points-funnel branch June 21, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant