Skip to content

Commit d8c88ef

Browse files
committed
Add In-app wallet page on Teams layout (#4361)
## Problem solved Short description of the bug fixed or feature added <!-- start pr-codex --> --- ## PR-Codex overview The focus of this PR is to enhance the in-app wallet functionality by updating configurations and adding analytics components. ### Detailed summary - Updated `Configure` component props for better data handling - Added `AnalyticsCallout` component for analytics tracking - Improved UI with new components like `InAppWaletFooterSection` > The following files were skipped due to too many changes: `apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/footer.tsx`, `apps/dashboard/src/pages/dashboard/connect/in-app-wallets.tsx` > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent aa556f1 commit d8c88ef

File tree

9 files changed

+281
-206
lines changed

9 files changed

+281
-206
lines changed

apps/dashboard/src/@/components/ui/tracked-link.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import { useTrack } from "hooks/analytics/useTrack";
24
import Link from "next/link";
35
import type React from "react";

apps/dashboard/src/components/embedded-wallets/Users/Analytics.tsx renamed to apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/AnalyticsCallout.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import { Button } from "@/components/ui/button";
24
import { TrackedLinkTW } from "@/components/ui/tracked-link";
35
import { useAccountUsage } from "@3rdweb-sdk/react/hooks/useApi";
@@ -6,11 +8,13 @@ import { ArrowRightIcon } from "lucide-react";
68
import { useMemo } from "react";
79
import { toNumber, toPercent } from "utils/number";
810

9-
interface AnalyticsProps {
11+
type AnalyticsCalloutProps = {
1012
trackingCategory: string;
11-
}
13+
};
1214

13-
export const Analytics: React.FC<AnalyticsProps> = ({ trackingCategory }) => {
15+
export const AnalyticsCallout: React.FC<AnalyticsCalloutProps> = ({
16+
trackingCategory,
17+
}) => {
1418
const usageQuery = useAccountUsage();
1519

1620
const walletsMetrics = useMemo(() => {
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { TrackedLinkTW } from "@/components/ui/tracked-link";
2+
import { ArrowRightIcon } from "lucide-react";
3+
import { SupportedPlatformLink } from "../../../../../../../components/wallets/SupportedPlatformLink";
4+
5+
export function InAppWaletFooterSection(props: {
6+
trackingCategory: string;
7+
}) {
8+
return (
9+
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
10+
<ViewDocs trackingCategory={props.trackingCategory} />
11+
<Templates trackingCategory={props.trackingCategory} />
12+
</div>
13+
);
14+
}
15+
16+
function ViewDocs(props: {
17+
trackingCategory: string;
18+
}) {
19+
const TRACKING_CATEGORY = props.trackingCategory;
20+
return (
21+
<div className="p-4 lg:p-6 bg-muted/50 border border-border rounded-lg">
22+
<div className="flex items-center gap-2">
23+
<h3 className="font-semibold">View Docs</h3>
24+
<ArrowRightIcon className="size-4" />
25+
</div>
26+
27+
<div className="h-4" />
28+
29+
<div className="grid grid-cols-2 gap-4">
30+
<SupportedPlatformLink
31+
trackingCategory={TRACKING_CATEGORY}
32+
platform="React"
33+
href="https://portal.thirdweb.com/connect/in-app-wallet/overview"
34+
/>
35+
36+
<SupportedPlatformLink
37+
trackingCategory={TRACKING_CATEGORY}
38+
platform="Unity"
39+
href="https://portal.thirdweb.com/unity/wallets/providers/embedded-wallet"
40+
/>
41+
<SupportedPlatformLink
42+
trackingCategory={TRACKING_CATEGORY}
43+
platform="React Native"
44+
href="https://portal.thirdweb.com/react/v5/in-app-wallet/get-started"
45+
/>
46+
<SupportedPlatformLink
47+
trackingCategory={TRACKING_CATEGORY}
48+
platform="TypeScript"
49+
href="https://portal.thirdweb.com/connect/in-app-wallet/overview"
50+
/>
51+
</div>
52+
53+
<div className="h-6" />
54+
55+
<div className="flex items-center gap-2">
56+
<h3 className="font-semibold">Relevant Guides</h3>
57+
<ArrowRightIcon className="size-4" />
58+
</div>
59+
60+
<div className="h-4" />
61+
62+
<div className="flex flex-col gap-3">
63+
<GuideLink
64+
href="https://blog.thirdweb.com/what-are-embedded-wallets/"
65+
label="what-is-an-embedded-wallet"
66+
trackingCategory={TRACKING_CATEGORY}
67+
>
68+
What is an in-app wallet?
69+
</GuideLink>
70+
71+
<GuideLink
72+
href="https://portal.thirdweb.com/connect/in-app-wallet/get-started"
73+
label="sdks-get-started"
74+
trackingCategory={TRACKING_CATEGORY}
75+
>
76+
Get started with In-App Wallets
77+
</GuideLink>
78+
79+
<GuideLink
80+
href="https://portal.thirdweb.com/connect/in-app-wallet/how-to/connect-users"
81+
label="how-to-connect-your-users"
82+
trackingCategory={TRACKING_CATEGORY}
83+
>
84+
Using In-App Wallets with Connect
85+
</GuideLink>
86+
87+
<GuideLink
88+
href="https://portal.thirdweb.com/connect/in-app-wallet/how-to/build-your-own-ui"
89+
label="how-to-build-your-own-ui"
90+
trackingCategory={TRACKING_CATEGORY}
91+
>
92+
How to Build Your Own UI
93+
</GuideLink>
94+
95+
<GuideLink
96+
href="https://portal.thirdweb.com/connect/in-app-wallet/custom-auth/custom-auth-server"
97+
label="how-to-custom-auth-server"
98+
trackingCategory={TRACKING_CATEGORY}
99+
>
100+
Create a custom auth server
101+
</GuideLink>
102+
</div>
103+
</div>
104+
);
105+
}
106+
107+
function GuideLink(props: {
108+
label: string;
109+
children: React.ReactNode;
110+
href: string;
111+
trackingCategory: string;
112+
}) {
113+
return (
114+
<TrackedLinkTW
115+
category={props.trackingCategory}
116+
label={"guide"}
117+
trackingProps={{
118+
guide: props.label,
119+
}}
120+
href={props.href}
121+
className="text-sm !text-muted-foreground hover:!text-foreground"
122+
target="_blank"
123+
>
124+
{props.children}
125+
</TrackedLinkTW>
126+
);
127+
}
128+
129+
function Templates(props: {
130+
trackingCategory: string;
131+
}) {
132+
return (
133+
<div className="p-4 lg:p-6 bg-muted/50 border border-border rounded-lg">
134+
<div className="flex items-center gap-2">
135+
<h3 className="font-semibold">Relevant Templates</h3>
136+
<ArrowRightIcon className="size-4" />
137+
</div>
138+
139+
<div className="h-6" />
140+
141+
<div className="flex flex-col gap-3">
142+
<GuideLink
143+
href="https://github.com/thirdweb-example/embedded-smart-wallet"
144+
label="embedded-smart-wallet"
145+
trackingCategory={props.trackingCategory}
146+
>
147+
In-App Wallet + Account Abstraction Starter Kit
148+
</GuideLink>
149+
150+
<GuideLink
151+
href="https://github.com/thirdweb-example/catattacknft"
152+
label="embedded-cat-attack"
153+
trackingCategory={props.trackingCategory}
154+
>
155+
Cat Attack [Demo Web Game]
156+
</GuideLink>
157+
158+
<GuideLink
159+
href="https://github.com/thirdweb-example/embedded-wallet-custom-ui"
160+
label="embedded-wallet-with-custom-ui-react"
161+
trackingCategory={props.trackingCategory}
162+
>
163+
In-App Wallet With Custom UI [React]
164+
</GuideLink>
165+
166+
<GuideLink
167+
href="https://github.com/thirdweb-example/embedded-wallet-custom-ui-react-native"
168+
label="embedded-wallet-with-custom-ui-react-native"
169+
trackingCategory={props.trackingCategory}
170+
>
171+
In-App Wallet With Custom UI [ReactNative]
172+
</GuideLink>
173+
</div>
174+
</div>
175+
);
176+
}
Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,61 @@
1-
export default function Page() {
1+
import { getProject } from "@/api/projects";
2+
import { TrackedLinkTW } from "@/components/ui/tracked-link";
3+
import { notFound } from "next/navigation";
4+
import { EmbeddedWallets } from "../../../../../../components/embedded-wallets";
5+
import { AnalyticsCallout } from "./_components/AnalyticsCallout";
6+
import { InAppWaletFooterSection } from "./_components/footer";
7+
8+
export default async function Page(props: {
9+
params: {
10+
team_slug: string;
11+
project_slug: string;
12+
};
13+
}) {
14+
const project = await getProject(
15+
props.params.team_slug,
16+
props.params.project_slug,
17+
);
18+
19+
if (!project) {
20+
return notFound();
21+
}
22+
23+
const TRACKING_CATEGORY = "team/in-app-wallets";
24+
225
return (
3-
<div className="h-full py-6 container flex items-center justify-center">
4-
<h1 className="text-4xl tracking-tighter text-muted-foreground">
5-
In-app wallets
26+
<div className="pb-10 max-sm:pt-6">
27+
<h1 className="font-semibold text-2xl md:text-3xl tracking-tight mb-3">
28+
In-App Wallets
629
</h1>
30+
31+
<p className="max-w-[700px] text-muted-foreground mt-3 mb-7">
32+
A wallet infrastructure that enables apps to create, manage, and control
33+
their users wallets. Email login, social login, and bring-your-own auth
34+
supported.{" "}
35+
<TrackedLinkTW
36+
target="_blank"
37+
href="https://portal.thirdweb.com/connect/in-app-wallet/overview"
38+
label="learn-more"
39+
category={TRACKING_CATEGORY}
40+
className="text-link-foreground hover:text-foreground"
41+
>
42+
Learn more
43+
</TrackedLinkTW>
44+
</p>
45+
46+
<EmbeddedWallets
47+
apiKey={{
48+
...project,
49+
key: project.publishableKey, // clientId
50+
}}
51+
trackingCategory={TRACKING_CATEGORY}
52+
/>
53+
54+
<div className="h-16" />
55+
<AnalyticsCallout trackingCategory={TRACKING_CATEGORY} />
56+
<div className="h-5" />
57+
58+
<InAppWaletFooterSection trackingCategory={TRACKING_CATEGORY} />
759
</div>
860
);
961
}

apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function Layout(props: {
4040
return (
4141
<div className="h-full container flex gap-4">
4242
<Sidebar links={links} />
43-
<div className="grow py-6">
43+
<div className="grow py-6 max-sm:w-full">
4444
<ConnectMobileSidebar links={links} />
4545
{props.children}
4646
</div>

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ import { toast } from "sonner";
3939
import { toArrFromList } from "utils/string";
4040

4141
interface ConfigureProps {
42-
apiKey: ApiKey;
42+
apiKey: Pick<
43+
ApiKey,
44+
"id" | "name" | "domains" | "bundleIds" | "services" | "redirectUrls"
45+
>;
4346
trackingCategory: string;
4447
}
4548

@@ -60,7 +63,7 @@ export const Configure: React.FC<ConfigureProps> = (props) => {
6063
if (!dashboardAccount) {
6164
return (
6265
<div className="flex items-center justify-center h-[500px]">
63-
<Spinner className="size-4" />
66+
<Spinner className="size-10" />
6467
</div>
6568
);
6669
}
@@ -209,7 +212,7 @@ export const InAppWalletSettingsUI: React.FC<
209212
<form
210213
onSubmit={handleSubmit}
211214
autoComplete="off"
212-
className="px-[1px] flex flex-col gap-6"
215+
className="flex flex-col gap-6"
213216
>
214217
{/* Branding */}
215218
<BrandingFieldset

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

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
"use client";
2+
13
import { PaginationButtons } from "@/components/pagination-buttons";
24
import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
35
import { Button } from "@/components/ui/button";
46
import { Switch } from "@/components/ui/switch";
5-
import type { EmbeddedWalletUser } from "@3rdweb-sdk/react/hooks/useEmbeddedWallets";
7+
import {
8+
type EmbeddedWalletUser,
9+
useEmbeddedWallets,
10+
} from "@3rdweb-sdk/react/hooks/useEmbeddedWallets";
611
import { createColumnHelper } from "@tanstack/react-table";
712
import { TWTable } from "components/shared/TWTable";
813
import { format } from "date-fns/format";
@@ -12,13 +17,6 @@ import { withinDays } from "utils/date-utils";
1217

1318
const ACTIVE_THRESHOLD_DAYS = 30;
1419

15-
interface UsersProps {
16-
wallets: EmbeddedWalletUser[];
17-
isLoading: boolean;
18-
isFetched: boolean;
19-
trackingCategory: string;
20-
}
21-
2220
const columnHelper = createColumnHelper<EmbeddedWalletUser>();
2321

2422
const columns = [
@@ -75,12 +73,13 @@ const columns = [
7573
}),
7674
];
7775

78-
export const Users: React.FC<UsersProps> = ({
79-
wallets,
80-
isLoading,
81-
isFetched,
76+
export const Users = (props: {
77+
clientId: string;
78+
trackingCategory: string;
8279
}) => {
8380
const [onlyActive, setOnlyActive] = useState(true);
81+
const walletsQuery = useEmbeddedWallets(props.clientId);
82+
const wallets = walletsQuery?.data || [];
8483

8584
const activeWallets = useMemo(() => {
8685
if (!wallets) {
@@ -163,8 +162,8 @@ export const Users: React.FC<UsersProps> = ({
163162
title="active in-app wallets"
164163
data={itemsToShow}
165164
columns={columns}
166-
isLoading={isLoading}
167-
isFetched={isFetched}
165+
isLoading={walletsQuery.isLoading}
166+
isFetched={walletsQuery.isFetched}
168167
/>
169168

170169
{totalPages > 1 && (

0 commit comments

Comments
 (0)