Add top metrics filter

pull/225/head
artemkolodko 2 years ago
parent d02dee86f6
commit 7d1b49af4e
  1. 4
      src/api/client.ts
  2. 10
      src/pages/TopStatsPage/CommonTopTable.tsx
  3. 52
      src/pages/TopStatsPage/OptionsSelect.tsx
  4. 110
      src/pages/TopStatsPage/Transaction.tsx
  5. 6
      src/types/api.ts

@ -6,7 +6,7 @@ import {
RPCTransactionHarmony,
RelatedTransaction,
Log, LogDetailed, AddressDetails,
ShardID, MetricsType, MetricsDailyItem, MetricsTopType, MetricsTopItem
ShardID, MetricsType, MetricsDailyItem, MetricsTopType, MetricsTopItem, MetricsTopPeriod
} from "src/types";
import {
IHoldersInfo,
@ -115,7 +115,7 @@ export function getMetricsByType(type: MetricsType, offset = 0, limit = 14) {
return transport("getMetricsByType", [type, offset, limit]) as Promise<MetricsDailyItem[]>;
}
export function getTopMetricsByType(type: MetricsTopType, period: 1 | 3 | 7, limit = 10) {
export function getTopMetricsByType(type: MetricsTopType, period: MetricsTopPeriod, limit = 10) {
return transport("getTopMetricsByType", [type, period, limit]) as Promise<MetricsTopItem[]>;
}

@ -10,6 +10,7 @@ export interface TopTableProps {
items: MetricsTopItem[]
title: string
columns: string[]
isLoading?: boolean
}
interface TopTableRowProps {
@ -20,9 +21,10 @@ const TableContainer = styled(Box)`
flex: 0 0 calc(50% - 16px);
margin-left: 8px;
margin-right: 8px;
min-width: 500px;
@media (max-width: 1024px) {
flex: 0 0 calc(50% - 16px);
flex: 0 0 calc(100% - 16px);
margin-bottom: 0.75rem;
}
@ -93,7 +95,7 @@ const TopTableRow = (props: TopTableRowProps) => {
<Text size={'small'}>{rank}</Text>
</Box>
<Box width={columnsWidth[1]}>
<Address address={address} hideCopyBtn={true} />
<Address address={address} hideCopyBtn={true} isShortEllipsis={true} />
</Box>
<Box width={columnsWidth[2]} direction={'row'} align={'center'} gap={'6px'}>
{isOneTransfer && <LogoWrapper>
@ -112,10 +114,12 @@ export const TopTable = (props: TopTableProps) => {
border={{ size: '1px' }}
round={'8px'}
overflow={'hidden'}
margin={{ bottom: '16px' }}
style={{ opacity: props.isLoading ? 0.5 : 1 }}
>
<Box>
<Box pad={'8px'} border={{ size: '1px', side: 'bottom' }} background={'backgroundBackEmpty'}>
<Text>{props.title}</Text>
<Text size={'small'}>{props.title}</Text>
</Box>
<TopTableHeader columns={props.columns} />
{props.items.map(item => <TopTableRow key={item.address} item={item} />)}

@ -0,0 +1,52 @@
import React from 'react'
import {Box} from "grommet";
import {MetricsTopPeriod} from "../../types";
const OptionAlias = {
[MetricsTopPeriod.d1]: '1 Day',
[MetricsTopPeriod.d3]: '3 Days',
[MetricsTopPeriod.d7]: '7 Days',
}
export const ChartOptions = Object.values(MetricsTopPeriod).filter(v => typeof v === 'number') as MetricsTopPeriod[]
const Option = (props: { value: MetricsTopPeriod, isActive: boolean, onSelect: (value: MetricsTopPeriod) => void }) => {
const {value, isActive, onSelect} = props
return <Box
align={'center'}
pad={'8px'}
round={'8px'}
background={isActive ? 'background' : 'unset'}
onClick={() => onSelect(value)}
style={{ cursor: 'pointer', fontWeight: isActive ? 'bold': 'normal' }}
>
{OptionAlias[value]}
</Box>
}
export interface OptionsSelectProps {
activeOption: MetricsTopPeriod
onSelect: (option: MetricsTopPeriod) => void
disabled?: boolean
}
export const OptionsSelect = (props: OptionsSelectProps) => {
const { activeOption, disabled, onSelect } = props
return <Box
direction={'row'}
justify={'between'}
pad={'4px'}
gap={'8px'}
round={'8px'}
background={'backgroundBack'}
border={{ size: '1px' }}
>
{ChartOptions.map(option => <Option
key={option}
value={option}
isActive={activeOption === option}
onSelect={(option) => !disabled ? onSelect(option) : undefined}
/>)}
</Box>
}

@ -1,17 +1,13 @@
import React, {useEffect, useState} from 'react'
import {Box} from "grommet";
import {Box, Spinner} from "grommet";
import {TopTable} from "./CommonTopTable";
import {getTopMetricsByType} from "../../api/client";
import {MetricsTopItem, MetricsTopType} from "../../types";
enum PeriodOption {
d1 = 1,
d3 = 3,
d7 = 7
}
import {MetricsTopItem, MetricsTopPeriod, MetricsTopType} from "../../types";
import {OptionsSelect} from "./OptionsSelect";
export const TransactionTopStats = () => {
const [period, setPeriod] = useState(PeriodOption.d1)
const [isLoading, setLoading] = useState(false)
const [period, setPeriod] = useState(MetricsTopPeriod.d1)
const [oneSenders, setOneSenders] = useState<MetricsTopItem[]>([])
const [oneReceivers, setOneReceivers] = useState<MetricsTopItem[]>([])
const [txsSenders, setTxsSenders] = useState<MetricsTopItem[]>([])
@ -19,45 +15,69 @@ export const TransactionTopStats = () => {
useEffect(() => {
const loadData = async () => {
const rowsOneSent = await getTopMetricsByType(MetricsTopType.topOneSender, 1)
const rowsOneReceive = await getTopMetricsByType(MetricsTopType.topOneReceiver, 1)
const rowsTxsSent = await getTopMetricsByType(MetricsTopType.topTxsCountSent, 1)
const rowsTxsReceived = await getTopMetricsByType(MetricsTopType.topTxsCountReceived, 1)
try {
setLoading(true)
const rowsOneSent = await getTopMetricsByType(MetricsTopType.topOneSender, period)
const rowsOneReceive = await getTopMetricsByType(MetricsTopType.topOneReceiver, period)
const rowsTxsSent = await getTopMetricsByType(MetricsTopType.topTxsCountSent, period)
const rowsTxsReceived = await getTopMetricsByType(MetricsTopType.topTxsCountReceived, period)
await new Promise(resolve => setTimeout(resolve, 2000))
setOneSenders(rowsOneSent)
setOneReceivers(rowsOneReceive)
setTxsSenders(rowsTxsSent)
setTxsReceivers(rowsTxsReceived)
setOneSenders(rowsOneSent)
setOneReceivers(rowsOneReceive)
setTxsSenders(rowsTxsSent)
setTxsReceivers(rowsTxsReceived)
} catch (e) {
console.error('Error on loading top metrics:', (e as Error).message)
} finally {
setLoading(false)
}
}
loadData()
}, [])
}, [period])
return <Box
wrap
direction={'row'}
pad={"small"}
justify={'center'}
align={'center'}
>
<TopTable
items={oneSenders}
title={'Top ONE Senders'}
columns={['Rank', 'Address', 'Total ONE', 'Share']}
/>
<TopTable
items={oneReceivers}
title={'Top ONE Receivers'}
columns={['Rank', 'Address', 'Total ONE', 'Share']}
/>
<TopTable
items={txsSenders}
title={'Top Txs Count Sent'}
columns={['Rank', 'Address', 'Total Txs', 'Share']}
/>
<TopTable
items={txsReceivers}
title={'Top Txs Count Received'}
columns={['Rank', 'Address', 'Total Txs', 'Share']}
/>
return <Box gap={'16px'}>
<Box align={'center'} pad={'8px'} direction={'row'} gap={'24px'}>
<OptionsSelect
disabled={isLoading}
activeOption={period}
onSelect={(option) => setPeriod(option)}
/>
<Box>
{isLoading && <Spinner size={'small'} />}
</Box>
</Box>
<Box
wrap
direction={'row'}
justify={'center'}
align={'center'}
>
<TopTable
items={oneSenders}
title={'Top ONE Senders'}
columns={['Rank', 'Address', 'Total ONE', 'Share']}
isLoading={isLoading}
/>
<TopTable
items={oneReceivers}
title={'Top ONE Receivers'}
columns={['Rank', 'Address', 'Total ONE', 'Share']}
isLoading={isLoading}
/>
<TopTable
items={txsSenders}
title={'Top Txs Count Sent'}
columns={['Rank', 'Address', 'Total Txs', 'Share']}
isLoading={isLoading}
/>
<TopTable
items={txsReceivers}
title={'Top Txs Count Received'}
columns={['Rank', 'Address', 'Total Txs', 'Share']}
isLoading={isLoading}
/>
</Box>
</Box>
}

@ -74,3 +74,9 @@ export interface MetricsTopItem {
value: string
updatedAt: string
}
export enum MetricsTopPeriod {
d1 = 1,
d3 = 3,
d7 = 7
}

Loading…
Cancel
Save