19.05.2026 okkk

This commit is contained in:
2026-05-19 21:03:21 +03:00
parent fad50a1b1b
commit 29fbd71d8f
7 changed files with 301 additions and 111 deletions

View File

@@ -1,7 +1,8 @@
import { useState } from 'react'
import { GAS_PRICE, USDT_RATE } from '@shared/config/constants'
import { useConverter } from '../model/useConverter'
import { progressPercent } from '../model/tiers'
import { usePaymentConfig, usePaymentQuote } from '@features/payment'
import { usePaymentConfig, usePaymentQuote, usePaymentQuoteByRub } from '@features/payment'
import { useDebounce } from '@shared/lib/hooks/useDebounce'
import { CommissionTable } from './CommissionTable'
import styles from './Converter.module.css'
@@ -11,20 +12,44 @@ import { ROUTES } from '@shared/config/routes'
export function Converter() {
const { data: config } = usePaymentConfig()
const [direction, setDirection] = useState<'usdt_to_rub' | 'rub_to_usdt'>('usdt_to_rub')
const [rubInputVal, setRubInputVal] = useState('1000')
const configUsdtRate = Number(config?.usdt_exchange_rate) || USDT_RATE
const gasPriceRub = Number(config?.gas_fee) || GAS_PRICE
const c = useConverter({ usdtRate: configUsdtRate })
const isUsdtToRub = direction === 'usdt_to_rub'
const debouncedUsdt = useDebounce(c.numRub, 400)
const { data: quote } = usePaymentQuote(debouncedUsdt)
const { data: quoteUsdtToRub } = usePaymentQuote(isUsdtToRub ? debouncedUsdt : 0)
const rubTotal = quote?.total_price ?? ''
const numRubInput = Number.parseFloat(rubInputVal) || 0
const debouncedRub = useDebounce(numRubInput, 400)
const { data: quoteRubToUsdt } = usePaymentQuoteByRub(!isUsdtToRub ? debouncedRub : 0)
function updateRubInput(raw: string) {
setRubInputVal(raw.replace(/[^0-9.]/g, ''))
}
function handleSwap() {
setDirection(d => d === 'usdt_to_rub' ? 'rub_to_usdt' : 'usdt_to_rub')
}
const rubTotal = quoteUsdtToRub?.total_price ?? ''
const rubTotalNum = Number(rubTotal) || 0
const usdtFromRub = quoteRubToUsdt?.usdt_amount ?? ''
const usdtFromRubNum = Number(usdtFromRub) || 0
const commission = Number(quote?.service_fee) || 0
const effectiveRate = c.numRub > 0 ? rubTotalNum / c.numRub : 0
const commission = isUsdtToRub
? Number(quoteUsdtToRub?.service_fee) || 0
: Number(quoteRubToUsdt?.service_fee) || 0
const displayRubAmount = isUsdtToRub ? rubTotalNum : numRubInput
const effectiveRate = isUsdtToRub
? (c.numRub > 0 ? rubTotalNum / c.numRub : 0)
: (usdtFromRubNum > 0 ? numRubInput / usdtFromRubNum : 0)
return (
<section className={styles.section} id="converter">
@@ -57,52 +82,102 @@ export function Converter() {
</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
{isUsdtToRub ? (
<>
<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>
</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={rubTotal} readOnly placeholder="0" />
<div className={styles.currency}>
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}></span> RUB
<div className={styles.swapWrap}>
<button
type="button"
className={styles.swapBtn}
onClick={handleSwap}
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>
</div>
<div className={styles.field}>
<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 className={styles.field}>
<div className={styles.fieldInput}>
<input
type="text"
value={rubInputVal}
onChange={(e) => updateRubInput(e.target.value)}
placeholder="0"
inputMode="decimal"
/>
<div className={styles.currency}>
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}></span> RUB
</div>
</div>
</div>
<div className={styles.swapWrap}>
<button
type="button"
className={styles.swapBtn}
onClick={handleSwap}
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={usdtFromRub} readOnly placeholder="0" />
<div className={styles.currency}>
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}></span> USDT
</div>
</div>
</div>
</>
)}
</div>
<CommissionTable
amount={rubTotalNum}
progress={progressPercent(rubTotalNum)}
amount={displayRubAmount}
progress={progressPercent(displayRubAmount)}
commission={commission}
effectiveRate={effectiveRate}
/>