Skip to content

Commit bac2612

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

File tree

11 files changed

+242
-12
lines changed

11 files changed

+242
-12
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: 9 additions & 4 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,19 +23,23 @@ 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-
<h1 className="mb-2 font-bold text-3xl lg:text-5xl tracking-tighter">
26+
<div className="container max-w-7xl">
27+
<h1 className="mb-2 font-bold text-4xl lg:text-5xl tracking-tight">
2728
Explore
2829
</h1>
29-
<p className="max-w-screen-sm text-base text-muted-foreground">
30+
<p className="max-w-screen-sm text-sm lg:text-base text-muted-foreground">
3031
The best place for web3 developers to explore smart contracts from
3132
world-class web3 protocols & engineers all deployable with one
3233
click.
3334
</p>
3435
</div>
3536
</div>
3637

37-
<div className="container flex flex-col gap-4 py-10">
38+
<div className="container max-w-7xl pt-8 pb-4">
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: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"use client";
2+
3+
import { ZapIcon } 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:py-8 lg:px-6 border rounded-xl relative w-full overflow-hidden">
13+
<GridPattern
14+
width={30}
15+
height={30}
16+
strokeDasharray={"4 2"}
17+
className="text-border dark:text-border/70 hidden lg:block translate-x-5"
18+
style={{
19+
maskImage:
20+
"linear-gradient(to bottom left,white,transparent,transparent)",
21+
}}
22+
/>
23+
24+
<Badge
25+
variant="outline"
26+
className="text-sm bg-background h-auto px-3 py-1 gap-2 mb-4"
27+
>
28+
<div className="rounded-full bg-primary size-2" />
29+
New
30+
</Badge>
31+
32+
<h2 className="font-semibold text-2xl tracking-tight mb-1">
33+
Launch Your Tokens Effortlessly
34+
</h2>
35+
<p className="text-muted-foreground mb-6 text-sm lg:text-base">
36+
Deploy contract and configure all settings you need to launch your token
37+
in one seamless flow
38+
</p>
39+
40+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 max-w-4xl">
41+
<CardLink
42+
assetType="coin"
43+
title="Launch Coin"
44+
description="Launch an ERC-20 token to create a cryptocurrency"
45+
href="/team/~/~project/tokens/create/token"
46+
bullets={[
47+
"Deploy Contract",
48+
"Configure Price and Supply",
49+
"Airdrop Tokens",
50+
]}
51+
/>
52+
53+
<CardLink
54+
assetType="nft"
55+
title="Launch NFT Collection"
56+
description="Launch an ERC-721 or ERC-1155 NFT collection"
57+
href="/team/~/~project/tokens/create/nft"
58+
bullets={[
59+
"Deploy Contract",
60+
"Upload NFTs",
61+
"Configure Price and Supply",
62+
]}
63+
/>
64+
</div>
65+
</div>
66+
);
67+
}
68+
69+
function CardLink(props: {
70+
title: string;
71+
description: string;
72+
href: string;
73+
assetType: "nft" | "coin";
74+
bullets: string[];
75+
}) {
76+
return (
77+
<div
78+
className={cn(
79+
"relative flex flex-col rounded-lg border p-4 cursor-pointer hover:border-active-border bg-background",
80+
)}
81+
>
82+
<div className="mb-3 flex">
83+
<div className="flex items-center justify-center rounded-full border p-2 bg-card">
84+
<ZapIcon className="size-4 text-muted-foreground" />
85+
</div>
86+
</div>
87+
88+
<h3 className="mb-0.5 font-semibold text-lg tracking-tight">
89+
<Link
90+
className="before:absolute before:inset-0"
91+
href={props.href}
92+
onClick={() => {
93+
reportExploreTokenCardClicked({ assetType: props.assetType });
94+
}}
95+
>
96+
{props.title}
97+
</Link>
98+
</h3>
99+
<p className="text-muted-foreground text-sm">{props.description}</p>
100+
101+
<ul className="mt-4 space-y-1 text-sm list-disc list-inside text-muted-foreground">
102+
{props.bullets.map((bullet) => (
103+
<li key={bullet}>{bullet}</li>
104+
))}
105+
</ul>
106+
</div>
107+
);
108+
}

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)