refactor: Изменен порядок формы - проверка полиса на первом шаге
Изменения в UX: - Шаг 1: Проверка полиса (было: телефон + SMS) - Шаг 2: Детали происшествия (без изменений) - Шаг 3: Телефон + SMS + Выплата (было: только выплата) Обновленные компоненты: - Удален: Step1Phone.tsx - Создан: Step1Policy.tsx - проверка полиса через API - Обновлен: Step3Payment.tsx - добавлена SMS верификация - Обновлен: ClaimForm.tsx - новая структура шагов Логика: сначала проверяем полис, потом детали, в конце верификация телефона и выплата
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Form, Button, Select, message } from 'antd';
|
||||
import { QrcodeOutlined } from '@ant-design/icons';
|
||||
import { useState } from 'react';
|
||||
import { Form, Input, Button, Select, message, Space, Divider } from 'antd';
|
||||
import { PhoneOutlined, SafetyOutlined, QrcodeOutlined } from '@ant-design/icons';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@@ -9,12 +9,89 @@ interface Props {
|
||||
updateFormData: (data: any) => void;
|
||||
onPrev: () => void;
|
||||
onSubmit: () => void;
|
||||
isPhoneVerified: boolean;
|
||||
setIsPhoneVerified: (verified: boolean) => void;
|
||||
}
|
||||
|
||||
export default function Step3Payment({ formData, updateFormData, onPrev, onSubmit }: Props) {
|
||||
export default function Step3Payment({
|
||||
formData,
|
||||
updateFormData,
|
||||
onPrev,
|
||||
onSubmit,
|
||||
isPhoneVerified,
|
||||
setIsPhoneVerified
|
||||
}: Props) {
|
||||
const [form] = Form.useForm();
|
||||
const [codeSent, setCodeSent] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [verifyLoading, setVerifyLoading] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const sendCode = async () => {
|
||||
try {
|
||||
const phone = form.getFieldValue('phone');
|
||||
if (!phone) {
|
||||
message.error('Введите номер телефона');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
const response = await fetch('http://147.45.146.17:8100/api/v1/sms/send', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone }),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
message.success('Код отправлен на ваш телефон');
|
||||
setCodeSent(true);
|
||||
if (result.debug_code) {
|
||||
message.info(`DEBUG: Код ${result.debug_code}`);
|
||||
}
|
||||
} else {
|
||||
message.error(result.detail || 'Ошибка отправки кода');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('Ошибка соединения с сервером');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const verifyCode = async () => {
|
||||
try {
|
||||
const phone = form.getFieldValue('phone');
|
||||
const code = form.getFieldValue('smsCode');
|
||||
|
||||
if (!code) {
|
||||
message.error('Введите код из SMS');
|
||||
return;
|
||||
}
|
||||
|
||||
setVerifyLoading(true);
|
||||
const response = await fetch('http://147.45.146.17:8100/api/v1/sms/verify', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone, code }),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
message.success('Телефон подтвержден!');
|
||||
setIsPhoneVerified(true);
|
||||
} else {
|
||||
message.error(result.detail || 'Неверный код');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('Ошибка соединения с сервером');
|
||||
} finally {
|
||||
setVerifyLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
@@ -36,65 +113,162 @@ export default function Step3Payment({ formData, updateFormData, onPrev, onSubmi
|
||||
initialValues={formData}
|
||||
style={{ marginTop: 24 }}
|
||||
>
|
||||
<Form.Item
|
||||
label="Способ выплаты"
|
||||
name="paymentMethod"
|
||||
initialValue="sbp"
|
||||
>
|
||||
<div style={{ padding: '12px', background: '#f0f9ff', borderRadius: '8px', border: '1px solid #91d5ff' }}>
|
||||
<QrcodeOutlined style={{ fontSize: 20, color: '#1890ff', marginRight: 8 }} />
|
||||
<strong>СБП (Система быстрых платежей)</strong>
|
||||
<p style={{ margin: '8px 0 0 0', color: '#666', fontSize: 13 }}>
|
||||
Выплата поступит на ваш счет в течение нескольких минут
|
||||
</p>
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Выберите ваш банк"
|
||||
name="bankName"
|
||||
rules={[{ required: true, message: 'Выберите банк для получения выплаты' }]}
|
||||
>
|
||||
<Select
|
||||
placeholder="Выберите банк"
|
||||
size="large"
|
||||
showSearch
|
||||
filterOption={(input: string, option: any) => {
|
||||
const children = option?.children;
|
||||
if (typeof children === 'string') {
|
||||
return children.toLowerCase().includes(input.toLowerCase());
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
{/* Блок верификации телефона */}
|
||||
<div style={{
|
||||
padding: 16,
|
||||
background: '#f6f8fa',
|
||||
borderRadius: 8,
|
||||
marginBottom: 24
|
||||
}}>
|
||||
<h3 style={{ marginTop: 0 }}>📱 Подтверждение телефона</h3>
|
||||
|
||||
<Form.Item
|
||||
label="Номер телефона"
|
||||
name="phone"
|
||||
rules={[
|
||||
{ required: true, message: 'Введите номер телефона' },
|
||||
{ pattern: /^\+7\d{10}$/, message: 'Формат: +79001234567' }
|
||||
]}
|
||||
>
|
||||
<Option value="sberbank">🟢 Сбербанк</Option>
|
||||
<Option value="tinkoff">🟡 Тинькофф</Option>
|
||||
<Option value="vtb">🔵 ВТБ</Option>
|
||||
<Option value="alfabank">🔴 Альфа-Банк</Option>
|
||||
<Option value="raiffeisen">🟡 Райффайзенбанк</Option>
|
||||
<Option value="gazprombank">🔵 Газпромбанк</Option>
|
||||
<Option value="rosbank">🔴 Росбанк</Option>
|
||||
<Option value="sovcombank">🟢 Совкомбанк</Option>
|
||||
<Option value="otkritie">🔵 Открытие</Option>
|
||||
<Option value="other">💳 Другой банк</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<div style={{ display: 'flex', gap: 8, marginTop: 32 }}>
|
||||
<Button onClick={onPrev}>Назад</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
loading={submitting}
|
||||
style={{ flex: 1 }}
|
||||
<Input
|
||||
prefix={<PhoneOutlined />}
|
||||
placeholder="+79001234567"
|
||||
disabled={isPhoneVerified}
|
||||
maxLength={12}
|
||||
size="large"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{!isPhoneVerified && (
|
||||
<>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={sendCode}
|
||||
loading={loading}
|
||||
disabled={codeSent}
|
||||
block
|
||||
>
|
||||
{codeSent ? 'Код отправлен' : 'Отправить код'}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
|
||||
{codeSent && (
|
||||
<Form.Item
|
||||
label="Код из SMS"
|
||||
name="smsCode"
|
||||
rules={[
|
||||
{ required: true, message: 'Введите код' },
|
||||
{ len: 6, message: '6 цифр' }
|
||||
]}
|
||||
>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<Input
|
||||
prefix={<SafetyOutlined />}
|
||||
placeholder="123456"
|
||||
maxLength={6}
|
||||
style={{ width: '70%' }}
|
||||
size="large"
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={verifyCode}
|
||||
loading={verifyLoading}
|
||||
style={{ width: '30%' }}
|
||||
size="large"
|
||||
>
|
||||
Проверить
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</Form.Item>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{isPhoneVerified && (
|
||||
<div style={{
|
||||
padding: 12,
|
||||
background: '#f0f9ff',
|
||||
borderRadius: 8,
|
||||
border: '1px solid #91d5ff'
|
||||
}}>
|
||||
✅ Телефон подтвержден
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Блок выплаты (показывается только после верификации) */}
|
||||
{isPhoneVerified && (
|
||||
<>
|
||||
<Divider />
|
||||
|
||||
<h3>💳 Способ получения выплаты</h3>
|
||||
|
||||
<Form.Item
|
||||
label="Способ выплаты"
|
||||
name="paymentMethod"
|
||||
initialValue="sbp"
|
||||
>
|
||||
Отправить заявку
|
||||
</Button>
|
||||
</div>
|
||||
</Form.Item>
|
||||
<div style={{
|
||||
padding: '12px',
|
||||
background: '#f0f9ff',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #91d5ff'
|
||||
}}>
|
||||
<QrcodeOutlined style={{ fontSize: 20, color: '#1890ff', marginRight: 8 }} />
|
||||
<strong>СБП (Система быстрых платежей)</strong>
|
||||
<p style={{ margin: '8px 0 0 0', color: '#666', fontSize: 13 }}>
|
||||
Выплата поступит на ваш счет в течение нескольких минут
|
||||
</p>
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Выберите ваш банк"
|
||||
name="bankName"
|
||||
rules={[{ required: true, message: 'Выберите банк для получения выплаты' }]}
|
||||
>
|
||||
<Select
|
||||
placeholder="Выберите банк"
|
||||
size="large"
|
||||
showSearch
|
||||
filterOption={(input: string, option: any) => {
|
||||
const children = option?.children;
|
||||
if (typeof children === 'string') {
|
||||
return children.toLowerCase().includes(input.toLowerCase());
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
<Option value="sberbank">🟢 Сбербанк</Option>
|
||||
<Option value="tinkoff">🟡 Тинькофф</Option>
|
||||
<Option value="vtb">🔵 ВТБ</Option>
|
||||
<Option value="alfabank">🔴 Альфа-Банк</Option>
|
||||
<Option value="raiffeisen">🟡 Райффайзенбанк</Option>
|
||||
<Option value="gazprombank">🔵 Газпромбанк</Option>
|
||||
<Option value="rosbank">🔴 Росбанк</Option>
|
||||
<Option value="sovcombank">🟢 Совкомбанк</Option>
|
||||
<Option value="otkritie">🔵 Открытие</Option>
|
||||
<Option value="other">💳 Другой банк</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<div style={{ display: 'flex', gap: 8, marginTop: 32 }}>
|
||||
<Button onClick={onPrev} size="large">Назад</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
loading={submitting}
|
||||
style={{ flex: 1 }}
|
||||
size="large"
|
||||
>
|
||||
Отправить заявку
|
||||
</Button>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user