Skip to content

Commit

Permalink
Merge pull request #132 from multiversx/default-coin-page
Browse files Browse the repository at this point in the history
Native Token Page
  • Loading branch information
radumojic authored Oct 18, 2024
2 parents e5e68e7 + b645a0e commit 0a9026c
Show file tree
Hide file tree
Showing 62 changed files with 1,014 additions and 781 deletions.
2 changes: 1 addition & 1 deletion src/assets/scss/components/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
@import '../../../components/Marquee/marquee.styles.scss';
@import '../../../components/MultilayerPercentage/multilayerPercentage.styles.scss';
@import '../../../components/NftPreview/nftPreview.styles.scss';
@import '../../../components/NodesTable/nodesTable.styles.scss';
@import '../../../components/Nodes/AuctionListTable/auctionListTables.styles.scss';
@import '../../../components/Nodes/NodesOverview/nodesOverview.styles.scss';
@import '../../../components/Nodes/NodesStatusPreviewCards/nodesStatusPreviewCards.styles.scss';
@import '../../../components/NodesTable/nodesTable.styles.scss';
@import '../../../components/NotificationsBar/notificationsBar.styles.scss';
@import '../../../components/Pager/pager.styles.scss';
@import '../../../components/PageState/components/IconState/iconState.styles.scss';
Expand Down
2 changes: 2 additions & 0 deletions src/assets/scss/components/_pages.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
@import '../../../pages/AccountDetails/AccountTokensTable/accountTokensTable.styles.scss';
@import '../../../pages/Analytics/analytics.styles.scss';
@import '../../../pages/BlockDetails/blockDetails.styles.scss';
@import '../../../pages/Home/home.styles.scss';
@import '../../../pages/Identities/identities.styles.scss';
@import '../../../pages/NativeToken/nativeToken.styles.scss';
@import '../../../pages/NftDetails/nftDetails.styles.scss';
@import '../../../pages/NodeDetails/components/NetworkMetrics/networkMetrics.styles.scss';
@import '../../../pages/NodeDetails/components/Rounds/rounds.styles.scss';
Expand Down
8 changes: 4 additions & 4 deletions src/assets/scss/components/_widgets.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@import '../../../widgets/ChartCard/chartCard.styles.scss';
@import '../../../widgets/ChartContractsTransactions/chartContractsTransactions.styles.scss';
@import '../../../widgets/EconomicsCard/economicsCard.styles.scss';
@import '../../../widgets/HeroHome/heroHome.styles.scss';
@import '../../../widgets/HeroNodes/heroNodes.styles.scss';
@import '../../../widgets/HeroPills/heroPills.styles.scss';
@import '../../../widgets/MostUsed/mostUsed.styles.scss';
@import '../../../widgets/ValidatorsStatusCard/validatorsStatusCard.styles.scss';
@import '../../../widgets/StatsCard/statsCard.styles.scss';

// temp
@import '../../../pages/Home/components/ChartContractsTransactions/chartContractsTransactions.styles.scss';
@import '../../../widgets/ValidatorsStatusCard/validatorsStatusCard.styles.scss';
4 changes: 2 additions & 2 deletions src/assets/scss/elements/_tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
border-radius: 0.5rem;
background-color: transparent;

@media (min-width: 768px) {
@include media-breakpoint-up(md) {
font-size: 1rem;
padding: 0.75rem 1rem;
}
Expand All @@ -45,7 +45,7 @@
&.active {
color: var(--primary);
}
@media (min-width: 768px) {
@include media-breakpoint-up(md) {
font-size: 1.5rem;
padding: 0.5rem 0.75rem;
}
Expand Down
2 changes: 1 addition & 1 deletion src/assets/scss/plugins/_sdk-dapp-overrides.scss
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ a .dapp-core-component__trim-styles__ellipsis {
}
}

@media (min-width: 768px) {
@include media-breakpoint-up(md) {
.dapp-core-component__signWithDeviceModalStyles__modal-layout-content.dapp-core-component__signWithDeviceModalStyles__spaced {
padding: 2rem 0.75rem 1.5rem 0.75rem !important;
}
Expand Down
170 changes: 170 additions & 0 deletions src/components/AccountsTable/AccountsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import BigNumber from 'bignumber.js';
import classNames from 'classnames';

import {
FormatAmount,
AccountLink,
FormatNumber,
FormatUSD,
PercentageBar,
Pager,
PageSize,
Loader,
PageState
} from 'components';
import { DECIMALS } from 'config';
import { formatBigNumber, parseAmount } from 'helpers';
import { faUser } from 'icons/regular';
import { AccountType, TokenLockedAccountType, WithClassnameType } from 'types';

export interface AccountsTableUIType extends WithClassnameType {
accounts: AccountType[] | TokenLockedAccountType[];
accountsCount: number;
title?: React.ReactNode;
message?: string;
decimals?: number;
showValue?: boolean;
supply?: string | number;
price?: number;
isDataReady?: boolean;
hasNameColumn?: boolean;
isNativeToken?: boolean;
}

export const AccountsTable = ({
accounts,
accountsCount,
title,
message = 'Accounts',
decimals = DECIMALS,
showValue,
price,
supply,
isNativeToken = false,
isDataReady,
hasNameColumn
}: AccountsTableUIType) => {
const hasSupply = new BigNumber(supply ?? 0).isGreaterThan(0);
const showAccounts = isDataReady === true && accounts.length > 0;

return (
<div className='card'>
<div className='card-header'>
<div className='card-header-item table-card-header d-flex justify-content-between align-items-center flex-wrap gap-3'>
{title}
<Pager
total={accountsCount}
show={accounts.length > 0}
className='d-flex ms-auto me-auto me-sm-0'
/>
</div>
</div>
{showAccounts ? (
<>
<div className='card-body'>
<div className='table-wrapper animated-list'>
<table className='table mb-0'>
<thead>
<tr>
<th className={classNames({ 'w-50': !price })}>Address</th>
{hasNameColumn && <th>Name</th>}
<th>Balance</th>
{hasSupply && (
<th className='percentage-column'>Percentage</th>
)}
{showValue && <th className='value-column'>Value</th>}
</tr>
</thead>
<tbody data-testid='accountsTable'>
{accounts.map((account) => {
const holdingsPercentage =
hasSupply && supply
? new BigNumber(account.balance)
.times(100)
.dividedBy(parseAmount(supply, decimals))
: new BigNumber(0);
const hasAccountName =
hasNameColumn && (account as TokenLockedAccountType).name;

return (
<tr key={account.address}>
<td>
<div className='d-flex align-items-center gap-2'>
<AccountLink
address={account.address}
assets={account.assets}
className={price ? 'hash hash-xl' : 'full-hash'}
linkClassName={price ? '' : 'trim-only-sm'}
/>
</div>
</td>
{hasAccountName && (
<td>{(account as TokenLockedAccountType).name}</td>
)}
<td>
<FormatAmount
value={account.balance}
decimals={decimals}
showLastNonZeroDecimal={true}
showLabel={isNativeToken}
showSymbol={isNativeToken}
showUsdValue={false}
/>
</td>
{hasSupply && (
<td>
<div className='mb-1'>
<FormatNumber
value={holdingsPercentage}
label='%'
/>
</div>
<PercentageBar
overallPercent={0}
fillPercent={holdingsPercentage.toNumber()}
fillPercentLabel={`${formatBigNumber({
value: holdingsPercentage
})}%`}
type='small'
/>
</td>
)}
{showValue && (
<td>
<FormatUSD
value={account.balance}
decimals={decimals}
usd={price}
/>
</td>
)}
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<div className='card-footer table-footer'>
<PageSize />
<Pager total={accountsCount} show={accounts.length > 0} />
</div>
</>
) : (
<>
{isDataReady === undefined && <Loader data-testid='accountsLoader' />}
{isDataReady === false && (
<PageState
icon={faUser}
title={`Unable to load ${message}`}
isError
/>
)}
{isDataReady === true && accounts.length === 0 && (
<PageState icon={faUser} title={`No ${message}`} />
)}
</>
)}
</div>
);
};
1 change: 1 addition & 0 deletions src/components/AccountsTable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './AccountsTable';
83 changes: 33 additions & 50 deletions src/components/HeroDetailsCard/HeroDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface HeroDetailsCardUIType extends WithClassnameType {
title?: React.ReactNode;
titleContent?: React.ReactNode;
icon?: string;
iconComponent?: React.ReactNode;
iconPlaceholder?: React.ReactNode;
isVerified?: boolean;
verifiedComponent?: React.ReactNode;
Expand All @@ -40,6 +41,7 @@ export const HeroDetailsCard = ({
title,
titleContent,
icon,
iconComponent,
iconPlaceholder,
isVerified,
verifiedComponent,
Expand All @@ -55,7 +57,7 @@ export const HeroDetailsCard = ({
const dispatch = useDispatch();
const isMainnet = useIsMainnet();
const hasStatCards = statsCards.length > 0 || smallStatsCards.length > 0;
const hasIcon = Boolean(icon || iconPlaceholder);
const hasIcon = Boolean(icon || iconPlaceholder || iconComponent);

useEffect(() => {
if (seoDetails?.completeDetails && isMainnet) {
Expand All @@ -70,6 +72,33 @@ export const HeroDetailsCard = ({
}
}, [seoDetails, isMainnet]);

const Icon = ({ className }: WithClassnameType) => (
<span
className={classNames('hero-details-card-logo', className, {
'default-image': !icon && !iconComponent,
'has-placeholder': !icon && iconPlaceholder,
'icon-component': !icon && !iconPlaceholder && iconComponent
})}
>
{hasIcon &&
(iconComponent ? (
<>{iconComponent}</>
) : (
<>
{icon ? (
<ImageWithFallback
src={icon}
className='logo-img'
alt={seoDetails?.title ? `${seoDetails.title} Logo` : 'Logo'}
/>
) : (
iconPlaceholder
)}
</>
))}
</span>
);

return (
<div
className={classNames(
Expand All @@ -83,31 +112,8 @@ export const HeroDetailsCard = ({
'mb-3': !hasStatCards
})}
>
<span
className={classNames(
'hero-details-card-logo d-none d-md-flex col-md-3',
{
'default-image': !icon,
'has-placeholder': !icon && iconPlaceholder
}
)}
>
{hasIcon && (
<>
{icon ? (
<ImageWithFallback
src={icon}
className='logo-img'
alt={
seoDetails?.title ? `${seoDetails.title} Logo` : 'Logo'
}
/>
) : (
iconPlaceholder
)}
</>
)}
</span>
<Icon className='d-none d-md-flex col-md-3' />

<div className='hero-details-card-overview d-flex flex-column flex-fill col-9'>
{title && (
<div
Expand All @@ -118,30 +124,7 @@ export const HeroDetailsCard = ({
})}
>
<div className='d-flex align-items-center'>
<span
className={classNames('hero-details-card-logo d-md-none', {
'default-image': !icon,
'has-placeholder': !icon && iconPlaceholder
})}
>
{hasIcon && (
<>
{icon ? (
<ImageWithFallback
src={icon}
className='logo-img'
alt={
seoDetails?.title
? `${seoDetails.title} Logo`
: 'Logo'
}
/>
) : (
iconPlaceholder
)}
</>
)}
</span>
<Icon className='d-md-none' />
<h1
className={classNames('mb-0', {
'has-content': Boolean(titleContent || isVerified)
Expand Down
16 changes: 12 additions & 4 deletions src/components/HeroDetailsCard/heroDetailsCard.styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,18 @@
height: 100%;
color: transparent;
}
svg {
width: auto;
height: 50%;
color: var(--neutral-700);
&.icon-component {
svg {
width: 100%;
height: 100%;
}
}
&:not(.icon-component) {
svg {
width: auto;
height: 50%;
color: var(--neutral-700);
}
}
&.has-placeholder {
border-radius: unset;
Expand Down
1 change: 1 addition & 0 deletions src/components/Select/select.styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
border: none;
box-shadow: none;
min-height: auto;
min-width: 5rem;
cursor: pointer;

&:hover,
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import SharedIdentity from './SharedIdentity';
import TransactionActionBlock from './TransactionActionBlock';

export * from './AccountName';
export * from './AccountsTable';
export * from './BlockGasUsed';
export * from './BlocksTable';
export * from './Cards';
Expand Down
Loading

0 comments on commit 0a9026c

Please sign in to comment.