Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions apps/dashboard/src/@3rdweb-sdk/react/hooks/useEmbeddedWallets.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
keepPreviousData,
useMutation,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { THIRDWEB_EWS_API_HOST } from "constants/urls";
import { useActiveAccount } from "thirdweb/react";
import type { WalletUser } from "thirdweb/wallets";
Expand Down Expand Up @@ -33,7 +28,6 @@ const fetchAccountList = ({
const json = await res.json();
return json as {
users: WalletUser[];
totalPages: number;
};
};
};
Expand All @@ -57,11 +51,11 @@ export function useEmbeddedWallets(params: {
clientId,
pageNumber: page,
}),
placeholderData: keepPreviousData,
enabled: !!address && !!clientId,
});
}

// TODO: fetching list of all users needs to be improved
export function useAllEmbeddedWallets(params: {
authToken: string;
}) {
Expand All @@ -70,15 +64,13 @@ export function useAllEmbeddedWallets(params: {
const address = useActiveAccount()?.address;

return useMutation({
mutationFn: async ({
clientId,
totalPages,
}: { clientId: string; totalPages: number }) => {
const walletRes = [];
for (let page = 1; page <= totalPages; page++) {
const res = queryClient.fetchQuery<{
mutationFn: async ({ clientId }: { clientId: string }) => {
const responses: WalletUser[] = [];
let page = 1;

while (true) {
const res = await queryClient.fetchQuery<{
users: WalletUser[];
totalPages: number;
}>({
queryKey: embeddedWalletsKeys.embeddedWallets(
address || "",
Expand All @@ -91,9 +83,16 @@ export function useAllEmbeddedWallets(params: {
pageNumber: page,
}),
});
walletRes.push(res);

if (res.users.length === 0) {
break;
}

page++;
responses.push(...res.users);
}
return (await Promise.all(walletRes)).flatMap((res) => res.users);

return responses;
},
});
}
77 changes: 40 additions & 37 deletions apps/dashboard/src/components/embedded-wallets/Users/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";

import { WalletAddress } from "@/components/blocks/wallet-address";
import { PaginationButtons } from "@/components/pagination-buttons";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import {
Expand All @@ -17,6 +16,7 @@ import {
import { createColumnHelper } from "@tanstack/react-table";
import { TWTable } from "components/shared/TWTable";
import { format } from "date-fns/format";
import { ArrowLeft, ArrowRight } from "lucide-react";
import Papa from "papaparse";
import { useCallback, useState } from "react";
import type { WalletUser } from "thirdweb/wallets";
Expand Down Expand Up @@ -97,21 +97,18 @@ const columns = [
}),
];

export const InAppWalletUsersPageContent = (props: {
export function InAppWalletUsersPageContent(props: {
clientId: string;
trackingCategory: string;
authToken: string;
}) => {
}) {
const [activePage, setActivePage] = useState(1);
const walletsQuery = useEmbeddedWallets({
authToken: props.authToken,
clientId: props.clientId,
page: activePage,
});
const { users: wallets, totalPages } = walletsQuery?.data || {
users: [],
totalPages: 1,
};
const wallets = walletsQuery?.data?.users || [];
const { mutateAsync: getAllEmbeddedWallets, isPending } =
useAllEmbeddedWallets({
authToken: props.authToken,
Expand All @@ -123,7 +120,6 @@ export const InAppWalletUsersPageContent = (props: {
}
const usersWallets = await getAllEmbeddedWallets({
clientId: props.clientId,
totalPages,
});
const csv = Papa.unparse(
usersWallets.map((row) => {
Expand All @@ -144,13 +140,13 @@ export const InAppWalletUsersPageContent = (props: {
tempLink.href = csvUrl;
tempLink.setAttribute("download", "download.csv");
tempLink.click();
}, [wallets, props.clientId, totalPages, getAllEmbeddedWallets]);
}, [wallets, props.clientId, getAllEmbeddedWallets]);

return (
<div>
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-4">
{/* Top section */}
<div className="flex items-center justify-between">
<div className="flex items-center justify-end">
<Button
disabled={wallets.length === 0 || isPending}
variant="outline"
Expand All @@ -161,35 +157,42 @@ export const InAppWalletUsersPageContent = (props: {
{isPending && <Spinner className="size-4" />}
Download as .csv
</Button>

<div className="flex items-center justify-end gap-2">
{walletsQuery.isPlaceholderData && (
<>
<Spinner className="size-4" />
<p className="text-muted-foreground text-sm">
Loading page {activePage} of {totalPages}
</p>
</>
)}
</div>
</div>

<TWTable
title="in-app wallets"
data={wallets}
columns={columns}
isPending={walletsQuery.isPending}
isFetched={walletsQuery.isFetched}
/>

{totalPages > 1 && (
<PaginationButtons
activePage={activePage}
onPageClick={setActivePage}
totalPages={totalPages}
<div>
<TWTable
title="in-app wallets"
data={wallets}
columns={columns}
isPending={walletsQuery.isPending}
isFetched={walletsQuery.isFetched}
tableContainerClassName="rounded-b-none"
/>
)}

<div className="flex justify-center gap-3 rounded-b-lg border border-t-0 bg-card p-6">
<Button
variant="outline"
size="sm"
className="gap-2 bg-background"
onClick={() => setActivePage((p) => Math.max(1, p - 1))}
disabled={activePage === 1 || walletsQuery.isPending}
>
<ArrowLeft className="size-4" />
Previous
</Button>
<Button
variant="outline"
size="sm"
className="gap-2 bg-background"
onClick={() => setActivePage((p) => p + 1)}
disabled={wallets.length === 0 || walletsQuery.isPending}
>
Next
<ArrowRight className="size-4" />
</Button>
</div>
</div>
</div>
</div>
);
};
}
4 changes: 2 additions & 2 deletions apps/dashboard/src/components/shared/TWTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,10 @@ export function TWTable<TRowData>(tableProps: TWTableProps<TRowData>) {
{!tableProps.isPending &&
tableProps.data.length === 0 &&
tableProps.isFetched && (
<div className="flex items-center justify-center">
<div className="flex items-center justify-center py-16">
<div className="flex items-center gap-4 py-4">
<p className="text-muted-foreground text-sm">
No {pluralize(tableProps.title, 0, false)} found.
No {pluralize(tableProps.title, 0, false)} found
</p>
</div>
</div>
Expand Down
Loading