Прод-/trade-in/* обслуживает tradein-mvp/frontend (basePath=/trade-in, standalone), а не главный frontend — v2 по ошибке попал в главный, где прод его не отдаёт. Markup-only порт (fixtures, без API): - компоненты v2 → tradein-mvp/frontend/src/components/trade-in/v2/ - роут src/app/v2/ (basePath даёт прод-URL /trade-in/v2) - public/trade-in-v2/building.png - HeroBar: <img> → next/image (плоский img не префиксит basePath → 404) - удалён мёртвый v2 из главного frontend next build (NEXT_PUBLIC_BASE_PATH=/trade-in) зелёный, роут /v2 prerendered.
147 lines
4 KiB
TypeScript
147 lines
4 KiB
TypeScript
// OVERLAY 07: ПРЕДЫДУЩИЕ ОЦЕНКИ (cache view).
|
||
// Faithful markup port of МЕРА Оценка.dc.html lines 593-613.
|
||
// Data from fixtures (cacheKpi + cacheRows); no API, no local state.
|
||
|
||
import { tokens } from "./tokens";
|
||
import { cacheKpi, cacheRows } from "./fixtures";
|
||
|
||
const GRID_COLUMNS = "2.4fr 1fr 1fr 1fr";
|
||
|
||
export function CacheView() {
|
||
return (
|
||
<div style={{ display: "flex", flexDirection: "column", gap: 22 }}>
|
||
{/* 3 KPI cards */}
|
||
<div
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: "repeat(3,1fr)",
|
||
gap: 16,
|
||
}}
|
||
>
|
||
{cacheKpi.map((kpi) => (
|
||
<div
|
||
key={kpi.label}
|
||
style={{
|
||
background: tokens.surface.w55,
|
||
border: `1px solid ${tokens.line2}`,
|
||
borderRadius: 8,
|
||
padding: "16px 18px",
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
fontSize: 9.5,
|
||
letterSpacing: 1.5,
|
||
color: tokens.muted2,
|
||
}}
|
||
>
|
||
{kpi.label}
|
||
</div>
|
||
<div
|
||
style={{
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 30,
|
||
fontWeight: 300,
|
||
color: tokens.ink2,
|
||
margin: "8px 0 5px",
|
||
}}
|
||
>
|
||
{kpi.value}
|
||
{kpi.unit && (
|
||
<>
|
||
{kpi.unit !== "%" && " "}
|
||
<span style={{ fontSize: 14, color: tokens.muted }}>
|
||
{kpi.unit}
|
||
</span>
|
||
</>
|
||
)}
|
||
</div>
|
||
<div style={{ fontSize: 10, color: tokens.hint }}>{kpi.sub}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
{/* Последние оценки table */}
|
||
<div
|
||
style={{
|
||
background: tokens.surface.w55,
|
||
border: `1px solid ${tokens.line2}`,
|
||
borderRadius: 8,
|
||
overflow: "hidden",
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
padding: "14px 18px",
|
||
borderBottom: `1px solid ${tokens.lineSoft}`,
|
||
fontSize: 12,
|
||
fontWeight: 600,
|
||
color: tokens.ink2,
|
||
}}
|
||
>
|
||
Последние оценки
|
||
</div>
|
||
<div
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: GRID_COLUMNS,
|
||
gap: 10,
|
||
padding: "9px 18px",
|
||
fontSize: 9,
|
||
letterSpacing: 1,
|
||
color: tokens.muted2,
|
||
borderBottom: `1px solid ${tokens.lineSoft2}`,
|
||
}}
|
||
>
|
||
<span>АДРЕС</span>
|
||
<span>ВРЕМЯ</span>
|
||
<span>ИСТОЧНИКОВ</span>
|
||
<span>СТАТУС</span>
|
||
</div>
|
||
{cacheRows.map((r, i) => (
|
||
<div
|
||
key={`${r.addr}-${i}`}
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: GRID_COLUMNS,
|
||
gap: 10,
|
||
padding: "12px 18px",
|
||
fontSize: 11,
|
||
borderBottom: `1px solid ${tokens.lineSoft3}`,
|
||
alignItems: "center",
|
||
}}
|
||
>
|
||
<span style={{ color: tokens.body }}>{r.addr}</span>
|
||
<span
|
||
style={{ fontFamily: tokens.font.mono, color: tokens.muted2 }}
|
||
>
|
||
{r.time}
|
||
</span>
|
||
<span style={{ fontFamily: tokens.font.mono, color: tokens.muted }}>
|
||
{r.src}
|
||
</span>
|
||
<span
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 6,
|
||
fontSize: 10,
|
||
color: r.statusColor,
|
||
}}
|
||
>
|
||
<span
|
||
style={{
|
||
width: 7,
|
||
height: 7,
|
||
borderRadius: "50%",
|
||
background: r.statusColor,
|
||
}}
|
||
/>
|
||
{r.status}
|
||
</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|