Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b52049c

Browse files
committed
[Dashboard] Improve team overview page load perf + UI adjustments (thirdweb-dev#5475)
Move the chart data fetching inside suspense boundary with loading fallback to speed up page load <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on improving the layout and structure of several components in the dashboard, enhancing the user interface by adjusting styles and adding new features like loading states. It also refines the `TeamOverviewPage` to better handle data and display. ### Detailed summary - Updated styles in `range-selector.tsx` for improved layout. - Added `w-full` class in `EmptyState.tsx` for full-width section. - Adjusted gap sizes in `AnalyticsHeader.tsx`. - Modified `TeamOverviewPage` to include a loading state using `Suspense`. - Introduced `OverviewPageContent` function to manage content rendering. - Enhanced conditionals to simplify rendering logic in `TeamOverviewPage`. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent a67e980 commit b52049c

File tree

4 files changed

+103
-80
lines changed

4 files changed

+103
-80
lines changed

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

Lines changed: 97 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,28 @@ import { EmptyState } from "../../components/Analytics/EmptyState";
2525
import { PieChartCard } from "../../components/Analytics/PieChartCard";
2626

2727
import { getTeamBySlug } from "@/api/team";
28+
import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage";
29+
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
2830
import { getAccount } from "app/account/settings/getAccount";
2931
import { EmptyStateCard } from "app/team/components/Analytics/EmptyStateCard";
3032
import { Changelog, type ChangelogItem } from "components/dashboard/Changelog";
33+
import { Suspense } from "react";
3134
import { TotalSponsoredChartCardUI } from "./_components/TotalSponsoredCard";
3235

3336
// revalidate every 5 minutes
3437
export const revalidate = 300;
3538

39+
type SearchParams = {
40+
usersChart?: string;
41+
from?: string;
42+
to?: string;
43+
type?: string;
44+
interval?: string;
45+
};
46+
3647
export default async function TeamOverviewPage(props: {
37-
params: { team_slug: string };
38-
searchParams: {
39-
usersChart?: string;
40-
from?: string;
41-
to?: string;
42-
type?: string;
43-
interval?: string;
44-
};
48+
params: Promise<{ team_slug: string }>;
49+
searchParams: Promise<SearchParams>;
4550
}) {
4651
const changelog = await getChangelog();
4752
const [params, searchParams] = await Promise.all([
@@ -67,6 +72,43 @@ export default async function TeamOverviewPage(props: {
6772
redirect("/login");
6873
}
6974

75+
return (
76+
<div className="flex grow flex-col">
77+
<div className="border-b">
78+
<AnalyticsHeader
79+
title="Team Overview"
80+
interval={interval}
81+
range={range}
82+
/>
83+
</div>
84+
<div className="flex grow flex-col justify-between gap-10 md:container md:pt-8 md:pb-16 xl:flex-row">
85+
<Suspense fallback={<GenericLoadingPage />}>
86+
<OverviewPageContent
87+
account={account}
88+
range={range}
89+
interval={interval}
90+
searchParams={searchParams}
91+
/>
92+
</Suspense>
93+
<div className="shrink-0 max-md:container max-xl:hidden lg:w-[320px]">
94+
<h2 className="mb-4 font-semibold text-lg tracking-tight">
95+
Latest changes
96+
</h2>
97+
<Changelog changelog={changelog} />
98+
</div>
99+
</div>
100+
</div>
101+
);
102+
}
103+
104+
async function OverviewPageContent(props: {
105+
account: Account;
106+
range: Range;
107+
interval: "day" | "week";
108+
searchParams: SearchParams;
109+
}) {
110+
const { account, range, interval, searchParams } = props;
111+
70112
const [
71113
walletConnections,
72114
walletUserStatsTimeSeries,
@@ -116,77 +158,56 @@ export default async function TeamOverviewPage(props: {
116158
inAppWalletUsage.length === 0 &&
117159
userOpUsage.length === 0;
118160

161+
if (isEmpty) {
162+
return <EmptyState />;
163+
}
164+
119165
return (
120-
<div>
121-
<div className="w-full border-border-800 border-b px-6 dark:bg-muted/50">
122-
<AnalyticsHeader
123-
title="Team Overview"
124-
interval={interval}
125-
range={range}
126-
/>
127-
</div>
128-
<div className="flex flex-col justify-between gap-16 md:container md:pt-8 md:pb-16 xl:flex-row">
129-
<div className="grow">
130-
{isEmpty ? (
131-
<div className="container p-6">
132-
<EmptyState />
133-
</div>
134-
) : (
135-
<div className="space-y-6">
136-
{walletUserStatsTimeSeries.some((w) => w.totalUsers !== 0) ? (
137-
<div className="">
138-
<UsersChartCard
139-
userStats={walletUserStatsTimeSeries}
140-
searchParams={searchParams}
141-
/>
142-
</div>
143-
) : (
144-
<EmptyStateCard
145-
metric="Connect"
146-
link="https://portal.thirdweb.com/connect/quickstart"
147-
/>
148-
)}
149-
<div className="grid gap-6 max-md:px-6 md:grid-cols-2">
150-
{walletConnections.length > 0 ? (
151-
<WalletDistributionCard data={walletConnections} />
152-
) : (
153-
<EmptyStateCard
154-
metric="Connect"
155-
link="https://portal.thirdweb.com/connect/quickstart"
156-
/>
157-
)}
158-
{inAppWalletUsage.length > 0 ? (
159-
<AuthMethodDistributionCard data={inAppWalletUsage} />
160-
) : (
161-
<EmptyStateCard
162-
metric="In-App Wallets"
163-
link="https://portal.thirdweb.com/typescript/v5/inAppWallet"
164-
/>
165-
)}
166-
</div>
167-
{userOpUsage.length > 0 ? (
168-
<TotalSponsoredChartCardUI
169-
searchParams={searchParams}
170-
data={userOpUsageTimeSeries}
171-
aggregatedData={userOpUsage}
172-
className="max-md:rounded-none max-md:border-r-0 max-md:border-l-0"
173-
/>
174-
) : (
175-
<EmptyStateCard
176-
metric="Sponsored Transactions"
177-
link="https://portal.thirdweb.com/typescript/v5/account-abstraction/get-started"
178-
/>
179-
)}
180-
</div>
181-
)}
182-
</div>
183-
<div className="shrink-0 max-md:container max-xl:hidden lg:w-[320px]">
184-
<h2 className="mb-4 font-semibold text-lg tracking-tight">
185-
Latest changes
186-
</h2>
187-
<Changelog changelog={changelog} />
166+
<div className="flex grow flex-col gap-6">
167+
{walletUserStatsTimeSeries.some((w) => w.totalUsers !== 0) ? (
168+
<div className="">
169+
<UsersChartCard
170+
userStats={walletUserStatsTimeSeries}
171+
searchParams={searchParams}
172+
/>
188173
</div>
174+
) : (
175+
<EmptyStateCard
176+
metric="Connect"
177+
link="https://portal.thirdweb.com/connect/quickstart"
178+
/>
179+
)}
180+
<div className="grid gap-6 max-md:px-6 md:grid-cols-2">
181+
{walletConnections.length > 0 ? (
182+
<WalletDistributionCard data={walletConnections} />
183+
) : (
184+
<EmptyStateCard
185+
metric="Connect"
186+
link="https://portal.thirdweb.com/connect/quickstart"
187+
/>
188+
)}
189+
{inAppWalletUsage.length > 0 ? (
190+
<AuthMethodDistributionCard data={inAppWalletUsage} />
191+
) : (
192+
<EmptyStateCard
193+
metric="In-App Wallets"
194+
link="https://portal.thirdweb.com/typescript/v5/inAppWallet"
195+
/>
196+
)}
189197
</div>
198+
{userOpUsage.length > 0 ? (
199+
<TotalSponsoredChartCardUI
200+
searchParams={searchParams}
201+
data={userOpUsageTimeSeries}
202+
aggregatedData={userOpUsage}
203+
className="max-md:rounded-none max-md:border-r-0 max-md:border-l-0"
204+
/>
205+
) : (
206+
<EmptyStateCard
207+
metric="Sponsored Transactions"
208+
link="https://portal.thirdweb.com/typescript/v5/account-abstraction/get-started"
209+
/>
210+
)}
190211
</div>
191212
);
192213
}

apps/dashboard/src/app/team/components/Analytics/AnalyticsHeader.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ export function AnalyticsHeader(props: {
99
const { title, interval, range } = props;
1010

1111
return (
12-
<div className="container flex flex-col items-start gap-6 px-2 py-6 md:h-[120px] md:flex-row md:items-center md:p-6 md:py-0">
12+
<div className="container flex flex-col items-start gap-3 py-10 md:flex-row md:items-center">
1313
<div className="flex-1">
14-
<h1 className="font-semibold text-3xl text-foreground">{title}</h1>
14+
<h1 className="font-semibold text-2xl tracking-tight md:text-3xl">
15+
{title}
16+
</h1>
1517
</div>
1618
<RangeSelector interval={interval} range={range} />
1719
</div>

apps/dashboard/src/app/team/components/Analytics/EmptyState.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import walletsIcon from "../../../../../public/assets/tw-icons/wallets.svg";
1717

1818
export function EmptyState() {
1919
return (
20-
<section className="flex items-start justify-center md:min-h-[500px]">
20+
<section className="flex w-full items-start justify-center md:min-h-[500px]">
2121
<div className="group container flex flex-col items-center justify-center gap-8 rounded-lg border bg-card p-6 py-24">
2222
<div className="flex max-w-[500px] flex-col items-center justify-center gap-6">
2323
<AnimatedIcons />

apps/dashboard/src/components/analytics/range-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function RangeSelector({
7373
});
7474

7575
return (
76-
<div className="flex flex-col justify-end gap-3 sm:flex-row">
76+
<div className="flex justify-end gap-4">
7777
<DateRangeSelector
7878
range={localRange}
7979
setRange={(newRange) => {

0 commit comments

Comments
 (0)