Skip to content

Commit b82011e

Browse files
committed
Move /connect/in-app-wallets to app router (#4894)
## Problem solved Short description of the bug fixed or feature added <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing the `in-app-wallets` feature by adding new components and functionalities, including API key management and layout improvements. ### Detailed summary - Added `getInAppWalletSupportedAPIKeys` function to fetch and filter API keys. - Created `Layout` component with footer sections. - Implemented `InAppWalletsAPIKeysMenu` for API key selection. - Added `PageHeader` with description and link. - Enhanced `Page` component to handle redirects and display API keys. - Updated `EmbeddedWallets` component to use `defaultTab` prop instead of search params. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent a7e285a commit b82011e

File tree

9 files changed

+158
-143
lines changed

9 files changed

+158
-143
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { TrackedLinkTW } from "@/components/ui/tracked-link";
2+
3+
export function PageHeader() {
4+
return (
5+
<div>
6+
<h1 className="font-semibold text-3xl tracking-tigher">In-App Wallets</h1>
7+
<div className="h-3" />
8+
<p className="max-w-[500px] text-muted-foreground ">
9+
A wallet infrastructure that enables apps to create, manage, and control
10+
their users wallets. Email login, social login, and bring-your-own auth
11+
supported.{" "}
12+
<TrackedLinkTW
13+
target="_blank"
14+
href="https://portal.thirdweb.com/connect/in-app-wallet/overview"
15+
label="learn-more"
16+
category="embedded-wallet"
17+
className="text-link-foreground hover:text-foreground"
18+
>
19+
Learn more
20+
</TrackedLinkTW>
21+
</p>
22+
</div>
23+
);
24+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { redirect } from "next/navigation";
2+
import { EmbeddedWallets } from "../../../../../../components/embedded-wallets";
3+
import { getAuthToken } from "../../../../../api/lib/getAuthToken";
4+
import { PageHeader } from "../PageHeader";
5+
import { getInAppWalletSupportedAPIKeys } from "../getInAppWalletSupportedAPIKeys";
6+
import { InAppWalletsAPIKeysMenu } from "../inAppWalletsAPIKeysMenu";
7+
8+
export default async function Page(props: {
9+
params: {
10+
clientId: string;
11+
};
12+
searchParams: {
13+
tab?: string;
14+
};
15+
}) {
16+
const authToken = getAuthToken();
17+
const { clientId } = props.params;
18+
19+
if (!authToken) {
20+
redirect(
21+
`/login?next=${encodeURIComponent(`/dashboard/connect/in-app-wallets/${clientId}`)}`,
22+
);
23+
}
24+
25+
const apiKeys = await getInAppWalletSupportedAPIKeys();
26+
const apiKey = apiKeys.find((key) => key.key === clientId);
27+
28+
if (!apiKey) {
29+
redirect("/dashboard/connect/in-app-wallets");
30+
}
31+
32+
return (
33+
<div>
34+
{/* header */}
35+
<div className="flex flex-col gap-4 lg:flex-row lg:justify-between">
36+
<PageHeader />
37+
<div>
38+
<InAppWalletsAPIKeysMenu
39+
apiKeys={apiKeys.map((x) => ({
40+
name: x.name,
41+
key: x.key,
42+
}))}
43+
selectedAPIKey={apiKey}
44+
/>
45+
</div>
46+
</div>
47+
48+
<div className="h-8" />
49+
<EmbeddedWallets
50+
apiKey={apiKey}
51+
trackingCategory="embedded-wallet"
52+
defaultTab={props.searchParams.tab === "1" ? 1 : 0}
53+
/>
54+
</div>
55+
);
56+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { getApiKeys } from "../../../../api/lib/getAPIKeys";
2+
3+
export async function getInAppWalletSupportedAPIKeys() {
4+
return (await getApiKeys()).filter((key) => {
5+
return !!(key.services || []).find((srv) => srv.name === "embeddedWallets");
6+
});
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client";
2+
3+
import { useDashboardRouter } from "@/lib/DashboardRouter";
4+
import type { ApiKey } from "@3rdweb-sdk/react/hooks/useApi";
5+
import { ApiKeysMenu } from "../../../../../components/settings/ApiKeys/Menu";
6+
7+
export function InAppWalletsAPIKeysMenu(props: {
8+
apiKeys: Pick<ApiKey, "name" | "key">[];
9+
selectedAPIKey: Pick<ApiKey, "name" | "key">;
10+
}) {
11+
const router = useDashboardRouter();
12+
return (
13+
<ApiKeysMenu
14+
apiKeys={props.apiKeys}
15+
selectedKey={props.selectedAPIKey}
16+
onSelect={(key) => {
17+
router.push(`/dashboard/connect/in-app-wallets/${key.key}`);
18+
}}
19+
/>
20+
);
21+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AnalyticsCallout } from "../../../../team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/AnalyticsCallout";
2+
import { InAppWaletFooterSection } from "../../../../team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/footer";
3+
4+
export default function Layout(props: {
5+
children: React.ReactNode;
6+
}) {
7+
return (
8+
<div>
9+
{props.children}
10+
<div className="h-16" />
11+
{/* Footer */}
12+
<AnalyticsCallout trackingCategory="embedded-wallet" />
13+
<div className="h-5" />
14+
<InAppWaletFooterSection trackingCategory="embedded-wallet" />
15+
</div>
16+
);
17+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { redirect } from "next/navigation";
2+
import { NoApiKeys } from "../../../../../components/settings/ApiKeys/NoApiKeys";
3+
import { getAuthToken } from "../../../../api/lib/getAuthToken";
4+
import { PageHeader } from "./PageHeader";
5+
import { getInAppWalletSupportedAPIKeys } from "./getInAppWalletSupportedAPIKeys";
6+
7+
export default async function Page() {
8+
const authToken = getAuthToken();
9+
10+
if (!authToken) {
11+
redirect(
12+
`/login?next=${encodeURIComponent("/dashboard/connect/in-app-wallets")}`,
13+
);
14+
}
15+
16+
const apiKeys = await getInAppWalletSupportedAPIKeys();
17+
const firstKey = apiKeys[0];
18+
19+
if (firstKey) {
20+
redirect(`/dashboard/connect/in-app-wallets/${firstKey.key}`);
21+
}
22+
23+
return (
24+
<div>
25+
<PageHeader />
26+
<div className="h-8" />
27+
<NoApiKeys service="in-app wallets" />
28+
</div>
29+
);
30+
}

apps/dashboard/src/components/embedded-wallets/index.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { TabButtons } from "@/components/ui/tabs";
44
import type { ApiKey } from "@3rdweb-sdk/react/hooks/useApi";
5-
import { useSearchParams } from "next/navigation";
65
import { useState } from "react";
76
import { InAppWalletSettingsPage } from "./Configure";
87
import { InAppWalletUsersPageContent } from "./Users";
@@ -19,16 +18,16 @@ interface EmbeddedWalletsProps {
1918
| "key"
2019
>;
2120
trackingCategory: string;
21+
defaultTab: 0 | 1;
2222
}
2323

2424
export const EmbeddedWallets: React.FC<EmbeddedWalletsProps> = ({
2525
apiKey,
2626
trackingCategory,
27+
defaultTab,
2728
}) => {
28-
const searchParams = useSearchParams();
29-
const defaultTabIndex = searchParams?.get("tab") === "1" ? 1 : 0;
3029
const [selectedTab, setSelectedTab] = useState<"users" | "config">(
31-
defaultTabIndex === 0 ? "users" : "config",
30+
defaultTab === 0 ? "users" : "config",
3231
);
3332

3433
function updateSearchParams(value: string) {

apps/dashboard/src/page-id.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,6 @@ export enum PageId {
9898

9999
// thirdweb.com/dashboard/connect/smart-wallet
100100
DashboardConnectAccountAbstraction = "dashboard-wallets-smart-wallet",
101-
// thirdweb.com/dashboard/connect/embedded
102-
DashboardConnectEmbeddedWallets = "dashboard-wallets-embedded",
103101
// thirdweb.com/dashboard/contracts/build
104102
DashboardContractsBuild = "dashboard-contracts-build",
105103

apps/dashboard/src/pages/dashboard/connect/in-app-wallets.tsx

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

0 commit comments

Comments
 (0)