3 pages (market, PRINZIP drilldown, developers leaderboard) on top of existing v_developer_full_metrics + domrf_realization views. ECharts on the frontend, FastAPI router /api/v1/analytics on the backend.
106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
"use client";
|
||
|
||
import { usePrinzipInsights } from "@/lib/analytics-api";
|
||
|
||
export function InsightCards() {
|
||
const { data } = usePrinzipInsights();
|
||
|
||
if (!data)
|
||
return <div style={{ color: "#5b6066" }}>Загрузка рекомендаций…</div>;
|
||
|
||
return (
|
||
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
||
<p
|
||
style={{ margin: 0, fontSize: 15, lineHeight: 1.55, color: "#1f2937" }}
|
||
>
|
||
{data.headline}
|
||
</p>
|
||
|
||
<div>
|
||
<h3 style={h3}>Приоритеты</h3>
|
||
<div style={grid}>
|
||
{data.priorities.map((p) => (
|
||
<div key={p.rank} style={card}>
|
||
<div style={badge}>#{p.rank}</div>
|
||
<div style={{ fontWeight: 600, marginTop: 6 }}>{p.title}</div>
|
||
<p style={pStyle}>{p.why}</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<h3 style={h3}>Где строить новое</h3>
|
||
<div style={grid}>
|
||
{data.where_to_build.map((w) => (
|
||
<div key={w.district} style={card}>
|
||
<div style={{ fontWeight: 600 }}>{w.district}</div>
|
||
<p style={pStyle}>{w.why}</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<h3 style={h3}>Чего избегать</h3>
|
||
<ul
|
||
style={{
|
||
margin: 0,
|
||
paddingLeft: 20,
|
||
lineHeight: 1.55,
|
||
color: "#374151",
|
||
}}
|
||
>
|
||
{data.what_to_avoid.map((s, i) => (
|
||
<li key={i}>{s}</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
|
||
<div>
|
||
<h3 style={h3}>Benchmark-модели</h3>
|
||
<div style={grid}>
|
||
{data.benchmarks.map((b) => (
|
||
<div key={b.name} style={card}>
|
||
<div style={{ fontWeight: 600 }}>{b.name}</div>
|
||
<p style={pStyle}>{b.model}</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
const h3 = {
|
||
fontSize: 14,
|
||
fontWeight: 600,
|
||
color: "#374151",
|
||
margin: "0 0 8px",
|
||
};
|
||
const grid = {
|
||
display: "grid",
|
||
gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
|
||
gap: 12,
|
||
};
|
||
const card = {
|
||
background: "#f9fafb",
|
||
border: "1px solid #e6e8ec",
|
||
borderRadius: 8,
|
||
padding: "12px 14px",
|
||
};
|
||
const badge = {
|
||
display: "inline-block",
|
||
background: "#1d4ed8",
|
||
color: "#fff",
|
||
fontSize: 12,
|
||
fontWeight: 600,
|
||
borderRadius: 4,
|
||
padding: "2px 8px",
|
||
};
|
||
const pStyle = {
|
||
margin: "6px 0 0",
|
||
fontSize: 13,
|
||
color: "#4b5563",
|
||
lineHeight: 1.5,
|
||
};
|