Skip to content

Commit

Permalink
Merge pull request #561 from Concordium/x-account-selector
Browse files Browse the repository at this point in the history
Hook up account selector on main page
  • Loading branch information
limemloh authored Nov 5, 2024
2 parents 7e47281 + 9b6f443 commit 3b68429
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,7 @@
&_search-form {
display: flex;

.account-search__form {
width: 100%;

.form-search {
.form-input__field {
height: rem(32px);
padding: rem(10px);
Expand Down Expand Up @@ -211,7 +209,9 @@
display: flex;
padding: rem(12px) 0;
align-items: center;
border: unset;
border-bottom: 1px solid $color-grey-3;
background: none;

&:last-child {
border-bottom: none;
Expand All @@ -229,22 +229,28 @@

svg {
display: unset;
position: absolute;
left: rem(12px);
}
}
}

.account {
flex: 1;
display: flex;
align-items: center;

.text__additional_small {
text-align: left;
}

svg {
display: none;
margin-right: rem(4px);
}
}

.balance {
margin-left: auto;
min-width: rem(65px);
}

Expand All @@ -254,7 +260,6 @@
width: unset;
min-width: rem(100px);
justify-content: flex-end;
margin-left: rem(16px);

.token-icon {
display: flex;
Expand All @@ -264,6 +269,11 @@
height: rem(24px);
border-radius: rem(5px);
background-color: $color-main-bg;

img {
max-width: rem(24px);
max-height: rem(24px);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function Header({
<MenuButton setMenuOpen={setMenuOpen} menuOpen={menuOpen} hideMenu={hideMenu} />
</div>
<MenuTiles menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<AccountSelector showAccountSelector={accountOpen} />
<AccountSelector showAccountSelector={accountOpen} onUpdateSelectedAccount={() => setAccountOpen(false)} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,96 +1,120 @@
import React from 'react';
import React, { ChangeEvent, useMemo, useState } from 'react';
import CarretRight from '@assets/svgX/caret-right.svg';
import Form from '@popup/popupX/shared/Form/Form';
import EthLogo from '@assets/svgX/eth-logo.svg';
import DnwLogo from '@assets/svgX/dnw-logo.svg';
import EureLogo from '@assets/svgX/eure-logo.svg';
import BtcLogo from '@assets/svgX/btc-logo.svg';
import ArrowsUpDown from '@assets/svgX/arrows-down-up.svg';
import FormSearch from '@popup/popupX/shared/Form/Search';
import { Search } from '@popup/popupX/shared/Form/Search';
import Button from '@popup/popupX/shared/Button';
import { useAtom, useAtomValue } from 'jotai';
import { credentialsAtomWithLoading, selectedAccountAtom } from '@popup/store/account';
import { displayNameAndSplitAddress } from '@popup/shared/utils/account-helpers';
import { useAccountInfo } from '@popup/shared/AccountInfoListenerContext';
import { displayAsCcd } from 'wallet-common-helpers';
import { WalletCredential } from '@shared/storage/types';
import { useTranslation } from 'react-i18next';
import clsx from 'clsx';
import { tokensAtom } from '@popup/store/token';
import Img from '@popup/shared/Img';

type Props = { showAccountSelector: boolean };
function CcdBalance({ credential }: { credential: WalletCredential }) {
const accountInfo = useAccountInfo(credential);
const balance =
accountInfo === undefined ? '' : displayAsCcd(accountInfo.accountAmount.microCcdAmount, false, true);
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{balance}</>;
}

type Props = { showAccountSelector: boolean; onUpdateSelectedAccount: () => void };

function compareAsc(left: WalletCredential, right: WalletCredential): number {
if (left.credName === '' && right.credName !== '') {
return 1;
}
if (right.credName === '' && left.credName !== '') {
return -1;
}
return left.credName.localeCompare(right.credName) || left.address.localeCompare(right.address);
}

function compareDesc(left: WalletCredential, right: WalletCredential): number {
return compareAsc(right, left);
}

export default function AccountSelector({ showAccountSelector, onUpdateSelectedAccount }: Props) {
const { t } = useTranslation('x', { keyPrefix: 'header.accountSelector' });
const credentialsLoading = useAtomValue(credentialsAtomWithLoading);
const [selectedAccount, setSelectedAccount] = useAtom(selectedAccountAtom);
const [search, setSearch] = useState('');
const [ascSort, setAscSort] = useState(true);
const credentials = credentialsLoading.value ?? [];
const tokens = useAtomValue(tokensAtom);
const filtered = useMemo(
() =>
credentials.filter(
(credential) =>
credential.credName.toLowerCase().includes(search.toLowerCase()) ||
credential.address.toLowerCase().includes(search.toLowerCase())
),
[search, credentials]
);
const sorted = useMemo(() => filtered.sort(ascSort ? compareAsc : compareDesc), [filtered, ascSort]);
const onAccountClick = (address: string) => () => {
setSelectedAccount(address);
onUpdateSelectedAccount();
};

export default function AccountSelector({ showAccountSelector }: Props) {
if (!showAccountSelector) return null;
return (
<div className="main-header__account-selector fade-menu-bg">
<div className="main-header__account-selector_group">
<div className="main-header__account-selector_search-form">
<Form
onSubmit={() => {}}
// formMethods={}
className="account-search__form"
>
{(f) => {
return (
<FormSearch
control={f.control}
name="network"
placeholder="Search by name"
autoFocus
defaultValue="https://whatevertheaddressIs.com"
/>
);
}}
</Form>
<Button.IconText icon={<ArrowsUpDown />} label="Sort A-Z" />
<Search
autoFocus
placeholder={t('searchBy')}
value={search}
onChange={(e: ChangeEvent<HTMLInputElement>) => setSearch(e.target.value)}
/>
<Button.IconText
icon={<ArrowsUpDown />}
label={ascSort ? t('sortAsc') : t('sortDesc')}
onClick={() => setAscSort((a) => !a)}
/>
</div>
<div className="main-header__account-selector_list">
<div className="main-header__account-selector_list-item active">
<div className="account">
<CarretRight />
<span className="text__additional_small">Accout 1 / 6gk...k7o</span>
</div>
<div className="balance">
<span className="text__additional_small">1.2M CCD</span>
</div>
<div className="tokens">
<div className="token-icon">
<EthLogo />
</div>
<div className="token-icon">
<DnwLogo />
</div>
<div className="token-icon">
<EureLogo />
</div>
<div className="token-icon">
<BtcLogo />
</div>
</div>
</div>
<div className="main-header__account-selector_list-item">
<div className="account">
<CarretRight />
<span className="text__additional_small">Accout 2 / 6gk...k7o</span>
</div>
<div className="balance">
<span className="text__additional_small">0.4M CCD</span>
</div>
<div className="tokens">
<div className="token-icon">
<EthLogo />
{sorted.map((credential) => (
<Button.Base
className={clsx('main-header__account-selector_list-item', {
active: credential.address === selectedAccount,
})}
onClick={onAccountClick(credential.address)}
>
<div className="account">
{credential.address === selectedAccount && <CarretRight />}
<span className="text__additional_small">{displayNameAndSplitAddress(credential)}</span>
</div>
<div className="token-icon">
<DnwLogo />
<div className="balance">
<span className="text__additional_small">
<CcdBalance credential={credential} />
</span>
</div>
</div>
</div>
<div className="main-header__account-selector_list-item">
<div className="account">
<CarretRight />
<span className="text__additional_small">Accout 3 / 6gk...k7o</span>
</div>
<div className="balance">
<span className="text__additional_small">200k CCD</span>
</div>
<div className="tokens">
<div className="token-icon">
<EthLogo />
<div className="tokens">
{tokens.loading ||
Object.values(tokens.value[credential.address]).flatMap((contractTokens) =>
contractTokens.flatMap((token) =>
token.metadata.thumbnail?.url === undefined
? []
: [
<div className="token-icon">
<Img
src={token.metadata.thumbnail.url}
alt={token.metadata.symbol ?? '?'}
withDefaults
/>
</div>,
]
)
)}
</div>
</div>
</div>
</Button.Base>
))}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const t = {
restore: 'Restore',
oldUI: 'Old UI',
},
accountSelector: {
sortAsc: 'Sort A-Z',
sortDesc: 'Sort Z-A',
searchBy: 'Search by name or address',
},
};

export default t;

0 comments on commit 3b68429

Please sign in to comment.