# Dev Task: Enduro Trails — UX фиксы #1, #3, #5 **Файлы:** `/home/node/.openclaw/workspace/tasks/enduro-trails/prototype/static/` **Деплой:** `node /tmp/deploy_static.js` **Бэкенд не трогать.** --- ## Фикс 1: Кнопка «+» на мини-баре Сейчас чтобы добавить промежуточную точку нужно открыть полную панель. Нужно: добавить кнопку «+» прямо на мини-баре. ### HTML — в `#sheet-route-mini` добавить кнопку рядом со стрелками: ```html ``` Вставить в `.mini-route-info` после `.mini-route-arrows`. ### CSS: ```css .mini-add-btn { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; background: var(--accent); border: none; border-radius: 10px; color: #fff; cursor: pointer; flex-shrink: 0; -webkit-tap-highlight-color: transparent; } .mini-add-btn:active { opacity: 0.8; transform: scale(0.94); } ``` ### JS — новая функция: ```js function miniAddWaypoint() { // Enter waypoint-adding mode without opening full sheet if (!routeMode) { // Re-enter route mode silently (no sheet open) routeMode = true; document.getElementById('tb-route').classList.add('active'); updateMapModeClass(); } addWaypointMode(); // Show hint on mini-bar document.getElementById('mini-stats').textContent = 'Тапни на карте для добавления точки'; } ``` После добавления точки (в обработчике клика карты где `addingWaypoint = false`) — восстановить нормальный текст мини-бара: ```js // После rebuildWaypointMarkers(); renderWaypointsList(); при addingWaypoint updateMiniRouteCard(); // обновить мини-бар ``` --- ## Фикс 3: После добавления точки — свернуть панель в мини-бар Сейчас после добавления точки полная панель остаётся открытой. Нужно: после успешного построения маршрута (когда routeResults обновились) — если панель открыта, свернуть её в мини-бар. ### В функции `drawRouteResults()` — в конце добавить: ```js // Auto-minimize sheet after route is built const sheet = document.getElementById('sheet-route'); if (sheet && sheet.classList.contains('open')) { minimizeSheet('sheet-route'); } ``` **Важно:** это должно срабатывать только когда маршрут уже был (перестройка), а не при первом построении. Проверить: если `routeResults.length > 0` до вызова — значит это перестройка, сворачивать. Если первый раз — не сворачивать (пусть пользователь видит варианты). Логика: ```js const wasBuilt = routeResults.length > 0; // до обновления routeResults // ... существующий код drawRouteResults ... // В конце: if (wasBuilt) { const sheet = document.getElementById('sheet-route'); if (sheet && sheet.classList.contains('open')) { minimizeSheet('sheet-route'); } } ``` --- ## Фикс 5: Reverse geocoding — названия мест вместо координат Сейчас в списке точек показываются координаты: `55.7234, 37.6123`. Нужно: показывать название места через Nominatim reverse geocoding. ### Добавить функцию reverse geocoding: ```js const geocodeCache = {}; async function reverseGeocode(lat, lon) { const key = `${lat.toFixed(4)},${lon.toFixed(4)}`; if (geocodeCache[key]) return geocodeCache[key]; try { const resp = await fetch( `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json&accept-language=ru`, { headers: { 'Accept-Language': 'ru' } } ); const data = await resp.json(); // Приоритет: village/town/city > road > county const a = data.address || {}; const name = a.village || a.town || a.city || a.suburb || a.road || a.county || a.state || `${lat.toFixed(3)}, ${lon.toFixed(3)}`; geocodeCache[key] = name; return name; } catch(e) { return `${lat.toFixed(3)}, ${lon.toFixed(3)}`; } } ``` ### Изменить `renderWaypointsList()`: Сделать функцию async и использовать geocoding: ```js async function renderWaypointsList() { const list = document.getElementById('waypoints-list'); if (!routeWaypoints.length) { list.innerHTML = ''; return; } // Render immediately with coords, then update with names list.innerHTML = routeWaypoints.map((wp, i) => { const labelClass = i === 0 ? 'start' : i === routeWaypoints.length - 1 ? 'end' : 'mid'; const color = labelClass === 'start' ? 'var(--success)' : labelClass === 'end' ? 'var(--red)' : '#0066ff'; const coordText = `${wp.lat.toFixed(3)}, ${wp.lon.toFixed(3)}`; return `