Commit 8e703560 authored by tom's avatar tom

ERC-20 token items

parent caea207d
...@@ -82,6 +82,9 @@ const variantOutline = defineStyle((props) => { ...@@ -82,6 +82,9 @@ const variantOutline = defineStyle((props) => {
color, color,
borderColor, borderColor,
}, },
p: {
color: 'blue.400',
},
}, },
_disabled: { _disabled: {
opacity: 0.2, opacity: 0.2,
...@@ -94,6 +97,9 @@ const variantOutline = defineStyle((props) => { ...@@ -94,6 +97,9 @@ const variantOutline = defineStyle((props) => {
color, color,
borderColor, borderColor,
}, },
p: {
color: activeColor,
},
}, },
}; };
}); });
......
import { Box, Flex, Text, Icon, Button, Grid, Select } from '@chakra-ui/react'; import { Box, Flex, Text, Icon, Button, Grid } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
...@@ -15,6 +15,7 @@ import starOutlineIcon from 'icons/star_outline.svg'; ...@@ -15,6 +15,7 @@ import starOutlineIcon from 'icons/star_outline.svg';
import walletIcon from 'icons/wallet.svg'; import walletIcon from 'icons/wallet.svg';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import AddressTokenSelect from 'ui/address/details/AddressTokenSelect';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
...@@ -92,20 +93,11 @@ const AddressDetails = ({ addressQuery }: Props) => { ...@@ -92,20 +93,11 @@ const AddressDetails = ({ addressQuery }: Props) => {
title="Tokens" title="Tokens"
hint="All tokens in the account and total value." hint="All tokens in the account and total value."
alignSelf="center" alignSelf="center"
py="2px"
> >
{ tokenBalancesQuery.data.length > 0 ? ( { tokenBalancesQuery.data.length > 0 ? (
<> <>
{ /* TODO will be fixed later when we implement select with custom menu */ } <AddressTokenSelect data={ tokenBalancesQuery.data }/>
<Select
size="sm"
borderRadius="base"
focusBorderColor="none"
display="inline-block"
w="auto"
>
{ tokenBalancesQuery.data.map((token) =>
<option key={ token.token.address } value={ token.token.address }>{ token.token.symbol }</option>) }
</Select>
<Button variant="outline" size="sm" ml={ 3 }> <Button variant="outline" size="sm" ml={ 3 }>
<Icon as={ walletIcon } boxSize={ 5 }/> <Icon as={ walletIcon } boxSize={ 5 }/>
</Button> </Button>
......
import {
Icon, Text, Button, Menu, MenuButton, MenuGroup, MenuList,
Input, forwardRef, InputGroup, InputLeftElement, useColorModeValue,
} from '@chakra-ui/react';
import _groupBy from 'lodash/groupBy';
import type { ChangeEvent } from 'react';
import React from 'react';
import type { AddressTokenBalance } from 'types/api/address';
import arrowIcon from 'icons/arrows/east-mini.svg';
import searchIcon from 'icons/search.svg';
import tokensIcon from 'icons/tokens.svg';
import AddressTokenSelectErc20 from './AddressTokenSelectErc20';
const Trigger = forwardRef((props, ref) => {
return (
<Button
{ ...props }
ref={ ref }
size="sm"
variant="outline"
colorScheme="gray"
>
<Icon as={ tokensIcon } boxSize={ 5 } mr={ 2 }/>
<Text fontWeight={ 600 }>2</Text>
<Text whiteSpace="pre" variant="secondary" fontWeight={ 400 }> ($23 463.73 USD)</Text>
<Icon as={ arrowIcon } transform={ props.isActive ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="normal" boxSize={ 5 } ml={ 3 }/>
</Button>
);
});
interface Props {
data: Array<AddressTokenBalance>;
}
const AddressTokenSelect = ({ data }: Props) => {
const [ searchTerm, setSearchTerm ] = React.useState('');
const handleInputChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
setSearchTerm(event.target.value);
}, []);
const handleKeyDown = React.useCallback((event: React.SyntheticEvent) => {
event.stopPropagation();
}, []);
const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600');
const inputBorderColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.200');
const bgColor = useColorModeValue('white', 'gray.900');
const filteredData = data.filter(({ token }) => token.name?.toLowerCase().includes(searchTerm.toLowerCase()));
const groupedData = _groupBy(filteredData, 'token.type');
return (
<Menu>
{ ({ isOpen }) => (
<>
<MenuButton isActive={ isOpen } as={ Trigger }/>
<MenuList px={ 4 } py={ 6 } w="355px" bgColor={ bgColor } boxShadow="2xl">
<InputGroup size="xs" mb={ 5 }>
<InputLeftElement >
<Icon as={ searchIcon } boxSize={ 4 } color={ searchIconColor }/>
</InputLeftElement>
<Input
paddingInlineStart="38px"
placeholder="Search by token name"
ml="1px"
onChange={ handleInputChange }
borderColor={ inputBorderColor }
onKeyDown={ handleKeyDown }
/>
</InputGroup>
{ groupedData['ERC-20'] && (
<MenuGroup title={ `ERC-20 tokens (${ groupedData['ERC-20'].length })` } mb={ 3 } mt={ 0 } mx={ 0 } color="gray.500">
{ groupedData['ERC-20'].map((data) => <AddressTokenSelectErc20 key={ data.token.address } data={ data }/>) }
</MenuGroup>
) }
</MenuList>
</>
) }
</Menu>
);
};
export default React.memo(AddressTokenSelect);
import { MenuItem, Flex, Text, useColorModeValue } from '@chakra-ui/react';
import BigNumber from 'bignumber.js';
import React from 'react';
import type { AddressTokenBalance } from 'types/api/address';
import TokenLogo from 'ui/shared/TokenLogo';
interface Props {
data: AddressTokenBalance;
}
const AddressTokenSelect = ({ data }: Props) => {
const tokenDecimals = Number(data.token.decimals) || 18;
return (
<MenuItem
px={ 1 }
py="10px"
display="flex"
flexDir="column"
rowGap={ 2 }
borderColor={ useColorModeValue('blackAlpha.200', 'whiteAlpha.200') }
borderBottomWidth="1px"
_last={{
borderBottomWidth: '0px',
}}
_hover={{
bgColor: useColorModeValue('blue.50', 'gray.800'),
}}
fontSize="sm"
isFocusable={ false }
>
<Flex alignItems="center" w="100%">
<TokenLogo hash={ data.token.address } name={ data.token.name } boxSize={ 6 }/>
<Text fontWeight={ 700 } ml={ 2 }>{ data.token.name }</Text>
<Text fontWeight={ 700 } ml="auto">$23 463.73</Text>
</Flex>
<Flex alignItems="center" justifyContent="space-between" w="100%">
<Text >{ BigNumber(data.value).dividedBy(10 ** tokenDecimals).dp(2).toFormat() } { data.token.symbol }</Text>
<Text >@1.001</Text>
</Flex>
</MenuItem>
);
};
export default React.memo(AddressTokenSelect);
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