112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
import { useContext } from "react";
|
|
import {
|
|
LineChart,
|
|
Line,
|
|
XAxis,
|
|
YAxis,
|
|
CartesianGrid,
|
|
ResponsiveContainer,
|
|
} from "recharts";
|
|
import { DataContext } from "@/lib/data-context";
|
|
import { greet } from "@/lib/utils";
|
|
|
|
const colors: Record<string, string> = {
|
|
lizzy: "#d985e6",
|
|
alex: "#66d1c3",
|
|
};
|
|
|
|
export default function UpdateChart() {
|
|
const data = useContext(DataContext);
|
|
if (!data.whois) return null;
|
|
|
|
const groupedData: { [name: string]: { time: number; value: number }[] } = {};
|
|
data.whois.forEach((update, i, arr) => {
|
|
if (!(update.name in groupedData)) groupedData[update.name] = [];
|
|
const msPerHour = 60 * 60 * 1000;
|
|
|
|
if (i === arr.length - 1) {
|
|
const now = new Date();
|
|
groupedData[update.name].push({ time: update.time, value: 0 });
|
|
groupedData[update.name].push({
|
|
time: now.getTime(),
|
|
value: (now.getTime() - update.time) / msPerHour,
|
|
});
|
|
}
|
|
|
|
if (i === 0) return;
|
|
const prev = arr[i - 1];
|
|
|
|
groupedData[prev.name].push({ time: prev.time, value: 0 });
|
|
groupedData[prev.name].push({
|
|
time: update.time,
|
|
value: (update.time - prev.time) / msPerHour,
|
|
});
|
|
groupedData[prev.name].push({ time: update.time, value: 0 });
|
|
});
|
|
|
|
const uniqueNames = Object.keys(groupedData);
|
|
const chartData = Object.entries(groupedData)
|
|
.flatMap(([name, dataPoints]) =>
|
|
dataPoints.map((data) => ({ time: data.time, name, [name]: data.value }))
|
|
)
|
|
.sort((a, b) => a.time - b.time);
|
|
|
|
return (
|
|
<div className="glass rounded-lg p-6 shadow-lg">
|
|
<div className="flex justify-center items-center mb-8">
|
|
<h2 className="text-4xl font-bold">
|
|
{greet(data.whois ? data.whois[0].name : "Friend", new Date())}
|
|
</h2>
|
|
</div>
|
|
|
|
<div className="h-64">
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<LineChart data={chartData}>
|
|
<CartesianGrid
|
|
strokeDasharray="3 3"
|
|
stroke="rgba(var(--foreground), 0.1)"
|
|
/>
|
|
<XAxis
|
|
dataKey="time"
|
|
type="number"
|
|
domain={["dataMin", "dataMax"]}
|
|
tickFormatter={(tick) => new Date(tick).toLocaleTimeString()}
|
|
stroke="rgba(var(--foreground), 0.6)"
|
|
/>
|
|
<YAxis
|
|
stroke="rgba(var(--foreground), 0.6)"
|
|
tickFormatter={(tick) => (tick === 0 ? "" : `${tick} hrs`)}
|
|
/>
|
|
{uniqueNames.map((uniqueName, index) => (
|
|
<Line
|
|
key={uniqueName}
|
|
type="linear"
|
|
dataKey={uniqueName}
|
|
data={chartData.filter(({ name }) => name === uniqueName)}
|
|
name={uniqueName}
|
|
stroke={colors[uniqueName] ?? "#ff0000"}
|
|
strokeWidth={3}
|
|
dot={false}
|
|
isAnimationActive={false}
|
|
/>
|
|
))}
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
<div className="mt-4 flex flex-wrap gap-2">
|
|
{Object.keys(groupedData).map((name) => (
|
|
<span
|
|
key={name}
|
|
className="px-3 py-1 rounded-full text-sm bg-pink-100 text-pink-800 dark:bg-gray-700 dark:text-pink-200"
|
|
style={{ color: colors[name] }}
|
|
>
|
|
{name}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|