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