feat: UI switch grid list on nfa listing (#261)
* feat: display nfas grid or list * feat: add list view * chore: rename component * style: add margin * chore: add skeleton for nfa list * chore: add TODO comment * Update ui/src/views/explore/explore-list/nfa-list/nfa-list.styles.ts Co-authored-by: Felipe Mendes <zo.fmendes@gmail.com> * Update ui/src/views/explore/explore-list/nfa-list/nfa-list.styles.ts Co-authored-by: Felipe Mendes <zo.fmendes@gmail.com> * merge develop * style: responsiveness for explore view * chore: remove old file --------- Co-authored-by: Felipe Mendes <zo.fmendes@gmail.com>
This commit is contained in:
parent
3a4cd5fa7d
commit
6cf32bedb9
|
|
@ -22,6 +22,9 @@ query lastNFAsPaginated(
|
||||||
accessPoints {
|
accessPoints {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
owner {
|
||||||
|
id
|
||||||
|
}
|
||||||
verified
|
verified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,6 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||||
|
|
||||||
return props[size as 'sm' | 'md' | 'lg'];
|
return props[size as 'sm' | 'md' | 'lg'];
|
||||||
}, [size]);
|
}, [size]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
@ -73,7 +72,6 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||||
size={size}
|
size={size}
|
||||||
{...rest}
|
{...rest}
|
||||||
css={{
|
css={{
|
||||||
padding: 0,
|
|
||||||
minWidth,
|
minWidth,
|
||||||
fontSize,
|
fontSize,
|
||||||
borderRadius: isRound ? '$full' : undefined,
|
borderRadius: isRound ? '$full' : undefined,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { AiFillCheckCircle } from '@react-icons/all-files/ai/AiFillCheckCircle';
|
import { AiFillCheckCircle } from '@react-icons/all-files/ai/AiFillCheckCircle';
|
||||||
import { AiOutlineCheck } from '@react-icons/all-files/ai/AiOutlineCheck';
|
import { AiOutlineCheck } from '@react-icons/all-files/ai/AiOutlineCheck';
|
||||||
import { AiOutlineTwitter } from '@react-icons/all-files/ai/AiOutlineTwitter';
|
import { AiOutlineTwitter } from '@react-icons/all-files/ai/AiOutlineTwitter';
|
||||||
|
import { AiOutlineUnorderedList } from '@react-icons/all-files/ai/AiOutlineUnorderedList';
|
||||||
import { BiGitBranch } from '@react-icons/all-files/bi/BiGitBranch';
|
import { BiGitBranch } from '@react-icons/all-files/bi/BiGitBranch';
|
||||||
import { BiSearch } from '@react-icons/all-files/bi/BiSearch';
|
import { BiSearch } from '@react-icons/all-files/bi/BiSearch';
|
||||||
import { BsFillSquareFill } from '@react-icons/all-files/bs/BsFillSquareFill';
|
import { BsFillSquareFill } from '@react-icons/all-files/bs/BsFillSquareFill';
|
||||||
|
|
@ -12,6 +13,7 @@ import { IoArrowBackCircleSharp } from '@react-icons/all-files/io5/IoArrowBackCi
|
||||||
import { IoCheckmarkCircleSharp } from '@react-icons/all-files/io5/IoCheckmarkCircleSharp';
|
import { IoCheckmarkCircleSharp } from '@react-icons/all-files/io5/IoCheckmarkCircleSharp';
|
||||||
import { IoClose } from '@react-icons/all-files/io5/IoClose';
|
import { IoClose } from '@react-icons/all-files/io5/IoClose';
|
||||||
import { IoCloudUploadSharp } from '@react-icons/all-files/io5/IoCloudUploadSharp';
|
import { IoCloudUploadSharp } from '@react-icons/all-files/io5/IoCloudUploadSharp';
|
||||||
|
import { IoGridOutline } from '@react-icons/all-files/io5/IoGridOutline';
|
||||||
import { IoInformationCircleSharp } from '@react-icons/all-files/io5/IoInformationCircleSharp';
|
import { IoInformationCircleSharp } from '@react-icons/all-files/io5/IoInformationCircleSharp';
|
||||||
import { IoLogoGithub } from '@react-icons/all-files/io5/IoLogoGithub';
|
import { IoLogoGithub } from '@react-icons/all-files/io5/IoLogoGithub';
|
||||||
import { MdVerifiedUser } from '@react-icons/all-files/md/MdVerifiedUser';
|
import { MdVerifiedUser } from '@react-icons/all-files/md/MdVerifiedUser';
|
||||||
|
|
@ -43,7 +45,9 @@ export const IconLibrary = Object.freeze({
|
||||||
'fleek-logo': FleekLogo,
|
'fleek-logo': FleekLogo,
|
||||||
'fleek-name': FleekName,
|
'fleek-name': FleekName,
|
||||||
github: IoLogoGithub,
|
github: IoLogoGithub,
|
||||||
|
grid: IoGridOutline,
|
||||||
info: IoInformationCircleSharp,
|
info: IoInformationCircleSharp,
|
||||||
|
list: AiOutlineUnorderedList,
|
||||||
menu: FaBars,
|
menu: FaBars,
|
||||||
metamask: MetamaskIcon, //remove if not used
|
metamask: MetamaskIcon, //remove if not used
|
||||||
opensea: OpenseaIcon,
|
opensea: OpenseaIcon,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { Explore } from '../explore.context';
|
import { Explore } from '../explore.context';
|
||||||
import { NFAListFragment } from './nfa-list.fragment';
|
import { NFAsContainerFragment } from './nfa-list';
|
||||||
import { NFASearchFragment } from './nfa-search.fragment';
|
import { NFASearchFragment } from './nfa-search.fragment';
|
||||||
|
|
||||||
export const ExploreListFragment: React.FC = () => {
|
export const ExploreListFragment: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Explore.Provider>
|
<Explore.Provider>
|
||||||
<NFASearchFragment />
|
<NFASearchFragment />
|
||||||
<NFAListFragment />
|
<NFAsContainerFragment />
|
||||||
</Explore.Provider>
|
</Explore.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import { styled } from '@/theme';
|
|
||||||
|
|
||||||
export const NFAListFragmentStyles = {
|
|
||||||
Container: styled('div', {
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: 'repeat(auto-fill, minmax(12.5rem, 1fr))',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: '$6',
|
|
||||||
my: '$6',
|
|
||||||
minHeight: '50vh',
|
|
||||||
marginBottom: '30vh', // TODO: remove this if we add page footer
|
|
||||||
|
|
||||||
'@media (min-width: 1080px)': {
|
|
||||||
gridTemplateColumns: 'repeat(auto-fill, minmax(15rem, 1fr))',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
EmptyMessage: styled('span', {
|
|
||||||
padding: '$2 $3 $4 $3',
|
|
||||||
textAlign: 'center',
|
|
||||||
color: '$slate11',
|
|
||||||
width: '100%',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './nfas-container.fragment';
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { NFACard, NFACardSkeleton } from '@/components';
|
||||||
|
import { lastNFAsPaginatedQuery } from '@/graphclient';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
|
||||||
|
const LoadingSkeletons: React.FC = () => (
|
||||||
|
<>
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
<NFACardSkeleton />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
type NFAGridFragmentProps = {
|
||||||
|
tokens: Array<lastNFAsPaginatedQuery['tokens'][0]>;
|
||||||
|
isLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFAGridFragment: React.FC<NFAGridFragmentProps> = ({
|
||||||
|
tokens,
|
||||||
|
isLoading,
|
||||||
|
}: NFAGridFragmentProps) => (
|
||||||
|
<S.Container>
|
||||||
|
{tokens.map((token) => (
|
||||||
|
<NFACard data={token} key={token.id} />
|
||||||
|
))}
|
||||||
|
|
||||||
|
{isLoading && <LoadingSkeletons />}
|
||||||
|
|
||||||
|
{!isLoading && tokens.length === 0 && (
|
||||||
|
<S.EmptyMessage>Nothing found.</S.EmptyMessage>
|
||||||
|
)}
|
||||||
|
</S.Container>
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { Text } from '@/components';
|
||||||
|
import { lastNFAsPaginatedQuery } from '@/graphclient';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
import { NFARow } from './nfa-row.fragment';
|
||||||
|
import { NFARowSkeletonFragment } from './nfa-row.skeleton';
|
||||||
|
|
||||||
|
const LoadingListSkeleton: React.FC = () => (
|
||||||
|
<>
|
||||||
|
<NFARowSkeletonFragment />
|
||||||
|
<NFARowSkeletonFragment />
|
||||||
|
<NFARowSkeletonFragment />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
type NFAListFragmentProps = {
|
||||||
|
tokens: Array<lastNFAsPaginatedQuery['tokens'][0]>;
|
||||||
|
isLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFAListFragment: React.FC<NFAListFragmentProps> = ({
|
||||||
|
tokens,
|
||||||
|
isLoading,
|
||||||
|
}: NFAListFragmentProps) => {
|
||||||
|
return (
|
||||||
|
<S.Table.Container>
|
||||||
|
<S.Table.Root>
|
||||||
|
<S.Table.Head>
|
||||||
|
<S.Table.Row>
|
||||||
|
<S.Table.Data>NAME</S.Table.Data>
|
||||||
|
<S.Table.Data># HOSTED</S.Table.Data>
|
||||||
|
<S.Table.Data>Owner</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
</S.Table.Head>
|
||||||
|
<S.Table.Body>
|
||||||
|
{tokens.map((token) => (
|
||||||
|
<NFARow token={token} key={token.id} />
|
||||||
|
))}
|
||||||
|
|
||||||
|
{isLoading && <LoadingListSkeleton />}
|
||||||
|
|
||||||
|
{!isLoading && tokens.length === 0 && (
|
||||||
|
<S.Table.Row>
|
||||||
|
<S.Table.Data align="center" colSpan={5}>
|
||||||
|
<Text>No results</Text>
|
||||||
|
</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
)}
|
||||||
|
</S.Table.Body>
|
||||||
|
</S.Table.Root>
|
||||||
|
</S.Table.Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Skeleton } from '@/components';
|
||||||
|
import { styled } from '@/theme';
|
||||||
|
|
||||||
|
export const NFAListFragmentStyles = {
|
||||||
|
Container: styled('div', {
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: 'repeat(auto-fill, minmax(12.5rem, 1fr))',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
gap: '$6',
|
||||||
|
my: '$6',
|
||||||
|
minHeight: '50vh',
|
||||||
|
marginBottom: '30vh', // TODO: remove this if we add page footer
|
||||||
|
|
||||||
|
'@media (min-width: 1080px)': {
|
||||||
|
gridTemplateColumns: 'repeat(auto-fill, minmax(15rem, 1fr))',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
EmptyMessage: styled('span', {
|
||||||
|
padding: '$2 $3 $4 $3',
|
||||||
|
textAlign: 'center',
|
||||||
|
color: '$slate11',
|
||||||
|
width: '100%',
|
||||||
|
}),
|
||||||
|
Table: {
|
||||||
|
Container: styled('div', {
|
||||||
|
marginTop: '$6',
|
||||||
|
padding: '0 $5',
|
||||||
|
|
||||||
|
// maxHeight: '15.125rem',
|
||||||
|
overflow: 'auto',
|
||||||
|
}),
|
||||||
|
Root: styled('table', {
|
||||||
|
width: 'calc(100% + 2 * $space$5)',
|
||||||
|
margin: '0 -$5',
|
||||||
|
}),
|
||||||
|
Head: styled('thead', {
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
backgroundColor: '$black',
|
||||||
|
|
||||||
|
'&:after': {
|
||||||
|
position: 'absolute',
|
||||||
|
content: '""',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
borderBottom: '1px solid $slate6',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Row: styled('tr'),
|
||||||
|
Data: styled('td', {
|
||||||
|
padding: '$3',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}),
|
||||||
|
Body: styled('tbody', {
|
||||||
|
tr: {
|
||||||
|
height: '3rem',
|
||||||
|
'&:hover': {
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
|
||||||
|
Skeleton: styled(Skeleton, {
|
||||||
|
borderRadius: '$lg',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Flex, NFAPreview, ResolvedAddress } from '@/components';
|
||||||
|
import { lastNFAsPaginatedQuery } from '@/graphclient';
|
||||||
|
import { parseNumberToHexColor } from '@/utils/color';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
|
||||||
|
type NFARowProps = {
|
||||||
|
token: lastNFAsPaginatedQuery['tokens'][0];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NFARow: React.FC<NFARowProps> = ({ token }: NFARowProps) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleClick = (): void => {
|
||||||
|
navigate(`/nfa/${token.tokenId}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<S.Table.Row onClick={handleClick}>
|
||||||
|
<S.Table.Data>
|
||||||
|
<Flex
|
||||||
|
css={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: '$2',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<NFAPreview
|
||||||
|
css={{
|
||||||
|
borderRadius: '$lg',
|
||||||
|
borderWidth: '1px',
|
||||||
|
borderColor: `#${parseNumberToHexColor(token.color)}`,
|
||||||
|
}}
|
||||||
|
size="4rem"
|
||||||
|
name={token.name}
|
||||||
|
color={`#${parseNumberToHexColor(token.color)}`}
|
||||||
|
logo={token.logo}
|
||||||
|
ens={token.ENS}
|
||||||
|
/>
|
||||||
|
{token.name}
|
||||||
|
</Flex>
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data css={{ textAlign: 'center' }}>
|
||||||
|
{token.accessPoints?.length ?? 0}
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data>
|
||||||
|
{/* TODO add menu button once the component it's added */}
|
||||||
|
<ResolvedAddress>{token.owner.id}</ResolvedAddress>
|
||||||
|
</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Flex } from '@/components';
|
||||||
|
|
||||||
|
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
||||||
|
|
||||||
|
export const NFARowSkeletonFragment: React.FC = () => (
|
||||||
|
<S.Table.Row>
|
||||||
|
<S.Table.Data>
|
||||||
|
<Flex
|
||||||
|
css={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: '$3',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<S.Skeleton css={{ aspectRatio: 1, width: '5rem' }} />
|
||||||
|
<S.Skeleton css={{ height: '2rem', width: '100%' }} />
|
||||||
|
</Flex>
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data>
|
||||||
|
<S.Skeleton css={{ height: '2rem' }} />
|
||||||
|
</S.Table.Data>
|
||||||
|
<S.Table.Data>
|
||||||
|
<S.Skeleton css={{ height: '2rem' }} />
|
||||||
|
</S.Table.Data>
|
||||||
|
</S.Table.Row>
|
||||||
|
);
|
||||||
|
|
@ -1,33 +1,23 @@
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { NFACard, NFACardSkeleton } from '@/components';
|
|
||||||
import { lastNFAsPaginatedDocument } from '@/graphclient';
|
import { lastNFAsPaginatedDocument } from '@/graphclient';
|
||||||
import { useWindowScrollEnd } from '@/hooks';
|
import { useWindowScrollEnd } from '@/hooks';
|
||||||
|
|
||||||
import { Explore } from '../explore.context';
|
import { Explore } from '../../explore.context';
|
||||||
import { NFAListFragmentStyles as S } from './nfa-list.styles';
|
import { NFAGridFragment } from './nfa-grid.fragment';
|
||||||
|
import { NFAListFragment } from './nfa-list.fragment';
|
||||||
|
|
||||||
const pageSize = 10; //Set this size to test pagination
|
const pageSize = 10; //Set this size to test pagination
|
||||||
|
|
||||||
const LoadingSkeletons: React.FC = () => (
|
export const NFAsContainerFragment: React.FC = () => {
|
||||||
<>
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
<NFACardSkeleton />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const NFAListFragment: React.FC = () => {
|
|
||||||
const {
|
const {
|
||||||
endReached,
|
endReached,
|
||||||
orderBy,
|
orderBy,
|
||||||
orderDirection,
|
orderDirection,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
search,
|
search,
|
||||||
|
nfaView,
|
||||||
setEndReached,
|
setEndReached,
|
||||||
setPageNumber,
|
setPageNumber,
|
||||||
} = Explore.useContext();
|
} = Explore.useContext();
|
||||||
|
|
@ -65,17 +55,9 @@ export const NFAListFragment: React.FC = () => {
|
||||||
|
|
||||||
if (queryError) return <div>Error</div>; //TODO handle error
|
if (queryError) return <div>Error</div>; //TODO handle error
|
||||||
|
|
||||||
return (
|
if (nfaView === 'grid')
|
||||||
<S.Container>
|
return <NFAGridFragment tokens={tokens} isLoading={isLoading} />;
|
||||||
{tokens.map((token) => (
|
else {
|
||||||
<NFACard data={token} key={token.id} />
|
return <NFAListFragment tokens={tokens} isLoading={isLoading} />;
|
||||||
))}
|
}
|
||||||
|
|
||||||
{isLoading && <LoadingSkeletons />}
|
|
||||||
|
|
||||||
{!isLoading && tokens.length === 0 && (
|
|
||||||
<S.EmptyMessage>Nothing found.</S.EmptyMessage>
|
|
||||||
)}
|
|
||||||
</S.Container>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { Combobox, InputGroup, InputGroupText } from '@/components';
|
import { Combobox, Flex, Icon, InputGroup, InputGroupText } from '@/components';
|
||||||
import { totalTokensDocument } from '@/graphclient';
|
import { totalTokensDocument } from '@/graphclient';
|
||||||
import { useDebounce } from '@/hooks';
|
import { useDebounce } from '@/hooks';
|
||||||
import { FleekERC721 } from '@/integrations/ethereum/contracts';
|
import { FleekERC721 } from '@/integrations/ethereum/contracts';
|
||||||
|
|
@ -25,11 +25,13 @@ const orderResults: SortItem[] = [
|
||||||
export const NFASearchFragment: React.FC = () => {
|
export const NFASearchFragment: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
search,
|
search,
|
||||||
|
nfaView,
|
||||||
setEndReached,
|
setEndReached,
|
||||||
setOrderBy,
|
setOrderBy,
|
||||||
setOrderDirection,
|
setOrderDirection,
|
||||||
setSearch,
|
setSearch,
|
||||||
setPageNumber,
|
setPageNumber,
|
||||||
|
setNFAView,
|
||||||
} = Explore.useContext();
|
} = Explore.useContext();
|
||||||
const [selectedValue, setSelectedValue] = useState<SortItem>(orderResults[0]);
|
const [selectedValue, setSelectedValue] = useState<SortItem>(orderResults[0]);
|
||||||
|
|
||||||
|
|
@ -40,6 +42,10 @@ export const NFASearchFragment: React.FC = () => {
|
||||||
skip: Boolean(search),
|
skip: Boolean(search),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleViewChange = (view: View): void => {
|
||||||
|
setNFAView(view);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSortChange = (item: SortItem | undefined): void => {
|
const handleSortChange = (item: SortItem | undefined): void => {
|
||||||
if (item) {
|
if (item) {
|
||||||
setSelectedValue(item);
|
setSelectedValue(item);
|
||||||
|
|
@ -83,41 +89,64 @@ export const NFASearchFragment: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<S.Container>
|
<S.Container>
|
||||||
<S.Data.Wrapper>
|
<S.Data.Wrapper>
|
||||||
{totalTokens?.collection && (<>
|
{totalTokens?.collection && (
|
||||||
<S.Data.Text>All NFAs </S.Data.Text>
|
<>
|
||||||
<S.Data.Number>({totalTokens.collection.totalTokens})</S.Data.Number>
|
<S.Data.Text>All NFAs </S.Data.Text>
|
||||||
</>)}
|
<S.Data.Number>
|
||||||
|
({totalTokens.collection.totalTokens})
|
||||||
|
</S.Data.Number>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</S.Data.Wrapper>
|
</S.Data.Wrapper>
|
||||||
|
|
||||||
<S.Input.Wrapper>
|
<S.Flex>
|
||||||
<InputGroup css={{ flex: 1 }}>
|
<S.Input.Wrapper>
|
||||||
<S.Input.Icon name="search" />
|
<InputGroup css={{ flex: 1 }}>
|
||||||
<InputGroupText placeholder="Search" onChange={handleSearchChange} />
|
<S.Input.Icon name="search" />
|
||||||
</InputGroup>
|
<InputGroupText
|
||||||
<Combobox
|
placeholder="Search"
|
||||||
items={orderResults}
|
onChange={handleSearchChange}
|
||||||
selected={[selectedValue, handleSortChange]}
|
/>
|
||||||
css={{ minWidth: '$28' }}
|
</InputGroup>
|
||||||
queryKey="label"
|
<Combobox
|
||||||
>
|
items={orderResults}
|
||||||
{({ Field, Options }) => (
|
selected={[selectedValue, handleSortChange]}
|
||||||
<>
|
css={{ minWidth: '$28' }}
|
||||||
<Field
|
queryKey="label"
|
||||||
css={{
|
>
|
||||||
backgroundColor: '$slate4',
|
{({ Field, Options }) => (
|
||||||
borderColor: '$slate4',
|
<>
|
||||||
color: '$slate11',
|
<Field
|
||||||
}}
|
css={{
|
||||||
>
|
color: '$slate11',
|
||||||
{(selected) => selected?.label || 'Select'}
|
}}
|
||||||
</Field>
|
>
|
||||||
<Options disableSearch css={{ minWidth: '$44', left: 'unset' }}>
|
{(selected) => selected?.label || 'Select'}
|
||||||
{(item) => item.label}
|
</Field>
|
||||||
</Options>
|
<Options disableSearch css={{ minWidth: '$44', left: 'unset' }}>
|
||||||
</>
|
{(item) => item.label}
|
||||||
)}
|
</Options>
|
||||||
</Combobox>
|
</>
|
||||||
</S.Input.Wrapper>
|
)}
|
||||||
|
</Combobox>
|
||||||
|
</S.Input.Wrapper>
|
||||||
|
|
||||||
|
{/* TODO move this to the app context */}
|
||||||
|
<S.GridList.Wrapper>
|
||||||
|
<S.GridList.Icon
|
||||||
|
name="grid"
|
||||||
|
selected={nfaView === 'grid'}
|
||||||
|
css={{ btrr: '0', bbrr: '0' }}
|
||||||
|
onClick={() => handleViewChange('grid')}
|
||||||
|
/>
|
||||||
|
<S.GridList.Icon
|
||||||
|
name="list"
|
||||||
|
css={{ btlr: '0', bblr: '0' }}
|
||||||
|
selected={nfaView === 'list'}
|
||||||
|
onClick={() => handleViewChange('list')}
|
||||||
|
/>
|
||||||
|
</S.GridList.Wrapper>
|
||||||
|
</S.Flex>
|
||||||
</S.Container>
|
</S.Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,16 @@ export const NFASearchFragmentStyles = {
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Flex: styled(Flex, {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
gap: '$3h',
|
||||||
|
|
||||||
|
'@media (max-width: 374px)': {
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
Input: {
|
Input: {
|
||||||
Wrapper: styled(Flex, {
|
Wrapper: styled(Flex, {
|
||||||
gap: '$3',
|
gap: '$3',
|
||||||
|
|
@ -36,4 +46,31 @@ export const NFASearchFragmentStyles = {
|
||||||
fontSize: '$lg',
|
fontSize: '$lg',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
GridList: {
|
||||||
|
Wrapper: styled(Flex, {
|
||||||
|
border: '1px solid $slate7',
|
||||||
|
borderRadius: '$lg',
|
||||||
|
backgroundColor: '$slate7',
|
||||||
|
}),
|
||||||
|
Icon: styled(Icon, {
|
||||||
|
p: '$2 $3',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '$lg',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
selected: {
|
||||||
|
true: {
|
||||||
|
color: 'white',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
false: {
|
||||||
|
color: '$slate7 ',
|
||||||
|
backgroundColor: 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,21 @@ import { useState } from 'react';
|
||||||
import { OrderDirection, Token_orderBy } from '@/graphclient';
|
import { OrderDirection, Token_orderBy } from '@/graphclient';
|
||||||
import { createContext } from '@/utils';
|
import { createContext } from '@/utils';
|
||||||
|
|
||||||
|
type View = 'grid' | 'list';
|
||||||
|
|
||||||
export type ExploreContext = {
|
export type ExploreContext = {
|
||||||
search: string;
|
search: string;
|
||||||
orderBy: Token_orderBy;
|
orderBy: Token_orderBy;
|
||||||
orderDirection: OrderDirection;
|
orderDirection: OrderDirection;
|
||||||
pageNumber: number;
|
pageNumber: number;
|
||||||
endReached: boolean;
|
endReached: boolean;
|
||||||
|
nfaView: View;
|
||||||
setSearch: (search: string) => void;
|
setSearch: (search: string) => void;
|
||||||
setOrderBy: (orderBy: Token_orderBy) => void;
|
setOrderBy: (orderBy: Token_orderBy) => void;
|
||||||
setOrderDirection: (orderDirection: OrderDirection) => void;
|
setOrderDirection: (orderDirection: OrderDirection) => void;
|
||||||
setPageNumber: (pageNumber: number) => void;
|
setPageNumber: (pageNumber: number) => void;
|
||||||
setEndReached: (isEndReaced: boolean) => void;
|
setEndReached: (isEndReaced: boolean) => void;
|
||||||
|
setNFAView: (view: View) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const [ExploreProvider, useContext] = createContext<ExploreContext>({
|
const [ExploreProvider, useContext] = createContext<ExploreContext>({
|
||||||
|
|
@ -34,6 +38,7 @@ export abstract class Explore {
|
||||||
useState<OrderDirection>('desc');
|
useState<OrderDirection>('desc');
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
const [endReached, setEndReached] = useState(false);
|
const [endReached, setEndReached] = useState(false);
|
||||||
|
const [nfaView, setNFAView] = useState<View>('grid');
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
search,
|
search,
|
||||||
|
|
@ -41,11 +46,13 @@ export abstract class Explore {
|
||||||
orderDirection,
|
orderDirection,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
endReached,
|
endReached,
|
||||||
|
nfaView,
|
||||||
setSearch,
|
setSearch,
|
||||||
setOrderBy,
|
setOrderBy,
|
||||||
setOrderDirection,
|
setOrderDirection,
|
||||||
setPageNumber,
|
setPageNumber,
|
||||||
setEndReached,
|
setEndReached,
|
||||||
|
setNFAView,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <ExploreProvider value={context}>{children}</ExploreProvider>;
|
return <ExploreProvider value={context}>{children}</ExploreProvider>;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue