merge main в ветку PDF-подвала (перезапуск CI после флака test_auth_api таймингов)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 13s
CI / changes (pull_request) Successful in 13s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (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 / backend-tests (pull_request) Successful in 4m51s

This commit is contained in:
bot-backend 2026-08-14 15:41:41 +03:00
commit 7d89c87e21
5 changed files with 73 additions and 9 deletions

View file

@ -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() {
МЕРА
</div>
<p className={styles.headerTag}>
Оценка вторичного жилья · {REGION_NAME}
Оценка вторичного жилья по рыночным данным · {REGION_NAME}
</p>
</div>
</header>

View file

@ -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 },
};

View file

@ -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
</div>
)}
<p className="hero-duo__hint">
{/* Блок 4.1 (владелец, 14.08.2026) юр-строка идёт первым
предложением абзаца-дисклеймера, не отдельным блоком. */}
{SHORT_ESTIMATE_DISCLAIMER}{" "}
Диапазон отражает разброс цен по рынку, а не погрешность оценки.
{/* #2209: честное раскрытие точности замеренное покрытие бэктестом
по реальным ДКП Росреестра (2026-07: n=276, coverage 81.5%).

View file

@ -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({
})}
</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
style={{
// M3 — было 10px muted-микропринт; повышено до 12px body, чтобы
// ключевая honest-оговорка о разбросе читалась, а не терялась.
fontSize: 12,
lineHeight: 1.5,
lineHeight: 1.4,
color: body,
marginTop: -4,
marginTop: -6,
}}
>
Диапазоны показывают разброс цен на рынке, а не погрешность оценки.
{SHORT_ESTIMATE_DISCLAIMER} Диапазоны показывают разброс цен на рынке,
а не погрешность оценки.
</div>
{/* 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,

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