chore: display prices as full number on sales page (#11554)

* chore: display prices as full number on sales page

* fix: requested changes and ui fixes

* refactor: simplify layout structure in Timeline component

---------

Co-authored-by: Arjun Porwal <porwalarjun95@gmail.com>
This commit is contained in:
rajk93 2025-05-20 12:13:37 +05:30 committed by GitHub
parent e24434951d
commit 27b729b2e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 25 deletions

View File

@ -8,11 +8,10 @@ import React, { useMemo } from 'react';
import { styled } from '@polkadot/react-components';
import { useApi, useCall } from '@polkadot/react-hooks';
import { formatBalance } from '@polkadot/util';
import { PhaseName } from '../../constants.js';
import { useTranslation } from '../../translate.js';
import { getCorePriceAt } from '../../utils/sale.js';
import { formatBNToBalance, getCorePriceAt } from '../../utils/sale.js';
import { WhiteBox } from '../../WhiteBox.js';
export const Cores = ({ color, phaseName, salesInfo }: { phaseName: string, salesInfo: CoretimeInformation['salesInfo'], color: string }) => {
@ -21,6 +20,10 @@ export const Cores = ({ color, phaseName, salesInfo }: { phaseName: string, sale
const bestNumberFinalized = useCall<BlockNumber>(apiCoretime?.derive.chain.bestNumberFinalized);
const coretimePrice = useMemo(() => bestNumberFinalized && salesInfo && getCorePriceAt(bestNumberFinalized.toNumber(), salesInfo), [salesInfo, bestNumberFinalized]);
const formattedCoretimePrice = useMemo(() => {
return !coretimePrice ? null : formatBNToBalance(coretimePrice);
}, [coretimePrice]);
const CoresWrapper = styled(WhiteBox)`
justify-self: flex-end;
@ -42,7 +45,7 @@ export const Cores = ({ color, phaseName, salesInfo }: { phaseName: string, sale
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<div>
<p style={{ fontSize: '14px', marginBottom: '0.15rem', opacity: '0.8' }}>{t('current price')}</p>
<p style={{ color: `${color}`, fontSize: '20px' }}> {coretimePrice && formatBalance(coretimePrice)}</p>
<p style={{ color: `${color}`, fontSize: '20px' }}>{formattedCoretimePrice}</p>
</div>
<div>
<p style={{ fontSize: '14px', marginBottom: '0.15rem', opacity: '0.8' }}>{t('available cores')}</p>

View File

@ -8,20 +8,12 @@ import type { CoretimeInformation } from '@polkadot/react-hooks/types';
import React, { useMemo } from 'react';
import { CardSummary, ProgressBar, styled, SummaryBox } from '@polkadot/react-components';
import { formatBalance, formatNumber } from '@polkadot/util';
import { formatNumber } from '@polkadot/util';
import { useTranslation } from '../../translate.js';
import { getCorePriceAt, getSaleProgress } from '../../utils/sale.js';
import { formatBNToBalance, getCorePriceAt, getSaleProgress } from '../../utils/sale.js';
import { WhiteBox } from '../../WhiteBox.js';
const TimelineWrapper = styled(WhiteBox)`
justify-self: flex-start;
@media (min-width: 769px) and (max-width: 1024px) {
width: 100%;
}
`;
interface TimelineProps {
phaseName: string;
saleParams: SaleParameters;
@ -45,27 +37,23 @@ export const Timeline = ({ color, coretimeInfo: { salesInfo, status }, phaseName
const coretimePriceStart = useMemo(() => salesInfo && getCorePriceAt(salesInfo.saleStart, salesInfo), [salesInfo]);
const endPrice = useMemo(() => salesInfo.endPrice.toNumber() < 10 ** formatBalance.getDefaults().decimals
? `${salesInfo.endPrice.toNumber() / 10 ** formatBalance.getDefaults().decimals} ${formatBalance.getDefaults().unit}`
: formatBalance(salesInfo.endPrice), [salesInfo.endPrice]);
const startPrice = useMemo(() => coretimePriceStart && formatBNToBalance(coretimePriceStart), [coretimePriceStart]);
const endPrice = useMemo(() => salesInfo?.endPrice && formatBNToBalance(salesInfo.endPrice), [salesInfo?.endPrice]);
return (
<TimelineWrapper>
<p style={{ fontSize: '16px', fontWeight: 'bold' }}>{t('Sale timeline')}</p>
<SummaryBox>
<section>
<StyledSummaryBox>
<GridLayout>
{phaseName && <>
<CardSummary label='current phase'>{phaseName}</CardSummary>
<CardSummary label='current phase end'>{saleParams?.phaseConfig?.config[phaseName as keyof typeof saleParams.phaseConfig.config].end.date}</CardSummary>
<CardSummary label='last phase block'>{formatNumber(saleParams?.phaseConfig?.config[phaseName as keyof typeof saleParams.phaseConfig.config].end.blocks.relay)}</CardSummary>
</>}
<CardSummary label='start price'>{formatBalance(coretimePriceStart)}</CardSummary>
<CardSummary label='start price'>{startPrice}</CardSummary>
<CardSummary label='fixed price'>{endPrice}</CardSummary>
</section>
<section>
</section>
</SummaryBox>
</GridLayout>
</StyledSummaryBox>
<ProgressBar
color={color}
sections={progressValues as ProgressBarSection[] ?? []}
@ -73,3 +61,33 @@ export const Timeline = ({ color, coretimeInfo: { salesInfo, status }, phaseName
</TimelineWrapper>
);
};
const TimelineWrapper = styled(WhiteBox)`
justify-self: flex-start;
@media (min-width: 769px) and (max-width: 1024px) {
width: 100%;
}
`;
const StyledSummaryBox = styled(SummaryBox)`
margin-top: 0;
`;
const GridLayout = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 0.5rem;
row-gap: 1rem;
width: 100%;
/* Override CardSummary styling to align text left and remove padding */
article {
justify-content: flex-start;
padding: 0;
> .ui--Labelled {
text-align: left;
}
}
`;

View File

@ -5,7 +5,7 @@ import type { ChainConstants, PalletBrokerConfigRecord, PalletBrokerSaleInfoReco
import type { GetResponse, PhaseConfig, RegionInfo, RelayName, SaleParameters } from '../types.js';
import { type ProgressBarSection } from '@polkadot/react-components/types';
import { BN } from '@polkadot/util';
import { BN, formatBalance } from '@polkadot/util';
import { PhaseName } from '../constants.js';
import { createGet, estimateTime, FirstCycleStart, getCurrentRegionStartEndTs } from './index.js';
@ -13,6 +13,14 @@ import { createGet, estimateTime, FirstCycleStart, getCurrentRegionStartEndTs }
// We are scaling everything to avoid floating point precision issues.
const SCALE = new BN(10000);
/**
* Formats a BN value to a human-readable balance string with proper units
*
* @param num - The BN value to format
* @returns A formatted string with the balance value and unit
*/
export const formatBNToBalance = (num: BN) => formatBalance(num, { forceUnit: formatBalance.getDefaults().unit, withAll: true, withUnit: true });
export const leadinFactorAt = (scaledWhen: BN): BN => {
const scaledHalf = SCALE.div(new BN(2)); // 0.5 scaled to 10000