add pull page

This commit is contained in:
2026-06-17 17:54:30 +03:00
parent 474e9a3727
commit 7966ef1c52
27 changed files with 1487 additions and 1747 deletions

View 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>
)
}