Files
MikrotikManager/components/dashboard/latency-chart.tsx
T
2026-05-02 01:17:08 +07:00

92 lines
2.8 KiB
TypeScript

"use client"
interface LatencyChartProps {
series: Record<string, number[]>
}
// Maps to CSS variables defined in globals.css
const COLORS: Record<string, string> = {
msk: "var(--chart-line-1)",
spb: "var(--chart-line-2)",
fra: "var(--chart-line-3)",
ams: "var(--chart-line-4)",
}
const LABELS: Record<string, string> = {
msk: "MSK",
spb: "SPB",
fra: "FRA",
ams: "AMS",
}
export function LatencyChart({ series }: LatencyChartProps) {
const W = 800, H = 220
const pad = { l: 44, r: 12, t: 12, b: 28 }
const iw = W - pad.l - pad.r
const ih = H - pad.t - pad.b
const allVals = Object.values(series).flat()
const maxVal = Math.ceil(Math.max(...allVals) / 20) * 20 + 10
const xAt = (i: number, n: number) => pad.l + (i / (n - 1)) * iw
const yAt = (v: number) => pad.t + (1 - v / maxVal) * ih
const gridLines = [0, 0.25, 0.5, 0.75, 1]
return (
<div>
<svg viewBox={`0 0 ${W} ${H}`} style={{ width: "100%", height: 220, display: "block" }}>
{gridLines.map((p, i) => (
<g key={i}>
<line
x1={pad.l} x2={W - pad.r}
y1={pad.t + ih * p} y2={pad.t + ih * p}
style={{ stroke: "var(--border)" }}
strokeDasharray={p === 1 ? "0" : "2 4"}
/>
<text
x={pad.l - 8} y={pad.t + ih * p + 4}
textAnchor="end" fontSize="10"
style={{ fill: "var(--muted-foreground)" }}
fontFamily="var(--font-mono, monospace)"
>
{Math.round(maxVal * (1 - p))}мс
</text>
</g>
))}
{[0, 15, 30, 45, 59].map((i) => (
<text
key={i}
x={xAt(i, 60)} y={H - 6}
textAnchor="middle" fontSize="10"
style={{ fill: "var(--muted-foreground)" }}
fontFamily="var(--font-mono, monospace)"
>
-{60 - i}м
</text>
))}
{Object.entries(series).map(([key, arr]) => {
const pts = arr.map((v, i) => `${xAt(i, arr.length).toFixed(1)},${yAt(v).toFixed(1)}`).join(" ")
const color = COLORS[key] ?? "var(--chart-line-1)"
return (
<polyline key={key} points={pts} fill="none"
style={{ stroke: color }}
strokeWidth="1.6" strokeLinejoin="round" />
)
})}
</svg>
<div className="flex gap-4 pt-2 pl-11">
{Object.keys(series).map((k) => {
const color = COLORS[k] ?? "var(--chart-line-1)"
return (
<div key={k} className="flex items-center gap-1.5 text-xs">
<span className="w-3 h-0.5 rounded" style={{ background: color }} />
<span className="font-mono text-foreground">{LABELS[k]}</span>
</div>
)
})}
</div>
</div>
)
}