Files
wiki/tasks/enduro-trails/DEV_TASK_PHASE5_UX1.md
2026-05-05 17:10:02 +03:00

7.4 KiB
Raw Permalink Blame History

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 добавить кнопку рядом со стрелками:

<button class="mini-add-btn" id="mini-add-btn" onclick="miniAddWaypoint()" title="Добавить точку">
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
</button>

Вставить в .mini-route-info после .mini-route-arrows.

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 — новая функция:

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) — восстановить нормальный текст мини-бара:

// После rebuildWaypointMarkers(); renderWaypointsList(); при addingWaypoint
updateMiniRouteCard(); // обновить мини-бар

Фикс 3: После добавления точки — свернуть панель в мини-бар

Сейчас после добавления точки полная панель остаётся открытой. Нужно: после успешного построения маршрута (когда routeResults обновились) — если панель открыта, свернуть её в мини-бар.

В функции drawRouteResults() — в конце добавить:

// 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 до вызова — значит это перестройка, сворачивать. Если первый раз — не сворачивать (пусть пользователь видит варианты).

Логика:

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:

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:

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 `<div class="wl-item" id="wl-item-${i}">
      <div class="wl-dot" style="background:${color}"></div>
      <span class="wl-label" id="wl-label-${i}">${coordText}</span>
      <button class="wl-remove" onclick="removeWaypoint(${i})" title="Удалить">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
      </button>
    </div>`;
  }).join('');
  
  // Async update with place names
  routeWaypoints.forEach(async (wp, i) => {
    const name = await reverseGeocode(wp.lat, wp.lon);
    const el = document.getElementById(`wl-label-${i}`);
    if (el) el.textContent = name;
  });
}

Также обновить мини-бар stats при первом построении маршрута:

В updateMiniRouteCard() — stats показывает км и % грунт, это ок. Не трогать.


Порядок реализации

  1. Фикс 5 (geocoding) — добавить функцию, изменить renderWaypointsList
  2. Фикс 3 (auto-minimize) — изменить drawRouteResults
  3. Фикс 1 (кнопка + на мини-баре) — HTML + CSS + JS
  4. Деплой + проверка

Проверка

  1. Построить маршрут A→B → панель показывает варианты (не сворачивается при первом построении)
  2. Добавить промежуточную точку через кнопку «+» в мини-баре → маршрут перестраивается → панель сворачивается
  3. Открыть полную панель → в списке точек видны названия мест (не координаты)
  4. Добавить точку через кнопку «+ Точка» в полной панели → маршрут перестраивается → панель сворачивается