215 lines
7.0 KiB
Markdown
215 lines
7.0 KiB
Markdown
# MobileForm - Мобильная форма с психотипом
|
|
|
|
## Описание
|
|
|
|
Компонент `MobileForm.tsx` - мобильная форма для создания карточки пропавшего человека с блоком определения психотипа.
|
|
|
|
## Расположение
|
|
|
|
- **Компонент:** `frontend/src/components/MobileForm.tsx`
|
|
- **Стили:** `frontend/src/components/MobileForm.css`
|
|
|
|
## Структура формы
|
|
|
|
### 1. Основная информация
|
|
- Возраст (число)
|
|
- Пол (мужской/женский)
|
|
|
|
### 2. Диагнозы
|
|
Чекбоксы для выбора:
|
|
- РАС
|
|
- эпилепсия
|
|
- СДВГ
|
|
- деменция
|
|
|
|
### 3. Блок психотипа (необязательный)
|
|
|
|
**Заголовок:** "Поведение ребёнка (спросить родителей)"
|
|
**Подзаголовок:** "Помогает уточнить зону поиска"
|
|
|
|
#### Вопрос 1: Как ведёт себя в незнакомой обстановке?
|
|
- Активно исследует → `unfamiliar_env: 'explore'`
|
|
- Ждёт → `unfamiliar_env: 'wait'`
|
|
- Замирает → `unfamiliar_env: 'freeze'`
|
|
- Паникует → `unfamiliar_env: 'panic'`
|
|
|
|
#### Вопрос 2: Реакция на неудачи?
|
|
- Злится, кричит → `stress_reaction: 'active'`
|
|
- Плачет, замыкается → `stress_reaction: 'cry'`
|
|
- Спокойно ищет выход → `stress_reaction: 'calm'`
|
|
|
|
#### Вопрос 3: Лидер или ведомый?
|
|
- Лидер → `group_role: 'leader'`
|
|
- Иногда → `group_role: 'sometimes'`
|
|
- Всегда ведомый → `group_role: 'follower'`
|
|
|
|
#### Вопрос 4: Любит рисковать?
|
|
- Очень → `risk_taking: 'high'`
|
|
- Иногда → `risk_taking: 'medium'`
|
|
- Нет, осторожный → `risk_taking: 'low'`
|
|
|
|
## Формат данных
|
|
|
|
### Структура FormData
|
|
|
|
```typescript
|
|
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;
|
|
}
|
|
```
|
|
|
|
### Пример отправляемых данных
|
|
|
|
```json
|
|
{
|
|
"age": 8,
|
|
"gender": "male",
|
|
"diagnosis_type": ["РАС"],
|
|
"psychotype_answers": {
|
|
"unfamiliar_env": "freeze",
|
|
"stress_reaction": "cry",
|
|
"group_role": "follower",
|
|
"risk_taking": "low"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Интеграция с API
|
|
|
|
Для определения психотипа нужно отправить `psychotype_answers` на endpoint:
|
|
|
|
```bash
|
|
POST /api/v1/analyze/psychotype
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"stress_reaction": "cry",
|
|
"group_role": "follower",
|
|
"risk_taking": "low",
|
|
"unfamiliar_env": "freeze"
|
|
}
|
|
```
|
|
|
|
**Ответ:**
|
|
```json
|
|
{
|
|
"psychotype": "anxious",
|
|
"modifiers": {
|
|
"zone_0_500": 1.4,
|
|
"zone_500_1500": 1.1,
|
|
"zone_1500_2500": 0.5,
|
|
"zone_2500plus": 0.3,
|
|
"movement_model": "stay"
|
|
},
|
|
"recommendations": {
|
|
"priority_zones": "Ближняя зона (0-500м) - критически важна",
|
|
"search_pattern": "Тщательный осмотр ближайшей территории",
|
|
"key_locations": "Укрытия, углубления, густая растительность",
|
|
"communication": "Спокойные голосовые сигналы"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Дизайн и UX
|
|
|
|
### Touch-friendly кнопки
|
|
- Минимальная высота: **52px** (56px на мобильных)
|
|
- Крупный шрифт: **16px**
|
|
- Увеличенные отступы для удобного нажатия
|
|
- Визуальная обратная связь при нажатии (scale 0.98)
|
|
|
|
### Цветовая схема
|
|
- Выбранная кнопка: `#3498db` (синий)
|
|
- Hover: `#f0f8ff` (светло-голубой фон)
|
|
- Секция психотипа: `#f8f9fa` (светло-серый фон)
|
|
- Кнопка отправки: `#27ae60` (зелёный)
|
|
|
|
### Адаптивность
|
|
- Максимальная ширина: 600px
|
|
- Мобильная оптимизация для экранов < 768px
|
|
- Вертикальное расположение кнопок для удобства на телефоне
|
|
|
|
## Использование
|
|
|
|
### Вариант 1: Standalone компонент
|
|
|
|
```jsx
|
|
import MobileForm from './components/MobileForm';
|
|
|
|
function App() {
|
|
return <MobileForm />;
|
|
}
|
|
```
|
|
|
|
### Вариант 2: С обработкой отправки
|
|
|
|
```jsx
|
|
import MobileForm from './components/MobileForm';
|
|
|
|
function App() {
|
|
const handleSubmit = async (formData) => {
|
|
// Отправка на backend
|
|
const response = await fetch('/api/v1/cases', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(formData)
|
|
});
|
|
|
|
// Если есть psychotype_answers, получаем психотип
|
|
if (formData.psychotype_answers) {
|
|
const psychotypeResponse = await fetch('/api/v1/analyze/psychotype', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(formData.psychotype_answers)
|
|
});
|
|
const psychotypeData = await psychotypeResponse.json();
|
|
console.log('Психотип:', psychotypeData);
|
|
}
|
|
};
|
|
|
|
return <MobileForm onSubmit={handleSubmit} />;
|
|
}
|
|
```
|
|
|
|
## Маппинг ответов на психотипы
|
|
|
|
| Ответы | Психотип | Модель движения |
|
|
|--------|----------|-----------------|
|
|
| active + leader + high | dominant | chaotic_far |
|
|
| calm + leader + low | harmonic | linear_landmark |
|
|
| cry + follower + low | anxious | stay |
|
|
| freeze + follower + low | introvert_passive | stay_hidden |
|
|
| active + leader + medium | introvert_active | linear_landmark |
|
|
|
|
## Валидация
|
|
|
|
- Все поля психотипа **необязательные** - можно пропустить
|
|
- Если заполнен хотя бы один вопрос, рекомендуется заполнить все 4
|
|
- Backend API валидирует значения и вернёт ошибку при невалидных данных
|
|
|
|
## TODO
|
|
|
|
- [ ] Добавить prop `onSubmit` для обработки отправки формы
|
|
- [ ] Интегрировать с реальным API endpoint
|
|
- [ ] Добавить индикатор загрузки при отправке
|
|
- [ ] Показывать результат определения психотипа после отправки
|
|
- [ ] Добавить валидацию на фронтенде
|
|
- [ ] Сохранение черновика в localStorage
|
|
- [ ] Добавить больше полей (местность, погода, обстоятельства)
|
|
|
|
## Связанные файлы
|
|
|
|
- `backend/services/psychotype_service.py` - сервис определения психотипа
|
|
- `backend/api/v1/analyze.py` - API endpoint `/psychotype`
|
|
- `PSYCHOTYPE_API.md` - документация API
|