mhsf-dev/src/components/NewChart.tsx

175 lines
5.1 KiB
TypeScript
Raw Normal View History

2024-07-26 15:40:13 -05:00
"use client";
import * as React from "react";
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart";
import { useEffectOnce } from "@/lib/useEffectOnce";
import { ServerResponse } from "./ServerView";
const chartConfig = {
player_count: {
label: "Joins",
color: "hsl(var(--chart-1))",
},
favorites: {
label: "Favorites",
color: "hsl(var(--chart-3))",
},
} satisfies ChartConfig;
export function NewChart({ server }: { server: string }) {
const [activeChart, setActiveChart] =
React.useState<keyof typeof chartConfig>("player_count");
const [chartData, setChartData] = React.useState<any>([]);
const [joins, setJoins] = React.useState<any>(0);
const [favorites, setFavorites] = React.useState<any>(0);
const allNums = { player_count: joins, favorites };
useEffectOnce(() => {
fetch("/api/history/getShortTermData", {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
scopes: ["player_count", "favorites", "time"],
server,
}),
method: "POST",
}).then((c) => {
c.json().then((b) => {
setChartData(b.data);
fetch("/api/favorites/getCommunityNum", {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ server }),
method: "POST",
}).then((b) =>
b.json().then((f) => {
setFavorites(f.result);
})
);
fetch("https://api.minehut.com/server/" + server + "?byName=true").then(
(k) => {
k.json().then((p: { server: ServerResponse }) => {
setJoins(p.server.joins);
});
}
);
});
});
});
return (
<Card className="w-full">
<CardHeader className="flex flex-col items-stretch space-y-0 border-b p-0 sm:flex-row">
<div className="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
<CardTitle>
{chartConfig[activeChart].label} Chart for {server}
</CardTitle>
<CardDescription>Showing the past 30 entries.</CardDescription>
</div>
<div className="flex">
{["player_count", "favorites"].map((key) => {
const chart = key as keyof typeof chartConfig;
return (
<button
key={chart}
data-active={activeChart === chart}
className="flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l data-[active=true]:bg-muted/50 sm:border-l sm:border-t-0 sm:px-8 sm:py-6"
onClick={() => setActiveChart(chart)}
>
<span className="text-xs text-muted-foreground">
{chartConfig[chart].label}
</span>
<span className="text-lg font-bold leading-none sm:text-3xl">
{convert(allNums[chart])}
</span>
</button>
);
})}
</div>
</CardHeader>
<CardContent className="px-2 sm:p-6">
<ChartContainer
config={chartConfig}
className="aspect-auto h-[250px] w-full"
>
<LineChart
accessibilityLayer
data={chartData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="time"
tickLine={false}
axisLine={false}
tickMargin={8}
minTickGap={32}
tickFormatter={(value) => {
const date = new Date(value);
return date.toLocaleTimeString("en-US", {
timeStyle: "short",
});
}}
/>
<YAxis
dataKey={activeChart}
tickLine={false}
axisLine={false}
tickFormatter={(value) => {
return (
value +
(activeChart == "player_count"
? ` plyr${value != 1 ? "s" : ""}.`
: ` ${value == 1 ? "favorite" : "favrts."}`)
);
}}
/>
<ChartTooltip
content={
<ChartTooltipContent
className="w-[150px]"
nameKey={activeChart}
hideLabel
/>
}
/>
<Line
dataKey={activeChart}
type="monotone"
stroke={`var(--color-${activeChart})`}
strokeWidth={2}
dot={false}
/>
</LineChart>
</ChartContainer>
</CardContent>
</Card>
);
}
function convert(value: number) {
var result: string = value.toString();
if (value >= 1000000) {
result = Math.floor(value / 1000000) + "m";
} else if (value >= 1000) {
result = Math.floor(value / 1000) + "k";
}
return result;
}