feat(frontend): использование form_draft для формы подтверждения

- StepDraftSelection: кнопка 'Продолжить' активна для draft_docs_complete
- ClaimForm: проверка form_draft при загрузке черновика
- Если есть form_draft — преобразуем в propertyName и показываем форму подтверждения
- Поддержка статуса draft_docs_complete для перехода к подтверждению
This commit is contained in:
Fedor
2025-11-30 11:45:35 +03:00
parent 0f8631bf20
commit 81acd49fd9
2 changed files with 96 additions and 54 deletions

View File

@@ -127,10 +127,10 @@ const STATUS_CONFIG: Record<string, {
}, },
draft_docs_complete: { draft_docs_complete: {
color: 'orange', color: 'orange',
icon: <LoadingOutlined />, icon: <CheckCircleOutlined />,
label: 'Обработка', label: 'Документы загружены',
description: 'Формируется заявление...', description: 'Все документы обработаны',
action: 'Ожидайте', action: 'Продолжить',
}, },
draft_claim_ready: { draft_claim_ready: {
color: 'green', color: 'green',
@@ -274,11 +274,8 @@ export default function StepDraftSelection({
if (draft.is_legacy && onRestartDraft) { if (draft.is_legacy && onRestartDraft) {
// Legacy черновик - предлагаем начать заново с тем же описанием // Legacy черновик - предлагаем начать заново с тем же описанием
onRestartDraft(draftId, draft.problem_description || ''); onRestartDraft(draftId, draft.problem_description || '');
} else if (draft.status_code === 'draft_docs_complete') {
// Всё ещё обрабатывается - показываем сообщение
message.info('Заявление формируется. Пожалуйста, подождите.');
} else { } else {
// Обычный переход // ✅ Разрешаем переход на любом этапе до апрува по SMS
onSelectDraft(draftId); onSelectDraft(draftId);
} }
}; };
@@ -286,15 +283,12 @@ export default function StepDraftSelection({
// Кнопка действия // Кнопка действия
const getActionButton = (draft: Draft) => { const getActionButton = (draft: Draft) => {
const config = getStatusConfig(draft); const config = getStatusConfig(draft);
const isProcessing = draft.status_code === 'draft_docs_complete';
return ( return (
<Button <Button
type={isProcessing ? 'default' : 'primary'} type="primary"
onClick={() => handleDraftAction(draft)} onClick={() => handleDraftAction(draft)}
icon={config.icon} icon={config.icon}
disabled={isProcessing}
loading={isProcessing}
> >
{config.action} {config.action}
</Button> </Button>

View File

@@ -107,7 +107,7 @@ export default function ClaimForm() {
const [hasDrafts, setHasDrafts] = useState(false); const [hasDrafts, setHasDrafts] = useState(false);
useEffect(() => { useEffect(() => {
// 🔥 VERSION CHECK: Если видишь это в консоли - фронт обновился! // 🔥 VERSION CHECK: Если видишь это в консоли - фронт обновился!
console.log('🔥 ClaimForm v3.8 - 2025-11-20 15:10 - Fix session_id priority in loadDraft'); console.log('🔥 ClaimForm v3.8 - 2025-11-20 15:10 - Fix session_id priority in loadDraft');
}, []); }, []);
@@ -613,8 +613,13 @@ export default function ClaimForm() {
const hasDocuments = Array.isArray(documentsMeta) && documentsMeta.length > 0; const hasDocuments = Array.isArray(documentsMeta) && documentsMeta.length > 0;
const isDraft = claim.status_code === 'draft'; const isDraft = claim.status_code === 'draft';
// ✅ НОВОЕ: Проверяем наличие form_draft (собранные данные из RAG)
const formDraft = payload.form_draft;
const hasFormDraft = !!(formDraft && formDraft.user && formDraft.offenders);
const isDraftDocsComplete = claim.status_code === 'draft_docs_complete';
const allStepsFilled = hasDescription && hasWizardPlan && hasAnswers && hasDocuments; const allStepsFilled = hasDescription && hasWizardPlan && hasAnswers && hasDocuments;
const isReadyForConfirmation = allStepsFilled && isDraft; const isReadyForConfirmation = (allStepsFilled && isDraft) || (hasFormDraft && isDraftDocsComplete);
console.log('🔍 Проверка полноты черновика:', { console.log('🔍 Проверка полноты черновика:', {
hasDescription, hasDescription,
@@ -622,6 +627,8 @@ export default function ClaimForm() {
hasAnswers, hasAnswers,
hasDocuments, hasDocuments,
isDraft, isDraft,
hasFormDraft,
isDraftDocsComplete,
allStepsFilled, allStepsFilled,
isReadyForConfirmation, isReadyForConfirmation,
problemDescriptionFound: !!problemDescription, problemDescriptionFound: !!problemDescription,
@@ -707,19 +714,60 @@ export default function ClaimForm() {
// ✅ Если все шаги заполнены и статус = draft → переходим к форме подтверждения // ✅ Если все шаги заполнены и статус = draft → переходим к форме подтверждения
if (isReadyForConfirmation) { if (isReadyForConfirmation) {
console.log('✅ Все шаги заполнены, преобразуем данные для формы подтверждения'); console.log('✅ Все шаги заполнены, преобразуем данные для формы подтверждения');
console.log('✅ hasFormDraft:', hasFormDraft, 'isDraftDocsComplete:', isDraftDocsComplete);
setIsPhoneVerified(true); setIsPhoneVerified(true);
// Преобразуем данные из БД в формат propertyName для формы подтверждения let claimPlanData;
const claimPlanData = transformDraftToClaimPlanFormat({
claim, // ✅ НОВОЕ: Если есть form_draft — используем его!
payload, if (hasFormDraft && formDraft) {
body, console.log('✅ Используем form_draft из БД:', formDraft);
isTelegramFormat,
finalClaimId, // Преобразуем form_draft в формат propertyName
actualSessionId, claimPlanData = {
currentFormData: formData, propertyName: {
}); applicant: formDraft.user || {},
case: {
category: formDraft.project?.category || '',
description: formDraft.project?.description || problemDescription || '',
},
contract_or_service: {
subject: formDraft.project?.subject || '',
agrprice: formDraft.project?.agrprice || '',
agrdate: formDraft.project?.agrdate || '',
startdate: formDraft.project?.startdate || '',
finishdate: formDraft.project?.finishdate || '',
country: formDraft.project?.country || '',
hotel: formDraft.project?.hotel || '',
},
offenders: formDraft.offenders || [],
claim: {},
meta: {
claim_id: finalClaimId,
unified_id: formData.unified_id || '',
session_token: actualSessionId,
},
attachments_names: documentsMeta.map((d: any) => d.original_file_name || d.file_name || ''),
},
session_token: actualSessionId,
claim_id: finalClaimId,
prefix: 'clpr_',
};
} else {
// Старый способ: преобразуем данные из БД
claimPlanData = transformDraftToClaimPlanFormat({
claim,
payload,
body,
isTelegramFormat,
finalClaimId,
actualSessionId,
currentFormData: formData,
});
}
console.log('✅ claimPlanData для формы подтверждения:', claimPlanData);
// Сохраняем данные заявления в formData // Сохраняем данные заявления в formData
updateFormData({ updateFormData({
@@ -900,17 +948,17 @@ export default function ClaimForm() {
is_new_project: formData.is_new_project, is_new_project: formData.is_new_project,
// Основные поля формы (для удобства в n8n) // Основные поля формы (для удобства в n8n)
voucher: formData.voucher, voucher: formData.voucher,
phone: formData.phone, phone: formData.phone,
email: formData.email, email: formData.email,
event_type: formData.eventType, event_type: formData.eventType,
payment_method: formData.paymentMethod, payment_method: formData.paymentMethod,
bank_name: formData.bankName, bank_name: formData.bankName,
card_number: formData.cardNumber, card_number: formData.cardNumber,
account_number: formData.accountNumber, account_number: formData.accountNumber,
// Старый блок документов + новые загрузки визарда (пока как есть) // Старый блок документов + новые загрузки визарда (пока как есть)
documents: formData.documents || {}, documents: formData.documents || {},
wizard_uploads: formData.wizardUploads || {}, wizard_uploads: formData.wizardUploads || {},
// Всё состояние формы целиком — на всякий случай // Всё состояние формы целиком — на всякий случай
@@ -1257,19 +1305,19 @@ export default function ClaimForm() {
)} )}
{/* Кнопка "Начать заново" - показываем только после шага телефона */} {/* Кнопка "Начать заново" - показываем только после шага телефона */}
{currentStep > 0 && ( {currentStep > 0 && (
<button <button
onClick={handleReset} onClick={handleReset}
style={{ style={{
padding: '4px 12px', padding: '4px 12px',
background: '#fff', background: '#fff',
border: '1px solid #d9d9d9', border: '1px solid #d9d9d9',
borderRadius: '4px', borderRadius: '4px',
cursor: 'pointer', cursor: 'pointer',
fontSize: '14px' fontSize: '14px'
}} }}
> >
🔄 Начать заново 🔄 Начать заново
</button> </button>
)} )}
</Space> </Space>
) )
@@ -1284,15 +1332,15 @@ export default function ClaimForm() {
</div> </div>
) : ( ) : (
<> <>
<Steps current={currentStep} className="steps"> <Steps current={currentStep} className="steps">
{steps.map((item, index) => ( {steps.map((item, index) => (
<Step <Step
key={`step-${index}`} key={`step-${index}`}
title={item.title} title={item.title}
description={item.description} description={item.description}
/> />
))} ))}
</Steps> </Steps>
<div className="steps-content"> <div className="steps-content">
{steps[currentStep] ? steps[currentStep].content : ( {steps[currentStep] ? steps[currentStep].content : (
<div style={{ padding: '40px 0', textAlign: 'center' }}> <div style={{ padding: '40px 0', textAlign: 'center' }}>