From d86fc267f8f631a8f34dbc8c5bd213a0932d917a Mon Sep 17 00:00:00 2001 From: Stream Date: Tue, 5 May 2026 22:30:06 +0300 Subject: [PATCH] auto-sync: 2026-05-05 22:30:01 --- tasks/enduro-trails/DEV_TASK_PHASE5_UX3.md | 133 +++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tasks/enduro-trails/DEV_TASK_PHASE5_UX3.md diff --git a/tasks/enduro-trails/DEV_TASK_PHASE5_UX3.md b/tasks/enduro-trails/DEV_TASK_PHASE5_UX3.md new file mode 100644 index 0000000..2748702 --- /dev/null +++ b/tasks/enduro-trails/DEV_TASK_PHASE5_UX3.md @@ -0,0 +1,133 @@ +# Dev Task: Enduro Trails — UX маршрута дополнение (drag + дистанции) + +**Приоритет:** HIGH +**Проект:** enduro-trails +**Дата:** 2026-05-05 +**Дополнение к:** DEV_TASK_PHASE5_UX2.md + +--- + +## Задача 5: Drag точек в основном sheet — не закрывать sheet + +### Проблема +Сейчас в `_initWaypointDragHandles` после drop вызывается `debounceBuildRoute()` — это нормально. Но где-то в цепочке sheet закрывается. + +### Нужное поведение +При перетаскивании точек в `#waypoints-list` (основной sheet открыт): +- Sheet остаётся открытым +- Маршрут пересчитывается в фоне (колесо в мини-баре) +- После пересчёта — обновить карточки маршрута прямо в открытом sheet + +### Изменения + +В `endDrag()` внутри `_initWaypointDragHandles`: +```js +function endDrag(finalClientY) { + if (dragIdx < 0) return; + clearHighlights(); + const dy = Math.abs(finalClientY - startY); + + if (dragging && dy > 30 && lastOverEl !== null) { + const dropIdx = parseInt(lastOverEl.dataset.idx, 10); + let insertAt = lastOverPos === 'top' ? dropIdx : dropIdx + 1; + const moved = routeWaypoints.splice(dragIdx, 1)[0]; + if (insertAt > dragIdx) insertAt--; + routeWaypoints.splice(insertAt, 0, moved); + rebuildWaypointMarkers(); + renderWaypointsList(); + // НЕ закрывать sheet — просто пересчитать маршрут + if (routeWaypoints.length >= 2) { + showMiniRouteLoading(); // колесо в мини-баре + debounceBuildRoute(); + } + updateMiniRouteCard(); + } + + dragIdx = -1; + dragging = false; + lastOverEl = null; + lastOverPos = null; +} +``` + +В `buildRoute()` — после успешного построения, если основной sheet открыт, обновить карточки без закрытия: +```js +// После drawRouteResults(routeResults, 0): +const sheetOpen = document.getElementById('sheet-route')?.classList.contains('open'); +if (sheetOpen) { + renderRouteCards(routeResults); // обновить карточки в открытом sheet +} else { + showMiniRouteSheet(); // показать мини-бар +} +hideMiniRouteLoading(); +``` + +--- + +## Задача 6: Расстояние между точками в wl-item + +### Нужное поведение +В каждом `wl-item` (кроме первой точки) показывать расстояние от предыдущей точки. + +Формат: +- < 1 км → "130 м" +- ≥ 1 км → "2,3 км" (запятая как разделитель) + +### Реализация + +Добавить функцию форматирования дистанции между точками: +```js +function formatSegmentDist(m) { + if (m < 1000) return Math.round(m) + ' м'; + return (m / 1000).toFixed(1).replace('.', ',') + ' км'; +} +``` + +Использовать haversine для расчёта расстояния между соседними точками: +```js +function haversineM(a, b) { + const R = 6371000; + const dLat = (b.lat - a.lat) * Math.PI / 180; + const dLon = (b.lon - a.lon) * Math.PI / 180; + const s = Math.sin(dLat/2)**2 + Math.cos(a.lat*Math.PI/180) * Math.cos(b.lat*Math.PI/180) * Math.sin(dLon/2)**2; + return R * 2 * Math.atan2(Math.sqrt(s), Math.sqrt(1-s)); +} +``` + +В `renderWaypointsList()` добавить дистанцию в каждый wl-item (кроме первого): +```js +routeWaypoints.map((wp, i) => { + // ... + const distStr = i > 0 ? formatSegmentDist(haversineM(routeWaypoints[i-1], wp)) : ''; + return `
+
${waypointPinSvg(label, color)}
+
+ ${coordText} + ${distStr ? `${distStr}` : ''} +
+
${gripSvg}
+ +
`; +}) +``` + +CSS для `.wl-dist`: +```css +.wl-info { display: flex; flex-direction: column; flex: 1; min-width: 0; } +.wl-label { font-size: 13px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.wl-dist { font-size: 11px; color: var(--text3); margin-top: 1px; } +``` + +--- + +## Деплой +``` +/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-зависимостей +- Реализовать поверх изменений из DEV_TASK_PHASE5_UX2.md (они уже в коде или деплоятся параллельно)