summaryrefslogtreecommitdiff
path: root/app/components/WhoisChart.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'app/components/WhoisChart.tsx')
-rw-r--r--app/components/WhoisChart.tsx111
1 files changed, 111 insertions, 0 deletions
diff --git a/app/components/WhoisChart.tsx b/app/components/WhoisChart.tsx
new file mode 100644
index 0000000..43f5eb9
--- /dev/null
+++ b/app/components/WhoisChart.tsx
@@ -0,0 +1,111 @@
+"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>
+ );
+}