"use client" import { ServerDetailChartLoading } from "@/app/(main)/ClientComponents/ServerDetailLoading" import { NezhaAPISafe, ServerApi } from "@/app/types/nezha-api" import AnimatedCircularProgressBar from "@/components/ui/animated-circular-progress-bar" import { Card, CardContent } from "@/components/ui/card" import { ChartConfig, ChartContainer } from "@/components/ui/chart" import { formatBytes, formatNezhaInfo, formatRelativeTime, nezhaFetcher } from "@/lib/utils" import { useTranslations } from "next-intl" import { useEffect, useState } from "react" import { Area, AreaChart, CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts" import useSWRImmutable from "swr/immutable" type cpuChartData = { timeStamp: string cpu: number } type processChartData = { timeStamp: string process: number } type diskChartData = { timeStamp: string disk: number } type memChartData = { timeStamp: string mem: number swap: number } type networkChartData = { timeStamp: string upload: number download: number } type connectChartData = { timeStamp: string tcp: number udp: number } export default function ServerDetailChartClient({ server_id, }: { server_id: number show: boolean }) { const t = useTranslations("ServerDetailChartClient") const { data: allFallbackData } = useSWRImmutable("/api/server", nezhaFetcher) const fallbackData = allFallbackData?.result?.find((item) => item.id === server_id) const { data, error } = useSWRImmutable( `/api/detail?server_id=${server_id}`, nezhaFetcher, { fallbackData, }, ) if (error) { return ( <>

{error.message}

{t("chart_fetch_error_message")}

) } if (!data) return return (
) } function CpuChart({ data }: { data: NezhaAPISafe }) { const [cpuChartData, setCpuChartData] = useState([] as cpuChartData[]) const { cpu } = formatNezhaInfo(data) useEffect(() => { if (data) { const timestamp = Date.now().toString() let newData = [] as cpuChartData[] if (cpuChartData.length === 0) { newData = [ { timeStamp: timestamp, cpu: cpu }, { timeStamp: timestamp, cpu: cpu }, ] } else { newData = [...cpuChartData, { timeStamp: timestamp, cpu: cpu }] } if (newData.length > 30) { newData.shift() } setCpuChartData(newData) } }, [data]) const chartConfig = { cpu: { label: "CPU", }, } satisfies ChartConfig return (

CPU

{cpu.toFixed(0)}%

formatRelativeTime(value)} /> `${value}%`} />
) } function ProcessChart({ data }: { data: NezhaAPISafe }) { const t = useTranslations("ServerDetailChartClient") const [processChartData, setProcessChartData] = useState([] as processChartData[]) const { process } = formatNezhaInfo(data) useEffect(() => { if (data) { const timestamp = Date.now().toString() let newData = [] as processChartData[] if (processChartData.length === 0) { newData = [ { timeStamp: timestamp, process: process }, { timeStamp: timestamp, process: process }, ] } else { newData = [...processChartData, { timeStamp: timestamp, process: process }] } if (newData.length > 30) { newData.shift() } setProcessChartData(newData) } }, [data]) const chartConfig = { process: { label: "Process", }, } satisfies ChartConfig return (

{t("Process")}

{process}

formatRelativeTime(value)} />
) } function MemChart({ data }: { data: NezhaAPISafe }) { const t = useTranslations("ServerDetailChartClient") const [memChartData, setMemChartData] = useState([] as memChartData[]) const { mem, swap } = formatNezhaInfo(data) useEffect(() => { if (data) { const timestamp = Date.now().toString() let newData = [] as memChartData[] if (memChartData.length === 0) { newData = [ { timeStamp: timestamp, mem: mem, swap: swap }, { timeStamp: timestamp, mem: mem, swap: swap }, ] } else { newData = [...memChartData, { timeStamp: timestamp, mem: mem, swap: swap }] } if (newData.length > 30) { newData.shift() } setMemChartData(newData) } }, [data]) const chartConfig = { mem: { label: "Mem", }, swap: { label: "Swap", }, } satisfies ChartConfig return (

{t("Mem")}

{mem.toFixed(0)}%

{t("Swap")}

{swap.toFixed(0)}%

{formatBytes(data.status.MemUsed)} / {formatBytes(data.host.MemTotal)}
swap: {formatBytes(data.status.SwapUsed)}
formatRelativeTime(value)} /> `${value}%`} />
) } function DiskChart({ data }: { data: NezhaAPISafe }) { const t = useTranslations("ServerDetailChartClient") const [diskChartData, setDiskChartData] = useState([] as diskChartData[]) const { disk } = formatNezhaInfo(data) useEffect(() => { if (data) { const timestamp = Date.now().toString() let newData = [] as diskChartData[] if (diskChartData.length === 0) { newData = [ { timeStamp: timestamp, disk: disk }, { timeStamp: timestamp, disk: disk }, ] } else { newData = [...diskChartData, { timeStamp: timestamp, disk: disk }] } if (newData.length > 30) { newData.shift() } setDiskChartData(newData) } }, [data]) const chartConfig = { disk: { label: "Disk", }, } satisfies ChartConfig return (

{t("Disk")}

{disk.toFixed(0)}%

{formatBytes(data.status.DiskUsed)} / {formatBytes(data.host.DiskTotal)}
formatRelativeTime(value)} /> `${value}%`} />
) } function NetworkChart({ data }: { data: NezhaAPISafe }) { const t = useTranslations("ServerDetailChartClient") const [networkChartData, setNetworkChartData] = useState([] as networkChartData[]) const { up, down } = formatNezhaInfo(data) useEffect(() => { if (data) { const timestamp = Date.now().toString() let newData = [] as networkChartData[] if (networkChartData.length === 0) { newData = [ { timeStamp: timestamp, upload: up, download: down }, { timeStamp: timestamp, upload: up, download: down }, ] } else { newData = [...networkChartData, { timeStamp: timestamp, upload: up, download: down }] } if (newData.length > 30) { newData.shift() } setNetworkChartData(newData) } }, [data]) let maxDownload = Math.max(...networkChartData.map((item) => item.download)) maxDownload = Math.ceil(maxDownload) if (maxDownload < 1) { maxDownload = 1 } const chartConfig = { upload: { label: "Upload", }, download: { label: "Download", }, } satisfies ChartConfig return (

{t("Upload")}

{up.toFixed(2)} M/s

{t("Download")}

{down.toFixed(2)} M/s

formatRelativeTime(value)} /> `${value.toFixed(0)}M/s`} />
) } function ConnectChart({ data }: { data: NezhaAPISafe }) { const [connectChartData, setConnectChartData] = useState([] as connectChartData[]) const { tcp, udp } = formatNezhaInfo(data) useEffect(() => { if (data) { const timestamp = Date.now().toString() let newData = [] as connectChartData[] if (connectChartData.length === 0) { newData = [ { timeStamp: timestamp, tcp: tcp, udp: udp }, { timeStamp: timestamp, tcp: tcp, udp: udp }, ] } else { newData = [...connectChartData, { timeStamp: timestamp, tcp: tcp, udp: udp }] } if (newData.length > 30) { newData.shift() } setConnectChartData(newData) } }, [data]) const chartConfig = { tcp: { label: "TCP", }, udp: { label: "UDP", }, } satisfies ChartConfig return (

TCP

{tcp}

UDP

{udp}

formatRelativeTime(value)} />
) }