gendesign/tradein-mvp/frontend/src/app/cache/page.tsx
TradeIn Deploy abafb60120 feat(tradein): рабочие страницы История и Кэш (#399)
Заглушки навбара (href=#) → рабочие страницы.

- GET /api/v1/trade-in/history — последние оценки из trade_in_estimates.
- GET /api/v1/trade-in/cache-stats — счётчики данных/кэшей.
- app/history/page.tsx — таблица прошлых оценок, ссылки на отчёты.
- app/cache/page.tsx — состояние данных (объявления, сделки, кадастр,
  кэш геокодера, последний парсинг).
- navbar — ссылки История / Кэш ведут на страницы.

Closes #399
2026-05-22 11:28:27 +05:00

92 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
/* Состояние данных и кэшей (#399). */
import { useEffect, useState } from "react";
import "@/components/trade-in/trade-in.css";
import { API_BASE_URL } from "@/lib/api";
interface CacheStats {
geocode_cache: number;
geocode_cache_fresh: number;
listings_active: number;
listings_last_scraped: string | null;
deals: number;
cad_buildings: number;
house_metadata: number;
estimates_total: number;
}
export default function CachePage() {
const [stats, setStats] = useState<CacheStats | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`${API_BASE_URL}/api/v1/trade-in/cache-stats`)
.then((r) => (r.ok ? r.json() : null))
.then((d) => setStats(d as CacheStats | null))
.catch(() => setStats(null))
.finally(() => setLoading(false));
}, []);
const items: Array<[string, string]> = stats
? [
["Оценок всего", String(stats.estimates_total)],
["Объявлений активных", String(stats.listings_active)],
["Сделок", String(stats.deals)],
["Кадастр зданий", String(stats.cad_buildings)],
["Кэш домов (house_metadata)", String(stats.house_metadata)],
[
"Кэш геокодера (всего / свежих)",
`${stats.geocode_cache} / ${stats.geocode_cache_fresh}`,
],
[
"Последний парсинг объявлений",
stats.listings_last_scraped
? new Date(stats.listings_last_scraped).toLocaleString("ru-RU")
: "—",
],
]
: [];
return (
<main className="page" style={{ padding: 24, maxWidth: 700, margin: "0 auto" }}>
<p style={{ marginBottom: 12 }}>
<a href={`${API_BASE_URL}/`}> К оценке</a>
</p>
<h1 style={{ fontSize: 20, fontWeight: 700, marginBottom: 16 }}>
Состояние данных и кэшей
</h1>
{loading ? (
<p style={{ color: "var(--muted)" }}>Загрузка</p>
) : !stats ? (
<p style={{ color: "var(--muted)" }}>Не удалось загрузить статистику.</p>
) : (
<div
style={{
border: "1px solid var(--border, #e5e5e5)",
borderRadius: 8,
overflow: "hidden",
}}
>
{items.map(([k, v], i) => (
<div
key={k}
style={{
display: "flex",
justifyContent: "space-between",
padding: "11px 14px",
fontSize: 14,
borderTop: i === 0 ? "none" : "1px solid var(--border, #eee)",
}}
>
<span style={{ color: "var(--muted)" }}>{k}</span>
<span style={{ fontWeight: 600 }}>{v}</span>
</div>
))}
</div>
)}
</main>
);
}