From 1b7e047210e11787d8b0b9cea5d72ebd77697713 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Fri, 14 Aug 2026 15:25:58 +0300 Subject: [PATCH 1/2] =?UTF-8?q?feat(tradein/estimate):=20=D1=8E=D1=80-?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0=20=C2=AB=D0=9E=D1=80=D0=B8?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=BE=D1=87=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D1=80=D0=B0=D1=81=D1=87=D1=91=D1=82.=20=D0=9D?= =?UTF-8?q?=D0=B5=20=D1=8F=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F=20?= =?UTF-8?q?=D0=BE=D1=84=D0=B8=D1=86=D0=B8=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=BE=D1=86=D0=B5=D0=BD=D0=BA=D0=BE=D0=B9.=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Блок 4.1 юр-требований владельца (14.08.2026): под диапазоном цены на экране результата обязана быть эта строка. Вынесена в новый модуль lib/legal-copy.ts (SHORT_ESTIMATE_DISCLAIMER, без импортов) — используется и в v2/ResultPanel.tsx (боевой экран /v2), и в HeroSummary.tsx (legacy-контур /trade-in/ui-preview/estimate), первым предложением в уже существующем абзаце-дисклеймере про рыночный разброс. В ResultPanel.tsx подрезаны lineHeight/marginTop/padding соседнего блока, чтобы новая строка не сжимала плитки "ИСТОЧНИКИ ДАННЫХ" на фиксированной высоте артборда. --- .../src/components/trade-in/HeroSummary.tsx | 7 +++++ .../components/trade-in/v2/ResultPanel.tsx | 30 ++++++++++++++----- tradein-mvp/frontend/src/lib/legal-copy.ts | 25 ++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 tradein-mvp/frontend/src/lib/legal-copy.ts diff --git a/tradein-mvp/frontend/src/components/trade-in/HeroSummary.tsx b/tradein-mvp/frontend/src/components/trade-in/HeroSummary.tsx index 652bd91e..7a6b0b9f 100644 --- a/tradein-mvp/frontend/src/components/trade-in/HeroSummary.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/HeroSummary.tsx @@ -5,6 +5,9 @@ /** * HeroSummary — Секция 1 «Сводка» из mockup tradein.html. * Показывает медиану + достоверность CV + параметры объекта + 2 ценовых бара (объявления / сделки). + * + * hero-duo__hint под диапазоном сделок несёт юр-требование владельца от + * 14.08.2026 (блок 4.1): SHORT_ESTIMATE_DISCLAIMER — см. `lib/legal-copy.ts`. */ import { useState } from "react"; import type { AggregatedEstimate, TradeInEstimateInput, HouseType, RepairState, ConfidenceLevel } from "@/types/trade-in"; @@ -12,6 +15,7 @@ import { asHouseType, asRepairState } from "@/types/trade-in"; import { useActiveBrandSlug, useBrand } from "@/lib/useBrand"; import { sourceDot, sourceLabel } from "@/lib/source-registry"; import { dealsAsOfLabel } from "@/lib/rosreestr"; +import { SHORT_ESTIMATE_DISCLAIMER } from "@/lib/legal-copy"; import { HeroTransparency } from "./HeroTransparency"; interface Props { @@ -478,6 +482,9 @@ export function HeroSummary({ estimate, input, onResubmit, isResubmitting = fals )}

+ {/* Блок 4.1 (владелец, 14.08.2026) — юр-строка идёт первым + предложением абзаца-дисклеймера, не отдельным блоком. */} + {SHORT_ESTIMATE_DISCLAIMER}{" "} Диапазон отражает разброс цен по рынку, а не погрешность оценки. {/* #2209: честное раскрытие точности — замеренное покрытие бэктестом по реальным ДКП Росреестра (2026-07: n=276, coverage 81.5%). diff --git a/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx b/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx index e2d50e8d..80895489 100644 --- a/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/v2/ResultPanel.tsx @@ -1,9 +1,14 @@ "use client"; +/** + * §1.2-дисклеймер под ценовыми карточками несёт юр-требование владельца от + * 14.08.2026 (блок 4.1): SHORT_ESTIMATE_DISCLAIMER — см. `lib/legal-copy.ts`. + */ import { Fragment } from "react"; import type { Ref } from "react"; import { tokens } from "./tokens"; import type { ResultPanelData } from "./mappers"; +import { SHORT_ESTIMATE_DISCLAIMER } from "@/lib/legal-copy"; const { accent, @@ -557,20 +562,29 @@ export default function ResultPanel({ })} - {/* §1.2 честный разброс: диапазоны цен = рыночный спред, НЕ погрешность - оценки. Ставим сразу под ценовыми карточками, чтобы широкий диапазон - не читался как «неуверенность расчёта». */} + {/* §1.2 честный разброс + юр-дисклеймер (владелец, 14.08.2026, блок 4.1): + SHORT_ESTIMATE_DISCLAIMER идёт первым предложением, "разброс цен" + — вторым, один абзац (три отдельных оговорки подряд читались бы + как шум). Ставим сразу под ценовыми карточками, чтобы широкий + диапазон не читался как «неуверенность расчёта». + Компенсация высоты: этот блок стал на строку выше, чем до + SHORT_ESTIMATE_DISCLAIMER (776px средняя колонка узкая для двух + предложений в одну строку) — lineHeight/marginTop подрезаны, и + padding у "ranges + radar" box ниже уменьшен по вертикали, чтобы + не сжимать плитки "ИСТОЧНИКИ ДАННЫХ" (flex:1 ниже). Высота + артборда (1536×1024, v2/page.tsx) не менялась. */}

- Диапазоны показывают разброс цен на рынке, а не погрешность оценки. + {SHORT_ESTIMATE_DISCLAIMER} Диапазоны показывают разброс цен на рынке, + а не погрешность оценки.
{/* ranges + radar */} @@ -581,7 +595,9 @@ export default function ResultPanel({ backdropFilter: "blur(6px)", border: `1px solid ${line2}`, borderRadius: 8, - padding: "18px 20px", + // было "18px 20px" — вертикаль подрезана на 4px сверху/снизу, см. + // комментарий к дисклеймеру выше (компенсация высоты под #4.1). + padding: "14px 20px", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24, diff --git a/tradein-mvp/frontend/src/lib/legal-copy.ts b/tradein-mvp/frontend/src/lib/legal-copy.ts new file mode 100644 index 00000000..0ba3680e --- /dev/null +++ b/tradein-mvp/frontend/src/lib/legal-copy.ts @@ -0,0 +1,25 @@ +/** + * Юридические короткие оговорки для экранов расчёта «Меры». + * + * Источник: юр-требование владельца от 14.08.2026 (блок 4.1) — прямо под + * диапазоном цены на экране результата обязана быть строка «Ориентировочный + * расчёт. Не является официальной оценкой.». + * + * Модуль НАМЕРЕННО без импортов (кроме типов) — используется и из закрытого + * контура (`components/trade-in/v2/ResultPanel.tsx`, + * `components/trade-in/HeroSummary.tsx`), и потенциально из `/mera-public`, + * где действует isolation-guard + * (`scripts/check-mera-public-isolation.mjs`) — любой транзитивный импорт + * закрытого контура (useMe / lib/api / lib/sessionId / isPathAllowed) в + * публичный бандл провалит проверку. + * + * В репозитории уже есть соседние, но НЕ идентичные дисклеймеры — не путать + * и не плодить пятый/шестой литерал с той же сутью: + * - `src/app/mera-public/content.ts` → DELIVERABLES_DISCLAIMER (135-ФЗ) + * - `src/app/mera-public/_components/SiteFooter.tsx:109` + * - `src/app/oferta/page.tsx:253` + * - `backend/app/services/trade_in_pdf.py` (версия для PDF-отчёта) + */ + +export const SHORT_ESTIMATE_DISCLAIMER = + "Ориентировочный расчёт. Не является официальной оценкой."; From 91732d1acbecc7985bc7bff24d8dc7d784b3e8cd Mon Sep 17 00:00:00 2001 From: bot-backend Date: Fri, 14 Aug 2026 15:28:35 +0300 Subject: [PATCH 2/2] =?UTF-8?q?feat(mera):=20=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D1=83=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8=20=D1=88=D0=B0?= =?UTF-8?q?=D0=BF=D0=BA=D0=B8=20=D0=B8=20=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=B2=D0=BA=D0=BB=D0=B0=D0=B4=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=20=D1=8E=D1=80-=D1=82=D1=80=D0=B5=D0=B1?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20(=D0=B1=D0=BB?= =?UTF-8?q?=D0=BE=D0=BA=203)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Юр-документ владельца от 14.08.2026, блок 3: верхний дескриптор и заголовок вкладки должны уводить сервис от слова, отсылающего к отчёту оценщика по 135-ФЗ, и явно называть основание расчёта — рыночные данные. - Шапка лэндинга: «Оценка вторичного жилья · <регион>» → «Оценка вторичного жилья по рыночным данным · <регион>». Слово «МЕРА» остаётся вордмарком слева (у него свой letter-spacing), строка складывается из двух узлов; регион по-прежнему из REGION_NAME, не литералом. - Заголовок вкладки: «МЕРА — оценка квартиры на вторичном рынке» → «Мера · расчёт стоимости квартиры по рыночным данным». H1 первого экрана («Сколько на самом деле стоит ваша квартира») НЕ меняется — решение владельца: он не заявляет ничего про официальную оценку, а продающий заголовок терять незачем. Заголовки трёх юридических подстраниц живут по своему шаблону «<Документ> — МЕРА» и не затронуты. Проверено: tsc --noEmit, next lint, mera-public isolation guard (18 файлов). --- .../src/app/mera-public/_components/SiteHeader.tsx | 10 +++++++++- tradein-mvp/frontend/src/app/mera-public/layout.tsx | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tradein-mvp/frontend/src/app/mera-public/_components/SiteHeader.tsx b/tradein-mvp/frontend/src/app/mera-public/_components/SiteHeader.tsx index 4ec23dcc..a4c4d29a 100644 --- a/tradein-mvp/frontend/src/app/mera-public/_components/SiteHeader.tsx +++ b/tradein-mvp/frontend/src/app/mera-public/_components/SiteHeader.tsx @@ -4,6 +4,14 @@ * Логотип НЕ является ссылкой на "/": в next.config.ts стоит redirect "/" → "/v2", * то есть клик по нему выкинул бы публичного посетителя в закрытое B2B-приложение * (и дальше на /login). Пока публичная страница одна, вордмарк — просто текст. + * + * ФОРМУЛИРОВКА ДЕСКРИПТОРА (14.08.2026, юр-документ владельца, блок 3). Строка + * шапки обязана читаться как «МЕРА · Оценка вторичного жилья по рыночным данным · + * <регион>»: слова «по рыночным данным» — то, чем сервис отличается от оценки по + * 135-ФЗ, и юрист попросил, чтобы это стояло в самом заметном дескрипторе, а не + * только в дисклеймерах внизу. «МЕРА» приходит из вордмарка ниже (у него свой + * letter-spacing), поэтому в headerTag её нет — строка складывается из двух узлов. + * Регион — из REGION_NAME, не строкой (правило content.ts). */ import { REGION_NAME } from "../content"; @@ -18,7 +26,7 @@ export function SiteHeader() { МЕРА

- Оценка вторичного жилья · {REGION_NAME} + Оценка вторичного жилья по рыночным данным · {REGION_NAME}

diff --git a/tradein-mvp/frontend/src/app/mera-public/layout.tsx b/tradein-mvp/frontend/src/app/mera-public/layout.tsx index d3266fbb..a690d775 100644 --- a/tradein-mvp/frontend/src/app/mera-public/layout.tsx +++ b/tradein-mvp/frontend/src/app/mera-public/layout.tsx @@ -46,8 +46,16 @@ const plexMono = IBM_Plex_Mono({ display: "swap", }); +/** + * ЗАГОЛОВОК ВКЛАДКИ (14.08.2026, юр-документ владельца, блок 3). «Расчёт + * стоимости», а не «оценка квартиры»: заголовок вкладки — второе после шапки + * место, где формулировка читается как заявление о характере услуги, и юрист + * попросил увести её от слова, отсылающего к отчёту оценщика по 135-ФЗ. + * Заголовки трёх юридических подстраниц (оферта / возврат / ПДн) живут по + * своему шаблону «<Документ> — МЕРА» и этой правкой не затрагиваются. + */ export const metadata: Metadata = { - title: "МЕРА — оценка квартиры на вторичном рынке", + title: "Мера · расчёт стоимости квартиры по рыночным данным", description: `Узнайте рыночную стоимость квартиры по адресу: сделки Росреестра и объявления площадок. ${REGION_NAME}.`, robots: { index: false, follow: false }, };