Files
frontend/src/pages/converter/ui/LegalConverterPage.tsx
2026-06-06 16:55:48 +03:00

154 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react'
import { FormField, Select } from '@shared/ui'
import styles from './LegalConverterPage.module.css'
const MIN_ORDER = 500_000
// Чем дольше пользователь готов ждать, тем ниже комиссия сервиса.
const TERM_OPTIONS = [
{ days: 3, rate: 0.05 },
{ days: 4, rate: 0.04636 },
{ days: 5, rate: 0.04273 },
{ days: 6, rate: 0.03909 },
{ days: 7, rate: 0.03545 },
{ days: 8, rate: 0.03182 },
{ days: 9, rate: 0.02818 },
{ days: 10, rate: 0.02455 },
{ days: 11, rate: 0.02091 },
{ days: 12, rate: 0.01727 },
{ days: 13, rate: 0.01364 },
{ days: 14, rate: 0.01 },
] as const
const ru = (n: number) => n.toLocaleString('ru-RU', { maximumFractionDigits: 0 })
const dayLabel = (days: number) => {
const mod10 = days % 10
const mod100 = days % 100
if (mod10 === 1 && mod100 !== 11) return `${days} день`
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)) return `${days} дня`
return `${days} дней`
}
export function LegalConverterPage() {
const [amount, setAmount] = useState('')
const [name, setName] = useState('')
const [contact, setContact] = useState('')
const [days, setDays] = useState<number>(TERM_OPTIONS[0].days)
const numAmount = Number(amount.replace(/\D/g, '')) || 0
const belowMin = numAmount > 0 && numAmount < MIN_ORDER
const rate = TERM_OPTIONS.find((o) => o.days === days)?.rate ?? TERM_OPTIONS[0].rate
const commission = numAmount * rate
const total = numAmount + commission
const handleAmountChange = (value: string) => {
const digits = value.replace(/\D/g, '')
setAmount(digits ? ru(Number(digits)) : '')
}
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
// Бэкенд пока не подключён — заявка никуда не отправляется.
}
return (
<form className={styles.wrap} onSubmit={handleSubmit}>
<div className={styles.header}>
<h1 className={styles.title}>Оставить заявку</h1>
<p className={styles.subtitle}>
Конвертация крупных объёмов по индивидуальному курсу. Оставьте заявку
менеджер свяжется с вами, подтвердит актуальный курс и сопроводит сделку.
</p>
</div>
<div className={styles.body}>
<div className={styles.formCol}>
<FormField
label="Объём заявки, ₽"
type="text"
value={amount}
onChange={handleAmountChange}
placeholder="от 500 000"
/>
{belowMin && (
<p className={styles.hint}>
Минимальный объём заявки {ru(MIN_ORDER)}
</p>
)}
<Select
id="term"
label="Срок ожидания операции"
value={days}
onChange={setDays}
options={TERM_OPTIONS.map((o) => ({
value: o.days,
label: `${dayLabel(o.days)} — комиссия ${(o.rate * 100).toFixed(3)} %`,
}))}
/>
<FormField
label="Как к вам обращаться"
type="text"
value={name}
onChange={setName}
placeholder="Имя"
/>
<FormField
label="Email или телефон для связи"
type="text"
value={contact}
onChange={setContact}
placeholder="example@mail.ru / +7 900 000-00-00"
/>
</div>
<div className={styles.infoCol}>
<div className={styles.infoTitle}>УСЛОВИЯ</div>
<div className={styles.infoRow}>
<span className={styles.infoLabel}>Минимальный объём</span>
<span className={styles.infoValue}>{ru(MIN_ORDER)} </span>
</div>
<div className={styles.infoRow}>
<span className={styles.infoLabel}>Срок ожидания</span>
<span className={styles.infoValue}>{dayLabel(days)}</span>
</div>
<div className={styles.infoRow}>
<span className={styles.infoLabel}>Ставка комиссии</span>
<span className={styles.infoValue}>{(rate * 100).toFixed(3)} %</span>
</div>
<div className={styles.infoRow}>
<span className={styles.infoLabel}>Сумма комиссии</span>
<span className={styles.infoValue}>
{numAmount > 0 ? `${ru(commission)}` : '—'}
</span>
</div>
<div className={styles.infoRow} data-accent>
<span className={styles.infoLabel}>Итого к оплате</span>
<span className={styles.infoValue}>
{numAmount > 0 ? `${ru(total)}` : '—'}
</span>
</div>
<p className={styles.note}>
Итоговая комиссия рассчитывается индивидуально и зависит от объёма,
валюты и направления сделки.
</p>
</div>
</div>
<button type="submit" className={styles.submitBtn} disabled={belowMin}>
Оставить заявку
</button>
</form>
)
}