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
50 lines
2.0 KiB
JavaScript
50 lines
2.0 KiB
JavaScript
// ========================================
|
||
// Code Node: Формирование Response для фронта (безопасная версия с проверками)
|
||
// (перед финальной Response нодой)
|
||
// ========================================
|
||
|
||
// Получаем данные из предыдущих шагов
|
||
const claimResult = $node["CreateWebContact"]?.json?.result || {};
|
||
const sessionDataItem = $('Code in JavaScript1')?.first();
|
||
const sessionData = sessionDataItem?.json?.redis_value
|
||
? JSON.parse(sessionDataItem.json.redis_value)
|
||
: {};
|
||
const userData = $node["user_get"]?.json || {}; // ← Данные из PostgreSQL: Find or Create User
|
||
|
||
// Проверяем наличие unified_id (критически важно!)
|
||
if (!userData.unified_id) {
|
||
console.error('❌ ОШИБКА: unified_id не получен из ноды user_get!');
|
||
// Можно либо выбросить ошибку, либо продолжить без unified_id (не рекомендуется)
|
||
}
|
||
|
||
// Формируем ответ в формате, который ожидает фронт
|
||
return {
|
||
success: true,
|
||
result: {
|
||
claim_id: sessionData.claim_id || claimResult.claim_id,
|
||
contact_id: sessionData.contact_id || claimResult.contact_id,
|
||
project_id: sessionData.project_id,
|
||
|
||
// Unified ID из PostgreSQL (обязательно!)
|
||
unified_id: userData.unified_id, // из ноды user_get (PostgreSQL: Find or Create User)
|
||
|
||
// Данные заявки
|
||
ticket_id: claimResult.ticket_id,
|
||
ticket_number: claimResult.ticket_number,
|
||
title: claimResult.title,
|
||
category: claimResult.category,
|
||
status: claimResult.status,
|
||
|
||
// Метаданные
|
||
event_type: sessionData.event_type,
|
||
current_step: sessionData.current_step || 1,
|
||
updated_at: sessionData.updated_at || new Date().toISOString(),
|
||
|
||
// Дополнительно
|
||
is_new_contact: claimResult.is_new_contact || false
|
||
}
|
||
};
|
||
|
||
|
||
|