gitscope
← marzneshin / v0.7.2 / dashboard/src/modules/nodes/nodes-usage-widget/index.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/modules/nodes/nodes-usage-widget/index.tsx · TypeScript
Blame Raw
  1import { useState, FC } from 'react';
  2import { useTranslation } from 'react-i18next';
  3import {
  4    SectionWidget,
  5    ChartContainer,
  6    Awaiting,
  7    ChartTooltip,
  8    ChartTooltipContent,
  9    ChartConfig,
 10} from "@marzneshin/common/components";
 11import { XAxis, BarChart, YAxis, CartesianGrid, Bar } from "recharts"
 12import { format as formatByte } from '@chbphone55/pretty-bytes';
 13import { useNodesUsageQuery, NodeType } from "@marzneshin/modules/nodes";
 14import {
 15    useTransformDateUsageData,
 16    ChartDateInterval,
 17    SelectDateView,
 18    dateXAxisTicks,
 19    useFromNowInterval
 20} from "@marzneshin/libs/stats-charts";
 21
 22const chartConfig = {
 23    traffic: {
 24        label: "Traffic",
 25        color: "hsl(var(--chart-1))",
 26    },
 27} satisfies ChartConfig
 28
 29export const NodesUsageWidget: FC<{ node: NodeType }> = ({ node }) => {
 30    const { t } = useTranslation();
 31    const [timeRange, setTimeRange] = useState("1d")
 32    const { start, end } = useFromNowInterval(timeRange as ChartDateInterval);
 33    const { data } = useNodesUsageQuery({ nodeId: node.id, start, end })
 34    const chartData = useTransformDateUsageData(data.usages);
 35    const [totalAmount, totalMetric] = formatByte(data.total);
 36
 37    return (
 38        <Awaiting
 39            Component={
 40                <SectionWidget
 41                    title={
 42                        <div className="hstack justify-between w-full">
 43                            {t("page.nodes.nodes-usage-widget.title")}
 44                        </div>
 45                    }
 46                    description={t("page.nodes.nodes-usage-widget.desc")}
 47                    options={
 48                        <div className="vstack justify-end w-full">
 49                            <span className="text-lg leading-none sm:text-2xl w-full">
 50                                {totalAmount} {totalMetric}
 51                            </span>
 52                            <span className="text-sm flex justify-end  text-muted-foreground w-full">
 53                                Total
 54                            </span>
 55                        </div>
 56                    }
 57                    footer={
 58                        <SelectDateView timeRange={timeRange} setTimeRange={setTimeRange} />
 59                    }
 60                >
 61                    <ChartContainer
 62                        config={chartConfig}
 63                        className="aspect-auto h-[320px] w-full"
 64                    >
 65                        <BarChart
 66                            accessibilityLayer
 67                            data={chartData}
 68                            margin={{
 69                                left: 12,
 70                                top: 13,
 71                                right: 12,
 72                            }}
 73                        >
 74                            <CartesianGrid vertical={false} />
 75                            <YAxis
 76                                tickLine={false}
 77                                axisLine={false}
 78                                tickMargin={8}
 79                                tickFormatter={(value) => {
 80                                    const [amount, metric] = formatByte(value)
 81                                    return `${amount} ${metric}`
 82                                }}
 83                            />
 84                            <XAxis
 85                                dataKey="datetime"
 86                                tickLine={false}
 87                                axisLine={false}
 88                                tickMargin={8}
 89                                tickFormatter={(value) => dateXAxisTicks(value, timeRange as ChartDateInterval)}
 90                            />
 91                            <ChartTooltip
 92                                content={
 93                                    <ChartTooltipContent
 94                                        indicator='line'
 95                                        labelFormatter={(value) => {
 96                                            return new Date(value).toLocaleDateString("en-US", {
 97                                                month: "short",
 98                                                day: "numeric",
 99                                                year: "numeric",
100                                                hour: "numeric"
101                                            })
102                                        }}
103                                        valueFormatter={(value) => {
104                                            const [amount, metric] = formatByte(value as number)
105                                            return `${amount} ${metric}`
106                                        }}
107                                    />
108                                }
109                            />
110                            <Bar dataKey="traffic" fill={`var(--color-traffic)`} />
111                        </BarChart>
112                    </ChartContainer>
113                </SectionWidget>
114            }
115        />
116    );
117};