Commit 1439504f authored by tom's avatar tom

desktop layout

parent 86d8e34f
/* eslint-disable max-len */
import { block } from './block';
export const blocks = [
{
...block,
timestamp: Date.now() - 25_000,
},
{
...block,
height: 15006917,
timestamp: Date.now() - 1_000 * 60 * 2,
miner: {
address: '0xdAd49e6CbDE849353ab27DeC6319E687BFc91A41',
name: undefined,
},
transactionsNum: 185,
size: 452,
gas_limit: 30000000,
gas_used: 15671326,
gas_target: 14671326,
burnt_fees: 0.3988042215537949,
},
{
...block,
height: 15006916,
timestamp: Date.now() - 1_000 * 60 * 60 * 17,
transactionsNum: 377,
size: 5222,
gas_limit: 30000000,
gas_used: 23856751,
gas_target: 28856751,
burnt_fees: 0.0000019660909367,
},
];
......@@ -5,8 +5,6 @@ import localizedFormat from 'dayjs/plugin/localizedFormat';
import relativeTime from 'dayjs/plugin/relativeTime';
import updateLocale from 'dayjs/plugin/updateLocale';
dayjs.locale('en');
const relativeTimeConfig = {
thresholds: [
{ l: 's', r: 1 },
......@@ -51,4 +49,27 @@ dayjs.updateLocale('en', {
},
});
dayjs.locale('en-short', {
name: 'en-short',
relativeTime: {
s: '1s',
future: 'in %s',
past: '%s ago',
m: '1m',
mm: '%dm',
h: '1h',
hh: '%dh',
d: '1d',
dd: '%dd',
M: '1mo',
MM: '%dmo',
y: '1y',
yy: '%dy',
// have to trick typescript 🎩 🐇
...{ ss: '%ds' },
},
});
dayjs.locale('en');
export default dayjs;
......@@ -128,6 +128,11 @@ const BlockDetails = () => {
>
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500"/>
<Text ml={ 1 }>{ block.burnt_fees.toLocaleString('en', { minimumFractionDigits: 18 }) } Ether</Text>
<Tooltip label="Burnt fees / Txn fees * 100%">
<Box>
<Utilization ml={ 4 } value={ block.burnt_fees / block.reward.tx_fee }/>
</Box>
</Tooltip>
</DetailsInfoItem>
<DetailsInfoItem
title="Extra data"
......
import { Box, Text } from '@chakra-ui/react';
import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
import BlocksTable from 'ui/blocks/BlocksTable';
import Pagination from 'ui/shared/Pagination';
const BlocksContent = () => {
const isMobile = useIsMobile();
return (
<>
<Text>Total of 15,044,883 blocks</Text>
<BlocksTable/>
<Box mx={{ base: 0, lg: 6 }} my={{ base: 6, lg: 3 }}>
<Pagination currentPage={ 1 } isMobile={ isMobile }/>
</Box>
</>
);
};
export default BlocksContent;
import { Table, Thead, Tbody, Tr, Th, TableContainer } from '@chakra-ui/react';
import React from 'react';
import { blocks } from 'data/blocks';
import BlocksTableItem from 'ui/blocks/BlocksTableItem';
const BlocksTable = () => {
return (
<TableContainer width="100%" mt={ 8 }>
<Table variant="simple" minWidth="1040px" size="md" fontWeight={ 500 }>
<Thead>
<Tr>
<Th width="124px">Block</Th>
<Th width="112px">Size</Th>
<Th width="144px">Miner</Th>
<Th width="64px" isNumeric>Txn</Th>
<Th width="40%">Gas used</Th>
<Th width="30%">Reward ETH</Th>
<Th width="30%">Burnt fees ETH</Th>
</Tr>
</Thead>
<Tbody>
{ blocks.map((item, index) => <BlocksTableItem key={ item.height } data={ item } isPending={ index === 0 }/>) }
</Tbody>
</Table>
</TableContainer>
);
};
export default BlocksTable;
import { Tr, Td, Text, Link, Flex, Box, Stat, StatArrow, Icon, Tooltip, Spinner, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import type ArrayElement from 'types/utils/ArrayElement';
import type { blocks } from 'data/blocks';
import flameIcon from 'icons/flame.svg';
import dayjs from 'lib/date/dayjs';
import useLink from 'lib/link/useLink';
import AddressLink from 'ui/shared/address/AddressLink';
import Utilization from 'ui/shared/Utilization';
interface Props {
data: ArrayElement<typeof blocks>;
isPending?: boolean;
}
const BlocksTableItem = ({ data, isPending }: Props) => {
const link = useLink();
const gasUsedPercentage = (data.gas_used / data.gas_target - 1) * 100;
const spinnerEmptyColor = useColorModeValue('blackAlpha.200', 'whiteAlpha.200');
return (
<Tr>
<Td fontSize="sm">
<Flex columnGap={ 2 } alignItems="center">
{ isPending && <Spinner size="sm" color="blue.500" emptyColor={ spinnerEmptyColor }/> }
<Link
fontWeight={ 600 }
href={ link('block_index', { id: String(data.height) }) }
>
{ data.height }
</Link>
</Flex>
<Text variant="secondary" mt={ 2 } fontWeight={ 400 }>{ dayjs(data.timestamp).locale('en-short').fromNow() }</Text>
</Td>
<Td fontSize="sm">{ data.size.toLocaleString('en') } bytes</Td>
<Td fontSize="sm">
<AddressLink alias={ data.miner?.name } hash={ data.miner.address } truncation="constant"/>
</Td>
<Td isNumeric fontSize="sm">{ data.transactionsNum }</Td>
<Td fontSize="sm">
<Box>{ data.gas_used.toLocaleString('en') }</Box>
<Flex mt={ 2 }>
<Utilization colorScheme="gray" value={ data.gas_used / data.gas_limit }/>
<Stat ml={ 2 }>
<StatArrow type={ gasUsedPercentage >= 0 ? 'increase' : 'decrease' }/>
<Text as="span" color={ gasUsedPercentage >= 0 ? 'green.500' : 'red.500' } fontWeight={ 600 }>
{ Math.abs(gasUsedPercentage).toLocaleString('en', { maximumFractionDigits: 2 }) } %
</Text>
</Stat>
</Flex>
</Td>
<Td fontSize="sm">{ (data.reward.static + data.reward.tx_fee - data.burnt_fees).toLocaleString('en', { maximumFractionDigits: 5 }) }</Td>
<Td fontSize="sm">
<Flex alignItems="center" columnGap={ 1 }>
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500"/>
{ data.burnt_fees.toLocaleString('en', { maximumFractionDigits: 6 }) }
</Flex>
<Tooltip label="Burnt fees / Txn fees * 100%">
<Box>
<Utilization mt={ 2 } value={ data.burnt_fees / data.reward.tx_fee }/>
</Box>
</Tooltip>
</Td>
</Tr>
);
};
export default React.memo(BlocksTableItem);
import { useRouter } from 'next/router';
import React from 'react';
import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import BlocksContent from 'ui/blocks/BlocksContent';
import Page from 'ui/shared/Page';
import PageHeader from 'ui/shared/PageHeader';
import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs';
const TABS: Array<RoutedTab> = [
{ routeName: 'blocks', title: 'All', component: <div>All</div> },
{ routeName: 'reorgs', title: 'Forked', component: <div>Forked</div> },
{ routeName: 'uncles', title: 'Uncles', component: <div>Uncles</div> },
{ routeName: 'blocks', title: 'All', component: <BlocksContent/> },
{ routeName: 'reorgs', title: 'Forked', component: <BlocksContent/> },
{ routeName: 'uncles', title: 'Uncles', component: <BlocksContent/> },
];
export interface Props {
......@@ -18,11 +18,9 @@ export interface Props {
}
const BlocksPageContent = ({ tab }: Props) => {
const router = useRouter();
return (
<Page>
<PageHeader text={ `Block #${ router.query.id || '' }` }/>
<PageHeader text="Blocks"/>
<RoutedTabs
tabs={ TABS }
defaultActiveTab={ tab }
......
......@@ -10,7 +10,7 @@ interface Props {
const WIDTH = 50;
const Utilization = ({ className, value, colorScheme = 'green' }: Props) => {
const valueString = (value * 100).toFixed(2) + '%';
const valueString = (value * 100).toLocaleString('en', { maximumFractionDigits: 2 }) + '%';
const colorGrayScheme = useColorModeValue('gray.500', 'gray.500');
const color = colorScheme === 'gray' ? colorGrayScheme : 'green.500';
......
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