From a9410b4d27bc8df40fd451e34d491a5123e666ab Mon Sep 17 00:00:00 2001 From: samepant Date: Fri, 19 Jan 2024 19:57:16 -0500 Subject: [PATCH] add pagination to collection grid --- .../src/components/NFTGrid/NFTGrid.module.css | 8 ++++ frontend/src/components/NFTGrid/index.tsx | 43 +++++++++++++++---- .../src/components/NFTItem/NFTItem.module.css | 4 ++ frontend/src/components/NFTItem/index.tsx | 23 ++++------ frontend/src/hooks/useCollection.ts | 21 ++++++--- 5 files changed, 70 insertions(+), 29 deletions(-) diff --git a/frontend/src/components/NFTGrid/NFTGrid.module.css b/frontend/src/components/NFTGrid/NFTGrid.module.css index ac292fe..2187b63 100644 --- a/frontend/src/components/NFTGrid/NFTGrid.module.css +++ b/frontend/src/components/NFTGrid/NFTGrid.module.css @@ -38,3 +38,11 @@ padding: 20px; font-size: 12px; } + +.pageButtons { + display: flex; + gap: 20px; + margin-top: 20px; + justify-content: center; + align-items: center; +} diff --git a/frontend/src/components/NFTGrid/index.tsx b/frontend/src/components/NFTGrid/index.tsx index 626b9c6..857c8de 100644 --- a/frontend/src/components/NFTGrid/index.tsx +++ b/frontend/src/components/NFTGrid/index.tsx @@ -9,6 +9,7 @@ import useTokenBalances from "../../hooks/useTokenBalances" import { getNFTContext, getNFTContexts } from "../../utils/getNFTContext" import { MoralisNFT } from "../../types/Token" import useCollection from "../../hooks/useCollection" +import Button from "../Button" interface Props { address: string @@ -57,11 +58,16 @@ export const AccountNftGrid: React.FC = ({ address }) => { export const CollectionNftGrid: React.FC = ({ address }) => { const chainId = useChainId() - const { data, isLoading, error } = useCollection({ + const { data, isLoading, fetchNextPage, fetchPreviousPage } = useCollection({ tokenAddress: address, chainId, }) - const nftBalances = data || [] + const currentPage = data?.pages[0] + const nftBalances = + (currentPage?.result as MoralisNFT[]) || ([] as MoralisNFT[]) + + const previousPageAvailable = (data?.pageParams[0] as string[]).length > 0 + const nextPageAvailable = currentPage?.cursor && currentPage.cursor.length > 0 const deployedMechs = useDeployedMechs(getNFTContexts(nftBalances), chainId) @@ -78,12 +84,31 @@ export const CollectionNftGrid: React.FC = ({ address }) => { if (isLoading) return return ( -
    - {nfts.map((nft, index) => ( -
  • - -
  • - ))} -
+ <> +
    + {nfts.map((nft, index) => ( +
  • + +
  • + ))} +
+
+ + + +
+ ) } diff --git a/frontend/src/components/NFTItem/NFTItem.module.css b/frontend/src/components/NFTItem/NFTItem.module.css index 8473ead..64dd07d 100644 --- a/frontend/src/components/NFTItem/NFTItem.module.css +++ b/frontend/src/components/NFTItem/NFTItem.module.css @@ -32,6 +32,10 @@ .tokenName { max-width: 68%; + color: var(--text-color); +} +.tokenName:hover { + filter: brightness(1.2); } .main { diff --git a/frontend/src/components/NFTItem/index.tsx b/frontend/src/components/NFTItem/index.tsx index 28aa0d0..ab78117 100644 --- a/frontend/src/components/NFTItem/index.tsx +++ b/frontend/src/components/NFTItem/index.tsx @@ -13,6 +13,8 @@ import { formatUnits } from "viem" import { MoralisNFT } from "../../types/Token" import { getNFTContext } from "../../utils/getNFTContext" import { AccountNftGrid } from "../NFTGrid" +import NFTMedia from "../NFTMedia" +import { Link } from "react-router-dom" interface Props { nft: MoralisNFT @@ -41,26 +43,19 @@ const NFTItem: React.FC = ({ nft, chainId }) => { return (
-

{name}

+ +

{name}

+

{nft.token_id}

- {(imageError || !metadata?.image) && ( -
- )} - {!imageError && metadata?.image && ( -
- {name} setImageError(true)} - /> -
- )} +
  • diff --git a/frontend/src/hooks/useCollection.ts b/frontend/src/hooks/useCollection.ts index bf095f1..7fa5cb7 100644 --- a/frontend/src/hooks/useCollection.ts +++ b/frontend/src/hooks/useCollection.ts @@ -1,4 +1,4 @@ -import { useQuery } from "@tanstack/react-query" +import { useInfiniteQuery, useQuery } from "@tanstack/react-query" import { MoralisApiListResponse, MoralisNFT } from "../types/Token" interface Props { @@ -12,21 +12,30 @@ if (!process.env.REACT_APP_PROXY_URL) { } const useCollection = ({ tokenAddress, chainId, page = 0 }: Props) => { - return useQuery({ + return useInfiniteQuery({ queryKey: ["collection", chainId, tokenAddress], - queryFn: async () => { + queryFn: async ({ pageParam }) => { if (!chainId || !tokenAddress) throw new Error("No chainId or token") - + const params = new URLSearchParams([ + ["cursor", pageParam], + ["media_items", "true"], + ]) // get collection metadata const nftRes = await fetch( - `${process.env.REACT_APP_PROXY_URL}/${chainId}/moralis/nft/${tokenAddress}?media_items=true` + `${ + process.env.REACT_APP_PROXY_URL + }/${chainId}/moralis/nft/${tokenAddress}?${params.toString()}` ) if (!nftRes.ok) { throw new Error("NFT request failed") } const collection = (await nftRes.json()) as MoralisApiListResponse - return collection.result as MoralisNFT[] + return collection }, + initialPageParam: "", + maxPages: 1, + getNextPageParam: (lastPage) => lastPage.cursor || "", + getPreviousPageParam: (firstPage) => firstPage.cursor || "", enabled: !!chainId && !!tokenAddress, }) }