Files
openclaw-market/components/dashboard/activity-timeline.tsx

96 lines
2.6 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { useTranslations } from "next-intl";
import {
AreaChart,
Area,
XAxis,
YAxis,
Tooltip,
ResponsiveContainer,
} from "recharts";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
interface HourlyData {
hour: string;
count: number;
}
export function ActivityTimeline() {
const t = useTranslations("activityTimeline");
const [data, setData] = useState<HourlyData[]>([]);
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch("/api/v1/stats");
if (res.ok) {
const json = await res.json();
setData(json.hourlyActivity ?? []);
}
} catch {
// retry on next interval
}
};
fetchData();
const interval = setInterval(fetchData, 30000);
return () => clearInterval(interval);
}, []);
return (
<Card className="border-white/5">
<CardHeader className="pb-2">
<CardTitle>{t("title")}</CardTitle>
</CardHeader>
<CardContent>
<div className="h-[160px] w-full">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={data}>
<defs>
<linearGradient id="activityGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#00f0ff" stopOpacity={0.3} />
<stop offset="100%" stopColor="#00f0ff" stopOpacity={0} />
</linearGradient>
</defs>
<XAxis
dataKey="hour"
tick={{ fill: "#64748b", fontSize: 10 }}
axisLine={false}
tickLine={false}
interval="preserveStartEnd"
/>
<YAxis hide />
<Tooltip
contentStyle={{
backgroundColor: "#1a1f2e",
border: "1px solid rgba(255,255,255,0.1)",
borderRadius: "8px",
color: "#e2e8f0",
fontSize: 12,
}}
labelStyle={{ color: "#94a3b8" }}
/>
<Area
type="monotone"
dataKey="count"
stroke="#00f0ff"
strokeWidth={2}
fill="url(#activityGradient)"
dot={false}
activeDot={{
r: 4,
fill: "#00f0ff",
stroke: "#0a0e1a",
strokeWidth: 2,
}}
/>
</AreaChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
);
}