feat(tradein/estimate): юр-строка «Ориентировочный расчёт. Не является официальной оценкой.»
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-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 1m3s

Блок 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 соседнего блока, чтобы новая строка не сжимала
плитки "ИСТОЧНИКИ ДАННЫХ" на фиксированной высоте артборда.
This commit is contained in:
bot-backend 2026-08-14 15:25:58 +03:00
parent b0776cd01d
commit 1b7e047210
3 changed files with 55 additions and 7 deletions

View file

@ -5,6 +5,9 @@
/** /**
* HeroSummary Секция 1 «Сводка» из mockup tradein.html. * HeroSummary Секция 1 «Сводка» из mockup tradein.html.
* Показывает медиану + достоверность CV + параметры объекта + 2 ценовых бара (объявления / сделки). * Показывает медиану + достоверность CV + параметры объекта + 2 ценовых бара (объявления / сделки).
*
* hero-duo__hint под диапазоном сделок несёт юр-требование владельца от
* 14.08.2026 (блок 4.1): SHORT_ESTIMATE_DISCLAIMER см. `lib/legal-copy.ts`.
*/ */
import { useState } from "react"; import { useState } from "react";
import type { AggregatedEstimate, TradeInEstimateInput, HouseType, RepairState, ConfidenceLevel } from "@/types/trade-in"; 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 { useActiveBrandSlug, useBrand } from "@/lib/useBrand";
import { sourceDot, sourceLabel } from "@/lib/source-registry"; import { sourceDot, sourceLabel } from "@/lib/source-registry";
import { dealsAsOfLabel } from "@/lib/rosreestr"; import { dealsAsOfLabel } from "@/lib/rosreestr";
import { SHORT_ESTIMATE_DISCLAIMER } from "@/lib/legal-copy";
import { HeroTransparency } from "./HeroTransparency"; import { HeroTransparency } from "./HeroTransparency";
interface Props { interface Props {
@ -478,6 +482,9 @@ export function HeroSummary({ estimate, input, onResubmit, isResubmitting = fals
</div> </div>
)} )}
<p className="hero-duo__hint"> <p className="hero-duo__hint">
{/* Блок 4.1 (владелец, 14.08.2026) юр-строка идёт первым
предложением абзаца-дисклеймера, не отдельным блоком. */}
{SHORT_ESTIMATE_DISCLAIMER}{" "}
Диапазон отражает разброс цен по рынку, а не погрешность оценки. Диапазон отражает разброс цен по рынку, а не погрешность оценки.
{/* #2209: честное раскрытие точности замеренное покрытие бэктестом {/* #2209: честное раскрытие точности замеренное покрытие бэктестом
по реальным ДКП Росреестра (2026-07: n=276, coverage 81.5%). по реальным ДКП Росреестра (2026-07: n=276, coverage 81.5%).

View file

@ -1,9 +1,14 @@
"use client"; "use client";
/**
* §1.2-дисклеймер под ценовыми карточками несёт юр-требование владельца от
* 14.08.2026 (блок 4.1): SHORT_ESTIMATE_DISCLAIMER см. `lib/legal-copy.ts`.
*/
import { Fragment } from "react"; import { Fragment } from "react";
import type { Ref } from "react"; import type { Ref } from "react";
import { tokens } from "./tokens"; import { tokens } from "./tokens";
import type { ResultPanelData } from "./mappers"; import type { ResultPanelData } from "./mappers";
import { SHORT_ESTIMATE_DISCLAIMER } from "@/lib/legal-copy";
const { const {
accent, accent,
@ -557,20 +562,29 @@ export default function ResultPanel({
})} })}
</div> </div>
{/* §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) не менялась. */}
<div <div
style={{ style={{
// M3 — было 10px muted-микропринт; повышено до 12px body, чтобы // M3 — было 10px muted-микропринт; повышено до 12px body, чтобы
// ключевая honest-оговорка о разбросе читалась, а не терялась. // ключевая honest-оговорка о разбросе читалась, а не терялась.
fontSize: 12, fontSize: 12,
lineHeight: 1.5, lineHeight: 1.4,
color: body, color: body,
marginTop: -4, marginTop: -6,
}} }}
> >
Диапазоны показывают разброс цен на рынке, а не погрешность оценки. {SHORT_ESTIMATE_DISCLAIMER} Диапазоны показывают разброс цен на рынке,
а не погрешность оценки.
</div> </div>
{/* ranges + radar */} {/* ranges + radar */}
@ -581,7 +595,9 @@ export default function ResultPanel({
backdropFilter: "blur(6px)", backdropFilter: "blur(6px)",
border: `1px solid ${line2}`, border: `1px solid ${line2}`,
borderRadius: 8, borderRadius: 8,
padding: "18px 20px", // было "18px 20px" — вертикаль подрезана на 4px сверху/снизу, см.
// комментарий к дисклеймеру выше (компенсация высоты под #4.1).
padding: "14px 20px",
display: "grid", display: "grid",
gridTemplateColumns: "1fr 1fr", gridTemplateColumns: "1fr 1fr",
gap: 24, gap: 24,

View file

@ -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 =
"Ориентировочный расчёт. Не является официальной оценкой.";