diff --git a/frontend/src/components/form/StepClaimConfirmation.tsx b/frontend/src/components/form/StepClaimConfirmation.tsx index 06d9a5f..1432299 100644 --- a/frontend/src/components/form/StepClaimConfirmation.tsx +++ b/frontend/src/components/form/StepClaimConfirmation.tsx @@ -1,5 +1,5 @@ -import { useEffect, useRef, useState } from 'react'; -import { Card, Spin, message } from 'antd'; +import { useEffect, useRef, useState, useCallback } from 'react'; +import { Card, Spin, message, Modal, Input, Button, Form } from 'antd'; import { generateConfirmationFormHTML } from './generateConfirmationFormHTML'; interface Props { @@ -16,6 +16,14 @@ export default function StepClaimConfirmation({ const [loading, setLoading] = useState(true); const iframeRef = useRef(null); const [htmlContent, setHtmlContent] = useState(''); + + // SMS Approval state + const [smsModalVisible, setSmsModalVisible] = useState(false); + const [smsCodeSent, setSmsCodeSent] = useState(false); + const [smsLoading, setSmsLoading] = useState(false); + const [smsVerifyLoading, setSmsVerifyLoading] = useState(false); + const [pendingFormData, setPendingFormData] = useState(null); + const [smsForm] = Form.useForm(); useEffect(() => { if (!claimPlanData) { @@ -84,6 +92,79 @@ export default function StepClaimConfirmation({ setLoading(false); }, [claimPlanData]); + // Функция сохранения данных формы (TODO: реализовать сохранение) + const saveFormData = useCallback(async (formData: any) => { + console.log('💾 Сохраняем данные формы:', formData); + // TODO: Реализовать сохранение данных в бэкенд/n8n + // Здесь будет вызов API для сохранения отредактированных данных формы + }, []); + + // Функция отправки SMS-кода + const sendSMSCode = useCallback(async (phone: string) => { + try { + setSmsLoading(true); + // SMS API ожидает телефон в формате +79001234567 + const phoneWithPlus = phone.startsWith('+') ? phone : `+${phone}`; + + const response = await fetch('/api/v1/sms/send', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ phone: phoneWithPlus }), + }); + + const result = await response.json(); + + if (response.ok) { + message.success('Код отправлен на ваш телефон'); + setSmsCodeSent(true); + if (result.debug_code) { + message.info(`DEBUG: Код ${result.debug_code}`); + } + } else { + message.error(result.detail || 'Ошибка отправки кода'); + } + } catch (error) { + message.error('Ошибка соединения с сервером'); + } finally { + setSmsLoading(false); + } + }, []); + + // Функция проверки SMS-кода + const verifySMSCode = useCallback(async (phone: string, code: string) => { + try { + setSmsVerifyLoading(true); + // SMS API ожидает телефон в формате +79001234567 + const phoneWithPlus = phone.startsWith('+') ? phone : `+${phone}`; + + const response = await fetch('/api/v1/sms/verify', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ phone: phoneWithPlus, code }), + }); + + const result = await response.json(); + + if (response.ok) { + message.success('Код подтвержден!'); + // Закрываем модалку и продолжаем с сохранением данных + setSmsModalVisible(false); + setSmsCodeSent(false); + smsForm.resetFields(); + + // Сохраняем данные и переходим дальше + await saveFormData(pendingFormData); + onNext(); + } else { + message.error(result.detail || 'Неверный код'); + } + } catch (error) { + message.error('Ошибка соединения с сервером'); + } finally { + setSmsVerifyLoading(false); + } + }, [pendingFormData, saveFormData, smsForm, onNext]); + useEffect(() => { // Слушаем сообщения от iframe const handleMessage = (event: MessageEvent) => { @@ -91,13 +172,29 @@ export default function StepClaimConfirmation({ if (event.data.type === 'claim_confirmed') { console.log('✅ Заявление подтверждено с данными:', event.data.data); - message.success('Заявление подтверждено!'); - // Здесь можно сохранить отредактированные данные перед переходом дальше - if (event.data.data) { - // Данные формы можно передать дальше через updateFormData или сохранить - console.log('📋 Отредактированные данные формы:', event.data.data); + + // Сохраняем данные формы для последующего сохранения после SMS-апрува + setPendingFormData(event.data.data); + + // Получаем телефон пользователя для отправки SMS + const phone = + claimPlanData?.propertyName?.applicant?.phone || + claimPlanData?.propertyName?.user?.mobile || + claimPlanData?.phone || + ''; + + if (!phone) { + message.error('Не удалось определить номер телефона для подтверждения'); + return; } - onNext(); + + // Показываем модалку SMS-апрува + setSmsModalVisible(true); + setSmsCodeSent(false); + smsForm.resetFields(); + + // Автоматически отправляем SMS-код + sendSMSCode(phone); } else if (event.data.type === 'claim_cancelled') { message.info('Подтверждение отменено'); onPrev(); @@ -134,7 +231,7 @@ export default function StepClaimConfirmation({ return () => { window.removeEventListener('message', handleMessage); }; - }, [onNext, onPrev]); + }, [onNext, onPrev, sendSMSCode, claimPlanData]); if (loading) { return ( @@ -147,33 +244,177 @@ export default function StepClaimConfirmation({ ); } + // Обработчик отправки SMS-кода из модалки + const handleSendCode = useCallback(async () => { + const phone = + claimPlanData?.propertyName?.applicant?.phone || + claimPlanData?.propertyName?.user?.mobile || + claimPlanData?.phone || + ''; + + if (!phone) { + message.error('Не удалось определить номер телефона'); + return; + } + + await sendSMSCode(phone); + }, [claimPlanData, sendSMSCode]); + + // Обработчик проверки SMS-кода из модалки + const handleVerifyCode = useCallback(async () => { + try { + const values = await smsForm.validateFields(); + const phone = + claimPlanData?.propertyName?.applicant?.phone || + claimPlanData?.propertyName?.user?.mobile || + claimPlanData?.phone || + ''; + + if (!phone) { + message.error('Не удалось определить номер телефона'); + return; + } + + await verifySMSCode(phone, values.code); + } catch (error) { + // Валидация не прошла + } + }, [claimPlanData, smsForm, verifySMSCode]); + + // Обработчик отмены SMS-апрува + const handleCancelSMS = () => { + setSmsModalVisible(false); + setSmsCodeSent(false); + setPendingFormData(null); + smsForm.resetFields(); + message.info('Подтверждение отменено'); + }; + + const phone = + claimPlanData?.propertyName?.applicant?.phone || + claimPlanData?.propertyName?.user?.mobile || + claimPlanData?.phone || + ''; + const displayPhone = phone ? (phone.length > 4 ? `${phone.slice(0, -4)}****` : '****') : '****'; + return ( - -