feat(tradein/ui): передавать город в геокодирование + честный признак неопределённости (#2576) #2584
Merged
lekss361
merged 3 commits from 2026-07-31 15:46:02 +00:00
feat/tradein-ui-city-hint into main
3 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
49ee85aae2 |
fix(tradein/ui): не называть неподтверждённый город в плашке неопределённости (#2576)
All checks were successful
CI / changes (pull_request) Successful in 14s
CI Trade-In / changes (pull_request) Successful in 14s
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / 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 1m33s
Deep-review R3: плашка city_ambiguous всегда подставляла {city} — внутреннее
состояние с дефолтом "Екатеринбург" (initCityLabel), а не то, что реально
определил бэкенд (в ответе только булев target_city_ambiguous, угаданного
города там нет). Ровно в целевом сценарии фикса — нетронутая форма, «Ленина
1», cityConfirmed=false — текст утверждал «если это не Екатеринбург»
независимо от реального результата (там мог быть Нижний Тагил) — та же
нечестность, которую предыдущий коммит убирал из запроса, только в тексте.
Текст плашки теперь ветвится по cityConfirmed:
- cityConfirmed=true (город реально был подтверждён и отправлен) — прежний
текст с конкретным {city} уместен, не меняю.
- cityConfirmed=false (это и есть путь, где cityAmbiguous обычно и
срабатывает после предыдущего коммита) — нейтральная формулировка без
упоминания конкретного города: «Если это неверно, выберите город выше и
повторите оценку.»
tsc --noEmit / next lint / next build — чисто (те же 2 pre-existing warning в
несвязанных файлах).
|
||
|
|
a8d29fa031 |
fix(tradein/ui): не слать city_hint по умолчанию — только явный выбор или город из адреса (#2576)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
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 1m15s
Deep-review R2 на #2580/#2576: предыдущий коммит слал city_hint="Екатеринбург"
даже когда дропдаун не тронут — бэкенд трактует ЛЮБОЙ city_hint как «пользователь
назвал город» (city_specified=True), так что target_city_ambiguous становился
false практически всегда, а необнаруженный житель Нижнего Тагила («Ленина, 1»
без явного упоминания города) молча резолвился бы в Екатеринбург — ровно баг,
который чинил backend, только переехавший из geocoder.py в city-registry.ts.
Вариант A (по рекомендации ревьюера): город реально известен (и поэтому
отправляется в city_hint) ТОЛЬКО когда пользователь явно выбрал его в
дропдауне ИЛИ detectCityInText нашёл совпадение в наборном тексте / выбранной
подсказке. Нетронутый дефолт → city_hint не уходит вовсе (ни в geocode/suggest,
ни в POST /estimate) — тогда backend честно возвращает target_city_ambiguous и
не форсит ЕКБ-bias без запроса.
- Новое состояние `cityConfirmed` (ParamsPanel.tsx) — гейт на отправку,
раздельный от `city` (best-guess для отображения/текста плашки). true после
explicit dropdown pick ИЛИ автодетекта из текста/подсказки; sticky —
мелкая правка адреса без нового совпадения его не сбрасывает.
- До подтверждения дропдаун показывает `UNCONFIRMED_CITY_LABEL`
("Определить автоматически"), не статичное "Екатеринбург" — не выдаёт
внутренний best-guess за подтверждённый пользователем выбор.
- useGeocodeSuggest получает city_hint только при cityConfirmed=true — для
нетронутой формы автокомплит тоже больше не форсит ЕКБ-bias молча, а видит
кандидатов из всей области (в т.ч. Нижний Тагил) — это и есть тот сценарий
из заголовка эпика.
- ЕКБ happy path не усложнён: как только пользователь печатает город в адресе
или (обычный путь) выбирает любую подсказку из автокомплита, detectCityInText
почти всегда находит "Екатеринбург" в full_address (провайдер возвращает
город как часть резолвленного адреса независимо от того, был ли отправлен
hint) — дропдаун сам переключается на "Екатеринбург" и cityConfirmed
становится true без отдельного клика. Требует лишнего действия только
редкий путь "напечатал произвольный адрес без города и нажал Enter, не
выбрав ни одной подсказки".
- city-registry.ts: явный комментарий-ссылка на бэкендовый гэзеттир
`SVERDLOVSK_OBLAST_CITIES` (tradein-mvp/backend/app/services/geocoder.py) —
parity-риск при добавлении нового города остаётся видимым с фронтовой
стороны (backend/тесты не трогаю — другой PR, вне моего scope).
tsc --noEmit / next lint / next build — чисто (только 2 pre-existing warning в
несвязанных файлах, как и в предыдущем коммите).
|
||
|
|
2779ef5e79 |
feat(tradein/ui): передавать город в геокодирование + честный признак неопределённости (#2576)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
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 1m7s
Раньше интерфейс город вообще не передавал — backend (#2580) больше не подставляет "Екатеринбург" молча, из-за чего житель Нижнего Тагила, вводя «Ленина, 1», получал бы результат по одноимённой екатеринбургской улице. - Новый справочник src/lib/city-registry.ts (растущий список городов области, сейчас: Екатеринбург, Нижний Тагил, Каменск-Уральский, Первоуральск, Верхняя Пышма, Серов) — DEFAULT_CITY = Екатеринбург, чтобы ЕКБ-сценарий не требовал никаких лишних действий. - ParamsPanel: компактный дропдаун «Город» рядом с лейблом адреса (переиспользует существующий <Dd> HUD-комбобокс) + автоопределение города из набранного текста/выбранной подсказки (detectCityInText, word-boundary safe — не путает "Серов" с "ул. Серова" в ЕКБ). city_hint уходит в geocode/suggest и в POST /trade-in/estimate. - useGeocodeSuggest(query, cityHint, limit) — city_hint в query-параметрах и в queryKey, чтобы смена города рефетчила подсказки. - Честная подсказка в ParamsPanel, когда estimate.target_city_ambiguous===true: спокойный (не danger) текст «Город определён автоматически — результат может относиться к другому населённому пункту области. Если это не {city}, выберите верный город выше и повторите оценку.» — не блокирует форму. - types/trade-in.ts: TradeInEstimateInput.city_hint, AggregatedEstimate.target_city_ambiguous (зеркалит backend PR #2580, ещё не смёржен — codegen не запускался, поля добавлены вручную по контракту схемы). tsc --noEmit / next lint / next build — чисто (только 2 pre-existing warning в несвязанных файлах). |