gendesign/tradein-mvp/frontend/src/lib
bot-backend 73c4c487ed
All checks were successful
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m6s
CI Trade-In / backend-tests (pull_request) Successful in 4m50s
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Successful in 48s
fix(mera/b2c): житель Серова получал «вы вне области», а подсказки игнорировали выбранный город
Два дефекта, найденных прогоном сценария глазами посетителя на живом домене.

## 1. Город предлагали выбрать, но отвечать по нему не умели

Дропдаун на сайте (`OBLAST_CITIES`, city-registry.ts) и списки покрытия
(`COVERAGE_GREEN/YELLOW_CITIES`, trade_in.py) — одно множество, записанное в
двух местах. Они разошлись в обе стороны:

  предлагали, но не отвечали:  Серов
  отвечали, но не предлагали:  Берёзовский, Среднеуральск, Ревда

Житель Серова выбирал СВОЙ город из НАШЕГО дропдауна и получал:

  «Этот адрес вне области, по которой мы собираем данные.
   Сейчас это Свердловская область: Екатеринбург целиком и ещё несколько
   городов вокруг.»

Про город в той же самой области. Серов при этом покрыт данными: 363 активных
объявления в радиусе 15 км, все свежие (замер по проде). Поэтому добавлен в
жёлтый тир, а не убран из дропдаунa; три недостающих города добавлены на фронт.

Шапка city-registry.ts этот риск прямо предсказывала — «перед добавлением
7-го города сверить оба списка вручную, теста на это пока нет». Теперь тест
есть: бэкендовый сьют читает TS-реестр и требует РАВЕНСТВА множеств. Плюс
проверка, что у каждого города с порогом есть центроид, — иначе порог мёртвый,
город по координатам не резолвится.

## 2. Подсказки не слушались выбранного города

`city_hint` доезжает до геокодера, но на выдачу не влияет: его смотрит только
екатеринбургский кадастровый тир (как признак «речь не про ЕКБ, тир
пропускаем»), а DaData-тир ограничен регионом целиком и хинта не принимает.

Замер: выбран Серов, введено «Ленина 1» → первой подсказкой «Невьянский р-н,
пгт Верх-Нейвинский». Человек выбирает верхний вариант и считает чужой дом —
ровно баг #2576, ради которого город и спрашивают.

Публичная ручка теперь подставляет город в саму строку запроса. Проверено на
проде: «Серов Ленина 1» даёт серовскую выдачу целиком. Для Екатеринбурга
подстановка безвредна — три разных адреса дали тот же результат с префиксом и
без, поэтому правило одно на все города, без исключения для основного трафика.

Чинится в публичной ручке, а не в геокодере: там от `city_hint` зависит
поведение закрытого контура (`target_city_ambiguous`).

## Фикстура теста

`_FAR_AWAY_CITY` стояла в 21 км от центра Серова и работала как «далеко от
всех» лишь потому, что Серов не был поддержан. Переехала в Тавду — 271 км до
ближайшего центроида.

## Мутации

  убрать Серов из покрытия (состояние прода) → падает сверка списков
  не подставлять город в строку             → падает проверка ручки
  откат                                     → 21 passed

Плюс backend 75 passed, vitest 56 passed, tsc, lint, build, isolation guard.

`city-registry.ts` добавлен в paths-фильтр БЭКЕНДОВОГО лэйна: сверку списков
делает бэкендовый тест, и без этой строки правка одного лишь дропдауна её бы
не запускала — то есть ровно тот путь, которым списки и разошлись.
2026-08-16 13:03:19 +03:00
..
admin-audit-api.ts feat(tradein/admin): audit + activity dashboards (Feature 2/3 UI) (#2521) 2026-07-13 20:45:34 +00:00
api.ts fix(tradein-frontend): safeUrl validator, apiFetch dedup, ListingsCard a11y, error boundary (#512) 2026-05-24 11:47:38 +00:00
buildInfo.ts feat(tradein): версионирование продукта — единый источник, подвал, PDF, /versions (#2824) 2026-08-10 16:00:54 +00:00
changelog.ts feat(tradein): версионирование продукта — единый источник, подвал, PDF, /versions (#2824) 2026-08-10 16:00:54 +00:00
city-registry.ts fix(mera/b2c): житель Серова получал «вы вне области», а подсказки игнорировали выбранный город 2026-08-16 13:03:19 +03:00
isPathAllowed.ts feat(rbac): frontend route-guard + nav filter (#586) 2026-05-26 06:51:45 +00:00
leaflet.ts fix(tradein/maps): убрать украинский флаг Leaflet и починить атрибуцию OSM (#2621) 2026-08-02 12:12:43 +00:00
legal-copy.ts merge main: объединить legal-copy.ts (PRIVACY_PATH + SHORT_ESTIMATE_DISCLAIMER) 2026-08-14 15:41:16 +03:00
logout.ts fix(tradein/auth): always-available logout button on NoAccessScreen 2026-06-27 15:16:42 +03:00
rosreestr.ts fix(tradein/dkp): «ФАКТИЧЕСКИЕ СДЕЛКИ» называют свой возраст, а не окно поиска (#2847) 2026-08-12 18:51:10 +00:00
safeUrl.ts fix(tradein-frontend): safeUrl validator, apiFetch dedup, ListingsCard a11y, error boundary (#512) 2026-05-24 11:47:38 +00:00
sale-share-api.ts feat(tradein): страница «доля квартир дома в продаже» — % слайдер, адреса, карта (#2058) 2026-06-28 14:53:38 +00:00
sessionId.ts feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
source-registry.ts chore(tradein/ui): вычистить источник n1 из source-registry и UI (#2204) 2026-07-03 10:16:53 +03:00
team-api.ts fix(tradein/team): admin управляет менеджерами — сброс пароля и блокировка (#2556) 2026-07-31 15:51:50 +03:00
trade-in-api.ts feat(tradein/ui): передавать город в геокодирование + честный признак неопределённости (#2576) 2026-07-31 17:08:46 +03:00
useBrand.ts fix(tradein): remove «Практика» white-label brand (DB row + account mapping + assets) 2026-06-19 12:53:37 +03:00
useDebouncedValue.ts feat(tradein): страница «доля квартир дома в продаже» — % слайдер, адреса, карта (#2058) 2026-06-28 14:53:38 +00:00
useLogout.ts fix(tradein/ui): чистить TanStack Query cache при смене identity (#2567) (#2651) 2026-08-05 10:06:31 +00:00
useMe.ts feat(tradein/ui): login-форма + session-aware RouteGuard (#2555) 2026-07-30 20:46:33 +03:00
useQuota.ts fix(tradein-frontend): остановить retry-storm на 401 — refetchOnMount:false + backoff (#800) 2026-06-13 16:47:58 +05:00
useSupportChat.ts feat(tradein/support): чат поддержки без входа — экран логина и «доступа нет» 2026-07-31 16:04:51 +03:00