From 49a84ba9f65d5dde9d7ec98f1c587d583366543f Mon Sep 17 00:00:00 2001 From: Light1YT Date: Mon, 22 Jun 2026 11:48:55 +0500 Subject: [PATCH] fix(site-finder/v2): remove resource legend overlay (overlapped POI legend) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #1868 добавил ресурсную легенду (электр/вода/канал/тепло/газ) поверх карты, но PticaMapInner уже отрисовывает свою POI/категорийную легенду top-left высотой ~215px. PR #1869 попытался разнести их (top → bottom-left) — безуспешно: моя легенда всё равно попадала в нижний хвост POI-overlay. Прагматичный исход: ресурсная легенда ДУБЛИРУЕТ данные карточки ИНЖЕНЕРИЯ (те же расстояния и статусы). Убираю её совсем и оставляю per-theme заголовок карты (тот фикс был полезный и не конфликтует) — POI-overlay PticaMapInner несёт уникальные счётчики POI, ради которых карта и нужна. Удалены: V2MapLegend.tsx и блок CSS-правил .mapLegend* в v2.module.css. --- .../analysis/[cad]/v2/v2.module.css | 69 +-------- .../components/site-finder/ptica-v2/V2Map.tsx | 4 - .../site-finder/ptica-v2/V2MapLegend.tsx | 133 ------------------ 3 files changed, 1 insertion(+), 205 deletions(-) delete mode 100644 frontend/src/components/site-finder/ptica-v2/V2MapLegend.tsx diff --git a/frontend/src/app/site-finder/analysis/[cad]/v2/v2.module.css b/frontend/src/app/site-finder/analysis/[cad]/v2/v2.module.css index 59c2be75..02bff111 100644 --- a/frontend/src/app/site-finder/analysis/[cad]/v2/v2.module.css +++ b/frontend/src/app/site-finder/analysis/[cad]/v2/v2.module.css @@ -1910,64 +1910,6 @@ display: inline; } -/* Resource legend (bottom-left of the map card) — compact 5-row panel. - Placed bottom-left, above Leaflet attribution, to avoid overlap with the - existing PticaMapInner POI/category legend that lives in the top-left. */ -.mapLegend { - position: absolute; - left: 11px; - bottom: 28px; - z-index: 6; - min-width: 168px; - max-width: 200px; - background: var(--surface-strong); - border: 1px solid var(--border); - border-radius: var(--radius-xs); - padding: 8px 9px; - backdrop-filter: blur(3px); - pointer-events: none; -} -.mapLegendTitle { - font-family: var(--font-mono); - font-size: 7.5px; - letter-spacing: 0.1em; - text-transform: uppercase; - color: var(--text-soft); - margin: 0 0 5px; -} -.mapLegendRow { - display: flex; - align-items: center; - gap: 6px; - height: 15px; - font-size: 9px; -} -.mapLegendDot { - width: 8px; - height: 8px; - border-radius: 50%; - flex: 0 0 auto; - box-shadow: 0 0 5px currentColor; -} -.mapLegendLabel { - font-family: var(--font-mono); - letter-spacing: 0.04em; - text-transform: uppercase; - color: var(--text); - font-size: 8.5px; -} -.mapLegendDist { - margin-left: auto; - font-family: var(--font-mono); - font-size: 8.5px; - color: var(--text-muted); - font-variant-numeric: tabular-nums; -} -.mapLegendDistEmpty { - color: var(--text-soft); - opacity: 0.7; -} - /* ===================================================================== * LIGHT THEME — targeted contrast polish * Tokens stay; just bump the value-side text and the cyan accents that @@ -1990,16 +1932,7 @@ } /* Map-legend value column — same readability bump on white. */ -.v2Root[data-theme="light"] .mapLegendDist { - color: var(--text-strong); -} -.v2Root[data-theme="light"] .mapLegendLabel { - color: var(--text-strong); -} -.v2Root[data-theme="light"] .mapLegendDot { - box-shadow: none; -} -/* Map title (light): drop the dark text-shadow that makes thin uppercase +.v2Root[data-theme="light"] .v2Root[data-theme="light"] .v2Root[data-theme="light"] /* Map title (light): drop the dark text-shadow that makes thin uppercase look smudgy on a satellite-light map base. */ .v2Root[data-theme="light"] .mapHead .ttl { text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6); diff --git a/frontend/src/components/site-finder/ptica-v2/V2Map.tsx b/frontend/src/components/site-finder/ptica-v2/V2Map.tsx index 3d5d25df..b9b60a38 100644 --- a/frontend/src/components/site-finder/ptica-v2/V2Map.tsx +++ b/frontend/src/components/site-finder/ptica-v2/V2Map.tsx @@ -19,7 +19,6 @@ import styles from "@/app/site-finder/analysis/[cad]/v2/v2.module.css"; import type { ParcelAnalysis } from "@/types/site-finder"; import { useConnectionPoints } from "@/hooks/useConnectionPoints"; import { useCustomPois } from "@/hooks/useCustomPois"; -import { V2MapLegend } from "@/components/site-finder/ptica-v2/V2MapLegend"; const PticaMapInner = dynamic( () => import("@/components/site-finder/ptica/PticaMapInner"), @@ -61,9 +60,6 @@ export function V2Map({ analysis }: Props) { СПУТНИК · СХЕМА ПОДКЛЮЧЕНИЙ - {/* Resource legend overlay (sibling of PticaMapInner, sits on top of the - map via absolute positioning — does not touch the shared inner map). */} - ); } diff --git a/frontend/src/components/site-finder/ptica-v2/V2MapLegend.tsx b/frontend/src/components/site-finder/ptica-v2/V2MapLegend.tsx deleted file mode 100644 index b4a64329..00000000 --- a/frontend/src/components/site-finder/ptica-v2/V2MapLegend.tsx +++ /dev/null @@ -1,133 +0,0 @@ -"use client"; - -/** - * V2MapLegend — compact resource legend overlay rendered ON TOP of the cockpit - * map card (prototype `ptica-v2/index.html`, block `.legend > .lg-block.lg-res`). - * - * Five rows — ЭЛЕКТРИЧЕСТВО / ВОДА / КАНАЛИЗАЦИЯ / ТЕПЛОСНАБЖЕНИЕ / ГАЗ — each - * showing the distance to the nearest engineering node + a status-dot (green when - * the узел is within ~1 km, orange when further). Data comes from - * `analysis.utilities.summary[]` whose `subtype` values are the OSM `road_class` - * tags produced by the backend (see `noise_loader._NOISE_QUERIES` + `parcels.py` - * `_nearest()` aliases) — we aggregate them into the 5 prototype buckets. - * - * The legend is a SIBLING of `PticaMapInner` inside `V2Map` (the inner Leaflet - * mount is shared with the старый ptica route and must NOT be touched). All - * styles live in the scoped v2 module so the overlay never leaks into the - * application chrome. - */ - -import styles from "@/app/site-finder/analysis/[cad]/v2/v2.module.css"; -import type { ParcelAnalysis } from "@/types/site-finder"; - -type ResourceKey = "electric" | "water" | "sewer" | "heat" | "gas"; - -interface ResourceDef { - key: ResourceKey; - label: string; - /** OSM road_class values that count toward this bucket. */ - subtypes: readonly string[]; - /** CSS var for the dot accent color (matches prototype --res-* tokens). */ - color: string; -} - -// Aliases mirror backend `_nearest()` in `backend/app/api/v1/parcels.py`: -// electric ← substation | transformer | power_line -// water ← water_main | water_works | water_tower -// sewer ← sewerage -// heat ← heat_substation -// gas ← gas_pipeline (legacy generic «pipeline» falls under gas) -const RESOURCES: readonly ResourceDef[] = [ - { - key: "electric", - label: "ЭЛЕКТРИЧЕСТВО", - subtypes: ["substation", "transformer", "power_line"], - color: "var(--res-electric)", - }, - { - key: "water", - label: "ВОДА", - subtypes: ["water_main", "water_works", "water_tower"], - color: "var(--res-water)", - }, - { - key: "sewer", - label: "КАНАЛИЗАЦИЯ", - subtypes: ["sewerage"], - color: "var(--res-sewer)", - }, - { - key: "heat", - label: "ТЕПЛОСНАБЖЕНИЕ", - subtypes: ["heat_substation"], - color: "var(--res-heat)", - }, - { - key: "gas", - label: "ГАЗ", - subtypes: ["gas_pipeline", "pipeline"], - color: "var(--res-gas)", - }, -] as const; - -const OK_THRESHOLD_M = 1000; - -function formatDistanceMeters(m: number): string { - // Prototype uses tabular-num, single-line «1 240 м». Round to whole meters. - return `${Math.round(m).toLocaleString("ru-RU")} м`; -} - -function nearestForResource( - summary: ReadonlyArray<{ subtype: string; nearest_m: number }>, - subtypes: readonly string[], -): number | null { - let best: number | null = null; - for (const u of summary) { - if (!subtypes.includes(u.subtype)) continue; - if (best === null || u.nearest_m < best) best = u.nearest_m; - } - return best; -} - -interface Props { - analysis: ParcelAnalysis; -} - -export function V2MapLegend({ analysis }: Props) { - const summary = analysis.utilities?.summary ?? []; - - return ( -
-
ТОЧКИ ПОДКЛЮЧЕНИЯ РЕСУРСОВ
- {RESOURCES.map((res) => { - const nearest = nearestForResource(summary, res.subtypes); - const hasData = nearest !== null; - const ok = hasData && nearest! <= OK_THRESHOLD_M; - const dotColor = hasData - ? ok - ? "var(--accent-green)" - : "var(--accent-orange)" - : "var(--text-soft)"; - return ( -
-
- ); - })} -
- ); -} -- 2.45.3