Repository Public
1import { useContext, useMemo, useState } from 'react';2import type { Nav } from '../App';3import { useNetworks, usePortfolio, useSettings } from '../hooks';4import { I18n, useT } from '../i18n';5import { Card, Chips, Icon, inputCls, Skeleton } from '../ui';6import { AssetRow } from './Home';78/** Every supported asset, searchable, filterable by network. */9export function Assets({ nav }: { nav: Nav }) {10 const t = useT(); const { locale } = useContext(I18n); const { settings } = useSettings();11 const pf = usePortfolio(), nets = useNetworks();12 const [q, setQ] = useState(''), [net, setNet] = useState('');13 const cur = settings.currency, ck = (cur === 'USD' ? 'usd' : 'cad') as 'usd' | 'cad';14 const rows = useMemo(() => {15 const s = q.trim().toLowerCase();16 // majors first: the market-cap rank of the price feed; assets without one go last17 const rank = (sym: string) => pf.data?.prices?.[sym]?.rank ?? 9999;18 return (pf.data?.balances ?? []).filter((b) => (!net || b.network === net) && (!s || b.symbol.toLowerCase().includes(s) || b.name.toLowerCase().includes(s) || b.networkName.toLowerCase().includes(s)))19 .sort((a, b) => Number(b.amount !== '0' && b.amount !== null) - Number(a.amount !== '0' && a.amount !== null) || rank(a.symbol) - rank(b.symbol) || a.symbol.localeCompare(b.symbol) || Number(b.asset === 'native') - Number(a.asset === 'native') || a.networkName.localeCompare(b.networkName));20 }, [pf.data, q, net]);21 if (!pf.data) return <Skeleton h="h-96" />;22 return (23 <div className="space-y-4">24 <div className="flex items-center gap-2 pt-1">25 <button onClick={() => nav({ tab: 'home' })} aria-label={t('back')} className="-ml-2 grid h-11 w-11 place-items-center rounded-full"><Icon n="chev" className="h-6 w-6 rotate-180" /></button>26 <h1 className="text-[26px] font-semibold tracking-[-0.02em]">{t('allAssets')}</h1>27 </div>28 <input className={inputCls} type="search" placeholder={t('search')} aria-label={t('search')} value={q} onChange={(e) => setQ(e.target.value)} autoCapitalize="off" autoCorrect="off" spellCheck={false} />29 <Chips label={t('network')} value={net} onChange={setNet} options={[{ id: '', label: t('all') }, ...(nets.data ?? []).map((n) => ({ id: n.id, label: n.name, net: n.id }))]} />30 <Card className="!px-0 !py-1">31 {rows.length === 0 ? <p className="px-5 py-6 text-center text-[14px] text-mute">{t('noMatch')}</p> :32 <ul>{rows.map((b, k) => <AssetRow key={b.network + b.asset} b={b} border={k > 0} nav={nav} cur={cur} ck={ck} hidden={settings.hideBalances} prices={pf.data!.prices} locale={locale} />)}</ul>}33 </Card>34 </div>35 );36}37