Skip to content

Commit 41e2ccb

Browse files
committed
Add isLegacyPlan flag to Team type and UI components
1 parent 68a1dca commit 41e2ccb

File tree

31 files changed

+121
-26
lines changed

31 files changed

+121
-26
lines changed

apps/dashboard/src/@/api/team/get-team.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "@/constants/public-envs";
88
import { API_SERVER_SECRET } from "@/constants/server-envs";
99
import { getMemberByAccountId } from "./team-members";
1010

11-
export type Team = TeamResponse & { stripeCustomerId: string | null };
11+
export type Team = TeamResponse & {
12+
stripeCustomerId: string | null;
13+
isLegacyPlan: boolean;
14+
};
1215

1316
export async function getTeamBySlug(slug: string) {
1417
const token = await getAuthToken();

apps/dashboard/src/@/components/blocks/GatedSwitch.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ function Variants() {
7070
key={currentPlan}
7171
requiredPlan={requiredPlan}
7272
teamSlug="foo"
73+
isLegacyPlan={false}
7374
/>
7475
</BadgeContainer>
7576
))}

apps/dashboard/src/@/components/blocks/GatedSwitch.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type GatedSwitchProps = {
1414
trackingLabel?: string;
1515
currentPlan: Team["billingPlan"];
1616
requiredPlan: Team["billingPlan"];
17+
isLegacyPlan: boolean;
1718
teamSlug: string;
1819
switchProps?: SwitchProps;
1920
};
@@ -33,7 +34,7 @@ export const GatedSwitch: React.FC<GatedSwitchProps> = (
3334
<div className="w-full min-w-[280px]">
3435
<h3 className="font-medium text-base">
3536
<span className="capitalize">
36-
{getTeamPlanBadgeLabel(props.requiredPlan)}+
37+
{getTeamPlanBadgeLabel(props.requiredPlan, false)}+
3738
</span>{" "}
3839
plan required
3940
</h3>
@@ -48,7 +49,8 @@ export const GatedSwitch: React.FC<GatedSwitchProps> = (
4849
rel="noopener noreferrer"
4950
target="_blank"
5051
>
51-
Upgrade to {getTeamPlanBadgeLabel(props.requiredPlan)} plan
52+
Upgrade to {getTeamPlanBadgeLabel(props.requiredPlan, false)}{" "}
53+
plan
5254
<ExternalLinkIcon className="size-4" />
5355
</Link>
5456
</Button>
@@ -61,6 +63,7 @@ export const GatedSwitch: React.FC<GatedSwitchProps> = (
6163
{isUpgradeRequired && (
6264
<TeamPlanBadge
6365
plan={props.requiredPlan}
66+
isLegacyPlan={props.isLegacyPlan}
6467
postfix="+"
6568
teamSlug={props.teamSlug}
6669
/>

apps/dashboard/src/@/components/blocks/TeamPlanBadge.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,42 @@ const teamPlanToBadgeVariant: Record<
2323
starter: "warning",
2424
};
2525

26-
export function getTeamPlanBadgeLabel(plan: Team["billingPlan"]) {
26+
export function getTeamPlanBadgeLabel(
27+
plan: Team["billingPlan"],
28+
isLegacyPlan: boolean,
29+
) {
2730
if (plan === "growth_legacy") {
2831
return "Growth - Legacy";
2932
}
3033

34+
if (isLegacyPlan) {
35+
return `${plan} - Legacy`;
36+
}
37+
3138
return plan;
3239
}
3340

3441
export function TeamPlanBadge(props: {
3542
teamSlug: string;
3643
plan: Team["billingPlan"];
44+
isLegacyPlan: boolean;
3745
className?: string;
3846
postfix?: string;
3947
}) {
4048
const router = useDashboardRouter();
4149

4250
function handleNavigateToBilling(e: React.MouseEvent | React.KeyboardEvent) {
51+
e.stopPropagation();
52+
e.preventDefault();
53+
54+
if (props.isLegacyPlan) {
55+
router.push(`/team/${props.teamSlug}/~/billing`);
56+
return;
57+
}
58+
4359
if (props.plan !== "free") {
4460
return;
4561
}
46-
e.stopPropagation();
47-
e.preventDefault();
4862
router.push(`/team/${props.teamSlug}/~/billing?showPlans=true`);
4963
}
5064

@@ -57,11 +71,13 @@ export function TeamPlanBadge(props: {
5771
handleNavigateToBilling(e);
5872
}
5973
}}
60-
role={props.plan === "free" ? "button" : undefined}
61-
tabIndex={props.plan === "free" ? 0 : undefined}
62-
variant={teamPlanToBadgeVariant[props.plan]}
74+
role={props.plan === "free" || props.isLegacyPlan ? "button" : undefined}
75+
tabIndex={props.plan === "free" || props.isLegacyPlan ? 0 : undefined}
76+
variant={
77+
props.isLegacyPlan ? "warning" : teamPlanToBadgeVariant[props.plan]
78+
}
6379
>
64-
{`${getTeamPlanBadgeLabel(props.plan)}${props.postfix || ""}`}
80+
{`${getTeamPlanBadgeLabel(props.plan, props.isLegacyPlan)}${props.postfix || ""}`}
6581
</Badge>
6682
);
6783
}

apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface UpsellWrapperProps {
2222
isLocked?: boolean;
2323
requiredPlan: Team["billingPlan"];
2424
currentPlan?: Team["billingPlan"];
25+
isLegacyPlan?: boolean;
2526
featureName: string;
2627
featureDescription: string;
2728
benefits?: {
@@ -41,6 +42,7 @@ export function UpsellWrapper({
4142
featureDescription,
4243
benefits = [],
4344
className,
45+
isLegacyPlan = false,
4446
}: UpsellWrapperProps) {
4547
if (!isLocked) {
4648
return <>{children}</>;
@@ -66,6 +68,7 @@ export function UpsellWrapper({
6668
featureDescription={featureDescription}
6769
featureName={featureName}
6870
requiredPlan={requiredPlan}
71+
isLegacyPlan={isLegacyPlan}
6972
teamSlug={teamSlug}
7073
/>
7174
</div>
@@ -79,6 +82,7 @@ export function UpsellContent(props: {
7982
featureDescription: string;
8083
requiredPlan: Team["billingPlan"];
8184
currentPlan: Team["billingPlan"];
85+
isLegacyPlan: boolean;
8286
benefits?: {
8387
description: string;
8488
status: "available" | "soon";
@@ -96,6 +100,7 @@ export function UpsellContent(props: {
96100
plan={props.requiredPlan}
97101
postfix=" Feature"
98102
teamSlug={props.teamSlug}
103+
isLegacyPlan={props.isLegacyPlan}
99104
/>
100105
<div className="space-y-1">
101106
<CardTitle className="font-bold text-2xl text-foreground md:text-3xl">

apps/dashboard/src/@/storybook/stubs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export function teamStub(id: string, billingPlan: Team["billingPlan"]): Team {
3030
billingPlan: billingPlan,
3131
billingStatus: "validPayment",
3232
canCreatePublicChains: null,
33+
isLegacyPlan: false,
3334
capabilities: {
3435
bundler: {
3536
enabled: true,

apps/dashboard/src/app/(app)/account/overview/AccountTeamsUI.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
DropdownMenuTrigger,
1919
} from "@/components/ui/dropdown-menu";
2020
import { useDashboardRouter } from "@/lib/DashboardRouter";
21-
import { getValidTeamPlan } from "@/utils/getValidTeamPlan";
2221
import { SearchInput } from "../components/SearchInput";
2322

2423
export function AccountTeamsUI(props: {
@@ -117,8 +116,6 @@ function TeamRow(props: {
117116
role: TeamAccountRole;
118117
client: ThirdwebClient;
119118
}) {
120-
const plan = getValidTeamPlan(props.team);
121-
122119
return (
123120
<div className="flex items-center justify-between gap-2">
124121
{/* start */}
@@ -133,7 +130,11 @@ function TeamRow(props: {
133130
<div>
134131
<div className="flex items-center gap-3">
135132
<p className="font-semibold text-sm">{props.team.name}</p>
136-
<TeamPlanBadge plan={plan} teamSlug={props.team.slug} />
133+
<TeamPlanBadge
134+
plan={props.team.billingPlan}
135+
teamSlug={props.team.slug}
136+
isLegacyPlan={props.team.isLegacyPlan}
137+
/>
137138
</div>
138139
<p className="text-muted-foreground text-sm capitalize">
139140
{props.role.toLowerCase()}

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/billing/components/PlanInfoCard.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,24 @@ export function PlanInfoCardUI(props: {
7373
<h3 className="font-semibold text-2xl capitalize tracking-tight">
7474
{validPlan === "growth_legacy" ? "Growth" : validPlan} Plan
7575
</h3>
76-
{validPlan.includes("legacy") && (
76+
{props.team.isLegacyPlan && (
7777
<Badge variant="warning">Legacy</Badge>
7878
)}
7979
{trialEndsInFuture && <Badge variant="default">Trial</Badge>}
8080
</div>
8181

82-
{validPlan.includes("legacy") && (
82+
{props.team.isLegacyPlan && (
8383
<p className="text-sm text-yellow-600">
84-
You are on the legacy plan. You may save by upgrading to new
85-
plan.{" "}
84+
Legacy plans will be upgraded to new plans automatically on
85+
January 1st, 2026.
86+
<br />
8687
<UnderlineLink
8788
className="decoration-yellow-600/50"
88-
href="/pricing"
89+
href="https://blog.thirdweb.com/retiring-legacy-pricing-plans-on-january-1st-2026"
90+
rel="noopener noreferrer"
91+
target="_blank"
8992
>
90-
Learn More
93+
Learn more about changes to legacy plans
9194
</UnderlineLink>
9295
</p>
9396
)}

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default async function Page(props: {
2828
<div className="flex flex-col grow justify-center items-center">
2929
<UpsellContent
3030
currentPlan={team.billingPlan}
31+
isLegacyPlan={team.isLegacyPlan}
3132
featureDescription="Create support cases for your projects"
3233
featureName="Support Center"
3334
requiredPlan="starter"

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default async function Page(props: {
4343
<div className="grow flex flex-col justify-center items-center">
4444
<UpsellContent
4545
currentPlan={team.billingPlan}
46+
isLegacyPlan={team.isLegacyPlan}
4647
featureDescription="View RPC, Wallet, Storage, Gas Sponsorship, Engine Cloud, Webhooks usage and more"
4748
featureName="Usage"
4849
requiredPlan="starter"

0 commit comments

Comments
 (0)