Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use FormatPrice component #1565

Merged
merged 9 commits into from
Sep 29, 2024
50 changes: 37 additions & 13 deletions packages/extension-polkagate/src/components/FormatPrice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import type { BN } from '@polkadot/util';

import { Grid, Skeleton } from '@mui/material';
import { Grid, Skeleton, Typography } from '@mui/material';
import React, { useMemo } from 'react';

import { useCurrency } from '../hooks';
Expand All @@ -13,23 +13,29 @@ interface Props {
amount?: BN | null;
decimalPoint?: number;
decimals?: number;
fontSize?: string;
fontWeight?: number;
lineHeight?: number;
mt?: string;
num?: number | string;
price?: number | null,
sign?: string;
skeletonHeight?: number;
textAlign?: 'left' | 'right';
textColor?: string;
height?: number;
width?: string;
mt?: string;
skeletonHeight?: number;
}

export function nFormatter (num: number, decimalPoint: number) {
const lookup = [
{ value: 1, symbol: '' },
{ value: 1e3, symbol: 'k' },
{ value: 1e6, symbol: 'M' },
{ value: 1e9, symbol: 'G' },
{ value: 1e12, symbol: 'T' },
{ value: 1e15, symbol: 'P' },
{ value: 1e18, symbol: 'E' }
{ symbol: '', value: 1 },
{ symbol: 'k', value: 1e3 },
{ symbol: 'M', value: 1e6 },
{ symbol: 'G', value: 1e9 },
{ symbol: 'T', value: 1e12 },
{ symbol: 'P', value: 1e15 },
{ symbol: 'E', value: 1e18 }
];

const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
Expand All @@ -44,11 +50,13 @@ export function nFormatter (num: number, decimalPoint: number) {
return item ? (num / item.value).toFixed(decimalPoint).replace(rx, '$1') + item.symbol : '0';
}

function FormatPrice ({ amount, decimalPoint = 2, decimals, mt = '0px', num, price, skeletonHeight = 15, textAlign = 'left', width = '90px' }: Props): React.ReactElement<Props> {
const DECIMAL_POINTS_FOR_CRYPTO_AS_CURRENCY = 4;

function FormatPrice ({ amount, decimalPoint = 2, decimals, fontSize, fontWeight, height, lineHeight = 1, mt = '0px', num, price, sign, skeletonHeight = 15, textAlign = 'left', textColor, width = '90px' }: Props): React.ReactElement<Props> {
const currency = useCurrency();

const total = useMemo(() => {
if (num) {
if (num !== undefined) {
return num;
}

Expand All @@ -59,14 +67,30 @@ function FormatPrice ({ amount, decimalPoint = 2, decimals, mt = '0px', num, pri
return undefined;
}, [amount, decimals, num, price]);

const _decimalPoint = useMemo(() => {
if (currency?.code && ['ETH', 'BTC'].includes(currency.code)) {
return DECIMAL_POINTS_FOR_CRYPTO_AS_CURRENCY;
}

return decimalPoint;
}, [currency?.code, decimalPoint]);

return (
<Grid
item
mt={mt}
sx={{ height }}
textAlign={textAlign}
>
{total !== undefined
? `${currency?.sign || ''}${nFormatter(total as number, decimalPoint)}`
? <Typography
fontSize={fontSize}
fontWeight={fontWeight}
lineHeight={lineHeight}
sx={{ color: textColor }}
>
{sign || currency?.sign || ''}{nFormatter(total as number, _decimalPoint)}
</Typography>
: <Skeleton
animation='wave'
height={skeletonHeight}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ const BalanceRow = ({ api, asset, pricesInCurrencies }: BalanceRowProps) => {
token={asset.token}
/>
</Grid>
<Grid item sx={{ fontSize: '13px', fontWeight: 400, lineHeight: 1 }}>
<FormatPrice
amount={total}
decimals={asset.decimal}
price={pricesInCurrencies?.prices?.[asset.priceId]?.value ?? 0}
/>
</Grid>
<FormatPrice
amount={total}
decimals={asset.decimal}
fontSize='13px'
fontWeight={ 400}
price={pricesInCurrencies?.prices?.[asset.priceId]?.value ?? 0}
/>
</Grid>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ interface PriceJSXType {
}

const Price = ({ balanceToShow, isPriceOutdated, price }: PriceJSXType) => (
<Grid item sx={{ '> div span': { display: 'block' }, color: isPriceOutdated ? 'primary.light' : 'text.primary', fontWeight: 400 }}>
<FormatPrice
amount={getValue('total', balanceToShow)}
decimals={balanceToShow?.decimal}
price={price}
skeletonHeight={22}
width='80px'
/>
</Grid>
<FormatPrice
amount={getValue('total', balanceToShow)}
decimals={balanceToShow?.decimal}
fontSize='28px'
fontWeight= { 400 }
price={price}
skeletonHeight={22}
textColor={ isPriceOutdated ? 'primary.light' : 'text.primary'}
width='80px'
/>
);

interface BalanceJSXType {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0
// @ts-nocheck

/* eslint-disable react/jsx-max-props-per-line */

Expand All @@ -12,14 +11,14 @@ import { useAssetHubAssets, useTokens } from '../../../hooks';

interface Props {
address: string | undefined;
onChange: (value: number) => void;
onChange: (value: number | string) => void;
label: string;
style: SxProps<Theme> | undefined;
assetId: number | undefined;
setAssetId: React.Dispatch<React.SetStateAction<number | undefined>>
}

function AssetSelect({ address, assetId, label, onChange, setAssetId, style }: Props) {
function AssetSelect ({ address, assetId, label, onChange, setAssetId, style }: Props) {
const tokens = useTokens(address);
const assets = useAssetHubAssets(address);
const options = useMemo(() => (tokens || []).concat(assets || []), [assets, tokens]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
/* eslint-disable react/jsx-max-props-per-line */

import type { Balance } from '@polkadot/types/interfaces';
import type { BN } from '@polkadot/util';

import { ArrowForwardIosRounded as ArrowForwardIosRoundedIcon } from '@mui/icons-material';
import { Divider, Grid, IconButton, Typography, useTheme } from '@mui/material';
import React from 'react';

import { BN } from '@polkadot/util';

import { FormatPrice, ShowBalance } from '../../../components';

interface Props {
Expand All @@ -24,7 +23,7 @@ interface Props {
openCollapse?: boolean;
}

export default function DisplayBalance({ amount, decimal, disabled, onClick, price, openCollapse, title, token }: Props): React.ReactElement {
export default function DisplayBalance ({ amount, decimal, disabled, onClick, openCollapse, price, title, token }: Props): React.ReactElement {
const theme = useTheme();

return (
Expand All @@ -43,14 +42,14 @@ export default function DisplayBalance({ amount, decimal, disabled, onClick, pri
/>
</Grid>
<Divider orientation='vertical' sx={{ backgroundColor: 'text.primary', height: '35px', mx: '10px', my: 'auto' }} />
<Grid item sx={{ '> div span': { display: 'block' }, fontSize: '22px', fontWeight: 400 }}>
<FormatPrice
amount={amount}
decimals={decimal}
price={price}
skeletonHeight={20}
/>
</Grid>
<FormatPrice
amount={amount}
decimals={decimal}
fontSize= '22px'
fontWeight= {400}
price={price}
skeletonHeight={20}
/>
{onClick &&
<Grid item m='auto' pl='8px'>
<IconButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ export default function LockedInReferendaFS ({ address, price, refreshNeeded, se
/>
</Grid>
<Divider orientation='vertical' sx={{ backgroundColor: 'text.primary', height: '35px', mx: '10px', my: 'auto' }} />
<Grid item sx={{ '> div span': { display: 'block' }, fontSize: '22px', fontWeight: 400 }}>
<FormatPrice
amount={totalLocked}
decimals={decimal}
price={price}
skeletonHeight={20}
/>
</Grid>
<FormatPrice
amount={totalLocked}
decimals={decimal}
fontSize= '22px'
fontWeight={ 400}
price={price}
skeletonHeight={20}
/>
Nick-1979 marked this conversation as resolved.
Show resolved Hide resolved
</Grid>
<Typography fontSize='12px' fontWeight={500} textAlign='right'>
{api && unlockableAmount && !unlockableAmount.isZero()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { Chart, registerables } from 'chart.js';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';

import { AssetLogo } from '../../../components';
import { nFormatter } from '../../../components/FormatPrice';
import { useCurrency, useTranslation } from '../../../hooks';
import FormatPrice from '../../../components/FormatPrice';
import { useTranslation } from '../../../hooks';
import { DEFAULT_COLOR } from '../../../util/constants';
import getLogo2 from '../../../util/getLogo2';
import { amountToHuman } from '../../../util/utils';
Expand All @@ -31,10 +31,9 @@ interface AssetsToShow extends FetchedBalance {
color: string
}

export default function TotalChart({ accountAssets, pricesInCurrency }: Props): React.ReactElement {
export default function TotalChart ({ accountAssets, pricesInCurrency }: Props): React.ReactElement {
const { t } = useTranslation();
const theme = useTheme();
const currency = useCurrency();
const chartRef = useRef(null);

Chart.register(...registerables);
Expand All @@ -45,10 +44,10 @@ export default function TotalChart({ accountAssets, pricesInCurrency }: Props):
const formatNumber = useCallback((num: number): number => parseFloat(Math.trunc(num) === 0 ? num.toFixed(2) : num.toFixed(1)), []);

const { assets, totalWorth } = useMemo(() => {
if (accountAssets && accountAssets.length) {
if (accountAssets?.length) {
const _assets = accountAssets as unknown as AssetsToShow[];

let totalWorth = 0;
let total = 0;

/** to add asset's worth and color */
accountAssets.forEach((asset, index) => {
Expand All @@ -58,20 +57,20 @@ export default function TotalChart({ accountAssets, pricesInCurrency }: Props):
_assets[index].worth = assetWorth;
_assets[index].color = adjustColor(asset.token, assetColor, theme);

totalWorth += assetWorth;
total += assetWorth;
});

/** to add asset's percentage */
_assets.forEach((asset) => {
asset.percentage = formatNumber((asset.worth / totalWorth) * 100);
asset.percentage = formatNumber((asset.worth / total) * 100);

return asset;
});

_assets.sort((a, b) => b.worth - a.worth);
const nonZeroAssets = _assets.filter((asset) => asset.worth > 0);

return { assets: nonZeroAssets, totalWorth: nFormatter(totalWorth, 2) };
return { assets: nonZeroAssets, totalWorth: total };
}

return { assets: undefined, totalWorth: undefined };
Expand All @@ -81,7 +80,7 @@ export default function TotalChart({ accountAssets, pricesInCurrency }: Props):
const worths = assets?.map(({ worth }) => worth);
const colors = assets?.map(({ color }) => color);

//@ts-ignore
// @ts-ignore
const chartInstance = new Chart(chartRef.current, {
data: {
datasets: [{
Expand All @@ -100,7 +99,7 @@ export default function TotalChart({ accountAssets, pricesInCurrency }: Props):
label: function (context) {
const index = colors?.findIndex((val) => val === context.element.options['backgroundColor']);

return index && index != -1 ? assets?.[index]?.token as string :'UNIT';
return index && index !== -1 ? assets?.[index]?.token : 'UNIT';
}
}
}
Expand All @@ -109,21 +108,24 @@ export default function TotalChart({ accountAssets, pricesInCurrency }: Props):
type: 'doughnut'
});

// Clean up the chart instance on component unmount
return () => {
chartInstance.destroy();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [assets?.length, theme.palette.divider]);

return (
<Grid alignItems='center' container direction='column' item justifyContent='center' sx={{ bgcolor: 'background.paper', borderRadius: '5px', boxShadow: '2px 3px 4px 0px rgba(0, 0, 0, 0.1)', maxHeight: '185px', p: '15px', width: 'inherit' }}>
<Grid alignItems='center' container gap='15px' item justifyContent='center'>
<Grid alignItems='center' container gap='15px' item justifyContent='center' height='54px'>
<Typography fontSize='18px' fontWeight={400}>
{t('Total')}
</Typography>
<Typography fontSize='36px' fontWeight={700}>
{`${currency?.sign ?? ''}${totalWorth ?? 0}`}
</Typography>
<FormatPrice
fontSize='36px'
fontWeight={700}
num={totalWorth}
skeletonHeight={22}
/>
</Grid>
{assets && assets.length > 0 &&
<Grid container item sx={{ borderTop: '1px solid', borderTopColor: 'divider', py: '5px' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,14 @@ export default function AccountDetails (): React.ReactElement {
}
}, [genesisHash, accountAssets, assetId, paramAssetId, selectedAsset]);

const onChangeAsset = useCallback((id: number) => {
const onChangeAsset = useCallback((id: number | string) => {
if (id === -1) { // this is the id of native token
setAssetIdOnAssetHub(0);

return;
}

setAssetIdOnAssetHub(id); // this works for asset hubs atm
setAssetIdOnAssetHub(id as number); // this works for asset hubs atm
}, []);

const goToSend = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { Circle } from 'better-react-spinkit';
import React, { useEffect, useState } from 'react';

import { Label } from '../../components';
import { nFormatter } from '../../components/FormatPrice';
import { useCurrency, useTranslation } from '../../hooks';
import FormatPrice from '../../components/FormatPrice';
import { useTranslation } from '../../hooks';
import { toTitleCase } from '../governance/utils/util';

interface Props {
Expand Down Expand Up @@ -44,7 +44,6 @@ const TOKEN_PRICE_KEY = 'tokenPrice';
export default function ShowChainInfo ({ metadata, price, style }: Props): React.ReactElement {
const { t } = useTranslation();
const theme = useTheme();
const currency = useCurrency();

const [selectedChainInfo, setSelectedChainInfo] = useState<SelectedChainInfo | undefined>();

Expand Down Expand Up @@ -88,7 +87,12 @@ export default function ShowChainInfo ({ metadata, price, style }: Props): React
Object.entries(selectedChainInfo).map(([key, value]) => (
<Typography fontSize='14px' fontWeight={300} height={`${LINE_HEIGHT}px`} key={key}>
{key === TOKEN_PRICE_KEY
? `${currency?.sign || ''}${nFormatter(value as number, 2)}`
? <FormatPrice
decimalPoint={4}
fontSize='14px'
fontWeight={300}
num={(value || 0) as number}
/>
: value ?? '--- ---'
}
</Typography>
Expand Down
Loading
Loading