diff --git a/apps/portal/src/components/others/AllSupportedWallets.tsx b/apps/portal/src/components/others/AllSupportedWallets.tsx index c9982d4c726..81150e640f7 100644 --- a/apps/portal/src/components/others/AllSupportedWallets.tsx +++ b/apps/portal/src/components/others/AllSupportedWallets.tsx @@ -1,11 +1,23 @@ +"use client"; + +import { + QueryClient, + QueryClientProvider, + useQuery, +} from "@tanstack/react-query"; +import { ChevronLeftIcon, ChevronRightIcon, SearchIcon } from "lucide-react"; import Image from "next/image"; +import { useMemo, useState } from "react"; import { getAllWalletsList, getWalletInfo, type WalletId, } from "thirdweb/wallets"; -import { DocLink, InlineCode } from "../Document"; +import { DocLink } from "../Document/DocLink"; +import { InlineCode } from "../Document/InlineCode"; import { Table, TBody, Td, Th, Tr } from "../Document/Table"; +import { Button } from "../ui/button"; +import { Input } from "../ui/input"; const specialWallets: { [key in WalletId]?: boolean; @@ -14,44 +26,215 @@ const specialWallets: { smart: true, }; -export async function AllSupportedWallets() { - const wallets = await getAllWalletsList(); +const ITEMS_PER_PAGE = 20; + +const queryClient = new QueryClient(); + +export function AllSupportedWallets() { + return ( + + + + ); +} + +function AllSupportedWalletsContent() { + const [searchQuery, setSearchQuery] = useState(""); + const [currentPage, setCurrentPage] = useState(1); + + const { data: wallets, isLoading: loading } = useQuery({ + queryKey: ["allWalletsList"], + queryFn: async () => { + const allWallets = await getAllWalletsList(); + return allWallets + .filter((w) => !(w.id in specialWallets)) + .map((w) => ({ + id: w.id, + name: w.name, + })); + }, + staleTime: 1000 * 60 * 5, // 5 minutes + }); + + const filteredWallets = useMemo(() => { + if (!searchQuery) return wallets || []; + if (!wallets) return []; + + setCurrentPage(1); + const query = searchQuery.toLowerCase(); + return wallets.filter( + (wallet) => + wallet.name.toLowerCase().includes(query) || + wallet.id.toLowerCase().includes(query), + ); + }, [wallets, searchQuery]); + + const totalPages = Math.ceil(filteredWallets.length / ITEMS_PER_PAGE); + const startIndex = (currentPage - 1) * ITEMS_PER_PAGE; + const endIndex = startIndex + ITEMS_PER_PAGE; + const currentWallets = filteredWallets.slice(startIndex, endIndex); + + const handlePreviousPage = () => { + setCurrentPage((prev) => Math.max(prev - 1, 1)); + }; + + const handleNextPage = () => { + setCurrentPage((prev) => Math.min(prev + 1, totalPages)); + }; + + const handlePageClick = (page: number) => { + setCurrentPage(page); + }; + + if (loading) { + return ( +
+
Loading wallets...
+
+ ); + } return ( - - - - - - - - {wallets - .filter((w) => !(w.id in specialWallets)) - .map((w) => { - return ( - +
+ {/* Search Input */} +
+ + setSearchQuery(e.target.value)} + className="pl-10" + /> +
+ + {/* Results count */} +
+ {filteredWallets.length === wallets?.length + ? `Showing ${filteredWallets.length} wallets` + : `Found ${filteredWallets.length} of ${wallets?.length} wallets`} +
+ + {/* Table */} +
Wallet ID
+ + + + + + + {currentWallets.length === 0 ? ( + + + + ) : ( + currentWallets.map((wallet) => ( + - ); - })} - -
WalletID
+ {searchQuery + ? "No wallets found matching your search." + : "No wallets available."} +
- - {w.name} + + {wallet.name} - +
+ )) + )} + + + + {/* Pagination */} + {totalPages > 1 && ( +
+
+ Page {currentPage} of {totalPages} + {filteredWallets.length > 0 && ( + + (showing {startIndex + 1}- + {Math.min(endIndex, filteredWallets.length)} of{" "} + {filteredWallets.length}) + + )} +
+ +
+ + + {/* Page numbers */} +
+ {Array.from({ length: Math.min(5, totalPages) }, (_, i) => { + let pageNumber: number; + + if (totalPages <= 5) { + pageNumber = i + 1; + } else if (currentPage <= 3) { + pageNumber = i + 1; + } else if (currentPage >= totalPages - 2) { + pageNumber = totalPages - 4 + i; + } else { + pageNumber = currentPage - 2 + i; + } + + return ( + + ); + })} +
+ + +
+
+ )} + ); } -async function WalletImage(props: { id: WalletId }) { - const img = await getWalletInfo(props.id, true); +function WalletImage(props: { id: WalletId }) { + const { data: img } = useQuery({ + queryKey: ["wallet-image", props.id], + queryFn: () => getWalletInfo(props.id, true), + staleTime: 1000 * 60 * 60 * 24, // 24 hours + }); + + if (!img) { + return ( +
+ ); + } + return ( );