Commit 25ddae54 authored by tom's avatar tom

sort ERC-1155 tokens

parent 81135ea4
...@@ -4,22 +4,56 @@ import { ...@@ -4,22 +4,56 @@ import {
Popover, PopoverTrigger, PopoverContent, PopoverBody, Box, Popover, PopoverTrigger, PopoverContent, PopoverBody, Box,
useDisclosure, useDisclosure,
Flex, Flex,
Link,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import _groupBy from 'lodash/groupBy'; import _groupBy from 'lodash/groupBy';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
import type { AddressTokenBalance } from 'types/api/address'; import type { AddressTokenBalance } from 'types/api/address';
import type { TokenType } from 'types/api/tokenInfo';
import arrowIcon from 'icons/arrows/east.svg';
import searchIcon from 'icons/search.svg'; import searchIcon from 'icons/search.svg';
import TokenItem from './TokenItem'; import TokenItem from './TokenItem';
import TokensButton from './TokensButton'; import TokensButton from './TokensButton';
const TOKEN_GROUPS_ORDER = [ 'ERC-20', 'ERC-721', 'ERC-1155' ]; type Sort = 'desc' | 'asc';
const SORTABLE_TOKENS: Array<TokenType> = [ 'ERC-20', 'ERC-1155' ];
const TOKEN_GROUPS_ORDER: Array<TokenType> = [ 'ERC-20', 'ERC-721', 'ERC-1155' ];
type TokenGroup = [string, Array<AddressTokenBalance>]; type TokenGroup = [string, Array<AddressTokenBalance>];
const sortTokenGroups = (groupA: TokenGroup, groupB: TokenGroup) => { const sortTokenGroups = (groupA: TokenGroup, groupB: TokenGroup) => {
return TOKEN_GROUPS_ORDER.indexOf(groupA[0]) > TOKEN_GROUPS_ORDER.indexOf(groupB[0]) ? 1 : -1; return TOKEN_GROUPS_ORDER.indexOf(groupA[0] as TokenType) > TOKEN_GROUPS_ORDER.indexOf(groupB[0] as TokenType) ? 1 : -1;
};
const sortErc1155Tokens = (sort: 'desc' | 'asc') => (dataA: AddressTokenBalance, dataB: AddressTokenBalance) => {
if (dataA.value === dataB.value) {
return 0;
}
if (sort === 'desc') {
return Number(dataA.value) > Number(dataB.value) ? -1 : 1;
}
return Number(dataA.value) > Number(dataB.value) ? 1 : -1;
};
const sortErc20Tokens = () => () => 0;
const sortErc721Tokens = () => () => 0;
const sortingFns = {
'ERC-20': sortErc20Tokens,
'ERC-721': sortErc721Tokens,
'ERC-1155': sortErc1155Tokens,
};
const filterTokens = (searchTerm: string) => ({ token }: AddressTokenBalance) => {
if (!token.name) {
return !searchTerm ? true : token.address.toLowerCase().includes(searchTerm);
}
return token.name?.toLowerCase().includes(searchTerm);
}; };
interface Props { interface Props {
...@@ -28,27 +62,25 @@ interface Props { ...@@ -28,27 +62,25 @@ interface Props {
const AddressTokenSelect = ({ data }: Props) => { const AddressTokenSelect = ({ data }: Props) => {
const [ searchTerm, setSearchTerm ] = React.useState(''); const [ searchTerm, setSearchTerm ] = React.useState('');
const [ erc1155sort, setErc1155Sort ] = React.useState<Sort>('desc');
const { isOpen, onToggle, onClose } = useDisclosure(); const { isOpen, onToggle, onClose } = useDisclosure();
const handleInputChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => { const handleInputChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
setSearchTerm(event.target.value); setSearchTerm(event.target.value);
}, []); }, []);
const handleKeyDown = React.useCallback((event: React.SyntheticEvent) => { const handleSortClick = React.useCallback((event: React.SyntheticEvent) => {
event.stopPropagation(); const tokenType = (event.currentTarget as HTMLAnchorElement).getAttribute('data-type');
if (tokenType === 'ERC-1155') {
setErc1155Sort((prevValue) => prevValue === 'desc' ? 'asc' : 'desc');
}
}, []); }, []);
const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600'); const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600');
const inputBorderColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.200'); const inputBorderColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.200');
const bgColor = useColorModeValue('white', 'gray.900'); const bgColor = useColorModeValue('white', 'gray.900');
const filteredData = data.filter(({ token }) => { const filteredData = data.filter(filterTokens(searchTerm.toLowerCase()));
if (!token.name) {
return !searchTerm ? true : token.address.toLowerCase().includes(searchTerm.toLowerCase());
}
return token.name?.toLowerCase().includes(searchTerm.toLowerCase());
});
const groupedData = _groupBy(filteredData, 'token.type'); const groupedData = _groupBy(filteredData, 'token.type');
return ( return (
...@@ -68,15 +100,33 @@ const AddressTokenSelect = ({ data }: Props) => { ...@@ -68,15 +100,33 @@ const AddressTokenSelect = ({ data }: Props) => {
ml="1px" ml="1px"
onChange={ handleInputChange } onChange={ handleInputChange }
borderColor={ inputBorderColor } borderColor={ inputBorderColor }
onKeyDown={ handleKeyDown }
/> />
</InputGroup> </InputGroup>
<Flex flexDir="column" rowGap={ 6 }> <Flex flexDir="column" rowGap={ 6 }>
{ Object.entries(groupedData).sort(sortTokenGroups).map(([ tokenType, tokenInfo ]) => { { Object.entries(groupedData).sort(sortTokenGroups).map(([ tokenType, tokenInfo ]) => {
const type = tokenType as TokenType;
const arrowTransform = type === 'ERC-1155' && erc1155sort === 'desc' ? 'rotate(90deg)' : 'rotate(-90deg)';
const sortDirection: Sort = (() => {
switch (type) {
case 'ERC-1155':
return erc1155sort;
default:
return 'desc';
}
})();
return ( return (
<Box key={ tokenType }> <Box key={ type }>
<Text mb={ 3 } color="gray.500" fontWeight={ 600 } fontSize="sm">{ tokenType } tokens ({ tokenInfo.length })</Text> <Flex justifyContent="space-between">
{ tokenInfo.map((data) => <TokenItem key={ data.token.address } data={ data }/>) } <Text mb={ 3 } color="gray.500" fontWeight={ 600 } fontSize="sm">{ type } tokens ({ tokenInfo.length })</Text>
{ SORTABLE_TOKENS.includes(type) && (
<Link data-type={ type } onClick={ handleSortClick }>
<Icon as={ arrowIcon } boxSize={ 5 } transform={ arrowTransform } transitionDuration="fast"/>
</Link>
) }
</Flex>
{ tokenInfo.sort(sortingFns[type](sortDirection)).map((data) => <TokenItem key={ data.token.address } data={ data }/>) }
</Box> </Box>
); );
}) } }) }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment