diff --git a/src/features/payment/api/paymentApi.ts b/src/features/payment/api/paymentApi.ts new file mode 100644 index 0000000..5c3e266 --- /dev/null +++ b/src/features/payment/api/paymentApi.ts @@ -0,0 +1,46 @@ +import { getCsrfToken } from '@shared/api/csrf' + +const PAYMENT_API_URL = 'https://app.payment.elcsa.ru' + +export interface PaymentConfig { + status_code: number + usdt_exchange_rate: string + gas_fee: string + service_fee_rate: string + one_usdt_service_fee: string + one_usdt_total_price: string + created_at: string +} + +export interface PaymentQuote { + status_code: number + usdt_amount: string + usdt_exchange_rate: string + gas_fee: string + service_fee: string + total_price: string + service_fee_rate: string + created_at: string +} + +export async function getPaymentConfig(): Promise { + const csrf = await getCsrfToken() + const res = await fetch(`${PAYMENT_API_URL}/config`, { + credentials: 'include', + headers: { 'X-CSRF-Token': csrf }, + }) + const data = await res.json() + if (!res.ok) throw data + return data +} + +export async function getPaymentQuote(usdtAmount: number): Promise { + const csrf = await getCsrfToken() + const res = await fetch(`${PAYMENT_API_URL}/payment/quote?usdt_amount=${usdtAmount}`, { + credentials: 'include', + headers: { 'X-CSRF-Token': csrf }, + }) + const data = await res.json() + if (!res.ok) throw data + return data +} diff --git a/src/features/payment/hooks/usePaymentConfig.ts b/src/features/payment/hooks/usePaymentConfig.ts new file mode 100644 index 0000000..0b94588 --- /dev/null +++ b/src/features/payment/hooks/usePaymentConfig.ts @@ -0,0 +1,11 @@ +import { useQuery } from '@tanstack/react-query' +import { getPaymentConfig } from '../api/paymentApi' +import type { PaymentConfig } from '../api/paymentApi' + +export function usePaymentConfig() { + return useQuery({ + queryKey: ['payment', 'config'], + queryFn: getPaymentConfig, + staleTime: 60_000, + }) +} diff --git a/src/features/payment/hooks/usePaymentQuote.ts b/src/features/payment/hooks/usePaymentQuote.ts new file mode 100644 index 0000000..8651f51 --- /dev/null +++ b/src/features/payment/hooks/usePaymentQuote.ts @@ -0,0 +1,12 @@ +import { useQuery } from '@tanstack/react-query' +import { getPaymentQuote } from '../api/paymentApi' +import type { PaymentQuote } from '../api/paymentApi' + +export function usePaymentQuote(usdtAmount: number) { + return useQuery({ + queryKey: ['payment', 'quote', usdtAmount], + queryFn: () => getPaymentQuote(usdtAmount), + enabled: usdtAmount > 0, + staleTime: 30_000, + }) +} diff --git a/src/features/payment/index.ts b/src/features/payment/index.ts new file mode 100644 index 0000000..81f5fb9 --- /dev/null +++ b/src/features/payment/index.ts @@ -0,0 +1,3 @@ +export { usePaymentConfig } from './hooks/usePaymentConfig' +export { usePaymentQuote } from './hooks/usePaymentQuote' +export type { PaymentConfig, PaymentQuote } from './api/paymentApi' diff --git a/src/shared/lib/hooks/useDebounce.ts b/src/shared/lib/hooks/useDebounce.ts index e69de29..036c2c1 100644 --- a/src/shared/lib/hooks/useDebounce.ts +++ b/src/shared/lib/hooks/useDebounce.ts @@ -0,0 +1,12 @@ +import { useEffect, useState } from 'react' + +export function useDebounce(value: T, delay: number): T { + const [debounced, setDebounced] = useState(value) + + useEffect(() => { + const id = setTimeout(() => setDebounced(value), delay) + return () => clearTimeout(id) + }, [value, delay]) + + return debounced +} diff --git a/src/widgets/converter-page/ui/ConverterSection.module.css b/src/widgets/converter-page/ui/ConverterSection.module.css index 21a12f1..47cc094 100644 --- a/src/widgets/converter-page/ui/ConverterSection.module.css +++ b/src/widgets/converter-page/ui/ConverterSection.module.css @@ -1,6 +1,4 @@ .wrap { - border-radius: 24px; - padding: 32px; position: relative; overflow: hidden; } @@ -168,12 +166,6 @@ color: var(--text-secondary); } -.swapBtn:hover { - border-color: var(--highlight); - color: var(--highlight); - transform: rotate(180deg); -} - .bottom { display: flex; justify-content: center; diff --git a/src/widgets/converter-page/ui/ConverterSection.tsx b/src/widgets/converter-page/ui/ConverterSection.tsx index 392a350..9a2a6ce 100644 --- a/src/widgets/converter-page/ui/ConverterSection.tsx +++ b/src/widgets/converter-page/ui/ConverterSection.tsx @@ -1,11 +1,23 @@ import { useConverter } from '@widgets/currency-converter' -import { GAS_PRICE, USDT_RATE } from '@shared/config/constants' +import { USDT_RATE, GAS_PRICE } from '@shared/config/constants' +import { useDebounce } from '@shared/lib/hooks/useDebounce' +import { usePaymentConfig, usePaymentQuote } from '@features/payment' import { CommissionPanel } from './CommissionPanel' import { AgreementCheck } from './AgreementCheck' import styles from './ConverterSection.module.css' export function ConverterSection() { - const c = useConverter({ usdtRate: USDT_RATE }) + const { data: config } = usePaymentConfig() + + const usdtRate = config ? Number(config.usdt_exchange_rate) || USDT_RATE : USDT_RATE + const gasPrice = config ? Number(config.gas_fee) || GAS_PRICE : GAS_PRICE + + const c = useConverter({ usdtRate }) + + const debouncedRub = useDebounce(c.numRub, 400) + const { data: quote } = usePaymentQuote(debouncedRub) + + const usdtVal = quote ? quote.usdt_amount : c.usdtVal return (
@@ -16,10 +28,10 @@ export function ConverterSection() {
- Цена газа в RUB {GAS_PRICE.toFixed(2)} RUB + Цена газа в RUB {gasPrice.toFixed(2)} RUB
- USDT/RUB {USDT_RATE.toFixed(2)} ₽ + USDT/RUB {usdtRate.toFixed(2)} ₽
@@ -46,18 +58,12 @@ export function ConverterSection() {
-
Конвертируете
+
Получаете
- c.updateRub(e.target.value)} - placeholder="0" - inputMode="decimal" - /> +
- - RUB + + USDT
@@ -66,8 +72,6 @@ export function ConverterSection() {