Skip to content

Commit 8489844

Browse files
committed
[Dashboard] Add 7-day free trial for Growth plan (#7322)
# Add 7-day free trial for Growth plan and include Starter plan in team onboarding This PR adds a 7-day free trial indicator for teams that have just signed up but haven't subscribed yet when selecting the Growth plan. It also updates the team onboarding flow to properly handle the Starter plan. Changes include: - Added logic to detect if a team qualifies for the 7-day trial (new signup with no payment on Growth plan) - Added a "7 day free trial" text display for qualifying teams - Updated the polling logic to consider both "free" and "starter" plans as non-paid plans - Modified the onboarding description text to remove reference to "free Starter plan" ## Summary by CodeRabbit - **New Features** - Added a clear "7 day free trial" indicator for eligible Growth plan users. - **Enhancements** - Updated onboarding modal text to remove "free" from the Starter plan description. - Modified billing plan polling logic to exclude both "free" and "starter" plans before proceeding. --- ## PR-Codex overview This PR focuses on updating the logic for determining billing plans and enhancing the user experience regarding trial periods in the `InviteTeamMembers` and `PricingCard` components. ### Detailed summary - In `InviteTeamMembers.tsx`, updated the condition for `isNonFreePlan` to exclude both "free" and "starter" plans. - Modified the text in `InviteModalContent` to clarify the Starter plan. - In `pricing-card.tsx`, added a condition for a 7-day trial for teams with a "growth" billing plan and "noPayment" status. - Changed the rendering logic for remaining trial days to include a message for the 7-day trial. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing the pricing logic and UI in the dashboard. It modifies how pricing is handled, specifically for trial periods, and updates the display of pricing information to better reflect the available options and trials. ### Detailed summary - Changed `price` type from `string | number` to `number`. - Updated `isNonFreePlan` logic to exclude "starter" plans. - Revised promotional text for the Growth plan. - Added logic for a 7-day free trial for new teams on the Growth plan. - Updated UI to display a "7 Day Free Trial" badge and adjusted pricing display accordingly. - Modified call-to-action button text based on trial eligibility. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a "7 Day Free Trial" badge and updated price display for eligible users on the Growth plan. - Call-to-action button now shows "Start 7 Day Free Trial" when applicable. - **Bug Fixes** - Improved onboarding flow by updating plan detection logic to better handle "Starter" and "Free" plans. - **Style** - Revised onboarding text to emphasize upgrading to the Growth plan and removed mention of the Starter plan. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 950bbae commit 8489844

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

apps/dashboard/src/@/components/blocks/pricing-card.tsx

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { CheckoutButton } from "../billing";
1616

1717
type PricingCardCta = {
1818
hint?: string;
19-
2019
onClick?: () => void;
2120
} & (
2221
| {
@@ -58,12 +57,17 @@ export const PricingCard: React.FC<PricingCardProps> = ({
5857
activeTrialEndsAt,
5958
}) => {
6059
const plan = TEAM_PLANS[billingPlan];
61-
const isCustomPrice = typeof plan.price === "string";
6260

6361
const trackEvent = useTrack();
6462
const remainingTrialDays =
6563
(activeTrialEndsAt ? remainingDays(activeTrialEndsAt) : 0) || 0;
6664

65+
// if the team has just signed up and has not subscribed yet, and the billing plan is growth, then they get a 7 day trial
66+
const has7DayTrial =
67+
remainingTrialDays === 0 &&
68+
billingStatus === "noPayment" &&
69+
billingPlan === "growth";
70+
6771
const handleCTAClick = () => {
6872
cta?.onClick?.();
6973
trackEvent({
@@ -97,6 +101,7 @@ export const PricingCard: React.FC<PricingCardProps> = ({
97101
{plan.title}
98102
</h3>
99103
{current && <Badge className="capitalize">Current plan</Badge>}
104+
{has7DayTrial && <Badge variant="success">7 Day Free Trial</Badge>}
100105
</div>
101106
<p className="max-w-[320px] text-muted-foreground text-sm">
102107
{plan.description}
@@ -108,15 +113,23 @@ export const PricingCard: React.FC<PricingCardProps> = ({
108113
{plan.isStartingPriceOnly && (
109114
<span className="text-muted-foreground text-xs">Starting at</span>
110115
)}
111-
<div className="flex items-center gap-2">
112-
<span className="font-semibold text-2xl text-foreground tracking-tight">
113-
${plan.price.toLocaleString()}
114-
</span>
115-
116-
{!isCustomPrice && (
116+
{has7DayTrial ? (
117+
<div className="flex flex-col items-start gap-0">
118+
<span className="font-bold text-2xl text-foreground tracking-tight">
119+
7 days free
120+
</span>
121+
<span className="text-muted-foreground text-sm">
122+
Then ${plan.price.toLocaleString()} / month
123+
</span>
124+
</div>
125+
) : (
126+
<div className="flex items-center gap-2">
127+
<span className="font-semibold text-2xl text-foreground tracking-tight">
128+
${plan.price.toLocaleString()}
129+
</span>
117130
<span className="text-muted-foreground">/ month</span>
118-
)}
119-
</div>
131+
</div>
132+
)}
120133

121134
{remainingTrialDays > 0 && (
122135
<p className="text-muted-foreground text-sm">
@@ -155,7 +168,7 @@ export const PricingCard: React.FC<PricingCardProps> = ({
155168
teamSlug={teamSlug}
156169
sku={billingPlanToSkuMap[billingPlan]}
157170
>
158-
{cta.label}
171+
{has7DayTrial ? "Start 7 Day Free Trial" : cta.label}
159172
</CheckoutButton>
160173
)}
161174

@@ -166,7 +179,7 @@ export const PricingCard: React.FC<PricingCardProps> = ({
166179
asChild
167180
>
168181
<Link href={cta.href} target="_blank" onClick={handleCTAClick}>
169-
{cta.label}
182+
{has7DayTrial ? "Start 7 Day Free Trial" : cta.label}
170183
</Link>
171184
</Button>
172185
)}

apps/dashboard/src/app/(app)/login/onboarding/team-onboarding/InviteTeamMembers.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ export function InviteTeamMembersUI(props: {
4949
await pollWithTimeout({
5050
shouldStop: async () => {
5151
const team = await props.getTeam();
52-
const isNonFreePlan = team.billingPlan !== "free";
52+
const isNonFreePlan =
53+
team.billingPlan !== "free" && team.billingPlan !== "starter";
5354

5455
if (isNonFreePlan) {
5556
props.trackEvent({
@@ -233,8 +234,8 @@ function InviteModalContent(props: {
233234
Choose a plan
234235
</SheetTitle>
235236
<SheetDescription className="text-left leading-relaxed">
236-
Get started with the free Starter plan or upgrade to Growth plan for
237-
increased limits and advanced features.{" "}
237+
Upgrade to the Growth plan to unlock team members and advanced
238+
features.{" "}
238239
<UnderlineLink href="https://thirdweb.com/pricing" target="_blank">
239240
Learn more about pricing
240241
</UnderlineLink>

apps/dashboard/src/utils/pricing.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const TEAM_PLANS: Record<
1111
{
1212
title: string;
1313
isStartingPriceOnly?: boolean;
14-
price: string | number;
14+
price: number;
1515
subTitle: string | null;
1616
trialPeriodDays: number;
1717
description: string;

0 commit comments

Comments
 (0)