mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
fixes
This commit is contained in:
+8
-1
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable max-len */
|
||||
export const tx = {
|
||||
hash: '0x1ea365d2144796f793883534aa51bf20d23292b19478994eede23dfc599e7c34',
|
||||
status: 'success',
|
||||
status: 'success' as TxStatus,
|
||||
block_num: 15006918,
|
||||
confirmation_num: 283,
|
||||
confirmation_duration: 30,
|
||||
@@ -9,10 +9,12 @@ export const tx = {
|
||||
address_from: {
|
||||
hash: '0x97Aa2EfcF35c0f4c9AaDDCa8c2330fa7A9533830',
|
||||
type: 'Address',
|
||||
alias: '',
|
||||
},
|
||||
address_to: {
|
||||
hash: '0x35317007D203b8a86CA727ad44E473E40450E378',
|
||||
type: 'Contract',
|
||||
alias: '',
|
||||
},
|
||||
amount: {
|
||||
value: 0.03,
|
||||
@@ -45,4 +47,9 @@ export const tx = {
|
||||
{ from: '0x12E80C27BfFBB76b4A8d26FF2bfd3C9f310FFA01', to: '0xF7A558692dFB5F456e291791da7FAE8Dd046574e', token: 'USDT', amount: 192.7, usd: 194.05 },
|
||||
{ from: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', to: '0x12E80C27BfFBB76b4A8d26FF2bfd3C9f310FFA01', token: 'TOKE', amount: 76.1851851851846, usd: 194.05 },
|
||||
],
|
||||
txType: 'transaction' as TxType,
|
||||
};
|
||||
|
||||
export type TxType = 'contract-call' | 'transaction' | 'token-transfer' | 'internal-tx' | 'multicall';
|
||||
|
||||
export type TxStatus = 'success' | 'failed' | 'pending';
|
||||
|
||||
+8
-5
@@ -1,16 +1,18 @@
|
||||
import { tx } from './tx';
|
||||
import type { TxType, TxStatus } from './tx';
|
||||
|
||||
export const txs = [
|
||||
{
|
||||
...tx,
|
||||
method: 'Withdraw',
|
||||
txType: 'transaction',
|
||||
txType: 'transaction' as TxType,
|
||||
errorText: '',
|
||||
},
|
||||
{
|
||||
...tx,
|
||||
status: 'failed',
|
||||
status: 'failed' as TxStatus,
|
||||
errorText: 'Error: (Awaiting internal transactions for reason)',
|
||||
txType: 'contract-call',
|
||||
txType: 'contract-call' as TxType,
|
||||
method: 'CommitHash CommitHash CommitHash CommitHash',
|
||||
amount: {
|
||||
value: 0.04,
|
||||
@@ -23,8 +25,8 @@ export const txs = [
|
||||
},
|
||||
{
|
||||
...tx,
|
||||
status: 'pending',
|
||||
txType: 'token-transfer',
|
||||
status: 'pending' as TxStatus,
|
||||
txType: 'token-transfer' as TxType,
|
||||
method: 'Multicall',
|
||||
address_from: {
|
||||
hash: '0x97Aa2EfcF35c0f4c9AaDDCa8c2330fa7A9533830',
|
||||
@@ -39,5 +41,6 @@ export const txs = [
|
||||
value: 0.002495904453623692,
|
||||
value_usd: 2.84,
|
||||
},
|
||||
errorText: '',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -19,7 +19,7 @@ const AddressTagsPage: NextPage<Props> = ({ pageParams }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<Head><title>{ title }</title></Head>
|
||||
<Transactions tab="pending"/>
|
||||
<Transactions tab="txs_pending"/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ const AddressTagsPage: NextPage<Props> = ({ pageParams }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<Head><title>{ title }</title></Head>
|
||||
<Transactions tab="validated"/>
|
||||
<Transactions tab="txs_validated"/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -35,7 +35,6 @@ const baseStyleContainer = defineStyle({
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
borderRadius: 'sm',
|
||||
lineHeight: '20px',
|
||||
...transitionProps,
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export type Sort = 'val-desc' | 'val-asc' | 'fee-desc' | 'fee-asc' | undefined;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Box } from '@chakra-ui/react'; import React from 'react';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ const TransactionPageContent = ({ tab }: Props) => {
|
||||
return (
|
||||
<Page>
|
||||
{ /* TODO should be shown only when navigating from txs list */ }
|
||||
<Link mb={ 6 } display="inline-flex" href={ link('txs') }>
|
||||
<Link mb={ 6 } display="inline-flex" href={ link('txs_validated') }>
|
||||
<Icon as={ eastArrowIcon } boxSize={ 6 } mr={ 2 } transform="rotate(180deg)"/>
|
||||
Transactions
|
||||
</Link>
|
||||
|
||||
+10
-34
@@ -1,56 +1,32 @@
|
||||
import {
|
||||
Box,
|
||||
Tab,
|
||||
Tabs,
|
||||
TabList,
|
||||
TabPanel,
|
||||
TabPanels,
|
||||
} from '@chakra-ui/react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
|
||||
|
||||
import useLink from 'lib/link/useLink';
|
||||
import Page from 'ui/shared/Page';
|
||||
import PageHeader from 'ui/shared/PageHeader';
|
||||
import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs';
|
||||
import TxsPending from 'ui/txs/TxsPending';
|
||||
import TxsValidated from 'ui/txs/TxsValidated';
|
||||
|
||||
const TABS = [ 'validated', 'pending' ] as const;
|
||||
|
||||
type TabName = typeof TABS[number];
|
||||
const TABS: Array<RoutedTab> = [
|
||||
{ routeName: 'txs_validated', title: 'Validated', component: <TxsValidated/> },
|
||||
{ routeName: 'txs_pending', title: 'Pending', component: <TxsPending/> },
|
||||
];
|
||||
|
||||
type Props = {
|
||||
tab: TabName;
|
||||
tab: RoutedTab['routeName'];
|
||||
}
|
||||
|
||||
const Transactions = ({ tab }: Props) => {
|
||||
const [ , setActiveTab ] = useState<TabName>(tab);
|
||||
|
||||
const link = useLink();
|
||||
|
||||
const onChangeTab = useCallback((index: number) => {
|
||||
setActiveTab(TABS[index]);
|
||||
const newUrl = link(TABS[index] === 'validated' ? 'txs_validated' : 'txs_pending');
|
||||
history.replaceState(history.state, '', newUrl);
|
||||
}, [ link ]);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Box h="100%">
|
||||
<PageHeader text="Transactions"/>
|
||||
<Tabs variant="soft-rounded" colorScheme="blue" isLazy onChange={ onChangeTab } defaultIndex={ TABS.indexOf(tab) }>
|
||||
<TabList marginBottom={{ base: 6, lg: 8 }}>
|
||||
<Tab>Validated</Tab>
|
||||
<Tab>Pending</Tab>
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
<TabPanel padding={ 0 }>
|
||||
<TxsValidated/>
|
||||
</TabPanel>
|
||||
<TabPanel padding={ 0 }>
|
||||
<TxsPending/>
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
<RoutedTabs tabs={ TABS } defaultActiveTab={ tab }/>
|
||||
</Box>
|
||||
</Page>
|
||||
);
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
// DEPRECATED
|
||||
// migrate to separate components
|
||||
// ui/shared/FilterButton.tsx + custom filter
|
||||
// ui/shared/FilterInput.tsx
|
||||
import { Flex, Icon, Button, Circle, InputGroup, InputLeftElement, Input, useColorModeValue } from '@chakra-ui/react';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import upDownArrow from 'icons/arrows/up-down.svg';
|
||||
import filterIcon from 'icons/filter.svg';
|
||||
import searchIcon from 'icons/search.svg';
|
||||
|
||||
const FilterIcon = <Icon as={ filterIcon } boxSize={ 5 }/>;
|
||||
|
||||
type Props = {
|
||||
isMobile?: boolean;
|
||||
}
|
||||
|
||||
const Filters = ({ isMobile }: Props) => {
|
||||
const [ isFilterActive, setIsFilterActive ] = React.useState(false);
|
||||
const [ value, setValue ] = React.useState('');
|
||||
const [ isSortActive, setIsSortActive ] = React.useState(false);
|
||||
|
||||
const handleClick = React.useCallback(() => {
|
||||
setIsFilterActive(flag => !flag);
|
||||
}, []);
|
||||
|
||||
const handleChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
|
||||
setValue(event.target.value);
|
||||
}, []);
|
||||
|
||||
const handleSort = React.useCallback(() => {
|
||||
setIsSortActive(flag => !flag);
|
||||
}, []);
|
||||
|
||||
const badgeColor = useColorModeValue('white', 'black');
|
||||
const badgeBgColor = useColorModeValue('blue.700', 'gray.50');
|
||||
const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600');
|
||||
const inputBorderColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.200');
|
||||
|
||||
return (
|
||||
<Flex>
|
||||
<Button
|
||||
leftIcon={ isMobile ? undefined : FilterIcon }
|
||||
rightIcon={ isFilterActive ? <Circle bg={ badgeBgColor } size={ 5 } color={ badgeColor }>2</Circle> : undefined }
|
||||
size="sm"
|
||||
variant="outline"
|
||||
colorScheme="gray-dark"
|
||||
onClick={ handleClick }
|
||||
isActive={ isFilterActive }
|
||||
px={ 1.5 }
|
||||
>
|
||||
{ isMobile ? FilterIcon : 'Filter' }
|
||||
</Button>
|
||||
{ isMobile && (
|
||||
<IconButton
|
||||
icon={ <Icon as={ upDownArrow } boxSize={ 5 }/> }
|
||||
aria-label="sort"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
colorScheme="gray-dark"
|
||||
ml={ 2 }
|
||||
minWidth="36px"
|
||||
onClick={ handleSort }
|
||||
isActive={ isSortActive }
|
||||
/>
|
||||
) }
|
||||
<InputGroup size="xs" ml={ isMobile ? 2 : 3 } maxW="360px">
|
||||
<InputLeftElement ml={ 1 }>
|
||||
<Icon as={ searchIcon } boxSize={ 5 } color={ searchIconColor }/>
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
paddingInlineStart="38px"
|
||||
placeholder="Search by addresses, hash, method..."
|
||||
ml="1px"
|
||||
borderWidth="2px"
|
||||
textOverflow="ellipsis"
|
||||
onChange={ handleChange }
|
||||
borderColor={ inputBorderColor }
|
||||
value={ value }
|
||||
size="xs"
|
||||
/>
|
||||
</InputGroup>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default Filters;
|
||||
@@ -0,0 +1,106 @@
|
||||
import { Button, Flex, Input, Icon, IconButton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import arrowIcon from 'icons/arrows/east-mini.svg';
|
||||
|
||||
type Props = {
|
||||
currentPage: number;
|
||||
maxPage?: number;
|
||||
isMobile?: boolean;
|
||||
}
|
||||
|
||||
const MAX_PAGE_DEFAULT = 50;
|
||||
|
||||
const Pagination = ({ currentPage, maxPage, isMobile }: Props) => {
|
||||
|
||||
const pageNumber = (
|
||||
<Flex alignItems="center">
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="gray"
|
||||
size="sm"
|
||||
isActive
|
||||
borderWidth="1px"
|
||||
fontWeight={ 400 }
|
||||
mr={ 3 }
|
||||
h={ 8 }
|
||||
>
|
||||
{ currentPage }
|
||||
</Button>
|
||||
of
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="gray"
|
||||
size="sm"
|
||||
width={ 8 }
|
||||
borderWidth="1px"
|
||||
fontWeight={ 400 }
|
||||
ml={ 3 }
|
||||
>
|
||||
{ maxPage || MAX_PAGE_DEFAULT }
|
||||
</Button>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Flex
|
||||
fontSize="sm"
|
||||
width="100%"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<IconButton
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label="Next page"
|
||||
w="36px"
|
||||
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 }/> }
|
||||
/>
|
||||
{ pageNumber }
|
||||
<IconButton
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label="Next page"
|
||||
w="36px"
|
||||
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 } transform="rotate(180deg)"/> }
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
fontSize="sm"
|
||||
>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label="Next page"
|
||||
leftIcon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 }/> }
|
||||
mr={ 8 }
|
||||
pl={ 1 }
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
{ pageNumber }
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label="Next page"
|
||||
rightIcon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 } transform="rotate(180deg)"/> }
|
||||
ml={ 8 }
|
||||
pr={ 1 }
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</Flex>
|
||||
<Flex alignItems="center" width="132px" ml={ 16 }>
|
||||
Go to <Input w="84px" size="xs" ml={ 2 }/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default Pagination;
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Icon, IconButton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import upDownArrow from 'icons/arrows/up-down.svg';
|
||||
|
||||
type Props = {
|
||||
handleSort: () => void;
|
||||
isSortActive: boolean;
|
||||
}
|
||||
|
||||
const SortButton = ({ handleSort, isSortActive }: Props) => {
|
||||
return (
|
||||
<IconButton
|
||||
icon={ <Icon as={ upDownArrow } boxSize={ 5 }/> }
|
||||
aria-label="sort"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
colorScheme="gray-dark"
|
||||
ml={ 2 }
|
||||
minWidth="36px"
|
||||
onClick={ handleSort }
|
||||
isActive={ isSortActive }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SortButton;
|
||||
@@ -16,8 +16,8 @@ import TxInternalsTable from 'ui/tx/internals/TxInternalsTable';
|
||||
const searchFn = (searchTerm: string) => (item: ArrayElement<typeof data>): boolean => {
|
||||
const formattedSearchTerm = searchTerm.toLowerCase();
|
||||
return item.type.toLowerCase().includes(formattedSearchTerm) ||
|
||||
item.from.toLowerCase().includes(formattedSearchTerm) ||
|
||||
item.to.toLowerCase().includes(formattedSearchTerm);
|
||||
item.from.hash.toLowerCase().includes(formattedSearchTerm) ||
|
||||
item.to.hash.toLowerCase().includes(formattedSearchTerm);
|
||||
};
|
||||
|
||||
const TxInternals = () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import AccountListItemMobile from 'ui/shared/AccountListItemMobile';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import TxStatus from 'ui/tx/TxStatus';
|
||||
import TxStatus from 'ui/shared/TxStatus';
|
||||
|
||||
type Props = ArrayElement<typeof data>;
|
||||
|
||||
@@ -23,13 +23,13 @@ const TxInternalsListItem = ({ type, status, from, to, value, gasLimit }: Props)
|
||||
</Flex>
|
||||
<Box w="100%" display="flex" columnGap={ 3 }>
|
||||
<Address width="calc((100% - 48px) / 2)">
|
||||
<AddressIcon hash={ from }/>
|
||||
<AddressLink ml={ 2 } fontWeight="500" hash={ from }/>
|
||||
<AddressIcon hash={ from.hash }/>
|
||||
<AddressLink ml={ 2 } fontWeight="500" hash={ from.hash }/>
|
||||
</Address>
|
||||
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500"/>
|
||||
<Address width="calc((100% - 48px) / 2)">
|
||||
<AddressIcon hash={ to }/>
|
||||
<AddressLink ml={ 2 } fontWeight="500" hash={ to }/>
|
||||
<AddressIcon hash={ to.hash }/>
|
||||
<AddressLink ml={ 2 } fontWeight="500" hash={ to.hash }/>
|
||||
</Address>
|
||||
</Box>
|
||||
<HStack spacing={ 3 }>
|
||||
|
||||
@@ -5,8 +5,8 @@ import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
|
||||
import TxStatus from 'ui/shared/TxStatus';
|
||||
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
|
||||
|
||||
interface Props {
|
||||
type: string;
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
|
||||
import { Button, Flex, Input, IconButton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
type Props = {
|
||||
currentPage: number;
|
||||
maxPage?: number;
|
||||
isMobile?: boolean;
|
||||
}
|
||||
|
||||
const MAX_PAGE_DEFAULT = 50;
|
||||
|
||||
const Pagination = ({ currentPage, maxPage, isMobile }: Props) => {
|
||||
|
||||
return (
|
||||
<Flex
|
||||
fontSize="sm"
|
||||
width={ isMobile ? '100%' : '434px' }
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Flex alignItems="center" justifyContent="space-between" flexGrow={ 1 }>
|
||||
<IconButton
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label="Next page"
|
||||
w="36px"
|
||||
icon={ <ChevronLeftIcon w={ 5 } h={ 5 }/> }
|
||||
/>
|
||||
<Flex alignItems="center">
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="gray"
|
||||
size="sm"
|
||||
isActive
|
||||
borderWidth="1px"
|
||||
fontWeight={ 400 }
|
||||
mr={ 3 }
|
||||
h={ 8 }
|
||||
>
|
||||
{ currentPage }
|
||||
</Button>
|
||||
of
|
||||
<Button
|
||||
variant="outline"
|
||||
colorScheme="gray"
|
||||
size="sm"
|
||||
width={ 8 }
|
||||
borderWidth="1px"
|
||||
fontWeight={ 400 }
|
||||
ml={ 3 }
|
||||
>
|
||||
{ maxPage || MAX_PAGE_DEFAULT }
|
||||
</Button>
|
||||
</Flex>
|
||||
<IconButton
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label="Next page"
|
||||
w="36px"
|
||||
icon={ <ChevronRightIcon w={ 5 } h={ 5 }/> }
|
||||
/>
|
||||
</Flex>
|
||||
{ !isMobile && (
|
||||
<Flex alignItems="center" width="132px" ml={ 16 }>
|
||||
Go to <Input w="84px" h="32px" size="sm" ml={ 2 }/>
|
||||
</Flex>
|
||||
) }
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default Pagination;
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Box, Heading, Text, Flex, Link, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type ArrayElement from 'types/utils/ArrayElement';
|
||||
|
||||
import type { txs } from 'data/txs';
|
||||
import useLink from 'lib/link/useLink';
|
||||
import Separator from 'ui/shared/Separator';
|
||||
import Utilization from 'ui/shared/Utilization';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const TxAdditionalInfo = ({ tx }: { tx: any }) => {
|
||||
const TxAdditionalInfo = ({ tx }: { tx: ArrayElement<typeof txs> }) => {
|
||||
|
||||
const sectionBorderColor = useColorModeValue('gray.200', 'whiteAlpha.200');
|
||||
const sectionProps = {
|
||||
|
||||
@@ -7,13 +7,13 @@ import React from 'react';
|
||||
|
||||
import infoIcon from 'icons/info.svg';
|
||||
|
||||
const TxAdditionalInfoButton = ({ isOpen, onClick }: {isOpen?: boolean; onClick?: () => void}) => {
|
||||
const TxAdditionalInfoButton = ({ isOpen, onClick }: {isOpen?: boolean; onClick?: () => void}, ref: React.ForwardedRef<HTMLDivElement>) => {
|
||||
|
||||
const infoBgColor = useColorModeValue('blue.50', 'gray.600');
|
||||
const infoColor = useColorModeValue('blue.600', 'blue.300');
|
||||
|
||||
return (
|
||||
<Center background={ isOpen ? infoBgColor : 'unset' } borderRadius="8px" w="30px" h="30px" onClick={ onClick }>
|
||||
<Center ref={ ref } background={ isOpen ? infoBgColor : 'unset' } borderRadius="8px" w="30px" h="30px" onClick={ onClick }>
|
||||
<Icon
|
||||
as={ infoIcon }
|
||||
boxSize={ 5 }
|
||||
@@ -24,4 +24,4 @@ const TxAdditionalInfoButton = ({ isOpen, onClick }: {isOpen?: boolean; onClick?
|
||||
);
|
||||
};
|
||||
|
||||
export default TxAdditionalInfoButton;
|
||||
export default React.forwardRef(TxAdditionalInfoButton);
|
||||
|
||||
+28
-5
@@ -1,11 +1,13 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { Box, HStack } from '@chakra-ui/react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { txs } from 'data/txs';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import Filters from 'ui/shared/Filters';
|
||||
import FilterButton from 'ui/shared/FilterButton';
|
||||
import FilterInput from 'ui/shared/FilterInput';
|
||||
import Pagination from 'ui/shared/Pagination';
|
||||
import SortButton from 'ui/shared/SortButton';
|
||||
|
||||
import Pagination from './Pagination';
|
||||
import TxsListItem from './TxsListItem';
|
||||
import TxsTable from './TxsTable';
|
||||
|
||||
@@ -69,11 +71,32 @@ const TxsContent = ({ isPending }: Props) => {
|
||||
return (
|
||||
<>
|
||||
{ !isPending && <Box mb={ 12 }>Only the first 10,000 elements are displayed</Box> }
|
||||
<Box mb={ 6 }><Filters isMobile={ isMobile }/></Box>
|
||||
<HStack mb={ 6 }>
|
||||
{ /* TODO */ }
|
||||
<FilterButton
|
||||
isActive={ false }
|
||||
isCollapsed={ isMobile }
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={ () => {} }
|
||||
appliedFiltersNum={ 0 }
|
||||
/>
|
||||
<SortButton
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
handleSort={ () => {} }
|
||||
isSortActive={ Boolean(sorting) }
|
||||
/>
|
||||
<FilterInput
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onChange={ () => {} }
|
||||
maxW="360px"
|
||||
size="xs"
|
||||
placeholder="Search by addresses, hash, method..."
|
||||
/>
|
||||
</HStack>
|
||||
{ isMobile ?
|
||||
sortedTxs.map(tx => <TxsListItem tx={ tx } key={ tx.hash }/>) :
|
||||
<TxsTable txs={ sortedTxs } sort={ sort } sorting={ sorting }/> }
|
||||
<Box mx={ isMobile ? 0 : 6 } my={ isMobile ? 6 : 3 }>
|
||||
<Box mx={{ base: 0, lg: 6 }} my={{ base: 6, lg: 3 }}>
|
||||
<Pagination currentPage={ 1 } isMobile={ isMobile }/>
|
||||
</Box>
|
||||
</>
|
||||
|
||||
+15
-21
@@ -8,12 +8,14 @@ import {
|
||||
ModalContent,
|
||||
ModalCloseButton,
|
||||
Text,
|
||||
Tooltip,
|
||||
useColorModeValue,
|
||||
useDisclosure } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import rightArrowIcon from 'icons/arrows/right.svg';
|
||||
import type ArrayElement from 'types/utils/ArrayElement';
|
||||
|
||||
import type { txs } from 'data/txs';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import transactionIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import useLink from 'lib/link/useLink';
|
||||
@@ -25,13 +27,10 @@ import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
|
||||
import TxAdditionalInfoButton from 'ui/txs/TxAdditionalInfoButton';
|
||||
import TxType from 'ui/txs/TxType';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const TxsListItem = ({ tx }: {tx: any}) => {
|
||||
const TxsListItem = ({ tx }: {tx: ArrayElement<typeof txs>}) => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
const iconColor = useColorModeValue('blue.600', 'blue.300');
|
||||
const secondaryTextColor = useColorModeValue('gray.500', 'gray.400');
|
||||
|
||||
const link = useLink();
|
||||
|
||||
return (
|
||||
@@ -61,34 +60,32 @@ const TxsListItem = ({ tx }: {tx: any}) => {
|
||||
/>
|
||||
</Address>
|
||||
</Flex>
|
||||
<Text color={ secondaryTextColor } fontWeight="400">{ dayjs(tx.timestamp).fromNow() }</Text>
|
||||
<Text variant="secondary" fontWeight="400">{ dayjs(tx.timestamp).fromNow() }</Text>
|
||||
</Flex>
|
||||
<Flex mt={ 3 }>
|
||||
<Text as="span" whiteSpace="pre">Method </Text>
|
||||
<Box
|
||||
color={ secondaryTextColor }
|
||||
<Text
|
||||
as="span"
|
||||
variant="secondary"
|
||||
overflow="hidden"
|
||||
whiteSpace="nowrap"
|
||||
textOverflow="ellipsis"
|
||||
>
|
||||
{ tx.method }
|
||||
</Box>
|
||||
</Text>
|
||||
</Flex>
|
||||
<Box mt={ 2 }>
|
||||
<Text as="span">Block </Text>
|
||||
<Link href={ link('block', { id: tx.block_num }) }>{ tx.block_num }</Link>
|
||||
<Link href={ link('block', { id: tx.block_num.toString() }) }>{ tx.block_num }</Link>
|
||||
</Box>
|
||||
<Flex alignItems="center" height={ 6 } mt={ 6 }>
|
||||
<Address width="calc((100%-40px)/2)">
|
||||
<Tooltip label={ tx.address_from.type } shouldWrapChildren>
|
||||
<AddressIcon hash={ tx.address_from.hash }/>
|
||||
</Tooltip>
|
||||
<AddressIcon hash={ tx.address_from.hash }/>
|
||||
<AddressLink
|
||||
hash={ tx.address_from.hash }
|
||||
alias={ tx.address_from.alias }
|
||||
fontWeight="500"
|
||||
ml={ 2 }
|
||||
truncation="constant"
|
||||
/>
|
||||
</Address>
|
||||
<Icon
|
||||
@@ -98,25 +95,22 @@ const TxsListItem = ({ tx }: {tx: any}) => {
|
||||
color="gray.500"
|
||||
/>
|
||||
<Address width="calc((100%-40px)/2)">
|
||||
<Tooltip label={ tx.address_to.type } shouldWrapChildren>
|
||||
<AddressIcon hash={ tx.address_to.hash }/>
|
||||
</Tooltip>
|
||||
<AddressIcon hash={ tx.address_to.hash }/>
|
||||
<AddressLink
|
||||
hash={ tx.address_to.hash }
|
||||
alias={ tx.address_to.alias }
|
||||
fontWeight="500"
|
||||
ml={ 2 }
|
||||
truncation="constant"
|
||||
/>
|
||||
</Address>
|
||||
</Flex>
|
||||
<Box mt={ 2 }>
|
||||
<Text as="span">Value xDAI </Text>
|
||||
<Text as="span" color={ secondaryTextColor }>{ tx.amount.value.toFixed(8) }</Text>
|
||||
<Text as="span" variant="secondary">{ tx.amount.value.toFixed(8) }</Text>
|
||||
</Box>
|
||||
<Box mt={ 2 } mb={ 3 }>
|
||||
<Text as="span">Fee xDAI </Text>
|
||||
<Text as="span" color={ secondaryTextColor }>{ tx.fee.value.toFixed(8) }</Text>
|
||||
<Text as="span" variant="secondary">{ tx.fee.value.toFixed(8) }</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
<Modal isOpen={ isOpen } onClose={ onClose } size="full">
|
||||
|
||||
+4
-5
@@ -1,7 +1,8 @@
|
||||
import { Link, Table, Thead, Tbody, Tr, Th, TableContainer, useBreakpointValue, Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import rightArrowIcon from 'icons/arrows/right.svg';
|
||||
import type { txs as data } from 'data/txs';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
|
||||
import TxsTableItem from './TxsTableItem';
|
||||
|
||||
@@ -10,8 +11,7 @@ const CURRENCY = 'xDAI';
|
||||
export type Sort = 'val-desc' | 'val-asc' | 'fee-desc' | 'fee-asc' | undefined;
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
txs: any;
|
||||
txs: typeof data;
|
||||
sort: (field: 'val' | 'fee') => () => void;
|
||||
sorting: Sort;
|
||||
}
|
||||
@@ -49,8 +49,7 @@ const TxsTable = ({ txs, sort, sorting }: Props) => {
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ }
|
||||
{ txs.map((item: any) => (
|
||||
{ txs.map((item) => (
|
||||
<TxsTableItem
|
||||
key={ item.hash }
|
||||
tx={ item }
|
||||
|
||||
+18
-13
@@ -12,12 +12,16 @@ import {
|
||||
PopoverTrigger,
|
||||
PopoverContent,
|
||||
PopoverBody,
|
||||
Portal,
|
||||
useBreakpointValue,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import rightArrowIcon from 'icons/arrows/right.svg';
|
||||
import type ArrayElement from 'types/utils/ArrayElement';
|
||||
|
||||
import type { txs } from 'data/txs';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import useLink from 'lib/link/useLink';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
@@ -30,16 +34,15 @@ import TxAdditionalInfoButton from 'ui/txs/TxAdditionalInfoButton';
|
||||
|
||||
import TxType from './TxType';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const TxsTableItem = ({ tx }: {tx: any}) => {
|
||||
const TxsTableItem = ({ tx }: {tx: ArrayElement<typeof txs>}) => {
|
||||
const link = useLink();
|
||||
|
||||
const isLargeScreen = useBreakpointValue({ base: false, xl: true });
|
||||
|
||||
const addressFrom = (
|
||||
<Address>
|
||||
<Tooltip label={ tx.address_from.type } shouldWrapChildren>
|
||||
<AddressIcon hash={ tx.address_from.hash }/>
|
||||
<Tooltip label={ tx.address_from.type }>
|
||||
<Box display="flex"><AddressIcon hash={ tx.address_from.hash }/></Box>
|
||||
</Tooltip>
|
||||
<AddressLink hash={ tx.address_from.hash } alias={ tx.address_from.alias } fontWeight="500" ml={ 2 }/>
|
||||
</Address>
|
||||
@@ -47,8 +50,8 @@ const TxsTableItem = ({ tx }: {tx: any}) => {
|
||||
|
||||
const addressTo = (
|
||||
<Address>
|
||||
<Tooltip label={ tx.address_to.type } shouldWrapChildren>
|
||||
<AddressIcon hash={ tx.address_to.hash }/>
|
||||
<Tooltip label={ tx.address_to.type }>
|
||||
<Box display="flex"> <AddressIcon hash={ tx.address_to.hash }/></Box>
|
||||
</Tooltip>
|
||||
<AddressLink hash={ tx.address_to.hash } alias={ tx.address_to.alias } fontWeight="500" ml={ 2 }/>
|
||||
</Address>
|
||||
@@ -64,11 +67,13 @@ const TxsTableItem = ({ tx }: {tx: any}) => {
|
||||
<PopoverTrigger>
|
||||
<TxAdditionalInfoButton isOpen={ isOpen }/>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent border="1px solid" borderColor={ infoBorderColor }>
|
||||
<PopoverBody>
|
||||
<TxAdditionalInfo tx={ tx }/>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
<Portal>
|
||||
<PopoverContent border="1px solid" borderColor={ infoBorderColor }>
|
||||
<PopoverBody>
|
||||
<TxAdditionalInfo tx={ tx }/>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</>
|
||||
) }
|
||||
</Popover>
|
||||
@@ -101,7 +106,7 @@ const TxsTableItem = ({ tx }: {tx: any}) => {
|
||||
</TruncatedTextTooltip>
|
||||
</Td>
|
||||
<Td>
|
||||
<Link href={ link('block', { id: tx.block_num }) }>{ tx.block_num }</Link>
|
||||
<Link href={ link('block', { id: tx.block_num.toString() }) }>{ tx.block_num }</Link>
|
||||
</Td>
|
||||
{ isLargeScreen ? (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user