Files
aiform_prod/frontend/src/components/form/Step1Phone.tsx

224 lines
7.7 KiB
TypeScript
Raw Normal View History

import { useState } from 'react';
import { Form, Input, Button, message, Space } from 'antd';
import { PhoneOutlined, SafetyOutlined } from '@ant-design/icons';
interface Props {
formData: any;
updateFormData: (data: any) => void;
onNext: () => void;
setIsPhoneVerified: (verified: boolean) => void;
addDebugEvent?: (type: string, status: string, message: string, data?: any) => void;
}
export default function Step1Phone({
formData,
updateFormData,
onNext,
setIsPhoneVerified,
addDebugEvent
}: Props) {
const [form] = Form.useForm();
const [codeSent, setCodeSent] = useState(false);
const [loading, setLoading] = useState(false);
const [verifyLoading, setVerifyLoading] = useState(false);
const sendCode = async () => {
try {
const values = await form.validateFields(['phone']);
const phone = `7${values.phone}`; // БЕЗ +, формат: 79001234567
setLoading(true);
addDebugEvent?.('sms', 'pending', `📱 Отправляю SMS на ${phone}...`, { phone });
const response = await fetch('/api/v1/sms/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone })
});
const result = await response.json();
if (response.ok) {
addDebugEvent?.('sms', 'success', `✅ SMS отправлен (DEBUG mode)`, {
phone,
debug_code: result.debug_code,
message: result.message
});
message.success('Код отправлен на ваш телефон');
setCodeSent(true);
updateFormData({ phone });
if (result.debug_code) {
message.info(`DEBUG: Код ${result.debug_code}`);
}
} else {
addDebugEvent?.('sms', 'error', `❌ Ошибка SMS: ${result.detail}`, { error: result.detail });
message.error(result.detail || 'Ошибка отправки кода');
}
} catch (error) {
if ((error as any)?.errorFields) {
message.error('Введите номер телефона');
} else {
message.error('Ошибка соединения с сервером');
}
} finally {
setLoading(false);
}
};
const verifyCode = async () => {
try {
const values = await form.validateFields(['phone', 'smsCode']);
const phone = `7${values.phone}`; // БЕЗ +, формат: 79001234567
const code = values.smsCode;
setVerifyLoading(true);
addDebugEvent?.('sms', 'pending', `🔐 Проверяю SMS код...`, { phone, code });
const response = await fetch('/api/v1/sms/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone, code })
});
const result = await response.json();
if (response.ok) {
addDebugEvent?.('sms', 'success', `✅ Телефон подтвержден успешно`, { phone, verified: true });
message.success('Телефон подтвержден!');
setIsPhoneVerified(true);
// После верификации создаём контакт в CRM через n8n
try {
addDebugEvent?.('crm', 'info', '📞 Создание контакта в CRM...', { phone });
const crmResponse = await fetch('https://n8n.clientright.pro/webhook/511fde97-88bb-4fb4-bea5-cafdc364be27', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone })
});
const crmResult = await crmResponse.json();
if (crmResponse.ok) {
addDebugEvent?.('crm', 'success', `✅ Контакт создан/найден в CRM`, crmResult);
// Сохраняем данные из CRM в форму
updateFormData({
phone,
contact_id: crmResult.contact_id,
claim_id: crmResult.claim_id,
is_new_contact: crmResult.is_new_contact
});
message.success(crmResult.is_new_contact ? 'Контакт создан!' : 'Контакт найден!');
onNext();
} else {
addDebugEvent?.('crm', 'error', '❌ Ошибка создания контакта в CRM', crmResult);
message.error('Ошибка создания контакта в CRM');
}
} catch (crmError) {
addDebugEvent?.('crm', 'error', '❌ Ошибка соединения с CRM', { error: String(crmError) });
message.error('Ошибка соединения с CRM');
}
} else {
addDebugEvent?.('sms', 'error', `❌ Неверный код SMS`, { phone, code, error: result.detail });
message.error(result.detail || 'Неверный код');
}
} catch (error) {
if ((error as any)?.errorFields) {
message.error('Введите код из SMS');
} else {
message.error('Ошибка соединения с сервером');
}
} finally {
setVerifyLoading(false);
}
};
return (
<Form
form={form}
layout="vertical"
initialValues={formData}
style={{ marginTop: 24 }}
>
<h3 style={{ marginTop: 0 }}>📱 Подтверждение телефона</h3>
<Form.Item
label="Номер телефона"
name="phone"
rules={[
{ required: true, message: 'Введите номер телефона' },
{ pattern: /^\d{10}$/, message: 'Введите 10 цифр без кода страны' }
]}
>
<Input
prefix={<PhoneOutlined />}
addonBefore="+7"
placeholder="9001234567"
maxLength={10}
size="large"
/>
</Form.Item>
<Form.Item>
{!codeSent ? (
<Button type="primary" onClick={sendCode} loading={loading} block>
Отправить код
</Button>
) : (
<Space.Compact style={{ width: '100%' }}>
<Input
prefix={<SafetyOutlined />}
placeholder="123456"
maxLength={6}
style={{ width: '70%' }}
size="large"
name="smsCode"
onChange={(e) => form.setFieldValue('smsCode', e.target.value)}
/>
<Button type="primary" onClick={verifyCode} loading={verifyLoading} style={{ width: '30%' }} size="large">
Проверить
</Button>
</Space.Compact>
)}
</Form.Item>
{/* 🔧 Технические кнопки для разработки */}
<div style={{
marginTop: 24,
padding: 16,
background: '#f0f0f0',
borderRadius: 8,
border: '2px dashed #999'
}}>
<div style={{ marginBottom: 8, fontSize: 12, color: '#666', fontWeight: 'bold' }}>
🔧 DEV MODE - Быстрая навигация (без валидации)
</div>
<div style={{ display: 'flex', gap: 8 }}>
<Button
type="dashed"
onClick={() => {
// Автозаполняем телефон и email
const devData = {
phone: '79001234567', // БЕЗ +
email: 'test@test.ru',
};
updateFormData(devData);
setIsPhoneVerified(true);
message.success('DEV: Телефон автоматически подтверждён');
onNext();
}}
size="small"
style={{ flex: 1 }}
>
Далее (Step 2) [пропустить]
</Button>
</div>
</div>
</Form>
);
}