Import Vector lab project
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
import React, { useState } from "react";
|
||||
import Step1Child from "./Step1Child";
|
||||
import Step2Health from "./Step2Health";
|
||||
import Step2bPsychotype from "./Step2bPsychotype";
|
||||
import Step3Circumstances from "./Step3Circumstances";
|
||||
import Step4Environment from "./Step4Environment";
|
||||
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 [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("Укажите дату и время потери");
|
||||
}
|
||||
if (!formData.last_known_place) {
|
||||
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 fetch("/api/v1/cases", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.detail || "Ошибка при создании карточки");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log("Case created:", result);
|
||||
|
||||
// Перенаправляем на страницу анализа с ID карточки
|
||||
window.location.href = `/analysis/${result.id}`;
|
||||
|
||||
} catch (err) {
|
||||
setErrors([err.message || "Ошибка при отправке данных"]);
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
const renderStep = () => {
|
||||
// Мобильная версия: 3 шага
|
||||
// 1 = Ребёнок, 2 = Здоровье, 3 = Обстоятельства
|
||||
if (isMobile) {
|
||||
switch (currentStep) {
|
||||
case 1: return <Step1Child data={formData} updateData={updateFormData} />;
|
||||
case 2: return <Step2Health data={formData} updateData={updateFormData} />;
|
||||
case 3: return <Step3Circumstances data={formData} updateData={updateFormData} />;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Десктопная версия: 5 шагов
|
||||
// 1 = Ребёнок, 2 = Здоровье, 3 = Психотип, 4 = Обстоятельства, 5 = Среда
|
||||
switch (currentStep) {
|
||||
case 1: return <Step1Child data={formData} updateData={updateFormData} />;
|
||||
case 2: return <Step2Health data={formData} updateData={updateFormData} />;
|
||||
case 3: return <Step2bPsychotype data={formData} updateData={updateFormData} />;
|
||||
case 4: return <Step3Circumstances data={formData} updateData={updateFormData} />;
|
||||
case 5: return <Step4Environment data={formData} updateData={updateFormData} />;
|
||||
default: return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="case-form">
|
||||
<div className="form-header">
|
||||
<h1>Карточка поиска</h1>
|
||||
<div className="step-indicator">
|
||||
Шаг {currentStep} из {totalSteps}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{errors.length > 0 && (
|
||||
<div className="error-banner">
|
||||
{errors.map((err, idx) => (
|
||||
<div key={idx}>{err}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="form-content">
|
||||
{renderStep()}
|
||||
</div>
|
||||
|
||||
<div className="form-navigation">
|
||||
{currentStep > 1 && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn-secondary"
|
||||
onClick={handleBack}
|
||||
disabled={submitting}
|
||||
>
|
||||
Назад
|
||||
</button>
|
||||
)}
|
||||
|
||||
{currentStep < totalSteps ? (
|
||||
<button
|
||||
type="button"
|
||||
className="btn-primary"
|
||||
onClick={handleNext}
|
||||
disabled={submitting}
|
||||
>
|
||||
Далее
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
className="btn-primary submit-btn"
|
||||
onClick={handleSubmit}
|
||||
disabled={submitting}
|
||||
>
|
||||
{submitting ? "Создание карточки..." : "Создать карточку"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CaseForm;
|
||||
Reference in New Issue
Block a user