# 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 `