Skip to content

Commit de05e07

Browse files
committed
dynamic default billing tab based on totalLinks
1 parent b9e01e0 commit de05e07

2 files changed

Lines changed: 76 additions & 28 deletions

File tree

apps/web/app/app.dub.co/(dashboard)/[slug]/settings/billing/plan-usage.tsx

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default function PlanUsage() {
4343
salesLimit,
4444
linksUsage,
4545
linksLimit,
46+
totalLinks,
4647
domains,
4748
domainsLimit,
4849
foldersUsage,
@@ -84,6 +85,52 @@ export default function PlanUsage() {
8485
return [];
8586
}, [billingCycleStart]);
8687

88+
const usageTabs = useMemo(() => {
89+
const tabs = [
90+
{
91+
id: "events",
92+
icon: CursorRays,
93+
title: "Events tracked",
94+
usage: usage,
95+
limit: usageLimit,
96+
},
97+
{
98+
id: "links",
99+
icon: Hyperlink,
100+
title: "Links created",
101+
usage: linksUsage,
102+
limit: linksLimit,
103+
},
104+
{
105+
id: "revenue",
106+
icon: CircleDollar,
107+
title: "Revenue tracked",
108+
usage: salesUsage,
109+
limit: salesLimit,
110+
unit: "$",
111+
requiresUpgrade: plan === "free" || plan === "pro",
112+
},
113+
];
114+
if (totalLinks && totalLinks > 100_000) {
115+
// Find the links tab and move it to the first position
116+
const linksTabIndex = tabs.findIndex((tab) => tab.id === "links");
117+
if (linksTabIndex !== -1) {
118+
const linksTab = tabs.splice(linksTabIndex, 1)[0];
119+
tabs.unshift(linksTab);
120+
}
121+
}
122+
return tabs;
123+
}, [
124+
plan,
125+
usage,
126+
usageLimit,
127+
linksUsage,
128+
linksLimit,
129+
totalLinks,
130+
salesUsage,
131+
salesLimit,
132+
]);
133+
87134
return (
88135
<div className="rounded-lg border border-neutral-200 bg-white">
89136
<div className="flex flex-col items-start justify-between gap-y-4 p-6 md:px-8 lg:flex-row">
@@ -127,29 +174,9 @@ export default function PlanUsage() {
127174
<div className="grid grid-cols-[minmax(0,1fr)] divide-y divide-neutral-200 border-t border-neutral-200">
128175
<div>
129176
<div className="grid gap-4 p-6 sm:grid-cols-3 md:p-8 lg:gap-6">
130-
<UsageTabCard
131-
id="events"
132-
icon={CursorRays}
133-
title="Events tracked"
134-
usage={usage}
135-
limit={usageLimit}
136-
/>
137-
<UsageTabCard
138-
id="links"
139-
icon={Hyperlink}
140-
title="Links created"
141-
usage={linksUsage}
142-
limit={linksLimit}
143-
/>
144-
<UsageTabCard
145-
id="revenue"
146-
icon={CircleDollar}
147-
title="Revenue tracked"
148-
usage={salesUsage}
149-
limit={salesLimit}
150-
unit="$"
151-
requiresUpgrade={plan === "free" || plan === "pro"}
152-
/>
177+
{usageTabs.map((tab) => (
178+
<UsageTabCard key={tab.id} {...tab} />
179+
))}
153180
</div>
154181
<div className="w-full px-2 pb-8 md:px-8">
155182
<UsageChart />
@@ -244,11 +271,22 @@ function UsageTabCard({
244271
requiresUpgrade?: boolean;
245272
}) {
246273
const { searchParams, queryParams } = useRouterStuff();
247-
const { slug } = useWorkspace();
274+
const { slug, totalLinks } = useWorkspace();
248275

249-
const isActive =
250-
searchParams.get("tab") === id ||
251-
(!searchParams.get("tab") && id === "events");
276+
const defaultActiveTab = useMemo(() => {
277+
if (totalLinks && totalLinks > 100_000) {
278+
return "links";
279+
}
280+
return "events";
281+
}, [totalLinks]);
282+
283+
const isActive = useMemo(() => {
284+
if (searchParams.get("tab")) {
285+
return searchParams.get("tab") === id;
286+
} else {
287+
return id === defaultActiveTab;
288+
}
289+
}, [searchParams, id, defaultActiveTab]);
252290

253291
const [usage, limit] =
254292
unit === "$" && usageProp !== undefined && limitProp !== undefined

apps/web/app/app.dub.co/(dashboard)/[slug]/settings/billing/usage-chart.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import useUsage from "@/lib/swr/use-usage";
2+
import useWorkspace from "@/lib/swr/use-workspace";
23
import { EmptyState, LoadingSpinner } from "@dub/ui";
34
import { Bars, TimeSeriesChart, XAxis, YAxis } from "@dub/ui/charts";
45
import { CircleDollar, CursorRays, Hyperlink } from "@dub/ui/icons";
@@ -32,8 +33,17 @@ const resourceEmptyStates: Record<
3233

3334
export function UsageChart() {
3435
const searchParams = useSearchParams();
36+
const { totalLinks } = useWorkspace();
37+
38+
const defaultActiveTab = useMemo(() => {
39+
if (totalLinks && totalLinks > 100_000) {
40+
return "links";
41+
}
42+
return "events";
43+
}, [totalLinks]);
44+
3545
const resource =
36-
RESOURCES.find((r) => r === searchParams.get("tab")) ?? "events";
46+
RESOURCES.find((r) => r === searchParams.get("tab")) ?? defaultActiveTab;
3747

3848
const { usage, loading } = useUsage({ resource });
3949

0 commit comments

Comments
 (0)