feat(frontend): использование form_draft для формы подтверждения
- StepDraftSelection: кнопка 'Продолжить' активна для draft_docs_complete - ClaimForm: проверка form_draft при загрузке черновика - Если есть form_draft — преобразуем в propertyName и показываем форму подтверждения - Поддержка статуса draft_docs_complete для перехода к подтверждению
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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' }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user