146 lines
4.7 KiB
TypeScript
146 lines
4.7 KiB
TypeScript
import { useConverter, progressPercent } from '@widgets/currency-converter'
|
||
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
||
import { usePaymentQuote, useCreateOrder } from '@features/payment'
|
||
import { CommissionPanel } from './CommissionPanel'
|
||
import { AgreementCheck } from './AgreementCheck'
|
||
import styles from './ConverterSection.module.css'
|
||
|
||
export function ConverterSection() {
|
||
const c = useConverter({ usdtRate: 0 })
|
||
|
||
const debouncedUsdt = useDebounce(c.numRub, 400)
|
||
const { data: quote, isError: quoteError } = usePaymentQuote(debouncedUsdt)
|
||
|
||
const usdtRate = Number(quote?.usdt_exchange_rate) || 0
|
||
const gasPrice = Number(quote?.gas_fee) || 0
|
||
|
||
const rubTotal = quote?.total_price ?? ''
|
||
const rubTotalNum = Number(rubTotal) || 0
|
||
|
||
const { mutate: submitOrder, isPending } = useCreateOrder()
|
||
|
||
function handlePay() {
|
||
submitOrder({
|
||
usdt_amount: c.numRub,
|
||
usdt_exchange_rate: 1,
|
||
gas_fee: 1,
|
||
total_price: Number(rubTotal) || 0,
|
||
})
|
||
}
|
||
|
||
return (
|
||
<div className={styles.wrap}>
|
||
<div className={styles.header}>
|
||
<div>
|
||
<h1 className={styles.title}>Конвертация</h1>
|
||
<div className={styles.subtitle}>Данные обновляются в реальном времени</div>
|
||
</div>
|
||
<div className={styles.pills}>
|
||
<div className={styles.pill}>
|
||
Цена газа в RUB <span className={styles.pillValue}>{gasPrice.toFixed(2)} RUB</span>
|
||
</div>
|
||
<div className={styles.pill}>
|
||
USDT/RUB <span className={styles.pillValue}>{usdtRate.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"
|
||
disabled
|
||
className={styles.tab}
|
||
data-active={c.mode === 'sell' || undefined}
|
||
onClick={() => c.setMode('sell')}
|
||
>
|
||
ПРОДАТЬ
|
||
</button>
|
||
</div>
|
||
|
||
<div className={styles.field}>
|
||
<div className={styles.fieldLabel}>Конвертируете</div>
|
||
<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>
|
||
{quoteError && (
|
||
<div className={styles.fieldError}>
|
||
Сумма слишком большая и превышает 600 000 ₽
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div className={styles.swapWrap}>
|
||
<button
|
||
type="button"
|
||
className={styles.swapBtn}
|
||
onClick={c.toggleMode}
|
||
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.fieldLabel}>Платите</div>
|
||
<div className={styles.fieldInput}>
|
||
<input type="text" value={rubTotal} readOnly placeholder="0" />
|
||
<div className={styles.currency}>
|
||
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span>
|
||
RUB
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<CommissionPanel
|
||
amount={rubTotalNum}
|
||
progress={progressPercent(rubTotalNum)}
|
||
commission={c.commission}
|
||
effectiveRate={c.effectiveRate}
|
||
/>
|
||
</div>
|
||
|
||
<div className={styles.bottom}>
|
||
<AgreementCheck checked={c.agreed} onToggle={() => c.setAgreed(!c.agreed)} />
|
||
</div>
|
||
|
||
<button
|
||
type="button"
|
||
className={styles.payBtn}
|
||
onClick={handlePay}
|
||
disabled={!rubTotal || isPending}
|
||
>
|
||
{isPending ? 'Обработка...' : 'Оплатить'}
|
||
</button>
|
||
</div>
|
||
)
|
||
}
|