import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import Step1Child from "./Step1Child"; import Step2Health from "./Step2Health"; import Step2bPsychotype from "./Step2bPsychotype"; import Step3Circumstances from "./Step3Circumstances"; import Step4Environment from "./Step4Environment"; import { apiFetch } from "../../api/client"; import "./CaseForm.css"; const INITIAL_DATA = { has_diagnosis: false, diagnosis_type: [], cant_swim: false, terrain: [], has_dog: false, extra_resources: [] }; const CaseForm = ({ isMobile = false }) => { const navigate = useNavigate(); const [currentStep, setCurrentStep] = useState(1); const [formData, setFormData] = useState(INITIAL_DATA); const [errors, setErrors] = useState([]); const [submitting, setSubmitting] = useState(false); // Мобильная: 3 шага, Десктоп: 5 шагов const totalSteps = isMobile ? 3 : 5; const updateFormData = (updates) => { setFormData(prev => ({ ...prev, ...updates })); }; const validateStep = (step) => { const newErrors = []; if (step === 1) { if (!formData.age_years || formData.age_years < 0 || formData.age_years > 120) { newErrors.push("Укажите корректный возраст"); } if (!formData.gender) { newErrors.push("Выберите пол"); } } // Для десктопа: Шаг 4 = Обстоятельства if (step === 4 && !isMobile) { if (!formData.reason) { newErrors.push("Укажите причину потери"); } if (!formData.lost_time) { newErrors.push("Укажите дату и время потери"); } } // Для десктопа: Шаг 5 = Среда и местность if (step === 5 && !isMobile) { if (!formData.terrain || formData.terrain.length === 0) { newErrors.push("Выберите хотя бы один тип местности"); } if (!formData.tnp_lat || !formData.tnp_lon) { newErrors.push("Укажите GPS координаты точки потери"); } } // Для мобильной: Шаг 3 = Обстоятельства (с GPS) if (step === 3 && isMobile) { if (!formData.reason) { newErrors.push("Укажите причину потери"); } if (!formData.tnp_lat || !formData.tnp_lon) { newErrors.push("Укажите GPS координаты ТНП"); } } setErrors(newErrors); return newErrors.length === 0; }; const handleNext = () => { if (validateStep(currentStep)) { setCurrentStep(prev => Math.min(prev + 1, totalSteps)); } }; const handleBack = () => { setCurrentStep(prev => Math.max(prev - 1, 1)); }; const handleSubmit = async () => { if (!validateStep(currentStep)) return; setSubmitting(true); setErrors([]); try { const payload = { ...formData, clothes_description: [ formData.clothes_upper, formData.clothes_lower, formData.clothes_shoes ].filter(Boolean).join(", ") }; // Создаем карточку const response = await apiFetch("/api/v1/cases", { method: "POST", body: JSON.stringify(payload) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || "Ошибка при создании карточки"); } const result = await response.json(); // E3: автоматически создаём поисковую операцию для карточки. try { await apiFetch('/api/v1/operations', { method: 'POST', body: JSON.stringify({ title: `Поиск: ${formData.child_name || 'без имени'}, ${formData.age_years || '?'} лет`, case_id: result.id, }), }); } catch { /* Операция не блокирует анализ (создастся позже вручную) */ } // Перенаправляем на страницу анализа с ID карточки. // SPA-переход: полная перезагрузка теряла состояние приложения. navigate(`/analysis/${result.id}`); } catch (err) { setErrors([err.message || "Ошибка при отправке данных"]); } finally { setSubmitting(false); } }; const renderStep = () => { // Мобильная версия: 3 шага // 1 = Ребёнок, 2 = Здоровье, 3 = Обстоятельства if (isMobile) { switch (currentStep) { case 1: return ; case 2: return ; case 3: return ; default: return null; } } // Десктопная версия: 5 шагов // 1 = Ребёнок, 2 = Здоровье, 3 = Психотип, 4 = Обстоятельства, 5 = Среда switch (currentStep) { case 1: return ; case 2: return ; case 3: return ; case 4: return ; case 5: return ; default: return null; } }; return (

Карточка поиска

Шаг {currentStep} из {totalSteps}
{errors.length > 0 && (
{errors.map((err, idx) => (
{err}
))}
)}
{renderStep()}
{currentStep > 1 && ( )} {currentStep < totalSteps ? ( ) : ( )}
); }; export default CaseForm;