Files
aiform_dev/frontend/src/components/form/StepClaimConfirmation.tsx

236 lines
7.6 KiB
TypeScript
Raw Normal View History

feat: Add claim plan confirmation flow via Redis SSE Problem: - After wizard form submission, need to wait for claim data from n8n - Claim data comes via Redis channel claim:plan:{session_token} - Need to display confirmation form with claim data Solution: 1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token} - Subscribes to Redis channel claim:plan:{session_token} - Streams claim data from n8n to frontend - Handles timeouts and errors gracefully 2. Frontend: Added subscription to claim:plan channel - StepWizardPlan: After form submission, subscribes to SSE - Waits for claim_plan_ready event - Shows loading message while waiting - On success: saves claimPlanData and shows confirmation step 3. New component: StepClaimConfirmation - Displays claim confirmation form in iframe - Receives claimPlanData from parent - Generates HTML form (placeholder - should call n8n for real HTML) - Handles confirmation/cancellation via postMessage 4. ClaimForm: Added conditional step for confirmation - Shows StepClaimConfirmation when showClaimConfirmation=true - Step appears after StepWizardPlan - Only visible when claimPlanData is available Flow: 1. User fills wizard form → submits 2. Form data sent to n8n via /api/v1/claims/wizard 3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token} 4. n8n processes data → publishes to Redis claim:plan:{session_token} 5. Backend receives → streams to frontend via SSE 6. Frontend receives → shows StepClaimConfirmation 7. User confirms → proceeds to next step Files: - backend/app/api/events.py: Added stream_claim_plan endpoint - frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan - frontend/src/components/form/StepClaimConfirmation.tsx: New component - frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00
import { useEffect, useRef, useState } from 'react';
import { Card, Spin, message } from 'antd';
interface Props {
claimPlanData: any; // Данные заявления от n8n
onNext: () => void;
onPrev: () => void;
}
export default function StepClaimConfirmation({
claimPlanData,
onNext,
onPrev,
}: Props) {
const [loading, setLoading] = useState(true);
const iframeRef = useRef<HTMLIFrameElement>(null);
const [htmlContent, setHtmlContent] = useState<string>('');
useEffect(() => {
if (!claimPlanData) {
message.error('Данные заявления не получены');
return;
}
console.log('📋 StepClaimConfirmation: получены данные claimPlanData:', claimPlanData);
console.log('📋 claimPlanData.claim_id:', claimPlanData?.claim_id);
console.log('📋 claimPlanData.unified_id:', claimPlanData?.unified_id);
console.log('📋 claimPlanData.propertyName?.meta?.claim_id:', claimPlanData?.propertyName?.meta?.claim_id);
console.log('📋 claimPlanData.propertyName?.meta?.unified_id:', claimPlanData?.propertyName?.meta?.unified_id);
feat: Add claim plan confirmation flow via Redis SSE Problem: - After wizard form submission, need to wait for claim data from n8n - Claim data comes via Redis channel claim:plan:{session_token} - Need to display confirmation form with claim data Solution: 1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token} - Subscribes to Redis channel claim:plan:{session_token} - Streams claim data from n8n to frontend - Handles timeouts and errors gracefully 2. Frontend: Added subscription to claim:plan channel - StepWizardPlan: After form submission, subscribes to SSE - Waits for claim_plan_ready event - Shows loading message while waiting - On success: saves claimPlanData and shows confirmation step 3. New component: StepClaimConfirmation - Displays claim confirmation form in iframe - Receives claimPlanData from parent - Generates HTML form (placeholder - should call n8n for real HTML) - Handles confirmation/cancellation via postMessage 4. ClaimForm: Added conditional step for confirmation - Shows StepClaimConfirmation when showClaimConfirmation=true - Step appears after StepWizardPlan - Only visible when claimPlanData is available Flow: 1. User fills wizard form → submits 2. Form data sent to n8n via /api/v1/claims/wizard 3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token} 4. n8n processes data → publishes to Redis claim:plan:{session_token} 5. Backend receives → streams to frontend via SSE 6. Frontend receives → shows StepClaimConfirmation 7. User confirms → proceeds to next step Files: - backend/app/api/events.py: Added stream_claim_plan endpoint - frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan - frontend/src/components/form/StepClaimConfirmation.tsx: New component - frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00
// Формируем данные для формы подтверждения
// Формат должен соответствовать тому, что ожидает HTML форма
const claimId = claimPlanData?.claim_id || claimPlanData?.propertyName?.meta?.claim_id || '';
const unifiedId = claimPlanData?.unified_id || claimPlanData?.propertyName?.meta?.unified_id || '';
console.log('📋 Извлечённые ID:', { claimId, unifiedId });
feat: Add claim plan confirmation flow via Redis SSE Problem: - After wizard form submission, need to wait for claim data from n8n - Claim data comes via Redis channel claim:plan:{session_token} - Need to display confirmation form with claim data Solution: 1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token} - Subscribes to Redis channel claim:plan:{session_token} - Streams claim data from n8n to frontend - Handles timeouts and errors gracefully 2. Frontend: Added subscription to claim:plan channel - StepWizardPlan: After form submission, subscribes to SSE - Waits for claim_plan_ready event - Shows loading message while waiting - On success: saves claimPlanData and shows confirmation step 3. New component: StepClaimConfirmation - Displays claim confirmation form in iframe - Receives claimPlanData from parent - Generates HTML form (placeholder - should call n8n for real HTML) - Handles confirmation/cancellation via postMessage 4. ClaimForm: Added conditional step for confirmation - Shows StepClaimConfirmation when showClaimConfirmation=true - Step appears after StepWizardPlan - Only visible when claimPlanData is available Flow: 1. User fills wizard form → submits 2. Form data sent to n8n via /api/v1/claims/wizard 3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token} 4. n8n processes data → publishes to Redis claim:plan:{session_token} 5. Backend receives → streams to frontend via SSE 6. Frontend receives → shows StepClaimConfirmation 7. User confirms → proceeds to next step Files: - backend/app/api/events.py: Added stream_claim_plan endpoint - frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan - frontend/src/components/form/StepClaimConfirmation.tsx: New component - frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00
const formData = {
case: {
user: claimPlanData?.propertyName?.applicant || {},
project: claimPlanData?.propertyName?.case || {},
offenders: claimPlanData?.propertyName?.offenders || [],
attachments: claimPlanData?.propertyName?.attachments_names || [],
meta: {
...claimPlanData?.propertyName?.meta,
session_token: claimPlanData?.session_token || '',
prefix: claimPlanData?.prefix || '',
telegram_id: claimPlanData?.telegram_id || '',
claim_id: claimId,
unified_id: unifiedId,
feat: Add claim plan confirmation flow via Redis SSE Problem: - After wizard form submission, need to wait for claim data from n8n - Claim data comes via Redis channel claim:plan:{session_token} - Need to display confirmation form with claim data Solution: 1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token} - Subscribes to Redis channel claim:plan:{session_token} - Streams claim data from n8n to frontend - Handles timeouts and errors gracefully 2. Frontend: Added subscription to claim:plan channel - StepWizardPlan: After form submission, subscribes to SSE - Waits for claim_plan_ready event - Shows loading message while waiting - On success: saves claimPlanData and shows confirmation step 3. New component: StepClaimConfirmation - Displays claim confirmation form in iframe - Receives claimPlanData from parent - Generates HTML form (placeholder - should call n8n for real HTML) - Handles confirmation/cancellation via postMessage 4. ClaimForm: Added conditional step for confirmation - Shows StepClaimConfirmation when showClaimConfirmation=true - Step appears after StepWizardPlan - Only visible when claimPlanData is available Flow: 1. User fills wizard form → submits 2. Form data sent to n8n via /api/v1/claims/wizard 3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token} 4. n8n processes data → publishes to Redis claim:plan:{session_token} 5. Backend receives → streams to frontend via SSE 6. Frontend receives → shows StepClaimConfirmation 7. User confirms → proceeds to next step Files: - backend/app/api/events.py: Added stream_claim_plan endpoint - frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan - frontend/src/components/form/StepClaimConfirmation.tsx: New component - frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00
user_id: claimPlanData?.user_id || claimPlanData?.propertyName?.meta?.user_id || '',
},
},
session_token: claimPlanData?.session_token || '',
telegram_id: claimPlanData?.telegram_id || '',
token: claimPlanData?.token || '',
sms_meta: {
session_token: claimPlanData?.session_token || '',
prefix: claimPlanData?.prefix || '',
telegram_id: claimPlanData?.telegram_id || '',
claim_id: claimId,
unified_id: unifiedId,
feat: Add claim plan confirmation flow via Redis SSE Problem: - After wizard form submission, need to wait for claim data from n8n - Claim data comes via Redis channel claim:plan:{session_token} - Need to display confirmation form with claim data Solution: 1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token} - Subscribes to Redis channel claim:plan:{session_token} - Streams claim data from n8n to frontend - Handles timeouts and errors gracefully 2. Frontend: Added subscription to claim:plan channel - StepWizardPlan: After form submission, subscribes to SSE - Waits for claim_plan_ready event - Shows loading message while waiting - On success: saves claimPlanData and shows confirmation step 3. New component: StepClaimConfirmation - Displays claim confirmation form in iframe - Receives claimPlanData from parent - Generates HTML form (placeholder - should call n8n for real HTML) - Handles confirmation/cancellation via postMessage 4. ClaimForm: Added conditional step for confirmation - Shows StepClaimConfirmation when showClaimConfirmation=true - Step appears after StepWizardPlan - Only visible when claimPlanData is available Flow: 1. User fills wizard form → submits 2. Form data sent to n8n via /api/v1/claims/wizard 3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token} 4. n8n processes data → publishes to Redis claim:plan:{session_token} 5. Backend receives → streams to frontend via SSE 6. Frontend receives → shows StepClaimConfirmation 7. User confirms → proceeds to next step Files: - backend/app/api/events.py: Added stream_claim_plan endpoint - frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan - frontend/src/components/form/StepClaimConfirmation.tsx: New component - frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00
user_id: claimPlanData?.user_id || claimPlanData?.propertyName?.meta?.user_id || '',
},
};
console.log('📋 Сформированные formData.meta:', formData.case.meta);
feat: Add claim plan confirmation flow via Redis SSE Problem: - After wizard form submission, need to wait for claim data from n8n - Claim data comes via Redis channel claim:plan:{session_token} - Need to display confirmation form with claim data Solution: 1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token} - Subscribes to Redis channel claim:plan:{session_token} - Streams claim data from n8n to frontend - Handles timeouts and errors gracefully 2. Frontend: Added subscription to claim:plan channel - StepWizardPlan: After form submission, subscribes to SSE - Waits for claim_plan_ready event - Shows loading message while waiting - On success: saves claimPlanData and shows confirmation step 3. New component: StepClaimConfirmation - Displays claim confirmation form in iframe - Receives claimPlanData from parent - Generates HTML form (placeholder - should call n8n for real HTML) - Handles confirmation/cancellation via postMessage 4. ClaimForm: Added conditional step for confirmation - Shows StepClaimConfirmation when showClaimConfirmation=true - Step appears after StepWizardPlan - Only visible when claimPlanData is available Flow: 1. User fills wizard form → submits 2. Form data sent to n8n via /api/v1/claims/wizard 3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token} 4. n8n processes data → publishes to Redis claim:plan:{session_token} 5. Backend receives → streams to frontend via SSE 6. Frontend receives → shows StepClaimConfirmation 7. User confirms → proceeds to next step Files: - backend/app/api/events.py: Added stream_claim_plan endpoint - frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan - frontend/src/components/form/StepClaimConfirmation.tsx: New component - frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00
// Здесь нужно будет получить HTML форму от n8n или использовать готовый шаблон
// Пока используем заглушку - в реальности нужно будет вызывать n8n workflow для генерации HTML
const html = generateConfirmationFormHTML(formData);
setHtmlContent(html);
setLoading(false);
}, [claimPlanData]);
// Функция генерации HTML формы (временная заглушка)
// В реальности это должен делать n8n workflow
const generateConfirmationFormHTML = (data: any): string => {
// Экранируем данные для безопасной вставки в HTML
const caseJson = JSON.stringify(data)
.replace(/</g, '\\u003c')
.replace(/>/g, '\\u003e');
return `<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Подтверждение данных</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 24px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #1f2937;
margin-bottom: 24px;
}
.info {
background: #f0f9ff;
border: 1px solid #bae6fd;
border-radius: 6px;
padding: 16px;
margin-bottom: 24px;
}
.info p {
margin: 8px 0;
color: #1e40af;
}
.button-group {
display: flex;
gap: 12px;
margin-top: 24px;
justify-content: center;
}
button {
padding: 12px 24px;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
font-weight: 600;
}
.btn-primary {
background: #3b82f6;
color: white;
}
.btn-primary:hover {
background: #2563eb;
}
.btn-secondary {
background: #e5e7eb;
color: #374151;
}
.btn-secondary:hover {
background: #d1d5db;
}
</style>
</head>
<body>
<div class="container">
<h1>📋 Подтверждение данных заявления</h1>
<div class="info">
<p><strong>Статус:</strong> Данные заявления получены</p>
<p><strong>Claim ID:</strong> ${data.case?.meta?.claim_id || 'не указан'}</p>
<p><strong>Unified ID:</strong> ${data.case?.meta?.unified_id || 'не указан'}</p>
</div>
<div class="button-group">
<button class="btn-primary" onclick="window.parent.postMessage({type: 'claim_confirmed'}, '*')">
Подтвердить и отправить
</button>
<button class="btn-secondary" onclick="window.parent.postMessage({type: 'claim_cancelled'}, '*')">
Отмена
</button>
</div>
</div>
<script id="case-data" type="application/json">${caseJson}</script>
<script>
// Слушаем сообщения от родительского окна
window.addEventListener('message', function(event) {
console.log('Message received:', event.data);
});
// Отправляем сообщение родителю при загрузке
window.parent.postMessage({type: 'claim_form_loaded'}, '*');
</script>
</body>
</html>`;
};
useEffect(() => {
// Слушаем сообщения от iframe
const handleMessage = (event: MessageEvent) => {
console.log('📨 Message from iframe:', event.data);
if (event.data.type === 'claim_confirmed') {
message.success('Заявление подтверждено!');
onNext();
} else if (event.data.type === 'claim_cancelled') {
message.info('Подтверждение отменено');
onPrev();
} else if (event.data.type === 'claim_form_loaded') {
setLoading(false);
}
};
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
};
}, [onNext, onPrev]);
if (loading) {
return (
<Card>
<div style={{ textAlign: 'center', padding: '40px' }}>
<Spin size="large" />
<p style={{ marginTop: '16px' }}>Загрузка формы подтверждения...</p>
</div>
</Card>
);
}
return (
<Card>
<iframe
ref={iframeRef}
srcDoc={htmlContent}
style={{
width: '100%',
height: '800px',
border: 'none',
borderRadius: '8px',
}}
title="Форма подтверждения заявления"
/>
</Card>
);
}