- Dashboard.jsx: счётчики (активных / всего / завершено за 24ч из
/operations/summary), фильтры по статусу, сетка карточек операций
(title, статус-бейдж, подразделение, время обновления), клик →
рабочее пространство (анализ по карточке операции).
- Роут /dashboard, «/» → дашборд (было /desktop).
- CaseForm: после создания карточки автоматически создаётся поисковая
операция (title «Поиск: имя, N лет») — операция не блокирует анализ.
- VCL-density, палитра ЦОУ (#ff4d00 акценты, статусы цветом).
1. Рекомендации не предписывают перекрывать водоёмы/ж/д — оператор ПРОВЕРЯЕТ
их (правки в rules_analysis, scoring_service ×2 копии, water.py + доки).
2. Геокодирование: район нужен (дубли улиц между районами) — подсказка формата
«пункт, район, адрес» и текст ошибки.
198 passed.
Мобильная версия выпилена — браузерная геолокация оператора больше не
нужна: ТНП задаётся адресом (кнопка «Найти координаты» → geocode) или
вручную. handleGetLocation и его состояния удалены; .gps-button остался
только у геокод-кнопки.
.gps-button { width:100% } в flex-строке съедал всю ширину, input сжимался
до огрызка. Inline width:auto/flexShrink:0 у кнопки и width:auto/minWidth:0
у инпута.
- Step3Circumstances: удалено дублирующее «Последнее известное место»
(last_known_place); остаётся только tnp_address на шаге координат.
- Step4Environment: кнопка «Найти координаты» теперь РАБОЧАЯ — вызывает
новый GET /api/v1/geocode (прокси Nominatim, countrycodes=by, короткий
запрос «пункт, адрес» по граблям geocoding), заполняет lat/lon,
показывает найденный display_name или ошибку. Без debounce-автоплейса
(Pitfall 2) — только явный клик.
- Step3Circumstances: «Прошло времени» считается автоматически из
lost_time (пересчёт каждые 30 с, округление до 0.1 ч); поле остаётся
редактируемым для корректировки.
- БАГФИКС: форма шлёт lost_time, модель хранит loss_time — алиас в
_normalize_case_data. Раньше время пропажи молча терялось
(Pydantic игнорирует неизвестные поля) — elapsed_hours приходилось
вводить руками.
- last_known_place убран из валидации шага 4.
- backend/routers/geocode.py: Nominatim-прокси с auth (operator/field/admin).
192 passed, JSX валиден.
Недостижимые от index.js -> App компоненты (23 файла):
- MobileForm.jsx/.tsx/.css (живая мобильная форма = CaseForm)
- BehavioralProfile.tsx/.css
- AnalysisLayout/, MapView/, ResultPanel/ (MapView/ResultPanel
импортировались только из неиспользуемого AnalysisLayout; живая
карта = SearchMap.jsx)
- admin/ (CaseDetail, CasesList, HeatmapView, Statistics) - AdminDashboard
использует inline-UI, не эти компоненты
- CaseForm/Step5Resources.jsx - не подключён в CaseForm.jsx
Сборка проходит. Мёртвый код с его багами (isPsycotypeSelected опечатка,
хардкод URL, NaN-гварды) уходит вместе с файлами.
Co-Authored-By: Claude <noreply@anthropic.com>
- api/client.js: apiFetch подставляет Bearer-токен, выставляет
Content-Type: application/json для не-FormData тел, ловит 401 -> событие
- context/AuthContext: валидация токена через /auth/me, loading-гейт,
logout(), подписка на 401
- components/ProtectedRoute: guard с ролями и заглушкой на время проверки
- pages/Login: форма входа (OAuth2 form-urlencoded), редирект на from
- App.js: AuthProvider, /login, ProtectedRoute на /sar /desktop
/analysis /admin (admin -> roles=[admin]) /mobile
- AdminDashboard/CaseForm/AnalysisResult: переход на apiFetch
- AdminDashboard: кнопка "Выйти" в шапке (useAuth().logout)
Co-Authored-By: Claude <noreply@anthropic.com>
B7: stop AdminDashboard refetching the case list on selection change
selectedCaseId was both read and written inside the list-loading effect and
listed in its deps, causing a second fetch on first render and after every
filter reset. Auto-select now uses a functional state update, so the effect
no longer depends on selectedCaseId; editForm stays in sync via the existing
selectedCase effect.