Skip to content

Commit 2dbb9e2

Browse files
[Dashboard] Move server wallet sections to wallets tab (#8174)
1 parent 00b8adf commit 2dbb9e2

File tree

4 files changed

+110
-43
lines changed

4 files changed

+110
-43
lines changed

apps/dashboard/src/@/components/in-app-wallet-users-content/AdvancedSearchInput.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function AdvancedSearchInput(props: {
4646
value={searchType}
4747
onValueChange={(value) => setSearchType(value as SearchType)}
4848
>
49-
<SelectTrigger className="w-[140px] bg-card">
49+
<SelectTrigger className="w-[140px] bg-background rounded-full">
5050
<SelectValue />
5151
</SelectTrigger>
5252
<SelectContent>
@@ -61,7 +61,7 @@ export function AdvancedSearchInput(props: {
6161
<div className="flex flex-1">
6262
<div className="relative flex-1">
6363
<Input
64-
className="bg-card pl-9 border-r-0 rounded-r-none"
64+
className="bg-background pl-9 border-r-0 rounded-r-none rounded-l-full"
6565
placeholder={`Search by ${searchType}...`}
6666
value={query}
6767
onChange={(e) => setQuery(e.target.value)}
@@ -86,7 +86,7 @@ export function AdvancedSearchInput(props: {
8686
onClick={handleSearch}
8787
variant="outline"
8888
disabled={!query.trim() || props.isLoading}
89-
className="rounded-l-none gap-2 bg-card disabled:opacity-100"
89+
className="rounded-l-none rounded-r-full gap-2 bg-background disabled:opacity-100"
9090
>
9191
{props.isLoading && <Spinner className="size-4" />}
9292
Search

apps/dashboard/src/@/components/in-app-wallet-users-content/in-app-wallet-users-content.tsx

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

33
import { createColumnHelper } from "@tanstack/react-table";
44
import { format } from "date-fns";
5-
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react";
5+
import { ArrowLeftIcon, ArrowRightIcon, UserIcon } from "lucide-react";
66
import Papa from "papaparse";
77
import { useCallback, useMemo, useState } from "react";
88
import type { ThirdwebClient } from "thirdweb";
@@ -264,11 +264,24 @@ export function InAppWalletUsersPageContent(
264264

265265
return (
266266
<div>
267-
<div className="flex flex-col gap-4">
268-
{/* Top section */}
269-
<div className="flex flex-col gap-4">
270-
<div className="flex flex-col md:flex-row lg:items-center justify-end gap-3">
271-
<div className="w-full max-w-lg">
267+
<div className="overflow-hidden rounded-xl border border-border bg-card">
268+
<div className="flex flex-col lg:flex-row lg:justify-between p-4 lg:px-6 py-5 lg:items-center gap-5">
269+
<div>
270+
<div className="flex mb-3">
271+
<div className="p-2 rounded-full bg-background border border-border">
272+
<UserIcon className="size-5 text-muted-foreground" />
273+
</div>
274+
</div>
275+
<h2 className="font-semibold text-2xl tracking-tight">
276+
User Wallets
277+
</h2>
278+
<p className="text-muted-foreground text-sm">
279+
View and manage your project's users
280+
</p>
281+
</div>
282+
283+
<div className="flex flex-col items-start lg:items-end gap-2.5 border-t lg:border-t-0 pt-5 lg:pt-0 border-dashed">
284+
<div className="w-full lg:w-auto lg:min-w-[320px]">
272285
<AdvancedSearchInput
273286
onSearch={handleSearch}
274287
onClear={handleClearSearch}
@@ -277,7 +290,7 @@ export function InAppWalletUsersPageContent(
277290
/>
278291
</div>
279292
<Button
280-
className="gap-2 bg-card"
293+
className="gap-2 bg-background rounded-full"
281294
disabled={wallets.length === 0 || isPending}
282295
onClick={downloadCSV}
283296
variant="outline"
@@ -298,11 +311,11 @@ export function InAppWalletUsersPageContent(
298311
data={wallets}
299312
isFetched={walletsQuery.isFetched}
300313
isPending={walletsQuery.isPending}
301-
tableContainerClassName="rounded-b-none"
314+
tableContainerClassName="rounded-none border-x-0 border-b-0"
302315
title="in-app wallets"
303316
/>
304317

305-
<div className="flex justify-center gap-3 rounded-b-lg border border-t-0 bg-card p-6">
318+
<div className="flex justify-center gap-3 border-t bg-card p-6">
306319
<Button
307320
className="gap-2 bg-background"
308321
disabled={activePage === 1 || walletsQuery.isPending}

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/wallet-table/wallet-table-ui.client.tsx

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,22 @@ export function ServerWalletsTableUI({
9696
</div>
9797

9898
<div className="flex flex-col items-start lg:items-end gap-5 border-t lg:border-t-0 pt-5 lg:pt-0 border-dashed">
99-
<SingleNetworkSelector
100-
chainId={selectedChainId}
101-
onChange={setSelectedChainId}
102-
client={client}
103-
disableChainId
104-
className="w-fit min-w-[180px] rounded-full bg-background hover:bg-accent/50"
105-
placeholder="Select network"
106-
popoverContentClassName="!w-[320px] rounded-xl overflow-hidden"
107-
/>
99+
<div className="flex flex-row gap-2.5">
100+
<CreateServerWallet
101+
managementAccessToken={managementAccessToken}
102+
project={project}
103+
teamSlug={teamSlug}
104+
/>
105+
<SingleNetworkSelector
106+
chainId={selectedChainId}
107+
onChange={setSelectedChainId}
108+
client={client}
109+
disableChainId
110+
className="w-fit min-w-[180px] rounded-full bg-background hover:bg-accent/50"
111+
placeholder="Select network"
112+
popoverContentClassName="!w-[320px] rounded-xl overflow-hidden"
113+
/>
114+
</div>
108115

109116
<div className="flex items-center gap-2.5">
110117
<Label
@@ -187,25 +194,10 @@ export function ServerWalletsTableUI({
187194
<XIcon className="size-5 text-muted-foreground" />
188195
</div>
189196
<p className="text-muted-foreground">No server wallets found</p>
190-
<CreateServerWallet
191-
managementAccessToken={managementAccessToken}
192-
project={project}
193-
teamSlug={teamSlug}
194-
/>
195197
</div>
196198
)}
197199
</TableContainer>
198200

199-
{wallets.length > 0 && (
200-
<div className="flex justify-end items-center p-4 py-5 lg:px-6 border-t">
201-
<CreateServerWallet
202-
managementAccessToken={managementAccessToken}
203-
project={project}
204-
teamSlug={teamSlug}
205-
/>
206-
</div>
207-
)}
208-
209201
{totalPages > 1 && (
210202
<div className="flex flex-col items-center border-t p-6">
211203
<div className="mb-4 text-muted-foreground text-sm">

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { createVaultClient, listEoas } from "@thirdweb-dev/vault-sdk";
12
import { redirect } from "next/navigation";
23
import { ResponsiveSearchParamsProvider } from "responsive-rsc";
34
import { getAuthToken } from "@/api/auth-token";
@@ -6,10 +7,13 @@ import type { DurationId } from "@/components/analytics/date-range-selector";
67
import { ResponsiveTimeFilters } from "@/components/analytics/responsive-time-filters";
78
import { ProjectPage } from "@/components/blocks/project-page/project-page";
89
import { InAppWalletUsersPageContent } from "@/components/in-app-wallet-users-content/in-app-wallet-users-content";
10+
import { NEXT_PUBLIC_THIRDWEB_VAULT_URL } from "@/constants/public-envs";
911
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
1012
import { WalletProductIcon } from "@/icons/WalletProductIcon";
1113
import { getFiltersFromSearchParams } from "@/lib/time";
1214
import { loginRedirect } from "@/utils/redirects";
15+
import type { Wallet } from "../transactions/server-wallets/wallet-table/types";
16+
import { ServerWalletsTable } from "../transactions/server-wallets/wallet-table/wallet-table";
1317
import { InAppWalletAnalytics } from "./analytics/chart";
1418
import { InAppWalletsSummary } from "./analytics/chart/Summary";
1519

@@ -20,6 +24,7 @@ export default async function Page(props: {
2024
to?: string;
2125
type?: string;
2226
interval?: string;
27+
page?: string;
2328
}>;
2429
}) {
2530
const [searchParams, params] = await Promise.all([
@@ -40,12 +45,47 @@ export default async function Page(props: {
4045
to: searchParams.to,
4146
});
4247

43-
const project = await getProject(params.team_slug, params.project_slug);
48+
const [vaultClient, project] = await Promise.all([
49+
createVaultClient({
50+
baseUrl: NEXT_PUBLIC_THIRDWEB_VAULT_URL,
51+
}).catch(() => undefined),
52+
getProject(params.team_slug, params.project_slug),
53+
]);
4454

4555
if (!project) {
4656
redirect(`/team/${params.team_slug}`);
4757
}
4858

59+
const projectEngineCloudService = project.services.find(
60+
(service) => service.name === "engineCloud",
61+
);
62+
63+
const managementAccessToken =
64+
projectEngineCloudService?.managementAccessToken;
65+
66+
// Fetch server wallets with pagination (5 per page)
67+
const pageSize = 5;
68+
const currentPage = Number.parseInt(searchParams.page ?? "1");
69+
70+
const eoas =
71+
vaultClient && managementAccessToken
72+
? await listEoas({
73+
client: vaultClient,
74+
request: {
75+
auth: {
76+
accessToken: managementAccessToken,
77+
},
78+
options: {
79+
page: currentPage - 1,
80+
// @ts-expect-error - TODO: fix this
81+
page_size: pageSize,
82+
},
83+
},
84+
})
85+
: { data: { items: [], totalRecords: 0 }, error: null, success: true };
86+
87+
const serverWallets = eoas.data?.items as Wallet[] | undefined;
88+
4989
const client = getClientThirdwebClient({
5090
jwt: authToken,
5191
teamId: project.teamId,
@@ -103,12 +143,34 @@ export default async function Page(props: {
103143
authToken={authToken}
104144
/>
105145

106-
<InAppWalletUsersPageContent
107-
authToken={authToken}
108-
client={client}
109-
projectClientId={project.publishableKey}
110-
teamId={project.teamId}
111-
/>
146+
{/* Server Wallets Section */}
147+
<div className="flex flex-col gap-4">
148+
{eoas.error ? null : (
149+
<ServerWalletsTable
150+
client={client}
151+
currentPage={currentPage}
152+
managementAccessToken={managementAccessToken ?? undefined}
153+
project={project}
154+
teamSlug={params.team_slug}
155+
totalPages={Math.ceil(eoas.data.totalRecords / pageSize)}
156+
totalRecords={eoas.data.totalRecords}
157+
wallets={serverWallets ?? []}
158+
/>
159+
)}
160+
</div>
161+
162+
{/* User Wallets Section */}
163+
<div className="flex flex-col gap-4">
164+
<h2 className="font-semibold text-2xl tracking-tight">
165+
User wallets
166+
</h2>
167+
<InAppWalletUsersPageContent
168+
authToken={authToken}
169+
client={client}
170+
projectClientId={project.publishableKey}
171+
teamId={project.teamId}
172+
/>
173+
</div>
112174
</div>
113175
</ProjectPage>
114176
</ResponsiveSearchParamsProvider>

0 commit comments

Comments
 (0)