2025-10-29 14:09:20 +03:00
|
|
|
|
import { useState, useMemo, useCallback } from 'react';
|
2025-10-24 22:13:52 +03:00
|
|
|
|
import { Steps, Card, message, Row, Col } from 'antd';
|
2025-11-01 13:31:05 +03:00
|
|
|
|
import Step1Phone from '../components/form/Step1Phone';
|
2025-10-24 20:40:44 +03:00
|
|
|
|
import Step1Policy from '../components/form/Step1Policy';
|
2025-10-29 12:36:30 +03:00
|
|
|
|
import Step2EventType from '../components/form/Step2EventType';
|
|
|
|
|
|
import StepDocumentUpload from '../components/form/StepDocumentUpload';
|
2025-10-24 16:19:58 +03:00
|
|
|
|
import Step3Payment from '../components/form/Step3Payment';
|
2025-10-24 22:13:52 +03:00
|
|
|
|
import DebugPanel from '../components/DebugPanel';
|
2025-10-29 12:36:30 +03:00
|
|
|
|
import { getDocumentsForEventType } from '../constants/documentConfigs';
|
2025-10-24 16:19:58 +03:00
|
|
|
|
import './ClaimForm.css';
|
|
|
|
|
|
|
|
|
|
|
|
const { Step } = Steps;
|
|
|
|
|
|
|
|
|
|
|
|
interface FormData {
|
2025-11-01 13:31:05 +03:00
|
|
|
|
// Шаг 1: Phone
|
|
|
|
|
|
phone?: string;
|
|
|
|
|
|
contact_id?: string;
|
|
|
|
|
|
is_new_contact?: boolean;
|
|
|
|
|
|
|
|
|
|
|
|
// Шаг 2: Policy
|
2025-10-29 12:36:30 +03:00
|
|
|
|
voucher: string;
|
|
|
|
|
|
claim_id?: string;
|
|
|
|
|
|
session_id?: string;
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-11-01 13:31:05 +03:00
|
|
|
|
// Шаг 3: Event Type
|
2025-10-29 12:36:30 +03:00
|
|
|
|
eventType?: string;
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-11-01 13:31:05 +03:00
|
|
|
|
// Шаги 4+: Documents
|
2025-10-29 12:36:30 +03:00
|
|
|
|
documents?: Record<string, {
|
|
|
|
|
|
uploaded: boolean;
|
|
|
|
|
|
data: any;
|
|
|
|
|
|
file_type: string;
|
|
|
|
|
|
skipped?: boolean;
|
|
|
|
|
|
}>;
|
|
|
|
|
|
|
|
|
|
|
|
// Последний шаг: Payment
|
|
|
|
|
|
fullName?: string;
|
|
|
|
|
|
email?: string;
|
|
|
|
|
|
paymentMethod?: string;
|
2025-10-24 16:19:58 +03:00
|
|
|
|
bankName?: string;
|
|
|
|
|
|
cardNumber?: string;
|
|
|
|
|
|
accountNumber?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default function ClaimForm() {
|
2025-11-01 16:53:10 +03:00
|
|
|
|
// ✅ claim_id будет создан n8n в Step1Phone после SMS верификации
|
|
|
|
|
|
// Не генерируем его локально!
|
2025-10-27 08:33:16 +03:00
|
|
|
|
|
|
|
|
|
|
// Генерируем session_id и сохраняем в sessionStorage
|
|
|
|
|
|
const [sessionId] = useState(() => {
|
|
|
|
|
|
let sid = sessionStorage.getItem('session_id');
|
|
|
|
|
|
if (!sid) {
|
|
|
|
|
|
sid = `sess-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
|
|
|
sessionStorage.setItem('session_id', sid);
|
|
|
|
|
|
}
|
|
|
|
|
|
return sid;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-10-24 16:19:58 +03:00
|
|
|
|
const [currentStep, setCurrentStep] = useState(0);
|
|
|
|
|
|
const [formData, setFormData] = useState<FormData>({
|
2025-10-24 20:54:57 +03:00
|
|
|
|
voucher: '',
|
2025-11-01 16:53:10 +03:00
|
|
|
|
claim_id: undefined, // ✅ Будет заполнен n8n в Step1Phone
|
2025-10-29 12:36:30 +03:00
|
|
|
|
session_id: sessionId,
|
2025-10-24 16:19:58 +03:00
|
|
|
|
paymentMethod: 'sbp',
|
|
|
|
|
|
});
|
|
|
|
|
|
const [isPhoneVerified, setIsPhoneVerified] = useState(false);
|
2025-10-24 22:13:52 +03:00
|
|
|
|
const [debugEvents, setDebugEvents] = useState<any[]>([]);
|
|
|
|
|
|
|
2025-11-01 16:53:10 +03:00
|
|
|
|
// 🔥 VERSION CHECK: Если видишь это в консоли - фронт обновился!
|
|
|
|
|
|
console.log('🔥 ClaimForm v2.0 - claim_id НЕ генерируется на фронте!');
|
|
|
|
|
|
|
2025-10-29 12:36:30 +03:00
|
|
|
|
// Динамически определяем список шагов на основе выбранного eventType
|
|
|
|
|
|
const documentConfigs = formData.eventType ? getDocumentsForEventType(formData.eventType) : [];
|
|
|
|
|
|
const totalDocumentSteps = documentConfigs.length;
|
|
|
|
|
|
|
2025-10-24 22:13:52 +03:00
|
|
|
|
const addDebugEvent = (type: string, status: string, message: string, data?: any) => {
|
|
|
|
|
|
const event = {
|
|
|
|
|
|
timestamp: new Date().toLocaleTimeString('ru-RU'),
|
|
|
|
|
|
type,
|
|
|
|
|
|
status,
|
|
|
|
|
|
message,
|
2025-10-27 08:33:16 +03:00
|
|
|
|
data: {
|
|
|
|
|
|
...data,
|
2025-11-01 16:53:10 +03:00
|
|
|
|
claim_id: formData.claim_id // ✅ Используем claim_id из formData (от n8n)
|
2025-10-27 08:33:16 +03:00
|
|
|
|
}
|
2025-10-24 22:13:52 +03:00
|
|
|
|
};
|
|
|
|
|
|
setDebugEvents(prev => [event, ...prev]);
|
|
|
|
|
|
};
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-11-01 16:53:10 +03:00
|
|
|
|
// ✅ claim_id будет залогирован в Step1Phone после получения от n8n
|
2025-10-27 08:33:16 +03:00
|
|
|
|
|
2025-10-29 14:09:20 +03:00
|
|
|
|
const updateFormData = useCallback((data: Partial<FormData>) => {
|
|
|
|
|
|
setFormData((prev) => ({ ...prev, ...data }));
|
|
|
|
|
|
}, []);
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-10-29 14:09:20 +03:00
|
|
|
|
const nextStep = useCallback(() => {
|
|
|
|
|
|
console.log('⏩ nextStep called');
|
|
|
|
|
|
setCurrentStep((prev) => {
|
|
|
|
|
|
console.log('📍 Current step:', prev, '→ Next:', prev + 1);
|
|
|
|
|
|
return prev + 1;
|
|
|
|
|
|
});
|
|
|
|
|
|
}, []);
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-10-29 14:09:20 +03:00
|
|
|
|
const prevStep = useCallback(() => {
|
|
|
|
|
|
console.log('⏪ prevStep called');
|
|
|
|
|
|
setCurrentStep((prev) => {
|
|
|
|
|
|
console.log('📍 Current step:', prev, '→ Prev:', prev - 1);
|
|
|
|
|
|
return prev - 1;
|
|
|
|
|
|
});
|
|
|
|
|
|
}, []);
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-10-29 14:09:20 +03:00
|
|
|
|
const handleSubmit = useCallback(async () => {
|
2025-10-24 16:19:58 +03:00
|
|
|
|
try {
|
2025-10-29 12:36:30 +03:00
|
|
|
|
addDebugEvent('form', 'info', '📤 Отправка заявки на сервер');
|
|
|
|
|
|
|
2025-10-30 19:22:14 +03:00
|
|
|
|
const response = await fetch('http://147.45.146.17:8100/api/v1/claims/create', {
|
2025-10-24 16:19:58 +03:00
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify({
|
2025-11-01 16:53:10 +03:00
|
|
|
|
claim_id: formData.claim_id, // ✅ Используем claim_id от n8n
|
2025-10-24 20:54:57 +03:00
|
|
|
|
voucher: formData.voucher,
|
2025-10-24 16:19:58 +03:00
|
|
|
|
email: formData.email,
|
2025-10-24 20:54:57 +03:00
|
|
|
|
phone: formData.phone,
|
2025-10-29 12:36:30 +03:00
|
|
|
|
event_type: formData.eventType,
|
2025-10-24 16:19:58 +03:00
|
|
|
|
payment_method: formData.paymentMethod,
|
|
|
|
|
|
bank_name: formData.bankName,
|
|
|
|
|
|
card_number: formData.cardNumber,
|
|
|
|
|
|
account_number: formData.accountNumber,
|
2025-10-29 12:36:30 +03:00
|
|
|
|
documents: formData.documents || {},
|
2025-10-24 16:19:58 +03:00
|
|
|
|
}),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
|
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
message.success(`Заявка ${result.claim_number} успешно создана!`);
|
2025-10-29 12:36:30 +03:00
|
|
|
|
addDebugEvent('form', 'success', `✅ Заявка ${result.claim_number} создана`);
|
|
|
|
|
|
|
2025-11-01 16:53:10 +03:00
|
|
|
|
// Сброс формы (создаём новую заявку, claim_id будет сгенерирован при следующем SMS)
|
2025-10-24 16:19:58 +03:00
|
|
|
|
setFormData({
|
2025-10-24 20:54:57 +03:00
|
|
|
|
voucher: '',
|
2025-11-01 16:53:10 +03:00
|
|
|
|
claim_id: undefined, // ✅ Очищаем для новой заявки
|
2025-10-29 12:36:30 +03:00
|
|
|
|
session_id: sessionId,
|
2025-10-24 16:19:58 +03:00
|
|
|
|
paymentMethod: 'sbp',
|
|
|
|
|
|
});
|
|
|
|
|
|
setCurrentStep(0);
|
|
|
|
|
|
setIsPhoneVerified(false);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
message.error('Ошибка при создании заявки');
|
2025-10-29 12:36:30 +03:00
|
|
|
|
addDebugEvent('form', 'error', '❌ Ошибка создания заявки');
|
2025-10-24 16:19:58 +03:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
message.error('Ошибка соединения с сервером');
|
2025-10-29 12:36:30 +03:00
|
|
|
|
addDebugEvent('form', 'error', '❌ Ошибка соединения');
|
2025-10-24 16:19:58 +03:00
|
|
|
|
console.error(error);
|
|
|
|
|
|
}
|
2025-11-01 16:53:10 +03:00
|
|
|
|
}, [formData, sessionId, addDebugEvent]);
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-10-29 12:36:30 +03:00
|
|
|
|
// Динамически генерируем шаги на основе выбранного eventType
|
|
|
|
|
|
const steps = useMemo(() => {
|
|
|
|
|
|
const stepsArray: any[] = [];
|
|
|
|
|
|
|
2025-11-01 13:31:05 +03:00
|
|
|
|
// Шаг 1: Phone (телефон + SMS верификация)
|
|
|
|
|
|
stepsArray.push({
|
|
|
|
|
|
title: 'Телефон',
|
|
|
|
|
|
description: 'Подтверждение по SMS',
|
|
|
|
|
|
content: (
|
|
|
|
|
|
<Step1Phone
|
2025-11-01 16:53:10 +03:00
|
|
|
|
formData={{ ...formData, session_id: sessionId }} // ✅ claim_id будет создан n8n
|
2025-11-01 13:31:05 +03:00
|
|
|
|
updateFormData={updateFormData}
|
|
|
|
|
|
onNext={nextStep}
|
|
|
|
|
|
onPrev={prevStep}
|
|
|
|
|
|
isPhoneVerified={isPhoneVerified}
|
|
|
|
|
|
setIsPhoneVerified={setIsPhoneVerified}
|
|
|
|
|
|
addDebugEvent={addDebugEvent}
|
|
|
|
|
|
/>
|
|
|
|
|
|
),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Шаг 2: Policy (всегда)
|
2025-10-29 12:36:30 +03:00
|
|
|
|
stepsArray.push({
|
2025-10-24 20:40:44 +03:00
|
|
|
|
title: 'Проверка полиса',
|
2025-10-29 12:36:30 +03:00
|
|
|
|
description: 'Полис ERV',
|
2025-10-24 16:19:58 +03:00
|
|
|
|
content: (
|
2025-10-27 08:33:16 +03:00
|
|
|
|
<Step1Policy
|
2025-11-01 16:53:10 +03:00
|
|
|
|
formData={{ ...formData, session_id: sessionId }} // ✅ claim_id уже в formData от n8n
|
2025-10-27 08:33:16 +03:00
|
|
|
|
updateFormData={updateFormData}
|
2025-10-24 16:19:58 +03:00
|
|
|
|
onNext={nextStep}
|
2025-10-24 22:13:52 +03:00
|
|
|
|
addDebugEvent={addDebugEvent}
|
2025-10-24 16:19:58 +03:00
|
|
|
|
/>
|
|
|
|
|
|
),
|
2025-10-29 12:36:30 +03:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-02 00:09:35 +03:00
|
|
|
|
// Шаг 3: Event Type Selection (всегда)
|
2025-10-29 12:36:30 +03:00
|
|
|
|
stepsArray.push({
|
|
|
|
|
|
title: 'Тип события',
|
|
|
|
|
|
description: 'Выбор случая',
|
2025-10-24 16:19:58 +03:00
|
|
|
|
content: (
|
2025-10-29 12:36:30 +03:00
|
|
|
|
<Step2EventType
|
|
|
|
|
|
formData={formData}
|
2025-10-24 16:19:58 +03:00
|
|
|
|
updateFormData={updateFormData}
|
|
|
|
|
|
onNext={nextStep}
|
|
|
|
|
|
onPrev={prevStep}
|
2025-11-02 00:09:35 +03:00
|
|
|
|
addDebugEvent={addDebugEvent}
|
2025-10-24 16:19:58 +03:00
|
|
|
|
/>
|
|
|
|
|
|
),
|
2025-10-29 12:36:30 +03:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-10-30 19:22:14 +03:00
|
|
|
|
// Шаги 3+: Document Upload (динамически, если выбран eventType)
|
2025-10-29 12:36:30 +03:00
|
|
|
|
if (formData.eventType && documentConfigs.length > 0) {
|
|
|
|
|
|
documentConfigs.forEach((docConfig, index) => {
|
|
|
|
|
|
stepsArray.push({
|
|
|
|
|
|
title: `Документ ${index + 1}`,
|
|
|
|
|
|
description: docConfig.name,
|
|
|
|
|
|
content: (
|
|
|
|
|
|
<StepDocumentUpload
|
|
|
|
|
|
key={`doc-${docConfig.file_type}`}
|
|
|
|
|
|
documentConfig={docConfig}
|
|
|
|
|
|
formData={formData}
|
|
|
|
|
|
updateFormData={updateFormData}
|
|
|
|
|
|
onNext={nextStep}
|
|
|
|
|
|
onPrev={prevStep}
|
|
|
|
|
|
isLastDocument={index === documentConfigs.length - 1}
|
|
|
|
|
|
currentDocNumber={index + 1}
|
|
|
|
|
|
totalDocs={documentConfigs.length}
|
|
|
|
|
|
/>
|
|
|
|
|
|
),
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Последний шаг: Payment (всегда)
|
|
|
|
|
|
stepsArray.push({
|
|
|
|
|
|
title: 'Оплата',
|
|
|
|
|
|
description: 'Контакты и выплата',
|
2025-10-24 16:19:58 +03:00
|
|
|
|
content: (
|
|
|
|
|
|
<Step3Payment
|
2025-11-01 16:53:10 +03:00
|
|
|
|
formData={formData} // ✅ claim_id уже в formData
|
2025-10-24 16:19:58 +03:00
|
|
|
|
updateFormData={updateFormData}
|
|
|
|
|
|
onPrev={prevStep}
|
|
|
|
|
|
onSubmit={handleSubmit}
|
2025-10-24 20:40:44 +03:00
|
|
|
|
isPhoneVerified={isPhoneVerified}
|
|
|
|
|
|
setIsPhoneVerified={setIsPhoneVerified}
|
2025-10-24 22:13:52 +03:00
|
|
|
|
addDebugEvent={addDebugEvent}
|
2025-10-24 16:19:58 +03:00
|
|
|
|
/>
|
|
|
|
|
|
),
|
2025-10-29 12:36:30 +03:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return stepsArray;
|
2025-11-01 16:53:10 +03:00
|
|
|
|
}, [formData, documentConfigs, isPhoneVerified, sessionId, nextStep, prevStep, updateFormData, handleSubmit, setIsPhoneVerified, addDebugEvent]);
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
2025-10-24 21:34:50 +03:00
|
|
|
|
const handleReset = () => {
|
|
|
|
|
|
setFormData({
|
|
|
|
|
|
voucher: '',
|
2025-11-01 16:53:10 +03:00
|
|
|
|
claim_id: undefined, // ✅ Очищаем для новой заявки
|
2025-10-29 12:36:30 +03:00
|
|
|
|
session_id: sessionId,
|
2025-10-24 21:34:50 +03:00
|
|
|
|
paymentMethod: 'sbp',
|
|
|
|
|
|
});
|
|
|
|
|
|
setCurrentStep(0);
|
|
|
|
|
|
setIsPhoneVerified(false);
|
|
|
|
|
|
message.info('Форма сброшена');
|
2025-10-29 12:36:30 +03:00
|
|
|
|
addDebugEvent('system', 'info', '🔄 Форма сброшена');
|
2025-10-24 21:34:50 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-24 16:19:58 +03:00
|
|
|
|
return (
|
2025-10-24 22:13:52 +03:00
|
|
|
|
<div className="claim-form-container" style={{ padding: '20px', background: '#f0f2f5' }}>
|
|
|
|
|
|
<Row gutter={16}>
|
|
|
|
|
|
{/* Левая часть - Форма */}
|
|
|
|
|
|
<Col xs={24} lg={14}>
|
|
|
|
|
|
<Card
|
|
|
|
|
|
title="Подать заявку на выплату"
|
|
|
|
|
|
className="claim-form-card"
|
|
|
|
|
|
extra={
|
|
|
|
|
|
currentStep > 0 && (
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={handleReset}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
padding: '4px 12px',
|
|
|
|
|
|
background: '#fff',
|
|
|
|
|
|
border: '1px solid #d9d9d9',
|
|
|
|
|
|
borderRadius: '4px',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
fontSize: '14px'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
🔄 Начать заново
|
|
|
|
|
|
</button>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Steps current={currentStep} className="steps">
|
2025-10-29 12:36:30 +03:00
|
|
|
|
{steps.map((item, index) => (
|
|
|
|
|
|
<Step
|
|
|
|
|
|
key={`step-${index}`}
|
|
|
|
|
|
title={item.title}
|
|
|
|
|
|
description={item.description}
|
|
|
|
|
|
/>
|
2025-10-24 22:13:52 +03:00
|
|
|
|
))}
|
|
|
|
|
|
</Steps>
|
|
|
|
|
|
<div className="steps-content">{steps[currentStep].content}</div>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Правая часть - Debug консоль */}
|
|
|
|
|
|
<Col xs={24} lg={10}>
|
|
|
|
|
|
<DebugPanel events={debugEvents} formData={formData} />
|
|
|
|
|
|
</Col>
|
|
|
|
|
|
</Row>
|
2025-10-24 16:19:58 +03:00
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|