124 lines
4.4 KiB
TypeScript
124 lines
4.4 KiB
TypeScript
import { USDT_RATE, GAS_PRICE } from '@shared/config/constants'
|
||
import { useConverter } from '../model/useConverter'
|
||
import { findTier, progressPercent } from '../model/tiers'
|
||
import { usePaymentConfig } from '@features/payment'
|
||
import { AgreementCheckbox } from './AgreementCheckbox'
|
||
import { CommissionTable } from './CommissionTable'
|
||
import styles from './Converter.module.css'
|
||
import { Title } from '@shared/ui/Title/Title'
|
||
|
||
export function Converter() {
|
||
const { data: config } = usePaymentConfig()
|
||
|
||
const configUsdtRate = Number(config?.usdt_exchange_rate) || USDT_RATE
|
||
const gasPriceRub = Number(config?.gas_fee) * configUsdtRate || GAS_PRICE
|
||
|
||
const c = useConverter({ usdtRate: configUsdtRate })
|
||
|
||
// c.rubVal / c.numRub used as USDT input; RUB is computed
|
||
const numUsdt = c.numRub
|
||
const approxRub = numUsdt * configUsdtRate
|
||
const { pct } = findTier(approxRub)
|
||
const effectiveRate = configUsdtRate * (1 + pct / 100)
|
||
const rubOutput = numUsdt > 0 ? (numUsdt * effectiveRate).toFixed(2) : ''
|
||
const commission = (approxRub * pct) / 100
|
||
|
||
return (
|
||
<section className={styles.section} id="converter">
|
||
<div className={styles.wrap}>
|
||
<div className={styles.header}>
|
||
<div>
|
||
<Title>Конвертация</Title>
|
||
<div className={styles.subtitle}>Данные обновляются в реальном времени</div>
|
||
</div>
|
||
<div className={styles.pills}>
|
||
<div className={styles.pill}>
|
||
Цена газа в RUB <span className={styles.pillValue}>{gasPriceRub.toFixed(2)} RUB</span>
|
||
</div>
|
||
<div className={styles.pill}>
|
||
USDT/RUB <span className={styles.pillValue}>{configUsdtRate.toFixed(2)} ₽</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className={styles.body}>
|
||
<div>
|
||
<div className={styles.tabs}>
|
||
<button
|
||
type="button"
|
||
className={styles.tab}
|
||
data-active={c.mode === 'buy' || undefined}
|
||
onClick={() => c.setMode('buy')}
|
||
>
|
||
КУПИТЬ
|
||
</button>
|
||
<button
|
||
type="button"
|
||
className={styles.tab}
|
||
data-active={c.mode === 'sell' || undefined}
|
||
onClick={() => c.setMode('sell')}
|
||
disabled
|
||
>
|
||
ПРОДАТЬ
|
||
</button>
|
||
</div>
|
||
|
||
<div className={styles.field}>
|
||
<div className={styles.fieldInput}>
|
||
<input
|
||
type="text"
|
||
value={c.rubVal}
|
||
onChange={(e) => c.updateRub(e.target.value)}
|
||
placeholder="0"
|
||
inputMode="decimal"
|
||
/>
|
||
<div className={styles.currency}>
|
||
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span> USDT
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className={styles.swapWrap}>
|
||
<button
|
||
type="button"
|
||
className={styles.swapBtn}
|
||
aria-label="Поменять направление"
|
||
>
|
||
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
||
<path
|
||
d="M8 2v12M4 10l4 4 4-4"
|
||
stroke="currentColor"
|
||
strokeWidth={1.5}
|
||
strokeLinecap="round"
|
||
strokeLinejoin="round"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div className={styles.field}>
|
||
<div className={styles.fieldInput}>
|
||
<input type="text" value={rubOutput} readOnly placeholder="0" />
|
||
<div className={styles.currency}>
|
||
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span> RUB
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<CommissionTable
|
||
amount={approxRub}
|
||
progress={progressPercent(approxRub)}
|
||
commission={commission}
|
||
effectiveRate={effectiveRate}
|
||
/>
|
||
</div>
|
||
|
||
<div className={styles.bottom}>
|
||
<AgreementCheckbox checked={c.agreed} onToggle={() => c.setAgreed(!c.agreed)} />
|
||
</div>
|
||
</div>
|
||
</section>
|
||
)
|
||
}
|