Skip to content

Commit 3cc65b9

Browse files
authored
Explorer nft collection (#50)
* wip * wip * rm unused * rm unused * rm unused * fix building error * fix bugs * fix bugs * fix bugs * fix bugs * change image * fix a bug * handle metadata * get metadata from loopring * fix a bug
1 parent 567e433 commit 3cc65b9

File tree

24 files changed

+655
-142
lines changed

24 files changed

+655
-142
lines changed

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{
2+
}

components/SearchForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const SearchForm: React.FC<{ className?: string }> = ({ className }) => {
3232
type="text"
3333
name="query"
3434
className="h-10 w-full lg:w-auto flex-1 rounded-xl px-3 py-3 lg:py-0 placeholder-loopring-lightBlue placeholder-opacity-70"
35-
placeholder="Search for block, tx, or account ID"
35+
placeholder="Search for block, tx, account ID, Collection Address"
3636
onFocus={() => router.prefetch("/search")}
3737
/>
3838
<button

components/TabbedView.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ interface Props {
55
title: string;
66
view: any;
77
}>;
8+
currentTab: number;
9+
setCurrentTab: (tab: number) => void;
810
}
911

10-
const TabbedView: React.FC<Props> = ({ tabs }) => {
11-
const [currentTab, setCurrentTab] = React.useState(0);
12-
12+
const TabbedView: React.FC<Props> = ({ tabs, currentTab, setCurrentTab}) => {
13+
1314
return (
1415
<div>
1516
<div className="flex items-center">

components/accountDetail/AccountNFTs.tsx

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,18 @@
11
import React from 'react';
2-
32
import NFT from '../NFT';
43
import AppLink from '../AppLink';
5-
import { OrderDirection, useAccountNftSlotsQuery } from '../../generated/loopringExplorer';
4+
import { OrderDirection } from '../../generated/loopringExplorer';
65
import CursorPagination from '../CursorPagination';
6+
import { useAccountNFT } from '../../hooks/useAccountNFT';
7+
78

89
interface Props {
910
accountId: string;
1011
}
1112

1213
const AccountNFTs: React.FC<Props> = ({ accountId }) => {
1314
const TOTAL_COUNT = 8;
14-
const { data, fetchMore, error, loading } = useAccountNftSlotsQuery({
15-
variables: {
16-
where: {
17-
account: accountId,
18-
balance_gt: 0,
19-
},
20-
orderDirection: OrderDirection.Desc,
21-
},
22-
fetchPolicy: 'cache-and-network',
23-
});
15+
const {total, loading, error, data, fetchMore, setSearchInput, searchInput, onClickSearch, feedSearchInput} = useAccountNFT(accountId)
2416

2517
if (loading) {
2618
return null;
@@ -34,14 +26,50 @@ const AccountNFTs: React.FC<Props> = ({ accountId }) => {
3426
);
3527
}
3628

29+
const totalCount = total?.accountNFTSlots
30+
? (total?.accountNFTSlots?.length >= 100 ? "100+" : total?.accountNFTSlots?.length)
31+
: "--"
32+
3733
return (
3834
<div>
35+
<div style={{marginBottom: "10px"}}>
36+
<span style={{
37+
fontSize: "20px",
38+
marginRight: "20px",
39+
}}>{totalCount} Items</span>
40+
<input
41+
type="text"
42+
name="query"
43+
className="gray-color h-10 w-full lg:w-auto flex-1 rounded-xl px-3 py-3 lg:py-0 placeholder-loopring-lightBlue placeholder-opacity-70"
44+
placeholder="Search NFT by NFT ID"
45+
style={{
46+
background: "transparent",
47+
48+
border: "1px solid rgb(154 161 185 / var(--tw-text-opacity))",
49+
width: "300px",
50+
}}
51+
value={searchInput}
52+
onInput={(e) => {
53+
setSearchInput(e.currentTarget.value)
54+
}}
55+
/>
56+
<button
57+
type="submit"
58+
className="bg-loopring-darkBlue mt-4 lg:mt-0 py-1 px-10 ml-2 rounded-xl text-white h-10 dark:bg-loopring-dark-blue"
59+
onClick={() => {
60+
onClickSearch()
61+
}}
62+
>
63+
Search
64+
</button>
65+
</div>
3966
{data.accountNFTSlots.length === 0 ? (
4067
<div className="text-gray-400 text-2xl h-40 flex items-center justify-center w-full border">
4168
No NFTs to show
4269
</div>
4370
) : (
4471
<>
72+
4573
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-2">
4674
{data.accountNFTSlots.map((slot, index) => {
4775
const { id, balance, nft } = slot;
@@ -66,24 +94,42 @@ const AccountNFTs: React.FC<Props> = ({ accountId }) => {
6694
})}
6795
</div>
6896
<CursorPagination
69-
onNextClick={(fetchNext, afterCursor) =>
97+
onNextClick={(fetchNext, afterCursor) => {
7098
fetchNext({
7199
variables: {
72100
where: {
73101
account: accountId,
74102
id_lt: afterCursor,
75103
balance_gt: 0,
104+
...(
105+
feedSearchInput
106+
? {
107+
nft_: {
108+
nftID: feedSearchInput
109+
}
110+
}
111+
: {}
112+
)
76113
},
77114
},
78115
})
79-
}
116+
}}
80117
onPreviousClick={(fetchPrevious, beforeCursor) =>
81118
fetchPrevious({
82119
variables: {
83120
where: {
84121
account: accountId,
85122
id_gt: beforeCursor,
86123
balance_gt: 0,
124+
...(
125+
feedSearchInput
126+
? {
127+
nft_: {
128+
nftID: feedSearchInput
129+
}
130+
}
131+
: {}
132+
)
87133
},
88134
orderDirection: OrderDirection.Asc,
89135
},

components/nftDetail/NFTTransactions.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const NFTTransactions: React.FC<{ nftId: string }> = ({ nftId }) => {
3131
};
3232
}
3333
const { data, error, loading, fetchMore } = useTransactionNfTsQuery({
34+
fetchPolicy: 'no-cache',
3435
variables,
3536
});
3637

components/transactionDetail/pending/PendingTransactionFromAPI.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ const PendingTransactionFromAPI: React.FC<{ txId: string }> = ({ txId }) => {
5656
? data[dataKey[txType]][0].storageInfo?.storageId
5757
: null;
5858
const { data: confirmedTx } = useCheckTxConfirmation(accountID, tokenID, storageID);
59-
6059
const getParsedTxData = (transaction) => {
6160
switch (txType) {
6261
case 'trade':

generated/loopringExplorer.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type Scalars = {
1717
BigDecimal: any;
1818
BigInt: any;
1919
Bytes: any;
20+
Int8: any;
2021
};
2122

2223
export type Account = {
@@ -12866,6 +12867,7 @@ export type AccountTokenBalancesQuery = {
1286612867
export type AccountNftSlotsQueryVariables = Exact<{
1286712868
where?: InputMaybe<AccountNftSlot_Filter>;
1286812869
orderDirection?: InputMaybe<OrderDirection>;
12870+
first?: InputMaybe<Scalars['Int']>;
1286912871
}>;
1287012872

1287112873
export type AccountNftSlotsQuery = {
@@ -14812,8 +14814,8 @@ export function refetchAccountTokenBalancesQuery(variables?: AccountTokenBalance
1481214814
return { query: AccountTokenBalancesDocument, variables: variables };
1481314815
}
1481414816
export const AccountNftSlotsDocument = gql`
14815-
query accountNFTSlots($where: AccountNFTSlot_filter, $orderDirection: OrderDirection) {
14816-
accountNFTSlots(orderDirection: $orderDirection, orderBy: id, first: 8, where: $where) {
14817+
query accountNFTSlots($where: AccountNFTSlot_filter, $orderDirection: OrderDirection, $first: Int) {
14818+
accountNFTSlots(orderDirection: $orderDirection, orderBy: id, first: $first, where: $where) {
1481714819
id
1481814820
nft {
1481914821
...NFTFragment
@@ -14844,6 +14846,7 @@ export const AccountNftSlotsDocument = gql`
1484414846
* variables: {
1484514847
* where: // value for 'where'
1484614848
* orderDirection: // value for 'orderDirection'
14849+
* first: // value for 'first'
1484714850
* },
1484814851
* });
1484914852
*/

graphql/queries/account.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ export const FETCH_ACCOUNT_BALANCES = gql`
4242
`;
4343

4444
export const FETCH_ACCOUNT_SLOTS = gql`
45-
query accountNFTSlots($where: AccountNFTSlot_filter, $orderDirection: OrderDirection) {
46-
accountNFTSlots(orderDirection: $orderDirection, orderBy: id, first: 8, where: $where) {
45+
query accountNFTSlots($where: AccountNFTSlot_filter, $orderDirection: OrderDirection, $first: Int) {
46+
accountNFTSlots(orderDirection: $orderDirection, orderBy: id, first: $first, where: $where) {
4747
id
4848
nft {
4949
...NFTFragment

hooks/useAccountNFT.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { ApolloQueryResult, gql, useQuery } from "@apollo/client";
2+
import { useCallback, useEffect, useState } from "react";
3+
import client from "../graphql";
4+
import { OrderDirection, useAccountNftSlotsQuery } from "../generated/loopringExplorer";
5+
import { debounce } from "lodash";
6+
import useDebounce from "./useDebounce";
7+
8+
const ACCOUNT_NFT_SLOTS = gql`
9+
query accountNFTSlots($where: AccountNFTSlot_filter, $orderDirection: OrderDirection, $first: number) {
10+
accountNFTSlots(orderDirection: $orderDirection, orderBy: id, first: $first, where: $where) {
11+
id
12+
}
13+
}
14+
`;
15+
16+
export const useAccountNFT = (accountId: string) => {
17+
const SUMMARY = 100;
18+
const [searchInput, setSearchInput] = useState('')
19+
const [feedSearchInput, setFeedSearchInput] = useState('')
20+
const { data, fetchMore, error, loading, refetch } = useAccountNftSlotsQuery({
21+
variables: {
22+
where: {
23+
account: accountId,
24+
balance_gt: 0,
25+
...(
26+
feedSearchInput
27+
? {
28+
nft_: {
29+
nftID: feedSearchInput
30+
}
31+
}
32+
: {}
33+
)
34+
},
35+
first: 8,
36+
orderDirection: OrderDirection.Desc,
37+
},
38+
fetchPolicy: 'cache-and-network',
39+
});
40+
const onClickSearch = useCallback(() => {
41+
setFeedSearchInput(searchInput)
42+
}, [searchInput])
43+
useEffect(() => {
44+
refetch()
45+
}, [feedSearchInput])
46+
const { data: total } = useAccountNftSlotsQuery({
47+
fetchPolicy: 'no-cache',
48+
query: ACCOUNT_NFT_SLOTS,
49+
variables: {
50+
where: {
51+
account: accountId,
52+
balance_gt: 0,
53+
...(
54+
feedSearchInput
55+
? {
56+
nft_: {
57+
nftID: feedSearchInput
58+
}
59+
}
60+
: {}
61+
)
62+
},
63+
first: SUMMARY,
64+
orderDirection: OrderDirection.Desc,
65+
},
66+
})
67+
return {total, loading, error, data, fetchMore, setSearchInput, searchInput, onClickSearch, feedSearchInput}
68+
}

hooks/useDebounce.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { useEffect, useState } from "react";
2+
3+
function useDebounce(value, delay) {
4+
const [debouncedValue, setDebouncedValue] = useState(value);
5+
6+
useEffect(() => {
7+
const timer = setTimeout(() => {
8+
setDebouncedValue(value);
9+
}, delay);
10+
11+
return () => {
12+
clearTimeout(timer);
13+
};
14+
}, [value, delay]);
15+
16+
return debouncedValue;
17+
}
18+
export default useDebounce

0 commit comments

Comments
 (0)