Skip to content

Commit 0bb87e0

Browse files
committed
Dashboard: Add tokens section in explore
1 parent 7883127 commit 0bb87e0

File tree

11 files changed

+229
-10
lines changed

11 files changed

+229
-10
lines changed

apps/dashboard/src/@/analytics/report.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,3 +503,16 @@ export function reportFundWalletSuccessful() {
503503
export function reportFundWalletFailed(params: { errorMessage: string }) {
504504
posthog.capture("fund wallet failed", params);
505505
}
506+
507+
/**
508+
* ### Why do we need to report this event?
509+
* - To track the conversion rate of the users choosing to create a token from new flow from the explore page
510+
*
511+
* ### Who is responsible for this event?
512+
* @MananTank
513+
*/
514+
export function reportExploreTokenCardClicked(params: {
515+
assetType: "nft" | "coin";
516+
}) {
517+
posthog.capture("explore token-card clicked", params);
518+
}

apps/dashboard/src/app/(app)/(dashboard)/explore/page.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ContractRow } from "./components/contract-row";
44
import { DeployUpsellCard } from "./components/upsells/deploy-your-own";
55
import { PublishUpsellCard } from "./components/upsells/publish-submit";
66
import { EXPLORE_PAGE_DATA } from "./data";
7+
import { TokensSection } from "./tokens-section";
78

89
const title = "List of smart contracts for EVM Developers";
910
const description =
@@ -22,7 +23,7 @@ export default async function ExplorePage() {
2223
return (
2324
<div className="flex flex-col">
2425
<div className="border-b py-10">
25-
<div className="container">
26+
<div className="container max-w-7xl">
2627
<h1 className="mb-2 font-bold text-3xl lg:text-5xl tracking-tighter">
2728
Explore
2829
</h1>
@@ -34,7 +35,11 @@ export default async function ExplorePage() {
3435
</div>
3536
</div>
3637

37-
<div className="container flex flex-col gap-4 py-10">
38+
<div className="container max-w-7xl py-10">
39+
<TokensSection />
40+
</div>
41+
42+
<div className="container max-w-7xl flex flex-col gap-8 py-10">
3843
<div className="flex flex-col gap-14">
3944
{EXPLORE_PAGE_DATA.map((category, idx) => (
4045
<Fragment key={category.id}>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"use client";
2+
3+
import { CoinsIcon, ImageIcon } from "lucide-react";
4+
import Link from "next/link";
5+
import { reportExploreTokenCardClicked } from "@/analytics/report";
6+
import { GridPattern } from "@/components/ui/background-patterns";
7+
import { Badge } from "@/components/ui/badge";
8+
import { cn } from "@/lib/utils";
9+
10+
export function TokensSection() {
11+
return (
12+
<div className="bg-card p-4 lg:p-8 border rounded-xl relative w-full overflow-hidden">
13+
<GridPattern
14+
width={30}
15+
height={30}
16+
x={-1}
17+
y={-1}
18+
strokeDasharray={"4 2"}
19+
className="text-border dark:text-border/70"
20+
style={{
21+
maskImage:
22+
"linear-gradient(to bottom right,transparent,transparent,white)",
23+
}}
24+
/>
25+
26+
<div className="absolute top-4 right-4 lg:top-6 lg:right-6">
27+
<Badge
28+
variant="outline"
29+
className="text-sm bg-background h-auto px-3 py-1"
30+
>
31+
New
32+
</Badge>
33+
</div>
34+
35+
<h2 className="font-semibold text-2xl tracking-tighter mb-1">
36+
Recommended
37+
</h2>
38+
<p className="text-muted-foreground mb-6 text-sm lg:text-base">
39+
Easily deploy tokens with built-in distribution mechanisms, <br /> fee
40+
recipient settings, and simple configuration of the contract and assets.
41+
</p>
42+
43+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
44+
<CardLink
45+
assetType="coin"
46+
title="Coin"
47+
description="Create an ERC-20 token to create cryptocurrencies"
48+
href="/team/~/~project/tokens/create/token"
49+
icon={<CoinsIcon className="size-5 text-muted-foreground" />}
50+
/>
51+
52+
<CardLink
53+
assetType="nft"
54+
title="NFT Collection"
55+
description="Create an ERC-721 or ERC-1155 token to create digital assets"
56+
href="/team/~/~project/tokens/create/nft"
57+
icon={<ImageIcon className="size-5 text-muted-foreground" />}
58+
/>
59+
</div>
60+
</div>
61+
);
62+
}
63+
64+
function CardLink(props: {
65+
title: string;
66+
description: string;
67+
href: string;
68+
icon: React.ReactNode;
69+
assetType: "nft" | "coin";
70+
}) {
71+
return (
72+
<div
73+
className={cn(
74+
"relative flex flex-col rounded-lg border p-4 cursor-pointer hover:border-active-border bg-background",
75+
)}
76+
>
77+
<div className="mb-4 flex">
78+
<div className="flex items-center justify-center rounded-full border p-2 bg-card">
79+
{props.icon}
80+
</div>
81+
</div>
82+
83+
<h3 className="mb-0.5 font-semibold text-lg tracking-tight">
84+
<Link
85+
className="before:absolute before:inset-0"
86+
href={props.href}
87+
onClick={() => {
88+
reportExploreTokenCardClicked({ assetType: props.assetType });
89+
}}
90+
>
91+
{props.title}
92+
</Link>
93+
</h3>
94+
<p className="text-muted-foreground text-sm">{props.description}</p>
95+
</div>
96+
);
97+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { AppFooter } from "@/components/footers/app-footer";
55
import { DotsBackgroundPattern } from "@/components/ui/background-patterns";
66
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
77
import { TeamHeader } from "../../components/TeamHeader/team-header";
8-
import { createTeamLink, TeamSelectorCard } from "./components/team-selector";
8+
import { createTeamLink, TeamSelectorCard } from "../_components/team-selector";
99

1010
export default async function Page(props: {
1111
params: Promise<{

apps/dashboard/src/app/(app)/team/~/components/TeamAndProjectSelectorCard.tsx renamed to apps/dashboard/src/app/(app)/team/~/_components/TeamAndProjectSelectorCard.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function ProjectAndTeamSelectorCard(props: {
1616
projects: PartialProject[];
1717
}[];
1818
client: ThirdwebClient;
19-
description: React.ReactNode;
19+
description: React.ReactNode | undefined;
2020
onSelect: (selected: { team: Team; project: PartialProject }) => void;
2121
}) {
2222
const teamAndProjects = props.teamAndProjects.filter(
@@ -31,10 +31,14 @@ export function ProjectAndTeamSelectorCard(props: {
3131
<div className="mb-2 self-start rounded-full border p-2">
3232
<BoxIcon className="size-5 text-muted-foreground" />
3333
</div>
34-
<h1 className="mb-0.5 font-semibold text-xl tracking-tight">
35-
Select a project
36-
</h1>
37-
<p className="text-muted-foreground text-sm">{props.description}</p>
34+
<div className="space-y-0.5">
35+
<h1 className="font-semibold text-xl tracking-tight">
36+
Select a project
37+
</h1>
38+
{props.description && (
39+
<p className="text-muted-foreground text-sm">{props.description}</p>
40+
)}
41+
</div>
3842
</div>
3943

4044
<div
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { PartialProject } from "@/api/project/getProjectContracts";
55
import type { Team } from "@/api/team/get-team";
66
import { useAddContractToProject } from "@/hooks/project-contracts";
77
import { useDashboardRouter } from "@/lib/DashboardRouter";
8-
import { ProjectAndTeamSelectorCard } from "../../../../../components/TeamAndProjectSelectorCard";
8+
import { ProjectAndTeamSelectorCard } from "./TeamAndProjectSelectorCard";
99

1010
export function SelectProjectForContract(props: {
1111
chainSlug: string;
@@ -78,3 +78,27 @@ export function ImportAndSelectProjectForContract(props: {
7878
/>
7979
);
8080
}
81+
82+
export function GenericProjectSelector(props: {
83+
client: ThirdwebClient;
84+
paths: string[] | undefined;
85+
description: React.ReactNode | undefined;
86+
teamAndProjects: {
87+
team: Team;
88+
projects: PartialProject[];
89+
}[];
90+
}) {
91+
const router = useDashboardRouter();
92+
return (
93+
<ProjectAndTeamSelectorCard
94+
client={props.client}
95+
description={props.description}
96+
onSelect={(selection) => {
97+
router.push(
98+
`/team/${selection.team.slug}/${selection.project.slug}${props.paths?.length ? `/${props.paths.join("/")}` : ""}`,
99+
);
100+
}}
101+
teamAndProjects={props.teamAndProjects}
102+
/>
103+
);
104+
}

apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { TeamHeader } from "../../../../../components/TeamHeader/team-header";
1717
import {
1818
ImportAndSelectProjectForContract,
1919
SelectProjectForContract,
20-
} from "./components/project-selector";
20+
} from "../../../../_components/project-selector";
2121

2222
export default async function Page(props: {
2323
params: Promise<{

0 commit comments

Comments
 (0)