"use client"; /** * #801: dev/CI-only preview-маршрут «денежного экрана» на статичной фикстуре. * * Зачем: a11y (axe) и lighthouse требуют отрендеренную контентную страницу. * Live trade-in за auth-gate, а локальный фронт без бэкенда = белый экран * (RouteGuard висит на pending /me). Эта страница рендерит реальные компоненты * результата (HeroSummary + карточки/чарты) полностью оффлайн — без сети. * * Включается ТОЛЬКО при NEXT_PUBLIC_ENABLE_PREVIEW=1 (иначе notFound) — в проде * по умолчанию недоступна. RouteGuard пропускает /ui-preview/* под тем же флагом. * (Папка НЕ может начинаться с "_" — Next трактует такие как private/non-routable.) * * Локально: echo NEXT_PUBLIC_ENABLE_PREVIEW=1 > .env.local && npm run dev * → http://localhost:3000/ui-preview/estimate * CI: собрать с флагом, поднять next start, навести axe/lighthouse. */ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { notFound } from "next/navigation"; import { useState } from "react"; import "@/components/trade-in/trade-in.css"; import { CianValuationCard } from "@/components/trade-in/CianValuationCard"; import { DealsCard } from "@/components/trade-in/DealsCard"; import { DistributionCard } from "@/components/trade-in/DistributionCard"; import { ExposureCard } from "@/components/trade-in/ExposureCard"; import { HeroSummary } from "@/components/trade-in/HeroSummary"; import { PriceTrendCard } from "@/components/trade-in/PriceTrendCard"; import { StreetDealsCard } from "@/components/trade-in/StreetDealsCard"; import { ME_QUERY_KEY, type UserScope } from "@/lib/useMe"; import { FIXTURE_ESTIMATE, FIXTURE_INPUT } from "./fixture"; const ENABLED = process.env.NEXT_PUBLIC_ENABLE_PREVIEW === "1"; // Фейковый authorized-юзер: засеивается в QueryClient → useMe/useBrand резолвятся // оффлайн (никакого /me, /quota, /brand), generic-бренд (brand=null). const PREVIEW_USER: UserScope = { username: "preview", role: "admin", allowed_paths: ["/**"], deny_paths: [], brand: null, }; function PreviewContent() { const [client] = useState(() => { const qc = new QueryClient({ defaultOptions: { queries: { retry: false, staleTime: Infinity, refetchOnWindowFocus: false }, }, }); qc.setQueryData(ME_QUERY_KEY, PREVIEW_USER); return qc; }); return ( {/* Те же layout-классы, что у реальной страницы (page.tsx): .page → .result-col (flex-column gap, --container ширина). Без них карточки рендерились узко/«мобильно». */}
{}} isResubmitting={false} />
); } export default function PreviewEstimatePage() { if (!ENABLED) notFound(); return ; }