add pull page
This commit is contained in:
99
src/widgets/pools/ui/PoolsTable.tsx
Normal file
99
src/widgets/pools/ui/PoolsTable.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { TokenIcon } from '@shared/ui'
|
||||
import { coinIcon, formatFeeTier, type Pool } from '../model/meta'
|
||||
import styles from './PoolsTable.module.css'
|
||||
|
||||
interface Props {
|
||||
pools: Pool[]
|
||||
selected: string | null
|
||||
onSelect: (poolAddress: string) => void
|
||||
}
|
||||
|
||||
const DASH = '—'
|
||||
|
||||
function formatUsd(value: number | null): string {
|
||||
if (value == null) return DASH
|
||||
if (value >= 1_000_000) return `$${(value / 1_000_000).toFixed(2)}M`
|
||||
if (value >= 1_000) return `$${(value / 1_000).toFixed(2)}K`
|
||||
return `$${value.toFixed(2)}`
|
||||
}
|
||||
|
||||
function formatPrice(value: number): string {
|
||||
return value.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
}
|
||||
|
||||
function PairIcons({ symbol0, symbol1 }: { symbol0: string; symbol1: string }) {
|
||||
return (
|
||||
<span className={styles.pair}>
|
||||
<span className={styles.icons}>
|
||||
<TokenIcon letter={symbol0[0]} color="var(--grad-center)" logo={coinIcon(symbol0)} size={24} />
|
||||
<TokenIcon letter={symbol1[0]} color="var(--grad-edge)" logo={coinIcon(symbol1)} size={24} />
|
||||
</span>
|
||||
<span className={styles.pairName}>
|
||||
{symbol0}/{symbol1}
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export function PoolsTable({ pools, selected, onSelect }: Props) {
|
||||
return (
|
||||
<div className={styles.card}>
|
||||
<div className={styles.head}>
|
||||
<span className={styles.title}>Курируемые пулы</span>
|
||||
</div>
|
||||
|
||||
<div className={styles.scroll}>
|
||||
<table className={styles.table}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={styles.thLeft}>Пул</th>
|
||||
<th>Комиссия</th>
|
||||
<th>Цена</th>
|
||||
<th>TVL</th>
|
||||
<th>Объём 24ч</th>
|
||||
<th>APR</th>
|
||||
<th aria-label="Действие" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{pools.map((p) => {
|
||||
const isSelected = p.poolAddress === selected
|
||||
return (
|
||||
<tr
|
||||
key={p.poolAddress}
|
||||
className={isSelected ? styles.rowSelected : styles.row}
|
||||
onClick={() => onSelect(p.poolAddress)}
|
||||
>
|
||||
<td className={styles.tdLeft}>
|
||||
<PairIcons symbol0={p.symbol0} symbol1={p.symbol1} />
|
||||
</td>
|
||||
<td>
|
||||
<span className={styles.fee}>{formatFeeTier(p.feeTier)}</span>
|
||||
</td>
|
||||
<td className={styles.mono}>{formatPrice(p.currentPrice)}</td>
|
||||
<td className={styles.mono}>{formatUsd(p.tvlUSD)}</td>
|
||||
<td className={styles.mono}>{formatUsd(p.volumeUSD24h)}</td>
|
||||
<td className={`${styles.mono} ${styles.apr}`}>
|
||||
{p.aprPercent != null ? `${p.aprPercent}%` : DASH}
|
||||
</td>
|
||||
<td className={styles.tdAction}>
|
||||
<button
|
||||
type="button"
|
||||
className={isSelected ? styles.btnSelected : styles.btn}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onSelect(p.poolAddress)
|
||||
}}
|
||||
>
|
||||
{isSelected ? 'Выбран' : 'Выбрать'}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user