Import Vector lab project
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
import React, { useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import './MobileForm.css';
|
||||
|
||||
interface PsychotypeAnswers {
|
||||
unfamiliar_env?: string;
|
||||
stress_reaction?: string;
|
||||
group_role?: string;
|
||||
risk_taking?: string;
|
||||
}
|
||||
|
||||
interface FormData {
|
||||
age?: number;
|
||||
gender?: string;
|
||||
diagnosis_type?: string[];
|
||||
psychotype_answers?: PsychotypeAnswers;
|
||||
}
|
||||
|
||||
const MobileForm: React.FC = () => {
|
||||
const [formData, setFormData] = useState<FormData>({
|
||||
diagnosis_type: [],
|
||||
psychotype_answers: {}
|
||||
});
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [success, setSuccess] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const handlePsychotypeAnswer = (question: keyof PsychotypeAnswers, value: string) => {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
psychotype_answers: {
|
||||
...prev.psychotype_answers,
|
||||
[question]: value
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
const isPsychotypeSelected = (question: keyof PsychotypeAnswers, value: string) => {
|
||||
return formData.psychotype_answers?.[question] === value;
|
||||
};
|
||||
|
||||
const validateForm = (): string | null => {
|
||||
if (!formData.age || formData.age < 0 || formData.age > 120) {
|
||||
return 'Укажите корректный возраст';
|
||||
}
|
||||
if (!formData.gender) {
|
||||
return 'Выберите пол';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const validationError = validateForm();
|
||||
if (validationError) {
|
||||
setError(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await axios.post('/api/v1/cases', formData);
|
||||
console.log('Case created:', response.data);
|
||||
setSuccess(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setFormData({
|
||||
diagnosis_type: [],
|
||||
psychotype_answers: {}
|
||||
});
|
||||
setSuccess(false);
|
||||
}, 2000);
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.detail || 'Ошибка при создании карточки');
|
||||
console.error('Submit error:', err);
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (success) {
|
||||
return (
|
||||
<div className="mobile-form">
|
||||
<div className="success-message">
|
||||
<div className="success-icon">✓</div>
|
||||
<h2>Карточка создана!</h2>
|
||||
<p>Данные успешно сохранены</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mobile-form">
|
||||
<h1>Карточка пропавшего</h1>
|
||||
|
||||
{error && (
|
||||
<div className="error-banner">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<section className="form-section">
|
||||
<h2>Основная информация</h2>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Возраст *</label>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="Лет"
|
||||
value={formData.age || ''}
|
||||
onChange={(e) => setFormData({...formData, age: parseInt(e.target.value)})}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Пол *</label>
|
||||
<div className="button-group">
|
||||
<button
|
||||
type="button"
|
||||
className={formData.gender === 'male' ? 'selected' : ''}
|
||||
onClick={() => setFormData({...formData, gender: 'male'})}
|
||||
>
|
||||
Мужской
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={formData.gender === 'female' ? 'selected' : ''}
|
||||
onClick={() => setFormData({...formData, gender: 'female'})}
|
||||
>
|
||||
Женский
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="form-section">
|
||||
<h2>Диагнозы (если есть)</h2>
|
||||
<div className="checkbox-group">
|
||||
{['РАС', 'эпилепсия', 'СДВГ', 'деменция'].map(diagnosis => (
|
||||
<label key={diagnosis} className="checkbox-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.diagnosis_type?.includes(diagnosis)}
|
||||
onChange={(e) => {
|
||||
const current = formData.diagnosis_type || [];
|
||||
setFormData({
|
||||
...formData,
|
||||
diagnosis_type: e.target.checked
|
||||
? [...current, diagnosis]
|
||||
: current.filter(d => d !== diagnosis)
|
||||
});
|
||||
}}
|
||||
/>
|
||||
{diagnosis}
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="form-section psychotype-section">
|
||||
<div className="section-header">
|
||||
<h2>Поведение ребёнка (спросить родителей)</h2>
|
||||
<p className="section-subtitle">Помогает уточнить зону поиска</p>
|
||||
</div>
|
||||
|
||||
<div className="psychotype-question">
|
||||
<label className="question-label">Как ведёт себя в незнакомой обстановке?</label>
|
||||
<div className="button-group-vertical">
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('unfamiliar_env', 'explore') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('unfamiliar_env', 'explore')}
|
||||
>
|
||||
Активно исследует
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('unfamiliar_env', 'wait') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('unfamiliar_env', 'wait')}
|
||||
>
|
||||
Ждёт
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('unfamiliar_env', 'freeze') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('unfamiliar_env', 'freeze')}
|
||||
>
|
||||
Замирает
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('unfamiliar_env', 'panic') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('unfamiliar_env', 'panic')}
|
||||
>
|
||||
Паникует
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="psychotype-question">
|
||||
<label className="question-label">Реакция на неудачи?</label>
|
||||
<div className="button-group-vertical">
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('stress_reaction', 'active') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('stress_reaction', 'active')}
|
||||
>
|
||||
Злится, кричит
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('stress_reaction', 'cry') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('stress_reaction', 'cry')}
|
||||
>
|
||||
Плачет, замыкается
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('stress_reaction', 'calm') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('stress_reaction', 'calm')}
|
||||
>
|
||||
Спокойно ищет выход
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="psychotype-question">
|
||||
<label className="question-label">Лидер или ведомый?</label>
|
||||
<div className="button-group-vertical">
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('group_role', 'leader') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('group_role', 'leader')}
|
||||
>
|
||||
Лидер
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('group_role', 'sometimes') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('group_role', 'sometimes')}
|
||||
>
|
||||
Иногда
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('group_role', 'follower') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('group_role', 'follower')}
|
||||
>
|
||||
Всегда ведомый
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="psychotype-question">
|
||||
<label className="question-label">Любит рисковать?</label>
|
||||
<div className="button-group-vertical">
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('risk_taking', 'high') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('risk_taking', 'high')}
|
||||
>
|
||||
Очень
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsycotypeSelected('risk_taking', 'medium') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('risk_taking', 'medium')}
|
||||
>
|
||||
Иногда
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={'psychotype-btn ' + (isPsychotypeSelected('risk_taking', 'low') ? 'selected' : '')}
|
||||
onClick={() => handlePsychotypeAnswer('risk_taking', 'low')}
|
||||
>
|
||||
Нет, осторожный
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button
|
||||
className="submit-btn"
|
||||
onClick={handleSubmit}
|
||||
disabled={submitting}
|
||||
>
|
||||
{submitting ? 'Создание...' : 'Создать карточку'}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobileForm;
|
||||
Reference in New Issue
Block a user