Skip to content

Commit

Permalink
feat: Simple pool join & call to action UI (#2050)
Browse files Browse the repository at this point in the history
Co-authored-by: Ting A Lin <[email protected]>
  • Loading branch information
Ross Bulat and TingALin authored Apr 2, 2024
1 parent 8914218 commit 6d04429
Show file tree
Hide file tree
Showing 92 changed files with 2,236 additions and 463 deletions.
119 changes: 119 additions & 0 deletions src/canvas/JoinPool/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import {
faArrowsRotate,
faHashtag,
faTimes,
} from '@fortawesome/free-solid-svg-icons';
import { ButtonPrimary } from 'kits/Buttons/ButtonPrimary';
import { ButtonPrimaryInvert } from 'kits/Buttons/ButtonPrimaryInvert';
import { TitleWrapper } from './Wrappers';
import { Polkicon } from '@w3ux/react-polkicon';
import { determinePoolDisplay, remToUnit } from '@w3ux/utils';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { PageTitleTabs } from 'kits/Structure/PageTitleTabs';
import { useTranslation } from 'react-i18next';
import { useOverlay } from 'kits/Overlay/Provider';
import type { JoinPoolHeaderProps } from './types';

export const Header = ({
activeTab,
bondedPool,
filteredBondedPools,
metadata,
autoSelected,
setActiveTab,
setSelectedPoolId,
setSelectedPoolCount,
}: JoinPoolHeaderProps) => {
const { t } = useTranslation();
const { closeCanvas } = useOverlay().canvas;

// Randomly select a new pool to display.
const handleChooseNewPool = () => {
// Trigger refresh of memoied selected bonded pool.
setSelectedPoolCount((prev: number) => prev + 1);

// Randomly select a filtered bonded pool and set it as the selected pool.
const index = Math.ceil(Math.random() * filteredBondedPools.length - 1);
setSelectedPoolId(filteredBondedPools[index].id);
};

return (
<>
<div className="head">
<ButtonPrimaryInvert
text={t('chooseAnotherPool', { ns: 'library' })}
iconLeft={faArrowsRotate}
onClick={() => handleChooseNewPool()}
lg
/>
<ButtonPrimary
text={t('cancel', { ns: 'library' })}
lg
onClick={() => closeCanvas()}
iconLeft={faTimes}
style={{ marginLeft: '1.1rem' }}
/>
</div>
<TitleWrapper>
<div className="inner">
<div>
<Polkicon
address={bondedPool?.addresses.stash || ''}
size={remToUnit('4rem')}
outerColor="transparent"
/>
</div>
<div>
<div className="title">
<h1>
{determinePoolDisplay(
bondedPool?.addresses.stash || '',
metadata
)}
</h1>
</div>
<div className="labels">
<h3>
{t('pool', { ns: 'library' })}{' '}
<FontAwesomeIcon icon={faHashtag} transform="shrink-2" />
{bondedPool.id}
{['Blocked', 'Destroying'].includes(bondedPool.state) && (
<span className={bondedPool.state.toLowerCase()}>
{t(bondedPool.state.toLowerCase(), { ns: 'library' })}
</span>
)}
</h3>

{autoSelected && (
<h3>
<span>{t('autoSelected', { ns: 'library' })}</span>
</h3>
)}
</div>
</div>
</div>

<PageTitleTabs
sticky={false}
tabs={[
{
title: t('pools.overview', { ns: 'pages' }),
active: activeTab === 0,
onClick: () => setActiveTab(0),
},
{
title: t('nominate.nominations', { ns: 'pages' }),
active: activeTab === 1,
onClick: () => setActiveTab(1),
},
]}
tabClassName="canvas"
inline={true}
/>
</TitleWrapper>
</>
);
};
53 changes: 53 additions & 0 deletions src/canvas/JoinPool/Nominations/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { ValidatorList } from 'library/ValidatorList';
import { ListWrapper } from 'modals/PoolNominations/Wrappers';
import { useTranslation } from 'react-i18next';
import { HeadingWrapper, NominationsWrapper } from '../Wrappers';
import type { NominationsProps } from '../types';
import { useValidators } from 'contexts/Validators/ValidatorEntries';
import { useBondedPools } from 'contexts/Pools/BondedPools';

export const Nominations = ({ stash, poolId }: NominationsProps) => {
const { t } = useTranslation();
const { validators } = useValidators();
const { poolsNominations } = useBondedPools();

// Extract validator entries from pool targets.
const targets = poolsNominations[poolId]?.targets || [];
const filteredTargets = validators.filter(({ address }) =>
targets.includes(address)
);

return (
<NominationsWrapper>
<HeadingWrapper>
<h3>
{targets.length}{' '}
{!targets.length
? t('nominate.noNominationsSet', { ns: 'pages' })
: ``}{' '}
{t('nominations', { ns: 'library', count: targets.length })}
</h3>
</HeadingWrapper>
<ListWrapper>
{targets.length > 0 ? (
<ValidatorList
format="nomination"
bondFor="pool"
validators={filteredTargets}
nominator={stash}
showMenu={false}
displayFor="canvas"
allowListFormat={false}
allowMoreCols={true}
refetchOnListUpdate
/>
) : (
<h3>{t('poolIsNotNominating', { ns: 'modals' })}</h3>
)}
</ListWrapper>
</NominationsWrapper>
);
};
45 changes: 45 additions & 0 deletions src/canvas/JoinPool/Overview/AddressSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { useHelp } from 'contexts/Help';
import { ButtonHelp } from 'kits/Buttons/ButtonHelp';
import { HeadingWrapper } from '../Wrappers';
import { Polkicon } from '@w3ux/react-polkicon';
import { CopyAddress } from 'library/ListItem/Labels/CopyAddress';
import { ellipsisFn, remToUnit } from '@w3ux/utils';
import type { AddressSectionProps } from '../types';

export const AddressSection = ({
address,
label,
helpKey,
}: AddressSectionProps) => {
const { openHelp } = useHelp();

return (
<section>
<HeadingWrapper>
<h4 className="heading">
{label}
{!!helpKey && (
<ButtonHelp marginLeft onClick={() => openHelp(helpKey)} />
)}
</h4>
</HeadingWrapper>

<div>
<span>
<Polkicon
address={address}
size={remToUnit('2.25rem')}
outerColor="transparent"
/>
</span>
<h4>
{ellipsisFn(address, 6)}
<CopyAddress address={address} />
</h4>
</div>
</section>
);
};
27 changes: 27 additions & 0 deletions src/canvas/JoinPool/Overview/Addresses.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { CardWrapper } from 'library/Card/Wrappers';
import { AddressesWrapper, HeadingWrapper } from '../Wrappers';
import { AddressSection } from './AddressSection';
import type { OverviewSectionProps } from '../types';
import { useTranslation } from 'react-i18next';

export const Addresses = ({
bondedPool: { addresses },
}: OverviewSectionProps) => {
const { t } = useTranslation('library');

return (
<CardWrapper className="canvas secondary">
<HeadingWrapper>
<h3>{t('addresses')}</h3>
</HeadingWrapper>

<AddressesWrapper>
<AddressSection address={addresses.stash} label="Stash" />
<AddressSection address={addresses.reward} label="Reward" />
</AddressesWrapper>
</CardWrapper>
);
};
Loading

0 comments on commit 6d04429

Please sign in to comment.