Skip to content

Geo Multi-Select в хэдере

Дата: 2026-02-12

Задача

Заменить одиночный выбор города в хэдере на мультиселект: один регион + опциональный выбор нескольких городов внутри.

Логика выбора

  • Пользователь выбирает один регион
  • Внутри региона — мультиселект городов (чекбоксы)
  • Если ни один город не выбран — фильтрация по всему региону
  • Если выбраны конкретные города — фильтрация только по ним
  • "Вся Россия" — сброс, без гео-фильтрации

Формат передачи на бэкенд

# Весь регион (города не выбраны)
GET /store/products?region_id=5

# Конкретные города
GET /store/products?city_ids=1,7,12

# Вся Россия — без гео-параметров
GET /store/products

Правило: если есть city_ids, region_id не передаётся. Обратная совместимость — старый city_id (ед. число) продолжает работать на бэкенде.

Geo Store

ts
interface GeoState {
  selectedRegion: Region | null     // Один выбранный регион
  selectedCities: City[]            // Города внутри региона (0 = весь регион)
  regions: Region[]                 // Кэш всех регионов
}

Геттеры:

  • regionId — ID региона или undefined
  • cityIds — number[] ID городов (пустой = весь регион)
  • hasGeoFilter — boolean
  • locationLabel — текст кнопки:
    • "Вся Россия" — ничего не выбрано
    • "Лен. область" — регион, городов 0
    • "Санкт-Петербург" — 1 город
    • "СПб + 2 города" — несколько городов

Персистенция: cookies geo_region_id + geo_city_ids (через запятую), 365 дней.

UI модалки CitySelector

┌─────────────────────────────────────┐
│  Выберите местоположение        ✕   │
├─────────────────────────────────────┤
│  [🔍 Поиск города...]               │
├─────────────────────────────────────┤
│  ● Вся Россия                       │  ← сброс
├─────────────────────────────────────┤
│  Регион:                            │
│  ┌─────────────────────────────┐    │
│  │ Ленинградская область    ▼  │    │  ← USelectMenu
│  └─────────────────────────────┘    │
├─────────────────────────────────────┤
│  Города:              (Все города)  │  ← ссылка сброса городов
│  ☑ Санкт-Петербург                  │
│  ☐ Выборг                          │
│  ☐ Гатчина                         │
│  ...                                │
├─────────────────────────────────────┤
│  [         Применить         ]      │  ← сохраняет и закрывает
└─────────────────────────────────────┘

Поведение:

  • Выбор региона загружает города с чекбоксами
  • Ни один город не отмечен = весь регион
  • Кнопка "Применить" сохраняет выбор и закрывает модалку
  • "Вся Россия" — быстрый сброс

Интеграция

Каталог (/catalog)

  • Читает region_id или city_ids из URL query
  • Fallback на гео-стор если нет в URL
  • Передаёт на бэкенд
  • При сабмите добавляет гео в URL: /catalog?q=стартер&city_ids=1,7
  • Автокомплит использует гео из стора

Главная страница

  • Недавние объявления фильтруются по гео из стора
  • Watch на cityIds/regionId → рефреш

Затронутые файлы

  • app/stores/geo.ts — переделка стора (selectedRegion, selectedCities)
  • app/features/geo-select/ui/CitySelector.vue — новый UI с мультиселектом
  • app/features/search/composables/useProductSearch.ts — city_ids вместо city_id
  • app/features/search/ui/SearchBar.vue — city_ids в URL
  • app/pages/catalog/index.vue — city_ids в фильтрах
  • app/pages/index.vue — city_ids/region_id в запросе
  • app/layouts/default.vue — минимальные изменения (CitySelector уже используется)