Files
Termix/src/ui/desktop/apps/features/server-stats/widgets/DiskWidget.tsx
T

126 lines
4.0 KiB
TypeScript
Raw Normal View History

+7
2025-11-05 10:36:16 -06:00
import React from "react";
+1
2025-12-31 22:20:12 -06:00
import { HardDrive } from "lucide-react";
+7
2025-11-05 10:36:16 -06:00
import { useTranslation } from "react-i18next";
import type { ServerMetrics } from "@/ui/main-axios.ts";
import { RechartsPrimitive } from "@/components/ui/chart.tsx";
const {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} = RechartsPrimitive;
+1
2025-12-31 22:20:12 -06:00
interface DiskWidgetProps {
+7
2025-11-05 10:36:16 -06:00
metrics: ServerMetrics | null;
metricsHistory: ServerMetrics[];
}
+1
2025-12-31 22:20:12 -06:00
export function DiskWidget({ metrics, metricsHistory }: DiskWidgetProps) {
+7
2025-11-05 10:36:16 -06:00
const { t } = useTranslation();
const chartData = React.useMemo(() => {
return metricsHistory.map((m, index) => ({
index,
+1
2025-12-31 22:20:12 -06:00
disk: m.disk?.percent || 0,
+7
2025-11-05 10:36:16 -06:00
}));
}, [metricsHistory]);
return (
+1
2025-12-31 22:20:12 -06:00
<div className="h-full w-full p-4 rounded-lg bg-elevated border border-edge/50 hover:bg-elevated/70 flex flex-col overflow-hidden">
+7
2025-11-05 10:36:16 -06:00
<div className="flex items-center gap-2 flex-shrink-0 mb-3">
+1
2025-12-31 22:20:12 -06:00
<HardDrive className="h-5 w-5 text-orange-400" />
<h3 className="font-semibold text-lg text-foreground">
{t("serverStats.diskUsage")}
+7
2025-11-05 10:36:16 -06:00
</h3>
</div>
<div className="flex flex-col flex-1 min-h-0 gap-2">
<div className="flex items-baseline gap-3 flex-shrink-0">
+1
2025-12-31 22:20:12 -06:00
<div className="text-2xl font-bold text-orange-400">
{typeof metrics?.disk?.percent === "number"
? `${metrics.disk.percent}%`
+7
2025-11-05 10:36:16 -06:00
: "N/A"}
</div>
+1
2025-12-31 22:20:12 -06:00
<div className="text-xs text-muted-foreground">
+7
2025-11-05 10:36:16 -06:00
{(() => {
+1
2025-12-31 22:20:12 -06:00
const used = metrics?.disk?.usedHuman;
const total = metrics?.disk?.totalHuman;
if (used && total) {
return `${used} / ${total}`;
+7
2025-11-05 10:36:16 -06:00
}
return "N/A";
})()}
</div>
</div>
+1
2025-12-31 22:20:12 -06:00
<div className="text-xs text-foreground-subtle flex-shrink-0">
+7
2025-11-05 10:36:16 -06:00
{(() => {
+1
2025-12-31 22:20:12 -06:00
const available = metrics?.disk?.availableHuman;
return available
? `${t("serverStats.available")}: ${available}`
: `${t("serverStats.available")}: N/A`;
+7
2025-11-05 10:36:16 -06:00
})()}
</div>
<div className="flex-1 min-h-0">
<ResponsiveContainer width="100%" height="100%">
+1
2025-12-31 22:20:12 -06:00
<AreaChart
data={chartData}
margin={{ top: 5, right: 5, left: -25, bottom: 5 }}
>
+7
2025-11-05 10:36:16 -06:00
<defs>
+1
2025-12-31 22:20:12 -06:00
<linearGradient id="diskGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#fb923c" stopOpacity={0.8} />
<stop offset="95%" stopColor="#fb923c" stopOpacity={0.1} />
+7
2025-11-05 10:36:16 -06:00
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="#374151" />
<XAxis
dataKey="index"
stroke="#9ca3af"
tick={{ fill: "#9ca3af" }}
hide
/>
<YAxis
domain={[0, 100]}
stroke="#9ca3af"
tick={{ fill: "#9ca3af" }}
/>
<Tooltip
contentStyle={{
backgroundColor: "#1f2937",
border: "1px solid #374151",
borderRadius: "6px",
color: "#fff",
}}
+1
2025-12-31 22:20:12 -06:00
formatter={(value: number) => [`${value.toFixed(1)}%`, "Disk"]}
cursor={{
stroke: "#fb923c",
strokeWidth: 1,
strokeDasharray: "3 3",
}}
+7
2025-11-05 10:36:16 -06:00
/>
<Area
type="monotone"
+1
2025-12-31 22:20:12 -06:00
dataKey="disk"
stroke="#fb923c"
+7
2025-11-05 10:36:16 -06:00
strokeWidth={2}
+1
2025-12-31 22:20:12 -06:00
fill="url(#diskGradient)"
+7
2025-11-05 10:36:16 -06:00
animationDuration={300}
+1
2025-12-31 22:20:12 -06:00
activeDot={{
r: 4,
fill: "#fb923c",
stroke: "#fff",
strokeWidth: 2,
}}
+7
2025-11-05 10:36:16 -06:00
/>
</AreaChart>
</ResponsiveContainer>
</div>
</div>
</div>
);
}