Skip to content

Commit e2fec1d

Browse files
committed
Dashboard: Migrate contract overview page components to tailwind/shadcn #1
1 parent f2abc8b commit e2fec1d

File tree

14 files changed

+554
-683
lines changed

14 files changed

+554
-683
lines changed

apps/dashboard/src/@/components/blocks/charts/area-chart.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type ThirdwebAreaChartProps<TConfig extends ChartConfig> = {
3030
description?: string;
3131
titleClassName?: string;
3232
};
33+
customHeader?: React.ReactNode;
3334
// chart config
3435
config: TConfig;
3536
data: Array<Record<keyof TConfig, number> & { time: number | string | Date }>;
@@ -60,6 +61,8 @@ export function ThirdwebAreaChart<TConfig extends ChartConfig>(
6061
</CardHeader>
6162
)}
6263

64+
{props.customHeader && props.customHeader}
65+
6366
<CardContent className={cn(!props.header && "pt-6")}>
6467
<ChartContainer config={props.config} className={props.chartClassName}>
6568
{props.isPending ? (

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/ContractOverviewPage.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import type { ThirdwebContract } from "thirdweb";
2-
import { AnalyticsOverview } from "./components/Analytics";
2+
import { TokenDetailsCard } from "../tokens/components/supply";
3+
import { ContractAnalyticsOverviewCard } from "./components/Analytics";
34
import { BuildYourApp } from "./components/BuildYourApp";
45
import { ContractChecklist } from "./components/ContractChecklist";
56
import { LatestEvents } from "./components/LatestEvents";
67
import { MarketplaceDetails } from "./components/MarketplaceDetails";
78
import { NFTDetails } from "./components/NFTDetails";
89
import { PermissionsTable } from "./components/PermissionsTable";
9-
import { TokenDetails } from "./components/TokenDetails";
1010

1111
interface ContractOverviewPageProps {
1212
contract: ThirdwebContract;
@@ -39,7 +39,7 @@ export const ContractOverviewPage: React.FC<ContractOverviewPageProps> = ({
3939
}) => {
4040
return (
4141
<div className="flex flex-col gap-8 lg:flex-row">
42-
<div className="flex flex-col gap-16">
42+
<div className="flex grow flex-col gap-10">
4343
<ContractChecklist
4444
isErc721={isErc721}
4545
isErc1155={isErc1155}
@@ -50,7 +50,7 @@ export const ContractOverviewPage: React.FC<ContractOverviewPageProps> = ({
5050
/>
5151

5252
{isAnalyticsSupported && (
53-
<AnalyticsOverview
53+
<ContractAnalyticsOverviewCard
5454
contractAddress={contract.address}
5555
chainId={contract.chain.id}
5656
trackingCategory={TRACKING_CATEGORY}
@@ -77,7 +77,7 @@ export const ContractOverviewPage: React.FC<ContractOverviewPageProps> = ({
7777
/>
7878
)}
7979

80-
{isErc20 && <TokenDetails contract={contract} />}
80+
{isErc20 && <TokenDetailsCard contract={contract} />}
8181

8282
<LatestEvents
8383
contract={contract}

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx

Lines changed: 51 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,16 @@ import { ArrowRightIcon } from "lucide-react";
1212
import Link from "next/link";
1313
import { useMemo, useState } from "react";
1414

15-
interface AnalyticsOverviewProps {
16-
chainId: number;
15+
function getDayKey(date: Date) {
16+
return date.toISOString().split("T")[0];
17+
}
18+
19+
export function ContractAnalyticsOverviewCard(props: {
1720
contractAddress: string;
21+
chainId: number;
1822
trackingCategory: string;
1923
chainSlug: string;
20-
}
21-
22-
export const AnalyticsOverview: React.FC<AnalyticsOverviewProps> = ({
23-
chainId,
24-
contractAddress,
25-
trackingCategory,
26-
chainSlug,
27-
}) => {
24+
}) {
2825
const trackEvent = useTrack();
2926
const [startDate] = useState(
3027
(() => {
@@ -35,55 +32,27 @@ export const AnalyticsOverview: React.FC<AnalyticsOverviewProps> = ({
3532
);
3633
const [endDate] = useState(new Date());
3734

38-
return (
39-
<div className="relative">
40-
<div className="mb-4 flex items-center justify-between gap-4">
41-
<h2 className="font-semibold text-2xl tracking-tight">Analytics</h2>
42-
<Button
43-
asChild
44-
className="gap-1"
45-
size="sm"
46-
variant="outline"
47-
onClick={() => {
48-
trackEvent({
49-
category: trackingCategory,
50-
action: "click",
51-
label: "view_all_analytics",
52-
});
53-
}}
54-
>
55-
<Link href={`/${chainSlug}/${contractAddress}/analytics`}>
56-
<span>View All</span>
57-
<ArrowRightIcon className="size-4" />
58-
</Link>
59-
</Button>
60-
</div>
61-
62-
<OverviewAnalytics
63-
chainId={chainId}
64-
contractAddress={contractAddress}
65-
endDate={endDate}
66-
startDate={startDate}
67-
/>
68-
</div>
69-
);
70-
};
35+
const wallets = useContractUniqueWalletAnalytics({
36+
chainId: props.chainId,
37+
contractAddress: props.contractAddress,
38+
startDate,
39+
endDate,
40+
});
7141

72-
type ChartProps = {
73-
contractAddress: string;
74-
chainId: number;
75-
startDate: Date;
76-
endDate: Date;
77-
};
42+
const transactions = useContractTransactionAnalytics({
43+
chainId: props.chainId,
44+
contractAddress: props.contractAddress,
45+
startDate,
46+
endDate,
47+
});
7848

79-
function getDayKey(date: Date) {
80-
return date.toISOString().split("T")[0];
81-
}
49+
const events = useContractEventAnalytics({
50+
chainId: props.chainId,
51+
contractAddress: props.contractAddress,
52+
startDate,
53+
endDate,
54+
});
8255

83-
function OverviewAnalytics(props: ChartProps) {
84-
const wallets = useContractUniqueWalletAnalytics(props);
85-
const transactions = useContractTransactionAnalytics(props);
86-
const events = useContractEventAnalytics(props);
8756
const isPending =
8857
wallets.isPending || transactions.isPending || events.isPending;
8958

@@ -135,7 +104,32 @@ function OverviewAnalytics(props: ChartProps) {
135104
data={mergedData || []}
136105
isPending={isPending}
137106
showLegend
138-
chartClassName="aspect-[1.5] lg:aspect-[3.5]"
107+
chartClassName="aspect-[1.5] lg:aspect-[3]"
108+
customHeader={
109+
<div className="flex items-center justify-between gap-4 border-b p-6 py-4">
110+
<h2 className="font-semibold text-xl tracking-tight">Analytics</h2>
111+
<Button
112+
asChild
113+
className="gap-2 bg-background text-muted-foreground"
114+
size="sm"
115+
variant="outline"
116+
onClick={() => {
117+
trackEvent({
118+
category: props.trackingCategory,
119+
action: "click",
120+
label: "view_all_analytics",
121+
});
122+
}}
123+
>
124+
<Link
125+
href={`/${props.chainSlug}/${props.contractAddress}/analytics`}
126+
>
127+
<span>View All</span>
128+
<ArrowRightIcon className="size-4" />
129+
</Link>
130+
</Button>
131+
</div>
132+
}
139133
/>
140134
);
141135
}
Lines changed: 36 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,41 @@
1-
"use client";
1+
import { TrackedLinkTW } from "@/components/ui/tracked-link";
2+
import { ReactIcon } from "../../../../../../../components/icons/brand-icons/ReactIcon";
3+
import { TypeScriptIcon } from "../../../../../../../components/icons/brand-icons/TypeScriptIcon";
24

3-
import {
4-
Flex,
5-
GridItem,
6-
LinkBox,
7-
LinkOverlay,
8-
SimpleGrid,
9-
} from "@chakra-ui/react";
10-
import { ChakraNextImage as Image } from "components/Image";
11-
import { PRODUCTS } from "components/product-pages/common/nav/data";
12-
import { Card } from "tw-components/card";
13-
import { TrackedLink, type TrackedLinkProps } from "tw-components/link";
14-
import { Text } from "tw-components/text";
15-
16-
const RENDERED_PRODUCTS = ["sdk", "storage", "ui-components", "auth"];
17-
18-
interface BuildYourAppProps {
19-
trackingCategory: TrackedLinkProps["category"];
5+
export function BuildYourApp(props: {
6+
trackingCategory: string;
207
contractAddress: string;
218
chainSlug: string;
22-
}
23-
24-
export const BuildYourApp: React.FC<BuildYourAppProps> = ({
25-
trackingCategory,
26-
contractAddress,
27-
chainSlug,
28-
}) => {
9+
}) {
2910
return (
30-
<Card
31-
px={{ base: 4, md: 8 }}
32-
py={{ base: 6, md: 8 }}
33-
as={LinkBox}
34-
transition="all 0.2s"
35-
_hover={{ borderColor: "whiteAlpha.300" }}
36-
>
37-
<SimpleGrid {...{ columns: { base: 1, md: 2 } }} gap={8}>
38-
<GridItem as={Flex} direction="column" gap={4}>
39-
<h2 className="font-semibold text-2xl tracking-tight">
40-
Build your app
41-
</h2>
42-
<Text size="body.md">
43-
<LinkOverlay
44-
as={TrackedLink}
45-
category={trackingCategory}
46-
label="build_your_app"
47-
href={`/${chainSlug}/${contractAddress}/code`}
48-
color="blue.500"
49-
>
50-
Learn more
51-
</LinkOverlay>{" "}
52-
about how you can use thirdweb tools to build apps on top of this
53-
contract.
54-
</Text>
55-
</GridItem>
56-
<GridItem as={Flex} align="center" justify="end" gap={3}>
57-
{RENDERED_PRODUCTS.map((p) => {
58-
const product = PRODUCTS.find((item) => item.label === p);
59-
return (
60-
product?.icon && (
61-
<Flex
62-
key={product.name}
63-
rounded="full"
64-
bg="#0E0E10"
65-
align="center"
66-
justify="center"
67-
w={14}
68-
h={14}
69-
>
70-
<Image boxSize={7} src={product.icon} alt={product.name} />
71-
</Flex>
72-
)
73-
);
74-
})}
75-
</GridItem>
76-
</SimpleGrid>
77-
</Card>
11+
<div className="relative flex flex-col justify-between gap-4 rounded-lg border bg-card p-6 hover:border-active-border lg:flex-row">
12+
{/* left */}
13+
<div className="max-w-sm">
14+
<h2 className="mb-2 font-semibold text-xl leading-none tracking-tight">
15+
Build your app
16+
</h2>
17+
<TrackedLinkTW
18+
category={props.trackingCategory}
19+
label="build_your_app"
20+
href={`/${props.chainSlug}/${props.contractAddress}/code`}
21+
className="block text-balance text-muted-foreground text-sm before:absolute before:inset-0"
22+
>
23+
Learn more about how you can use thirdweb tools to build apps on top
24+
of this contract
25+
</TrackedLinkTW>{" "}
26+
</div>
27+
28+
{/* right */}
29+
<div className="flex items-center justify-end gap-3">
30+
{[TypeScriptIcon, ReactIcon].map((Icon, i) => {
31+
return (
32+
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
33+
<div key={i} className="rounded-full border bg-background p-3">
34+
<Icon className="size-5 text-muted-foreground" />
35+
</div>
36+
);
37+
})}
38+
</div>
39+
</div>
7840
);
79-
};
41+
}

0 commit comments

Comments
 (0)