@@ -3,33 +3,35 @@ import type { Team } from "@/api/team";
33import { Badge } from "@/components/ui/badge" ;
44import { Button } from "@/components/ui/button" ;
55import { ToolTipLabel } from "@/components/ui/tooltip" ;
6- import { TrackedLinkTW } from "@/components/ui/tracked-link" ;
76import { cn } from "@/lib/utils" ;
8- import { CheckIcon , CircleAlertIcon , CircleDollarSignIcon } from "lucide-react" ;
7+ import { CheckIcon , CircleDollarSignIcon } from "lucide-react" ;
8+ import Link from "next/link" ;
99import type React from "react" ;
1010import { TEAM_PLANS } from "utils/pricing" ;
11+ import { useTrack } from "../../../hooks/analytics/useTrack" ;
1112import { remainingDays } from "../../../utils/date-utils" ;
1213import type { GetBillingCheckoutUrlAction } from "../../actions/billing" ;
14+ import type { ProductSKU } from "../../lib/billing" ;
1315import { CheckoutButton } from "../billing" ;
1416
15- type ButtonProps = React . ComponentProps < typeof Button > ;
16-
17- const PRO_CONTACT_US_URL =
18- "https://meetings.hubspot.com/sales-thirdweb/thirdweb-pro" ;
17+ type PricingCardCta = {
18+ hint ?: string ;
19+ title : string ;
20+ onClick ?: ( ) => void ;
21+ } & (
22+ | {
23+ type : "link" ;
24+ href : string ;
25+ }
26+ | {
27+ type : "checkout" ;
28+ }
29+ ) ;
1930
2031type PricingCardProps = {
2132 teamSlug : string ;
22- billingPlan : Exclude < Team [ "billingPlan" ] , "free" > ;
23- cta ?: {
24- hint ?: string ;
25- title : string ;
26- tracking : {
27- category : string ;
28- label ?: string ;
29- } ;
30- variant ?: ButtonProps [ "variant" ] ;
31- onClick ?: ( ) => void ;
32- } ;
33+ billingPlan : keyof typeof TEAM_PLANS ;
34+ cta ?: PricingCardCta ;
3335 ctaHint ?: string ;
3436 highlighted ?: boolean ;
3537 current ?: boolean ;
@@ -49,13 +51,23 @@ export const PricingCard: React.FC<PricingCardProps> = ({
4951 const plan = TEAM_PLANS [ billingPlan ] ;
5052 const isCustomPrice = typeof plan . price === "string" ;
5153
54+ const trackEvent = useTrack ( ) ;
5255 const remainingTrialDays =
5356 ( activeTrialEndsAt ? remainingDays ( activeTrialEndsAt ) : 0 ) || 0 ;
5457
58+ const handleCTAClick = ( ) => {
59+ cta ?. onClick ?.( ) ;
60+ trackEvent ( {
61+ category : "account" ,
62+ label : `${ billingPlan } Plan` ,
63+ action : "click" ,
64+ } ) ;
65+ } ;
66+
5567 return (
5668 < div
5769 className = { cn (
58- "z-10 flex w-full flex-col gap-6 rounded-xl border border-border bg-card p-4 md:p-6 " ,
70+ "z-10 flex w-full flex-col gap-4 rounded-xl border border-border bg-card p-4" ,
5971 current && "border-blue-500" ,
6072 highlighted && "border-active-border" ,
6173 ) }
@@ -71,44 +83,27 @@ export const PricingCard: React.FC<PricingCardProps> = ({
7183 < div className = "flex flex-col gap-5" >
7284 { /* Title + Desc */ }
7385 < div >
74- < div className = "mb-2 flex flex-row items-center gap-2 " >
86+ < div className = "mb-1 flex flex-row items-center gap-3 " >
7587 < h3 className = "font-semibold text-2xl capitalize tracking-tight" >
7688 { plan . title }
7789 </ h3 >
7890 { current && < Badge className = "capitalize" > Current plan</ Badge > }
7991 </ div >
80- < p className = "max-w-[320px] text-muted-foreground" >
92+ < p className = "max-w-[320px] text-muted-foreground text-sm " >
8193 { plan . description }
8294 </ p >
8395 </ div >
8496
8597 { /* Price */ }
8698 < div className = "flex flex-col gap-0.5" >
8799 < div className = "flex items-center gap-2" >
88- < span className = "font-semibold text-3xl text-foreground tracking-tight" >
100+ < span className = "font-semibold text-2xl text-foreground tracking-tight" >
89101 ${ plan . price }
90102 </ span >
91103
92104 { ! isCustomPrice && (
93105 < span className = "text-muted-foreground" > / month</ span >
94106 ) }
95-
96- { billingPlan === "starter" && (
97- < ToolTipLabel
98- contentClassName = "max-w-[320px]"
99- label = "We will place a temporary hold of $25 to verify your card, this will be immediately released back to you after verification."
100- >
101- < Button
102- asChild
103- variant = "ghost"
104- className = "h-auto w-auto p-1 text-muted-foreground hover:text-foreground"
105- >
106- < div >
107- < CircleAlertIcon className = "size-5 shrink-0" />
108- </ div >
109- </ Button >
110- </ ToolTipLabel >
111- ) }
112107 </ div >
113108
114109 { remainingTrialDays > 0 && (
@@ -124,7 +119,7 @@ export const PricingCard: React.FC<PricingCardProps> = ({
124119
125120 < div className = "flex grow flex-col items-start gap-2 text-foreground" >
126121 { plan . subTitle && (
127- < p className = "font-medium text-foreground" > { plan . subTitle } </ p >
122+ < p className = "font-medium text-foreground text-sm " > { plan . subTitle } </ p >
128123 ) }
129124
130125 { plan . features . map ( ( f ) => (
@@ -134,29 +129,30 @@ export const PricingCard: React.FC<PricingCardProps> = ({
134129
135130 { cta && (
136131 < div className = "flex flex-col gap-3" >
137- { billingPlan !== "pro" ? (
132+ { billingPlanToSkuMap [ billingPlan ] && cta . type === "checkout" && (
138133 < CheckoutButton
139134 buttonProps = { {
140- variant : cta . variant || "outline" ,
141- className : "gap-2 ",
142- onClick : cta . onClick ,
135+ variant : highlighted ? "default" : "outline" ,
136+ className : highlighted ? undefined : "bg-background ",
137+ onClick : handleCTAClick ,
143138 } }
144139 teamSlug = { teamSlug }
145- sku = { billingPlan === "starter" ? "plan:starter" : "plan:growth" }
140+ sku = { billingPlanToSkuMap [ billingPlan ] }
146141 getBillingCheckoutUrl = { getBillingCheckoutUrl }
147142 >
148143 { cta . title }
149144 </ CheckoutButton >
150- ) : (
151- < Button variant = { cta . variant || "outline" } asChild >
152- < TrackedLinkTW
153- href = { PRO_CONTACT_US_URL }
154- label = { cta . tracking ?. label }
155- category = { cta . tracking ?. category }
156- target = "_blank"
157- >
145+ ) }
146+
147+ { cta . type === "link" && (
148+ < Button
149+ variant = { highlighted ? "default" : "outline" }
150+ className = { highlighted ? undefined : "bg-background" }
151+ asChild
152+ >
153+ < Link href = { cta . href } target = "_blank" onClick = { handleCTAClick } >
158154 { cta . title }
159- </ TrackedLinkTW >
155+ </ Link >
160156 </ Button >
161157 ) }
162158
@@ -171,6 +167,19 @@ export const PricingCard: React.FC<PricingCardProps> = ({
171167 ) ;
172168} ;
173169
170+ const billingPlanToSkuMap : Record < Team [ "billingPlan" ] , ProductSKU | undefined > =
171+ {
172+ starter : "plan:starter" ,
173+ growth : "plan:growth" ,
174+ accelerate : "plan:accelerate" ,
175+ scale : "plan:scale" ,
176+ // we can't render checkout buttons for these plans:
177+ pro : undefined ,
178+ free : undefined ,
179+ growth_legacy : undefined ,
180+ starter_legacy : undefined ,
181+ } ;
182+
174183type FeatureItemProps = {
175184 text : string | string [ ] ;
176185} ;
0 commit comments