[tradein][ux] MapCard: ДКП-пины не рендерятся + клик по пину аналога не открывает детали #786

Closed
opened 2026-05-30 16:38:56 +00:00 by lekss361 · 2 comments
Owner

Worker: исполняемый спек. Делай по пунктам. Неясность с кодом → коммент, НЕ угадывай.

Задача

На карте аналитики результата (MapCard) не работают пины: (1) ДКП-сделки вообще не отображаются, (2) клик по пину аналога/квартиры не открывает popup с деталями (хотя подпись обещает «ДКП · клик по пину — детали», MapCard.tsx:245). Починить оба.

Корень A — клик перехватывается target-кругом (pure frontend, чинить точно)

components/trade-in/MapCard.tsx:171-177: целевой L.circle радиус 2000м интерактивен по умолчанию и добавляется на карту ПОСЛЕ маркеров аналогов (:135-146) и сделок (:150-161) → в общем SVG-пейне Leaflet он лежит сверху и перехватывает клики по пинам под ним → bindPopup не срабатывает.
Fix: добавить interactive: false в опции L.circle (:171) — круг чисто декоративный (радиус-обводка). Альтернативы: рисовать круг ДО маркеров, либо marker.bringToFront(). Проверить, что после фикса popup аналога/target открывается по клику.

Корень B — ДКП-пины не рендерятся (нет координат)

components/trade-in/MapCard.tsx:97-103: deals = estimate.actual_deals.filter(l => typeof l.lat==="number" && typeof l.lon==="number"). ДКП-сделки Росреестра — street-level, lat/lon обычно NULL (open dataset не даёт дом/гео; см. ADR Decision_Dkp_Listing_Linkage_Impossible) → фильтр выкидывает все → 0 зелёных пинов, легенда «сделки ДКП · 0» (:222,245).
Решение (выбрать, обосновать в PR):

  • (предпочт.) если у actual_deals[i] нет lat/lon — НЕ обещать кликабельные пины: убрать «· клик по пину — детали» для ДКП когда deals.length===0, и/или показать ДКП отдельным списком под картой (как DealsCard), а не пинами.
  • ЛИБО плотить ДКП по street-центроиду (если доступен) с явной пометкой «по улице, неточно» (согласовать с #722 street_only-честностью) — НЕ выдавать за точную точку дома.
  • Проверить РЕАЛЬНЫЙ payload: сделать оценку и посмотреть, есть ли в estimate.actual_deals[].lat/lon хоть у части (если backend геокодит часть — тогда пины частично валидны, и фикс только косметика подписи).

Files

  • components/trade-in/MapCard.tsx:171-177 (circle interactive), :97-103 (deals filter), :135-161 (маркеры), :219-245 (легенда/подпись «клик по пину»).
  • schemas/trade_in.py AnalogLot/actual_deals — проверить наличие lat/lon в контракте сделок.

Definition of Done

  • Клик по пину аналога И целевой квартиры открывает popup с деталями (вживую Playwright/браузер на реальной оценке).
  • ДКП: либо пины кликабельны (если есть координаты), либо подпись/легенда честны при 0 пинов (нет обещания «клик по пину» когда пинов нет) — без вранья клиенту.
  • Нет регресса: target-круг по-прежнему виден (декоративный), fitBounds работает.
  • npm run build/tsc clean.

Не делать

  • НЕ трогать backend-геокодинг сделок в рамках этой issue (если решение = плотить по центроиду и координат нет — отдельная backend-issue, сослаться).
  • НЕ трогать MapPicker (#771 — другой компонент).
> Worker: исполняемый спек. Делай по пунктам. Неясность с кодом → коммент, НЕ угадывай. ## Задача На карте аналитики результата (`MapCard`) не работают пины: (1) ДКП-сделки вообще не отображаются, (2) клик по пину аналога/квартиры не открывает popup с деталями (хотя подпись обещает «ДКП · клик по пину — детали», `MapCard.tsx:245`). Починить оба. ## Корень A — клик перехватывается target-кругом (pure frontend, чинить точно) `components/trade-in/MapCard.tsx:171-177`: целевой `L.circle` радиус 2000м интерактивен по умолчанию и добавляется на карту **ПОСЛЕ** маркеров аналогов (`:135-146`) и сделок (`:150-161`) → в общем SVG-пейне Leaflet он лежит сверху и **перехватывает клики** по пинам под ним → `bindPopup` не срабатывает. **Fix:** добавить `interactive: false` в опции `L.circle` (`:171`) — круг чисто декоративный (радиус-обводка). Альтернативы: рисовать круг ДО маркеров, либо `marker.bringToFront()`. Проверить, что после фикса popup аналога/target открывается по клику. ## Корень B — ДКП-пины не рендерятся (нет координат) `components/trade-in/MapCard.tsx:97-103`: `deals = estimate.actual_deals.filter(l => typeof l.lat==="number" && typeof l.lon==="number")`. ДКП-сделки Росреестра — **street-level, lat/lon обычно NULL** (open dataset не даёт дом/гео; см. ADR Decision_Dkp_Listing_Linkage_Impossible) → фильтр выкидывает все → 0 зелёных пинов, легенда «сделки ДКП · 0» (`:222,245`). **Решение (выбрать, обосновать в PR):** - (предпочт.) если у `actual_deals[i]` нет lat/lon — НЕ обещать кликабельные пины: убрать «· клик по пину — детали» для ДКП когда `deals.length===0`, и/или показать ДКП отдельным списком под картой (как DealsCard), а не пинами. - ЛИБО плотить ДКП по street-центроиду (если доступен) с явной пометкой «по улице, неточно» (согласовать с #722 street_only-честностью) — НЕ выдавать за точную точку дома. - Проверить РЕАЛЬНЫЙ payload: сделать оценку и посмотреть, есть ли в `estimate.actual_deals[].lat/lon` хоть у части (если backend геокодит часть — тогда пины частично валидны, и фикс только косметика подписи). ## Files - `components/trade-in/MapCard.tsx:171-177` (circle interactive), `:97-103` (deals filter), `:135-161` (маркеры), `:219-245` (легенда/подпись «клик по пину»). - `schemas/trade_in.py` `AnalogLot`/actual_deals — проверить наличие lat/lon в контракте сделок. ## Definition of Done - [ ] Клик по пину аналога И целевой квартиры открывает popup с деталями (вживую Playwright/браузер на реальной оценке). - [ ] ДКП: либо пины кликабельны (если есть координаты), либо подпись/легенда честны при 0 пинов (нет обещания «клик по пину» когда пинов нет) — без вранья клиенту. - [ ] Нет регресса: target-круг по-прежнему виден (декоративный), fitBounds работает. - [ ] `npm run build`/tsc clean. ## Не делать - НЕ трогать backend-геокодинг сделок в рамках этой issue (если решение = плотить по центроиду и координат нет — отдельная backend-issue, сослаться). - НЕ трогать MapPicker (#771 — другой компонент).
lekss361 added the
bug
ux
scope/frontend
status/ready
priority/p2
tradein
labels 2026-05-30 16:38:56 +00:00
bot-frontend self-assigned this 2026-05-30 16:41:02 +00:00
bot-frontend added
status/wip
and removed
status/ready
labels 2026-05-30 16:41:03 +00:00
bot-frontend added
status/review
and removed
status/wip
labels 2026-05-30 16:43:34 +00:00
Collaborator

Working on this in PR #787.

Working on this in PR #787.
bot-reviewer added
status/qa
and removed
status/review
labels 2026-05-30 16:46:09 +00:00
Collaborator

QA smoke PASS (PR #787 — diff на main + live Playwright на реальной оценке)

Fix A — клик по пину открывает popup (target-круг больше не перехватывает):

  • MapCard.tsx:174: L.circle({..., interactive: false}) ✓ — декоративный радиус-круг (рисуется ПОСЛЕ маркеров) пропускает клики к пинам под ним.
  • Runtime (Олимп estimate, leaflet-карта): целевой круг → pointer-events: none (1 path); клик по пину аналога → открылся popup: «Екатеринбург, Олимпийская набережная, 13 · Объявление (asking) · 995 671 ₽/м² · 207 000 000 ₽» ✓✓

Fix B — ДКП-честность (street-level, нет lat/lon → 0 пинов):

  • Легенда «● сделки ДКП · N» и badge «● ДКП» рендерятся ТОЛЬКО при deals.length > 0 ✓ — нет вранья «· 0» и нет ложного обещания «клик по пину» для ДКП когда пинов нет.
  • Runtime: легенда «сделки ДКП» отсутствует (deals=0); «клик по пину — детали» остался и теперь корректен (относится к кликабельным пинам аналогов).

Нет регресса: карта рендерится, пины интерактивны, target-круг виден (декоративный). npm run build/tsc — зелёные у воркера. → status/done, closing.

✅ **QA smoke PASS** (PR #787 — diff на `main` + live Playwright на реальной оценке) **Fix A — клик по пину открывает popup** (target-круг больше не перехватывает): - `MapCard.tsx:174`: `L.circle({..., interactive: false})` ✓ — декоративный радиус-круг (рисуется ПОСЛЕ маркеров) пропускает клики к пинам под ним. - **Runtime** (Олимп estimate, leaflet-карта): целевой круг → `pointer-events: none` (1 path); клик по пину аналога → **открылся popup**: «Екатеринбург, Олимпийская набережная, 13 · Объявление (asking) · 995 671 ₽/м² · 207 000 000 ₽» ✓✓ **Fix B — ДКП-честность** (street-level, нет lat/lon → 0 пинов): - Легенда «● сделки ДКП · N» и badge «● ДКП» рендерятся ТОЛЬКО при `deals.length > 0` ✓ — нет вранья «· 0» и нет ложного обещания «клик по пину» для ДКП когда пинов нет. - **Runtime:** легенда «сделки ДКП» отсутствует (deals=0); «клик по пину — детали» остался и теперь корректен (относится к кликабельным пинам аналогов). Нет регресса: карта рендерится, пины интерактивны, target-круг виден (декоративный). `npm run build`/tsc — зелёные у воркера. → `status/done`, closing.
bot-qa added
status/done
and removed
status/qa
labels 2026-05-30 16:57:53 +00:00
lekss361 added this to the Praktika demo — Mon 2026-06-01 milestone 2026-05-30 17:21:37 +00:00
Sign in to join this conversation.
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#786
No description provided.