feat(desktop): show Pro badge in account dropdown#3878
Conversation
Adds a `billing.activePlan` tRPC query and renders a Pro/Enterprise badge next to the user's name in the AgentsHeader dropdown and mobile drawer when the active org has a paid subscription.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdded a protected backend query Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Client UI
participant TRPC as TRPC Client
participant Router as billingRouter
participant DB as Database
UI->>TRPC: request activePlan
TRPC->>Router: invoke protected billing.activePlan
Router->>DB: query subscriptions for org (filter ACTIVE_SUBSCRIPTION_STATUSES, order by createdAt desc)
DB-->>Router: subscription or empty
Router-->>TRPC: { plan, status } (or fallback { plan: "free", status: null })
TRPC-->>UI: activePlan response
UI->>UI: compute isPaidPlan & planLabel
UI-->>UI: render Badge if paid
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Review rate limit: 3/8 reviews remaining, refill in 35 minutes and 46 seconds.Comment |
Greptile SummaryThis PR introduces a Confidence Score: 5/5Safe to merge — all findings are minor style/robustness suggestions with no blocking issues. Both changed files are straightforward. The only issues found are a redundant double-check of the subscription status (P2 style) and a slightly brittle planLabel fallback that is currently unreachable in practice (P2). No P0/P1 defects identified. No files require special attention.
|
| Filename | Overview |
|---|---|
| packages/trpc/src/router/billing/billing.ts | Adds activePlan tRPC query that fetches the org's active subscription from the DB, filters by active statuses, and returns the plan tier; contains a redundant double-check of the subscription status (P2). |
| apps/web/src/app/(agents)/components/AgentsHeader/AgentsHeader.tsx | Adds Pro/Enterprise badge rendering in both the desktop dropdown and mobile drawer; planLabel fallback defaults to "Pro" when data is loading, which is harmless today but slightly brittle (P2). |
Sequence Diagram
sequenceDiagram
participant UI as AgentsHeader (React)
participant tRPC as tRPC billing.activePlan
participant DB as Database (subscriptions)
UI->>tRPC: useQuery(activePlan)
tRPC->>tRPC: check ctx.activeOrganizationId
alt no active org
tRPC-->>UI: { plan: "free", status: null }
else has active org
tRPC->>DB: findFirst WHERE referenceId=orgId AND status IN ["active","trialing"] ORDER BY createdAt DESC
DB-->>tRPC: subscription | undefined
alt no active subscription
tRPC-->>UI: { plan: "free", status: null }
else active subscription found
tRPC-->>UI: { plan: subscription.plan, status: subscription.status }
end
end
UI->>UI: isPro = isPaidPlan(activePlan?.plan)
alt isPro
UI->>UI: Render Badge with capitalized plan name
else not paid
UI->>UI: No badge shown
end
Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/trpc/src/router/billing/billing.ts
Line: 84-86
Comment:
**Redundant status guard after filtered query**
The `inArray(subscriptions.status, ACTIVE_SUBSCRIPTION_STATUSES)` WHERE clause already guarantees that any row returned has an active-subscription status, so the `!isActiveSubscriptionStatus(subscription.status)` branch on line 84 is always false when a subscription is found. The secondary check adds no safety; it only adds noise and the risk of the two lists drifting apart silently.
```suggestion
if (!subscription) {
return { plan: "free" as const, status: null };
}
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/web/src/app/(agents)/components/AgentsHeader/AgentsHeader.tsx
Line: 52-54
Comment:
**Stale `planLabel` when `activePlan` is loading**
When `activePlan` is still loading (`undefined`), `activePlan?.plan` is `undefined` (falsy), so `planLabel` is hardcoded to `"Pro"`. At the same moment, `isPro` evaluates to `false`, so the badge is not rendered — the wrong default is never visible today. But if the loading-state logic ever changes (e.g., `isPro` uses a previous cached value while a new org's plan is being fetched), the stale `"Pro"` label could flash incorrectly.
Consider deriving the label only when `activePlan?.plan` is a known paid tier:
```suggestion
const planLabel =
activePlan?.plan && activePlan.plan !== "free"
? activePlan.plan.charAt(0).toUpperCase() + activePlan.plan.slice(1)
: null;
```
Then render `{isPro && planLabel && <Badge ...>{planLabel}</Badge>}`.
```suggestion
const planLabel =
activePlan?.plan && activePlan.plan !== "free"
? activePlan.plan.charAt(0).toUpperCase() + activePlan.plan.slice(1)
: null;
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat(web): show Pro badge in account dro..." | Re-trigger Greptile
| if (!subscription || !isActiveSubscriptionStatus(subscription.status)) { | ||
| return { plan: "free" as const, status: null }; | ||
| } |
There was a problem hiding this comment.
Redundant status guard after filtered query
The inArray(subscriptions.status, ACTIVE_SUBSCRIPTION_STATUSES) WHERE clause already guarantees that any row returned has an active-subscription status, so the !isActiveSubscriptionStatus(subscription.status) branch on line 84 is always false when a subscription is found. The secondary check adds no safety; it only adds noise and the risk of the two lists drifting apart silently.
| if (!subscription || !isActiveSubscriptionStatus(subscription.status)) { | |
| return { plan: "free" as const, status: null }; | |
| } | |
| if (!subscription) { | |
| return { plan: "free" as const, status: null }; | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/src/router/billing/billing.ts
Line: 84-86
Comment:
**Redundant status guard after filtered query**
The `inArray(subscriptions.status, ACTIVE_SUBSCRIPTION_STATUSES)` WHERE clause already guarantees that any row returned has an active-subscription status, so the `!isActiveSubscriptionStatus(subscription.status)` branch on line 84 is always false when a subscription is found. The secondary check adds no safety; it only adds noise and the risk of the two lists drifting apart silently.
```suggestion
if (!subscription) {
return { plan: "free" as const, status: null };
}
```
How can I resolve this? If you propose a fix, please make it concise.
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
Renders a Pro/Enterprise badge next to the org name in the desktop OrganizationDropdown trigger (topbar and expanded sidebar variants), using the existing useCurrentPlan hook.
- billing.activePlan: drop redundant status check; the WHERE clause already restricts to ACTIVE_SUBSCRIPTION_STATUSES. - AgentsHeader: derive planLabel only when on a paid tier so a stale "Pro" string can't surface if loading-state logic changes.
Summary
billing.activePlantRPC query that returns the active org's plan tier and subscription status (defaults tofreewhen there's no active subscription).Pro/Enterprisebadge next to the user's name in theAgentsHeaderdesktop dropdown and mobile drawer when the org is on a paid plan.(dashboard-legacy)/Header.tsxsince the v1 dashboard is being sunset.Test plan
freeplan — no badge shows.pro—Probadge renders next to the name in both the desktop dropdown and the mobile drawer.enterprise— badge label readsEnterprise.canceled) does not show a badge.Summary by cubic
Show a Pro/Enterprise badge when the active org has a paid plan in the web account menu (dropdown + mobile drawer) and the desktop Organization dropdown. Adds a
billing.activePlantRPC query to expose the active org’s plan and subscription status.New Features
billing.activePlanreturns{ plan, status }for the active org; defaults tofree/nulland filters to active statuses via@superset/shared/billing.AgentsHeader): render aBadgenext to the user’s name in the desktop dropdown and mobile drawer; label shows "Pro" or "Enterprise"; hidden for free or non-active subscriptions.OrganizationDropdown): render aBadgenext to the org name in both trigger variants usinguseCurrentPlan.Bug Fixes
billing.activePlan.Written for commit 3c17e8e. Summary will update on new commits. Review in cubic
Summary by CodeRabbit