Skip to content

Conversation

@shnai0
Copy link
Collaborator

@shnai0 shnai0 commented Nov 17, 2025

Summary by CodeRabbit

  • New Features

    • Introduced Data Rooms Premium tier with enhanced limits, dedicated support and security features.
    • Three-state plan selector (Base / Plus / Premium) and Premium badge in the UI.
    • Upgrade link added to seat modal and upgrade flows now include contextual view parameters.
    • Premium users can create teams directly.
  • Bug Fixes

    • Redirect to People settings after inviting team members.
  • Documentation

    • Pricing and feature text updated (uses "team member"; "unlimited visitors").

✏️ Tip: You can customize this high-level summary in your review settings.

@shnai0 shnai0 requested a review from mfts as a code owner November 17, 2025 20:13
@vercel
Copy link

vercel bot commented Nov 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
papermark Ready Ready Preview Comment Nov 20, 2025 7:46pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Walkthrough

The PR introduces a new "Data Rooms Premium" tier across billing: plan constants, limits, Stripe plan entries, webhook handling, usePlan surfaces, UI for selecting/upgrading plans, sidebar/team flows, and settings upgrade pages.

Changes

Cohort / File(s) Summary
Plan limits & server mapping
ee/limits/constants.ts, ee/limits/server.ts
Adds DATAROOMS_PREMIUM_PLAN_LIMITS and registers "datarooms-premium" in the server planLimits map.
Stripe constants & features
ee/stripe/constants.ts
Adds DataRoomsPremium to plan names, updates PLAN_NAME_MAP, PLAN_PRICING, and expands BASE_FEATURES to include a new Data Rooms Premium feature set and wording changes.
Stripe plan list
ee/stripe/utils.ts
Appends a datarooms-premium entry to exported PLANS with pricing/price IDs and minQuantity.
Stripe webhook handlers
ee/stripe/webhooks/checkout-session-completed.ts, ee/stripe/webhooks/customer-subscription-updated.ts
Imports DATAROOMS_PREMIUM_PLAN_LIMITS, extends planLimits type, and adds branches to handle datarooms-premium in webhook flows.
Billing hook surface
lib/swr/use-billing.ts
Extends BasePlan union with datarooms-premium, adds isDataroomsPremium to usePlan return, and includes premium slug in isDatarooms logic.
Upgrade modal & selector
components/billing/upgrade-plan-modal.tsx, components/billing/upgrade-plan-container.tsx, components/billing/add-seat-modal.tsx
Converts PlanSelector to three-state ("base"
Sidebar & team switcher
components/sidebar/app-sidebar.tsx, components/sidebar/team-switcher.tsx
Adds isDataroomsPremium to plan-based badge rendering; conditionally renders AddTeamModal vs UpgradePlanModal based on premium state.
Team members flow
components/teams/add-team-member-modal.tsx
Uses useRouter to redirect to /settings/people after successful invitation submission.
Settings upgrade page
pages/settings/upgrade.tsx
Adds PlanTypeSelector, planType state derived from router.query.view, and surfaces DataRoomsPremium in Data Rooms / Business Data Rooms views.

Possibly related PRs

Pre-merge checks

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title "New pricing plan" is vague and generic, failing to convey the specific nature of the changes (introduction of Data Rooms Premium tier). Consider a more descriptive title like "Add Data Rooms Premium plan tier" or "Introduce premium datarooms pricing tier" to clearly communicate the main change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (8)
ee/limits/constants.ts (1)

82-96: Data Rooms Premium limits look consistent; consider deduplicating with Plus

The premium limits are coherent (effectively “Plus with more seats”). To reduce drift risk between Plus and Premium, you could ...DATAROOMS_PLUS_PLAN_LIMITS and override only the fields that differ, but current explicit object is also fine.

components/sidebar/team-switcher.tsx (1)

48-49: Premium-gated team creation logic is sound; dropdown item can be DRY-ed up

Conditioning “Add new team” on isDataroomsPremium and otherwise routing through UpgradePlanModal for DataRoomsPremium aligns well with the new tier model. The two branches share identical DropdownMenuItem markup though; you could extract that into a small AddTeamMenuItem JSX fragment and wrap it with either AddTeamModal or UpgradePlanModal to keep this easier to maintain.

Also applies to: 108-137

components/sidebar/app-sidebar.tsx (1)

55-64: Premium badge integration is correct; consider a more explicit label

Hiding the generic plan badge when isDataroomsPremium and showing a dedicated “Premium” pill keeps the header clean and unambiguous. If you expect more “premium-ish” variants later, you might consider “Data Rooms Premium” as the badge text for extra clarity, but the current implementation is functionally fine.

Also applies to: 219-233

pages/settings/upgrade.tsx (2)

90-103: PlanTypeSelector only toggles 2 views while state supports 3

planType and getInitialView support "documents" | "datarooms" | "business-datarooms", and the effect correctly syncs from router.query.view. However, PlanTypeSelector renders only two buttons (Document Sharing / Data Rooms), and the showBusinessDatarooms prop is currently unused. This means the “Business + Data Rooms” view is reachable via ?view=business-datarooms but not discoverable from the on-page toggle.

If that’s intentional (i.e., only certain entrypoints should show the combined view) then it’s fine, but you may want to either:

  • Remove showBusinessDatarooms and keep the selector explicitly 2-state, or
  • Use showBusinessDatarooms to render a third button and widen the onChange signature accordingly so all three views can be navigated in-page.

Also applies to: 139-157, 185-190


158-164: Card layout for the three plan groups is duplicated and has some unreachable branches

The three sections (“Document Sharing”, “Business + Data Rooms”, “Data Rooms”) all implement nearly identical card markup: border color selection, badge rendering, pricing lookup via PLANS.find((p) => p.name === planOption), feature list, and upgrade CTA. That works, but it’s a lot of duplicated JSX and fetch/Stripe wiring to keep in sync across tiers.

A few small observations:

  • In the Document Sharing grid, documentSharingPlans never includes PlanEnum.DataRoomsPlus or PlanEnum.DataRoomsPremium, yet styling branches check for those values in the border color and badge logic, so those branches are currently dead code in this section.
  • In the other two grids, the planOption === PlanEnum.Business branch in the card border/badge logic is only relevant where Business is actually in the mapped list (the datarooms-only grid never includes Business).

Consider extracting a reusable PlanCard (and possibly PlanGrid) component that takes planOption, period, teamPlan, etc., and centralizes:

  • The border/badge selection for Business / DataRoomsPlus / DataRoomsPremium.
  • The repeated manage/upgrade fetch + Stripe checkout logic.

That would remove the unreachable branches in the first grid and make any future pricing/feature changes less error‑prone.

Also applies to: 192-341, 343-499, 501-655

components/billing/upgrade-plan-modal.tsx (3)

99-141: PlanSelector three-way toggle is clear; consider reusing the tier type

The three-option segmented control with "base" | "plus" | "premium" is straightforward and keeps the API clean. To avoid repeating the literal union in multiple places (here and in dataRoomsPlanSelection), consider extracting a small alias, e.g. type DataRoomsTier = "base" | "plus" | "premium";, and reusing it for value, onChange, and the state hook.


168-181: DataRooms selection state and plansToShow mapping look correct overall

Initializing dataRoomsPlanSelection to "base" and resetting it in the open effect when the dialog closes prevents stale selections leaking between sessions, which is good. The extended plansToShow switch covers the new DataRoomsPlus → DataRoomsPremium path while preserving existing Pro/Business flows. If you care about micro-optimizations/readability, const isDataRoomsUpgrade = plansToShow.includes(PlanEnum.DataRooms); could be hoisted outside the map since it’s constant per render.

Also applies to: 195-196


238-255: effectivePlan/displayPlanName wiring is consistent; strengthen keys and premium exposure

Mapping dataRoomsPlanSelection into effectivePlan and displayPlanName keeps getPlanFeatures, the PLANS price lookup, getPriceIdFromPlan, headings, and button copy all in sync, which is the right approach.

A couple of non-blocking points:

  • Using key={displayPlanName} works today but is a bit brittle: if future changes ever cause two cards to share the same displayPlanName, you’ll hit React key collisions. A composite key like key={`${planOption}-${displayPlanName}`} would guard against that while still forcing a remount when the user switches tiers.
  • From a UX perspective, when clickedPlan === PlanEnum.DataRooms the modal only ever shows DataRooms and DataRoomsPlus (no premium card or selector). The premium tier is reachable when clickedPlan is DataRoomsPlus/DataRoomsPremium (two-card layout) or via the Business → Data Rooms selector, but users entering via a “Data Rooms” CTA won’t see premium directly. If the intent is to always surface the new premium tier from any Data Rooms entrypoint, you may want to include PlanEnum.DataRoomsPremium in that plansToShow case or enable the selector there as well.
  • Ensure PLANS and getPriceIdFromPlan both have entries keyed exactly by PlanEnum.DataRoomsPremium; otherwise price display or checkout for the premium tier will fail even though the UI allows selecting it.

Also applies to: 260-287, 335-340, 395-397

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb1ebed and 439dd25.

📒 Files selected for processing (14)
  • components/billing/add-seat-modal.tsx (2 hunks)
  • components/billing/upgrade-plan-container.tsx (2 hunks)
  • components/billing/upgrade-plan-modal.tsx (9 hunks)
  • components/sidebar/app-sidebar.tsx (3 hunks)
  • components/sidebar/team-switcher.tsx (3 hunks)
  • components/teams/add-team-member-modal.tsx (3 hunks)
  • ee/limits/constants.ts (1 hunks)
  • ee/limits/server.ts (2 hunks)
  • ee/stripe/constants.ts (7 hunks)
  • ee/stripe/utils.ts (1 hunks)
  • ee/stripe/webhooks/checkout-session-completed.ts (3 hunks)
  • ee/stripe/webhooks/customer-subscription-updated.ts (3 hunks)
  • lib/swr/use-billing.ts (2 hunks)
  • pages/settings/upgrade.tsx (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
ee/stripe/webhooks/customer-subscription-updated.ts (1)
ee/limits/constants.ts (3)
  • DATAROOMS_PLUS_PLAN_LIMITS (66-80)
  • DATAROOMS_PREMIUM_PLAN_LIMITS (82-96)
  • PRO_PLAN_LIMITS (27-36)
pages/settings/upgrade.tsx (4)
ee/stripe/constants.ts (1)
  • getPlanFeatures (216-283)
ee/stripe/utils.ts (1)
  • PLANS (105-285)
ee/stripe/client.ts (1)
  • getStripe (6-30)
lib/utils.ts (1)
  • capitalize (160-163)
ee/limits/server.ts (1)
ee/limits/constants.ts (1)
  • DATAROOMS_PREMIUM_PLAN_LIMITS (82-96)
components/billing/upgrade-plan-modal.tsx (2)
lib/utils.ts (1)
  • cn (18-20)
ee/stripe/constants.ts (1)
  • getPlanFeatures (216-283)
components/sidebar/team-switcher.tsx (3)
lib/swr/use-billing.ts (1)
  • usePlan (87-138)
components/teams/add-team-modal.tsx (1)
  • AddTeamModal (29-112)
components/billing/upgrade-plan-modal.tsx (1)
  • UpgradePlanModal (146-432)
ee/stripe/webhooks/checkout-session-completed.ts (1)
ee/limits/constants.ts (3)
  • DATAROOMS_PLUS_PLAN_LIMITS (66-80)
  • DATAROOMS_PREMIUM_PLAN_LIMITS (82-96)
  • PRO_PLAN_LIMITS (27-36)
🔇 Additional comments (12)
ee/stripe/constants.ts (5)

85-85: Clarify commented retention feature.

The retention feature is commented out for the Pro plan. Please confirm whether this is intentional or if analytics retention should still be displayed for the Pro tier.


117-118: Verify commented features in Business plan.

Several features are commented out in the Business plan (file-types-advanced on line 117). Please confirm these features should be hidden from the Business tier or if this is temporary.


144-147: Clarify commented audit log and retention in Data Rooms plan.

Multiple features are commented out including audit log (line 144) and retention (line 147). Please verify these features are intentionally removed from the Data Rooms tier or if this represents incomplete work.


41-67: LGTM! Consistent pricing terminology.

The update from "per user" to "per additional team member" across all plans provides clearer communication about the pricing model. The Premium tier pricing is properly integrated.


179-203: Premium plan features look comprehensive.

The new Data Rooms Premium tier features are well-defined with appropriate highlights for unlimited storage and clear value propositions (teams, SSO, whitelabeling, API access, dedicated support).

components/billing/add-seat-modal.tsx (1)

188-194: Good UX enhancement with upgrade option.

Adding the upgrade link provides users with a clear alternative to simply adding more seats. This helps guide users toward the most cost-effective solution for their needs.

ee/limits/server.ts (1)

9-9: LGTM! Premium plan limits properly integrated.

The addition of DATAROOMS_PREMIUM_PLAN_LIMITS to the plan limits map follows the established pattern and correctly extends the system to support the new premium tier.

Also applies to: 28-28

components/billing/upgrade-plan-container.tsx (1)

48-48: LGTM! Premium plan display properly integrated.

The conditional rendering correctly displays "Premium" for the Data Rooms Premium tier, maintaining consistency with the existing "Datarooms+" display logic. The integration with the isDataroomsPremium flag from usePlan is correct.

Also applies to: 295-300

ee/stripe/webhooks/checkout-session-completed.ts (1)

5-5: LGTM! Webhook handling for premium plan is complete.

The webhook correctly handles checkout completion for Data Rooms Premium subscriptions by:

  1. Importing the premium limits constant
  2. Extending the type union to include premium limits
  3. Adding the conditional branch to clone premium limits when plan.slug === "datarooms-premium"

This follows the established pattern and will properly provision premium subscriptions.

Also applies to: 67-78

lib/swr/use-billing.ts (1)

45-46: LGTM! Plan type extensions are properly implemented.

The changes correctly:

  1. Extend BasePlan union to include "datarooms-plus" and "datarooms-premium"
  2. Update isDatarooms to recognize all three dataroom tier variants
  3. Add the isDataroomsPremium boolean flag for tier-specific logic

The implementation follows the established pattern and enables downstream components to properly handle the new premium tier.

Also applies to: 131-133

ee/stripe/webhooks/customer-subscription-updated.ts (1)

3-9: Correct mapping of datarooms-premium to its limits

The new import, union extension, and plan.slug === "datarooms-premium" branch correctly wire the premium plan to DATAROOMS_PREMIUM_PLAN_LIMITS while preserving the existing quantity→users logic.

Also applies to: 66-82

components/billing/upgrade-plan-modal.tsx (1)

405-415: Footer copy and “See all plans” link look good; confirm view query handling

Updating the copy to “unlimited visitors” is consistent with the Data Rooms terminology. The conditional query string on the “See all plans” link (?view=documents for Pro, ?view=business-datarooms for Business, otherwise default) makes sense; just double-check that /settings/upgrade uses those exact view values and that the fallback case (Data Rooms tiers) lands users on the intended tab.

Comment on lines +86 to +88

// Redirect to team members page
router.push("/settings/people");
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Verify redirect behavior across all modal usage contexts.

The unconditional redirect to /settings/people may disrupt the user flow if this modal is invoked from pages other than the settings area. For example, if a user adds a team member from the team switcher or another context, they might expect to remain on their current page.

Run the following script to identify all locations where AddTeamMembers is used:


🏁 Script executed:

#!/bin/bash
# Find all usages of AddTeamMembers component
rg -n "AddTeamMembers" --type=tsx --type=ts -C3

Length of output: 27



---

🏁 Script executed:

```shell
#!/bin/bash
# Find all usages of AddTeamMembers component without type specification
rg -n "AddTeamMembers" -C3

Length of output: 3445


🏁 Script executed:

#!/bin/bash
# Also search for imports of the modal to understand usage patterns
rg -n "add-team-member-modal" -C3

Length of output: 1131


🏁 Script executed:

#!/bin/bash
# Find file extensions in the components/teams directory to understand structure
fd . components/teams --type f

Length of output: 150



---

🏁 Script executed:

```shell
#!/bin/bash
# Find all usages of team-switcher component to understand where it appears
rg -n "team-switcher" -C2

Length of output: 390


🏁 Script executed:

#!/bin/bash
# Check the content of add-team-member-modal.tsx to see the full redirect context
cat components/teams/add-team-member-modal.tsx | head -100

Length of output: 2667


Fix unconditional redirect that disrupts user flow when adding team members from sidebar.

The modal redirects to /settings/people unconditionally after a successful invitation, which disrupts users who invoke it from the sidebar (used throughout the app, not just settings). Users adding members while on other pages (dashboard, projects, etc.) will be unexpectedly redirected away.

Options:

  • Remove the redirect entirely (modal closes, user stays on current page)
  • Make redirect conditional (e.g., only redirect if already on settings/people)
  • Accept a callback prop to let parent components control post-invitation navigation
🤖 Prompt for AI Agents
In components/teams/add-team-member-modal.tsx around lines 86-88, remove the
unconditional router.push("/settings/people") after a successful invitation and
instead either 1) simply close the modal so the user stays on the current page,
or 2) make the redirect conditional by checking the current route and only
calling router.push if the user is already on /settings/people, or 3) expose and
call an optional onSuccess callback prop (invoked with the invitation result) so
parent components can decide navigation; implement one of these approaches and
ensure the modal close logic still runs after a successful invite.

Comment on lines +250 to +284
{
name: "Data Rooms Premium",
slug: "datarooms-premium",
minQuantity: 10,
price: {
monthly: {
amount: 699,
unitPrice: 6990,
priceIds: {
test: {
old: "price_placeholder_test_old",
new: "price_1SUWeXBYvhH6u7U7u7CJgsRE",
},
production: {
old: "price_placeholder_prod_old",
new: "price_1SUWXqBYvhH6u7U7SJKKOCKU",
},
},
},
yearly: {
amount: 549,
unitPrice: 5490,
priceIds: {
test: {
old: "price_placeholder_test_yearly_old",
new: "price_1SUWhQBYvhH6u7U7BE6vVLcf",
},
production: {
old: "price_placeholder_prod_yearly_old",
new: "price_1SUWWqBYvhH6u7U7I5MpZ43K",
},
},
},
},
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Verify placeholder price IDs for old accounts.

The Data Rooms Premium plan uses placeholder price IDs for old accounts (e.g., price_placeholder_test_old on line 260). If legacy customers attempt to upgrade to the Premium tier, these placeholders will cause getPlanFromPriceId to fail. Please confirm whether:

  1. Premium tier should be unavailable to old accounts (if so, add validation)
  2. Real price IDs need to be created for old accounts

Run the following script to verify if old account handling exists elsewhere:

#!/bin/bash
# Check for old account gating or validation in upgrade flows
rg -n "isOldAccount|isOld.*premium" --type=ts --type=tsx -C3

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
components/billing/upgrade-plan-modal.tsx (4)

99-142: PlanSelector premium extension looks correct; consider de-duplicating the value type

The segmented control correctly introduces a third “premium” option and wires onChange("base" | "plus" | "premium") consistently. To avoid repeating the literal union in multiple places (PlanSelector props, dataRoomsPlanSelection state), consider extracting a local type alias, e.g. type DataRoomsTier = "base" | "plus" | "premium";, and reusing it for stronger coherence.


168-170: Data Rooms tier selection logic works for Business and Plus paths; confirm intended behavior for clickedPlan = DataRooms

The dataRoomsPlanSelection state + effectivePlan/displayPlanName wiring correctly:

  • Lets Business users see a single “Data Rooms” card whose price/features toggle between Base/Plus/Premium via PlanSelector.
  • Lets DataRoomsPlus/DataRoomsPremium clicks show separate Plus vs Premium cards with correct pricing (PLANS.find(...name === displayPlanName)) and price IDs (getPriceIdFromPlan({ planName: displayPlanName, ... })).

However, when clickedPlan === PlanEnum.DataRooms, plansToShow is [DataRooms, DataRoomsPlus], so:

  • DataRoomsPremium is never surfaced.
  • The PlanSelector is not rendered (!plansToShow.includes(PlanEnum.DataRoomsPlus) is false), so dataRoomsPlanSelection has no effect in that flow.

If users on the base Data Rooms plan are supposed to be able to upgrade directly to Premium from this modal, you may want to either:

  • Include PlanEnum.DataRoomsPremium in plansToShow for the DataRooms case, or
  • Allow the PlanSelector for the DataRooms card even when DataRoomsPlus is also present.

Otherwise, this asymmetry (Business → Premium allowed, DataRooms → Premium not shown) is product‑driven but worth double‑checking.

Also applies to: 181-183, 240-259, 305-311


189-199: Effect dependencies may be incomplete for analytics + reset behavior

The useEffect uses analytics, teamId, and setDataRoomsPlanSelection but only declares [open, trigger] as dependencies. This can lead to stale teamId/analytics references if the team context changes without toggling open.

Consider adding analytics and teamId (and optionally setDataRoomsPlanSelection) to the dependency array, or explicitly disabling the lint rule with a comment if you intend to lock the values to those at the time the modal is first opened.


405-415: Footer copy update is fine; consider aligning view param for Data Rooms tiers

The text change to “unlimited visitors” is straightforward and non‑breaking.

For the “See all plans” link, only clickedPlan === PlanEnum.Pro and clickedPlan === PlanEnum.Business currently get a contextual view (documents vs business-datarooms). If the intent is that all Data Rooms‑related entry points (DataRooms, DataRoomsPlus, DataRoomsPremium) should land on the same business-datarooms view, consider extending this conditional to include those enums as well.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 439dd25 and 967b418.

📒 Files selected for processing (1)
  • components/billing/upgrade-plan-modal.tsx (8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/billing/upgrade-plan-modal.tsx (2)
lib/utils.ts (1)
  • cn (18-20)
ee/stripe/constants.ts (1)
  • getPlanFeatures (216-283)
🔇 Additional comments (1)
components/billing/upgrade-plan-modal.tsx (1)

275-276: Using displayPlanName and effectivePlan for features, pricing, and price IDs is consistent

Deriving effectivePlan for getPlanFeatures and using displayPlanName for:

  • the card title,
  • pricing via PLANS.find((p) => p.name === displayPlanName),
  • and getPriceIdFromPlan({ planName: displayPlanName, ... })

keeps the Data Rooms Base/Plus/Premium variants internally consistent. This ensures that when the user selects Plus or Premium, both the shown price/features and the Stripe priceId line up with the chosen tier.

Also applies to: 283-288, 291-303, 333-341, 345-348

@mfts mfts merged commit ae31acb into main Nov 20, 2025
9 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Nov 20, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants