Files
wiki/tasks/enduro-trails/BRD_WAYPOINT_SEARCH.md
2026-05-06 01:00:01 +03:00

12 KiB
Raw Blame History

BRD: Enduro Trails — Поиск точек маршрута

Версия: 1.1
Дата: 2026-05-05
Автор: Стрим 🌊
Статус: 🔄 В разработке


1. Контекст и проблема

Сейчас добавить точку маршрута можно только тапом на карту. Если нужно попасть в конкретное место (деревня, перекрёсток, POI) — нужно сначала найти его на карте, потом тапнуть. Это неудобно, особенно на мобиле.

Верхний search bar решал задачу навигации по карте, но не интегрирован с маршрутом — найденное место просто центрировало карту, не добавляя точку. Плюс bar занимал место и мешал карте.


2. Цель

Убрать верхний search bar. Добавить поиск прямо в список точек маршрута — inline, для каждой точки отдельно. При первом открытии режима маршрута — онбординг с полями ввода старта и финиша.


3. Что меняется

  • Удалить #search-bar и #search-results из HTML
  • Удалить все CSS стили (#search-bar, #search-input, #search-results, .search-result-item, .sri-*)
  • Удалить вызов initSearch() из JS
  • Кнопку темы (#btn-theme) перенести в #map-controls-r (рядом с компасом и геолокацией)

3.2 Онбординг при активации режима маршрута

Когда пользователь тапает «Маршрут» в toolbar и точек ещё нет — показывать вместо пустого списка:

┌─────────────────────────────────┐
│ 🔍 Откуда?                      │  ← поле поиска старта
│    или тапни на карте           │  ← подсказка
└─────────────────────────────────┘

После выбора старта автоматически появляется:

┌─────────────────────────────────┐
│ S  Название старта              │  ← добавленная точка
├─────────────────────────────────┤
│ 🔍 Куда?                        │  ← поле поиска финиша
│    или тапни на карте           │
└─────────────────────────────────┘

После выбора финиша — поля исчезают, маршрут строится, показывается обычный wl-list.

Детали:

  • Поля поиска используют тот же Nominatim что и inline поиск в wl-item
  • Подсказка «или тапни на карте» — мелкий текст var(--text3) под полем
  • Тап на карте тоже работает — добавляет точку и переходит к следующему полю
  • Если точки уже есть — онбординг не показывается, сразу wl-list

3.3 Inline поиск в каждой точке маршрута

В каждом wl-item добавить кнопку-лупу. Тап → разворачивается inline панель поиска прямо под точкой.

UX flow:

  1. Пользователь видит список точек маршрута (S → 1 → F)
  2. Тапает иконку 🔍 рядом с нужной точкой
  3. Под точкой появляется поле ввода с автофокусом
  4. Вводит название места → через 400ms debounce → Nominatim поиск
  5. Выбирает результат → точка обновляется, карта летит к ней, маршрут перестраивается
  6. Панель закрывается

Детали:

  • Одновременно открыта только одна панель поиска (остальные закрываются)
  • Поиск через Nominatim (countrycodes=ru, accept-language=ru, limit=5)
  • Результат: название + подзаголовок (область/район)
  • После выбора: routeWaypoints[idx] обновляется, rebuildWaypointMarkers() + renderWaypointsList() + debounceBuildRoute()
  • map.flyTo() к выбранному месту (zoom 13, duration 600ms)

4. UI компоненты

Кнопка лупы в wl-item

  • Иконка: Lucide search SVG (15×15)
  • Цвет: var(--text3) → hover var(--accent)
  • Позиция: между .wl-info и .wl-drag-handle

Inline панель поиска

  • Фон: var(--surface), бордер сверху var(--border)
  • Input: var(--surface2) фон, var(--border) бордер, focus → var(--accent) бордер
  • Результаты: max-height 180px, scroll, hover var(--surface2)
  • Каждый результат: название (bold) + подзаголовок (мелкий, var(--text2))

Кнопка темы (перенос)

  • Переносится в #map-controls-r как .map-btn
  • updateThemeButtonIcon() продолжает работать — находит #btn-theme по id

5. Технические детали

Аспект Решение
Поиск API Nominatim /search (уже используется в проекте)
Debounce 400ms
Состояние wpSearchTimeout — глобальная переменная для debounce
Закрытие панели Тап на лупу повторно — закрывает; открытие другой — закрывает текущую
После выбора routeWaypoints[idx] = {lat, lon}, rebuild + route
Кнопка «Добавить точку» wl-add остаётся без изменений

6. Баги после редизайна (требуют исправления)

Баг Описание Вероятная причина
Метки в верхнем левом углу Попап метки отображается не на позиции маркера, а в углу экрана CSS position маркера сбивает позиционирование MapLibre
Метки линейки в верхнем углу Попап точки линейки отображается не на треке, а в углу Та же причина — CSS позиционирование маркера
Подсказка «Тапни на карте» пропала #route-status не виден когда точек нет Скрыт или перекрыт после редизайна

Вероятная причина багов с маркерами: в редизайне изменились глобальные CSS стили для position, transform или z-index — это сбивает позиционирование MapLibre маркеров. Маркер MapLibre должен иметь position: absolute без переопределения в глобальных стилях.

Фикс: проверить CSS для .maplibregl-marker, .marker-flag, .ruler-marker — убрать любой position: fixed/relative/static который может переопределять поведение маркера.


7. Definition of Done

Критерий Статус
Верхний search bar отсутствует
Кнопка темы работает в map-controls-r
При активации маршрута без точек — поле поиска старта
После старта — поле поиска финиша
Подсказка «или тапни на карте» видна
Иконка лупы в каждом wl-item
Тап на лупу → inline поиск открывается
Поиск находит места через Nominatim
Выбор результата → waypoint обновляется
Маршрут перестраивается после выбора
Карта летит к выбранному месту
Одновременно открыта только одна панель
Метки отображаются на позиции маркера (не в углу)
Метки линейки отображаются на треке
Деплой + health check OK

8. Файлы

Файл Изменения
prototype/static/index.html Удалить #search-bar, #search-results; перенести #btn-theme в #map-controls-r
prototype/static/app.css Удалить стили search bar; добавить .wl-search-*; исправить позиционирование маркеров
prototype/static/app.js Удалить initSearch(); добавить онбординг, openWaypointSearch(), doWaypointSearch(), selectWaypointSearchResult()


9. Дополнительные замечания (05.05.2026 — пакет 2)

# Замечание Детали
1 Иконка колеса Заменить на нормальное мотокросс колесо
2 Флажок финиша Чёрно-белая шахматная раскраска как финишный флаг
3 Спиннер в основном листе Вращающееся колесо пока строится маршрут (как в мини-баре)
4 Тёмная карта При тёмной теме — тёмный стиль карты, при светлой — светлый
5 Автозум на маршрут Плавный fitBounds после построения маршрута, маршрут по центру без выхода за границы
6 Мини-бар перекрывает кнопки справа Исправить z-index/позиционирование #sheet-route-mini

Детали по пунктам

П.1 Иконка колеса:
Заменить текущую SVG на нормальное мотокросс колесо — спицы, кноблинг, центральная втулка. Использовать Lucide bike или нарисовать SVG колеса с спицами.

П.2 Флажок финиша:
В waypointPinSvg('F', ...) для финишной точки использовать шахматный узор (SVG pattern чёрные/белые клетки) вместо красного цвета.

П.3 Спиннер в основном листе:
В #route-cards показывать skeleton/спиннер пока идёт запрос к OSRM. Тот же спиннер что в мини-баре.

П.4 Тёмная карта:
map.setStyle() при смене темы. Тёмный стиль: /style-dark.json (или текущий тёмный), светлый: /style-light.json (или текущий светлый). После setStyle пересоздать слои маршрутов через map.on('style.load', onMapStyleLoad).

П.5 Автозум:
После drawRouteResults() вызывать:

const coords = routeResults[0].geometry.coordinates;
const bounds = coords.reduce((b, c) => b.extend(c), new maplibregl.LngLatBounds(coords[0], coords[0]));
map.fitBounds(bounds, { padding: 60, duration: 1000, maxZoom: 14 });

П.6 Мини-бар:
#sheet-route-mini перекрывает #map-controls-r. Исправить right или width мини-бара чтобы не залезал на кнопки справа.