Skip to content

Commit 77d7d50

Browse files
committed
Move Deployed Contracts Page to App Router
1 parent 926d823 commit 77d7d50

File tree

10 files changed

+106
-71
lines changed

10 files changed

+106
-71
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"use client";
2+
3+
import { Spinner } from "@/components/ui/Spinner/Spinner";
4+
import { useAllContractList } from "@3rdweb-sdk/react/hooks/useRegistry";
5+
import { DeployedContracts } from "../../../../../components/contract-components/tables/deployed-contracts";
6+
import { GetStartedWithContractsDeploy } from "../../../../team/[team_slug]/[project_slug]/contracts/_components/GetStartedWithContractsDeploy";
7+
8+
export function DeployedContractsPage(props: {
9+
address: string;
10+
}) {
11+
const deployedContracts = useAllContractList(props.address);
12+
13+
if (deployedContracts.isPending) {
14+
return (
15+
<div className="flex h-full min-h-[300px] items-center justify-center">
16+
<Spinner className="size-10" />
17+
</div>
18+
);
19+
}
20+
const hasContracts =
21+
deployedContracts.data && deployedContracts.data.length > 0;
22+
23+
if (!hasContracts) {
24+
return <GetStartedWithContractsDeploy />;
25+
}
26+
27+
return (
28+
<DeployedContracts
29+
contractList={deployedContracts.data}
30+
limit={50}
31+
isPending={deployedContracts.isPending}
32+
/>
33+
);
34+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { redirect } from "next/navigation";
2+
import { getAuthTokenWalletAddress } from "../../../../api/lib/getAuthToken";
3+
import { DeployedContractsPage } from "./DeployedContractsPage";
4+
5+
export default function Page() {
6+
const accountAddress = getAuthTokenWalletAddress();
7+
if (!accountAddress) {
8+
return redirect(`/login?next=${encodeURIComponent("/dashboard")}`);
9+
}
10+
11+
return <DeployedContractsPage address={accountAddress} />;
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { BillingAlerts } from "../../../../components/settings/Account/Billing/alerts/Alert";
2+
import { ContractsSidebarLayout } from "../../../../core-ui/sidebar/contracts";
3+
4+
export default function Layout(props: {
5+
children: React.ReactNode;
6+
}) {
7+
return (
8+
<ContractsSidebarLayout>
9+
<BillingAlerts className="pb-6" />
10+
{props.children}
11+
</ContractsSidebarLayout>
12+
);
13+
}

apps/dashboard/src/app/(dashboard)/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default function DashboardLayout(props: { children: React.ReactNode }) {
77
<ErrorProvider>
88
<div className="flex min-h-screen flex-col bg-background">
99
<DashboardHeader />
10-
<main className="grow">{props.children}</main>
10+
<div className="flex grow flex-col">{props.children}</div>
1111
<AppFooter />
1212
</div>
1313
</ErrorProvider>

apps/dashboard/src/app/api/lib/getAuthToken.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,19 @@ export function getAuthToken() {
1010

1111
return token;
1212
}
13+
14+
export function getAuthTokenWalletAddress() {
15+
const cookiesManager = cookies();
16+
const activeAccount = cookiesManager.get(COOKIE_ACTIVE_ACCOUNT)?.value;
17+
if (!activeAccount) {
18+
return null;
19+
}
20+
21+
const token = cookiesManager.get(COOKIE_PREFIX_TOKEN + activeAccount)?.value;
22+
23+
if (token) {
24+
return activeAccount;
25+
}
26+
27+
return null;
28+
}

apps/dashboard/src/app/team/[team_slug]/[project_slug]/contracts/_components/GetStartedWithContractsDeploy.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,15 @@
11
"use client";
22
import { TabButtons } from "@/components/ui/tabs";
33
import { useDashboardRouter } from "@/lib/DashboardRouter";
4-
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
54
import Image from "next/image";
65
import { useMemo, useState } from "react";
7-
import { useActiveAccount } from "thirdweb/react";
86
import { ImportModal } from "../../../../../../components/contract-components/import-contract/modal";
97
import { StepsCard } from "../../../../../../components/dashboard/StepsCard";
108
import { useTrack } from "../../../../../../hooks/analytics/useTrack";
119

1210
export function GetStartedWithContractsDeploy() {
13-
const address = useActiveAccount()?.address;
1411
const steps = useMemo(
1512
() => [
16-
{
17-
title: "Connect your wallet to get started",
18-
description:
19-
"In order to interact with your contracts you need to connect an EVM compatible wallet.",
20-
children: <CustomConnectWallet />,
21-
completed: !!address,
22-
},
23-
2413
{
2514
title: "Build, deploy or import a contract",
2615
description:
@@ -29,7 +18,7 @@ export function GetStartedWithContractsDeploy() {
2918
completed: false, // because we only show this component if the user does not have any contracts
3019
},
3120
],
32-
[address],
21+
[],
3322
);
3423

3524
return (

apps/dashboard/src/app/team/[team_slug]/[project_slug]/contracts/page.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ export default function Page() {
2424
{!hasContracts ? (
2525
<GetStartedWithContractsDeploy />
2626
) : (
27-
<DeployedContracts contractListQuery={deployedContracts} limit={50} />
27+
<DeployedContracts
28+
contractList={deployedContracts.data}
29+
isPending={deployedContracts.isPending}
30+
limit={50}
31+
/>
2832
)}
2933
</div>
3034
);

apps/dashboard/src/components/contract-components/tables/deployed-contracts.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
usePagination,
4343
useTable,
4444
} from "react-table";
45+
import { SkeletonContainer } from "../../../@/components/ui/skeleton";
4546
import { useAllChainsData } from "../../../hooks/chains/allChains";
4647
import { useChainSlug } from "../../../hooks/chains/chainSlug";
4748
import { ImportModal } from "../import-contract/modal";
@@ -50,25 +51,27 @@ import { ShowMoreButton } from "./show-more-button";
5051

5152
interface DeployedContractsProps {
5253
noHeader?: boolean;
53-
contractListQuery: ReturnType<typeof useAllContractList>;
54+
contractList: ReturnType<typeof useAllContractList>["data"];
55+
isPending: boolean;
5456
limit?: number;
5557
}
5658

5759
export const DeployedContracts: React.FC<DeployedContractsProps> = ({
5860
noHeader,
59-
contractListQuery,
61+
contractList,
6062
limit = 10,
63+
isPending,
6164
}) => {
6265
const [importModalOpen, setImportModalOpen] = useState(false);
6366

6467
const chainIdsWithDeployments = useMemo(() => {
6568
const set = new Set<number>();
6669
// biome-ignore lint/complexity/noForEach: FIXME
67-
contractListQuery.data.forEach((contract) => {
70+
contractList.forEach((contract) => {
6871
set.add(contract.chainId);
6972
});
7073
return [...set];
71-
}, [contractListQuery.data]);
74+
}, [contractList]);
7275

7376
return (
7477
<div className="flex flex-col gap-8">
@@ -111,13 +114,13 @@ export const DeployedContracts: React.FC<DeployedContractsProps> = ({
111114
)}
112115

113116
<ContractTable
114-
combinedList={contractListQuery.data}
117+
combinedList={contractList}
115118
limit={limit}
116119
chainIdsWithDeployments={chainIdsWithDeployments}
117-
loading={contractListQuery.isPending}
120+
loading={isPending}
118121
/>
119122

120-
{contractListQuery.data.length === 0 && contractListQuery.isFetched && (
123+
{contractList.length === 0 && !isPending && (
121124
<div className="flex h-[100px] items-center justify-center text-muted-foreground">
122125
No contracts found
123126
</div>
@@ -142,7 +145,7 @@ const RemoveFromDashboardButton: React.FC<RemoveFromDashboardButtonProps> = ({
142145
variant="ghost"
143146
onClick={(e) => {
144147
e.stopPropagation();
145-
mutation.mutate({ chainId, contractAddress });
148+
mutation.mutateAsync({ chainId, contractAddress });
146149
}}
147150
disabled={mutation.isPending}
148151
className="!bg-background hover:!bg-accent gap-2"
@@ -236,9 +239,14 @@ const ContractTable: React.FC<ContractTableProps> = ({
236239
return (
237240
<div className="flex items-center gap-2">
238241
<ChainIcon size={24} ipfsSrc={data?.icon?.url} />
239-
<p className="text-muted-foreground text-sm">
240-
{cleanedChainName}
241-
</p>
242+
<SkeletonContainer
243+
loadedData={data ? cleanedChainName : undefined}
244+
skeletonData={`Chain ID ${cell.row.original.chainId}`}
245+
render={(v) => {
246+
return <p className="text-muted-foreground text-sm">{v}</p>;
247+
}}
248+
/>
249+
242250
{data?.testnet && (
243251
<Badge variant="outline" className="text-muted-foreground">
244252
Testnet
@@ -395,10 +403,12 @@ const ContractTable: React.FC<ContractTableProps> = ({
395403
const ContractTableRow = memo(({ row }: { row: Row<BasicContract> }) => {
396404
const chainSlug = useChainSlug(row.original.chainId);
397405
const router = useDashboardRouter();
406+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
407+
const { key, ...rowProps } = row.getRowProps();
398408

399409
return (
400410
<TableRow
401-
{...row.getRowProps()}
411+
{...rowProps}
402412
role="group"
403413
className="cursor-pointer hover:bg-muted/50"
404414
// TODO - replace this with before:absolute thing

apps/dashboard/src/pages/dashboard/contracts/deploy.tsx

Lines changed: 0 additions & 44 deletions
This file was deleted.

apps/dashboard/src/pages/profile/[profileAddress].tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ const UserPage: ThirdwebNextPage = (props: UserPageProps) => {
178178
{ens.data?.address && (
179179
<DeployedContracts
180180
noHeader
181-
contractListQuery={mainnetsContractList}
181+
contractList={mainnetsContractList.data}
182+
isPending={mainnetsContractList.isPending}
182183
/>
183184
)}
184185
</Flex>

0 commit comments

Comments
 (0)