From 17439951a1f47c5e6e22fe58240c2690d4cd7f36 Mon Sep 17 00:00:00 2001 From: Stream Date: Tue, 5 May 2026 22:10:01 +0300 Subject: [PATCH] auto-sync: 2026-05-05 22:10:01 --- tasks/enduro-trails/DEV_TASK_PHASE5_UX2.md | 223 +++++++++++++++++++++ tasks/enduro-trails/PROJECT.md | 8 +- 2 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 tasks/enduro-trails/DEV_TASK_PHASE5_UX2.md diff --git a/tasks/enduro-trails/DEV_TASK_PHASE5_UX2.md b/tasks/enduro-trails/DEV_TASK_PHASE5_UX2.md new file mode 100644 index 0000000..447620e --- /dev/null +++ b/tasks/enduro-trails/DEV_TASK_PHASE5_UX2.md @@ -0,0 +1,223 @@ +# Dev Task: Enduro Trails — UX маршрута + индикатор загрузки + +**Приоритет:** HIGH +**Проект:** enduro-trails +**Дата:** 2026-05-05 + +--- + +## Контекст + +Текущий UX маршрута неудобен: +1. После выбора двух точек автоматически открывается основной sheet — карта скрывается +2. «Добавить точку» в основном sheet не скрывает sheet — карта не видна для тапа +3. Основной sheet открывается сразу, хотя достаточно мини-бара +4. Нет индикатора что маршрут строится — пользователь не понимает что происходит + +**Файлы:** ТОЛЬКО `app.js`, `app.css`, `index.html` (бэкенд НЕ трогать) + +--- + +## Задача 1: Не открывать основной sheet автоматически + +### Текущее поведение +В `initRouteClicks` при добавлении второй точки вызывается `buildRoute()` — который внутри ничего не открывает, НО `toggleRouteMode()` при входе в режим уже открыл sheet через `openSheet('sheet-route')`. + +### Нужное поведение +- Вход в режим маршрута (`toggleRouteMode()`) → **НЕ открывать** `sheet-route` автоматически +- Sheet открывается ТОЛЬКО по явному тапу на мини-бар (уже работает через `showMiniRouteSheet`) +- Маршрут строится в фоне, карта остаётся видна, мини-бар показывает прогресс + +### Изменения в `toggleRouteMode()`: + +```js +function toggleRouteMode() { + const btn = document.getElementById('tb-route'); + + if (routeMode) { + // Если sheet открыт — закрыть sheet (но не выходить из режима) + const sheet = document.getElementById('sheet-route'); + if (sheet && sheet.classList.contains('open')) { + closeSheet('sheet-route'); + return; + } + // Если sheet закрыт — выйти из режима и сбросить маршрут + routeMode = false; + btn.classList.remove('active'); + clearRoute(); + window._map.getCanvas().style.cursor = ''; + } else { + // Войти в режим маршрута — НЕ открывать sheet + deactivateAllModes(); + routeMode = true; + btn.classList.add('active'); + clearRoute(); + window._map.getCanvas().style.cursor = 'crosshair'; + // sheet НЕ открываем — пользователь сам тапнет на мини-бар + } + updateMapModeClass(); +} +``` + +--- + +## Задача 2: «Добавить точку» скрывает sheet + +### В `addWaypointMode()`: + +```js +function addWaypointMode() { + if (routeWaypoints.length >= 10) return; + if (!routeMode) { + routeMode = true; + document.getElementById('tb-route').classList.add('active'); + updateMapModeClass(); + } + addingWaypoint = true; + window._map.getCanvas().style.cursor = 'crosshair'; + // Скрыть основной sheet чтобы карта была видна + closeSheet('sheet-route'); + // Показать подсказку в мини-баре + const statsEl = document.getElementById('mini-stats'); + if (statsEl) statsEl.textContent = 'Тапни на карте для добавления точки'; + document.getElementById('sheet-route-mini').classList.add('visible'); +} +``` + +--- + +## Задача 3: После построения маршрута — только мини-бар + +### В `buildRoute()` — убрать автоматическое открытие sheet, показывать только мини-бар: + +```js +async function buildRoute() { + if (routeWaypoints.length < 2) return; + + // Показать мини-бар с индикатором загрузки + showMiniRouteLoading(); + + // Закрыть основной sheet если открыт + closeSheet('sheet-route'); + + document.getElementById('route-status').textContent = 'Строю маршрут...'; + + try { + const resp = await fetch(...); + // ... существующая логика ... + + drawRouteResults(routeResults, 0); + + // После успеха — показать мини-бар с результатом (НЕ открывать sheet) + showMiniRouteSheet(); + hideMiniRouteLoading(); + document.getElementById('route-status').textContent = `${routeResults.length} маршрут(ов)`; + } catch(e) { + hideMiniRouteLoading(); + document.getElementById('route-status').textContent = '❌ ' + e.message; + // Показать ошибку в мини-баре + const statsEl = document.getElementById('mini-stats'); + if (statsEl) statsEl.textContent = '❌ ' + e.message; + } +} +``` + +--- + +## Задача 4: Индикатор загрузки — колесо мотоцикла + +### Анимация + +В мини-баре (`#sheet-route-mini`) показывать SVG колесо мотоцикла которое крутится пока строится маршрут. + +**SVG колесо (кросс/эндуро стиль — спицы, грунтозацепы):** + +```svg + + + + + + + + + + + + + + + + + +``` + +**CSS анимация:** +```css +.moto-wheel { + width: 32px; height: 32px; + animation: wheelSpin 0.8s linear infinite; + display: none; + flex-shrink: 0; +} +.moto-wheel.spinning { + display: block; +} +@keyframes wheelSpin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} +``` + +### Где показывать + +В `#sheet-route-mini` добавить элемент колеса рядом с `#mini-stats`: + +```html + +... +``` + +**Функции управления:** +```js +function showMiniRouteLoading() { + const wheel = document.getElementById('mini-wheel'); + const statsEl = document.getElementById('mini-stats'); + if (wheel) wheel.classList.add('spinning'); + if (statsEl) statsEl.textContent = 'Строю маршрут...'; + document.getElementById('sheet-route-mini').classList.add('visible'); +} + +function hideMiniRouteLoading() { + const wheel = document.getElementById('mini-wheel'); + if (wheel) wheel.classList.remove('spinning'); +} +``` + +--- + +## Итоговый UX-флоу + +``` +Тап на 🗺 → routeMode=true, cursor=crosshair, sheet НЕ открывается +Тап на карте (точка A) → маркер A, cursor=crosshair +Тап на карте (точка B) → маркер B, мини-бар появляется с крутящимся колесом +Маршрут построен → колесо исчезает, мини-бар показывает "120 км · 87% грунт" +Тап на мини-бар → открывается основной sheet с деталями +Тап «Добавить точку» в sheet → sheet скрывается, карта видна, cursor=crosshair +Тап на карте → точка добавлена, маршрут перестраивается (колесо в мини-баре) +``` + +--- + +## Деплой +``` +/tmp/deploy_static.js +SSH: host=82.22.50.71, port=22, user=slin, pass=motoZ@yaz2010 +Health: curl -s http://mva154:5558/api/health +``` + +## Ограничения +- НЕ трогать `app.py` +- Без npm-зависимостей +- Сохранить всю существующую логику (drag-and-drop, geocoding, GPX, etc.) diff --git a/tasks/enduro-trails/PROJECT.md b/tasks/enduro-trails/PROJECT.md index ae3f496..864aea2 100644 --- a/tasks/enduro-trails/PROJECT.md +++ b/tasks/enduro-trails/PROJECT.md @@ -79,10 +79,10 @@ docker restart prototype-enduro-trails-1 | F-08 | Исключить тротуары | footway/pedestrian/steps убрать из графа | 📋 BRD готов | 3.1 | | F-09 | Больше альтернатив | Penalized re-query + дедупликация | 📋 BRD готов | 3.1 | | F-10 | Слой препятствий | Шлагбаумы, броды, блокпосты на карте | 📋 BRD готов | 3.1 | -| F-11 | "Красивый маршрут" | Замкнутый круг через живописные места, scenic_score, варианты | ✅ Готово | 4 | +| F-11 | "Красивый маршрут" | Замкнутый круг через живописные места, scenic_score, варианты | ⏳ Бэклог | 4 | | F-12 | "Горка" | Макс набор высоты, мин дистанция (SRTM) | ⏳ Бэклог | 6 | -| F-13 | "Связка" | Соединить два трека грунтовками | ✅ Готово | 4 | -| F-14 | "Разведка" | Грунтовки вокруг точки, статистика по типам, POI | ✅ Готово | 4 | +| F-13 | "Связка" | Соединить два трека грунтовками | ⏳ Бэклог | 4 | +| F-14 | "Разведка" | Грунтовки вокруг точки, статистика по типам, POI | ⏳ Бэклог | 4 | | F-15 | "Народные треки" | OSM Traces, Wikiloc, Komoot, 4x4travel | ⏳ Бэклог | 8 | | F-16 | Тёмная тема + редизайн | Две темы (авто/светлая/тёмная), SunCalc, мобильный UI, drag-and-drop точек | ✅ Готово | 5 | | F-17 | PWA + офлайн | Service Worker, MBTiles, GPS-трекинг | ⏳ Бэклог | 7 | @@ -141,7 +141,7 @@ docker restart prototype-enduro-trails-1 - **F-13** «Связка» — соединить два трека грунтовками, альтернативы - **F-14** «Разведка» — грунтовки в радиусе 20/50/100 км, статистика по типам, POI -### ✅ Фаза 4 — Продвинутый роутинг (04.05.2026) +### ⏳ Фаза 4 — Продвинутый роутинг (в разработке) - **F-11** «Красивый маршрут» — замкнутый круг, scenic_score, варианты по дистанции (50/100/150/200 км) - **F-13** «Связка» — соединить два трека грунтовками, альтернативы - **F-14** «Разведка» — грунтовки в радиусе 20/50/100 км, статистика по типам, POI