gitscope
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/modules/users/components/widgets/user-nodes-usage-widget/index.tsx · v0.6.2
Source
1 e6e6467 Dawsh 2y ago import { FC } from 'react';
2 e6e6467 Dawsh 2y ago import { useTranslation } from 'react-i18next';
3 e6e6467 Dawsh 2y ago import {
4 e6e6467 Dawsh 2y ago SectionWidget,
5 e6e6467 Dawsh 2y ago ChartLegendContent,
6 e6e6467 Dawsh 2y ago ChartContainer,
7 e6e6467 Dawsh 2y ago Awaiting,
8 e6e6467 Dawsh 2y ago ChartLegend,
9 e6e6467 Dawsh 2y ago ChartTooltip,
10 e6e6467 Dawsh 2y ago ChartTooltipContent,
11 e6e6467 Dawsh 2y ago } from "@marzneshin/components";
12 e6e6467 Dawsh 2y ago import { Area, AreaChart, CartesianGrid, YAxis, XAxis } from "recharts"
13 e6e6467 Dawsh 2y ago import { useState } from "react";
14 6a4fee1 Dawsh 2y ago import { UserNodesUsageWidgetProps } from "./types";
15 6a4fee1 Dawsh 2y ago import { dateXAxisTicks, useFromNowInterval, SelectDateView, ChartDateInterval } from "@marzneshin/common/stats-charts";
16 6a4fee1 Dawsh 2y ago import { useChartConfig, useTransformData } from "./hooks";
17 e6e6467 Dawsh 2y ago import { format as formatByte } from '@chbphone55/pretty-bytes';
18 e6e6467 Dawsh 2y ago import { useUserNodeUsagesQuery } from "@marzneshin/modules/users";
19 e6e6467 Dawsh 2y ago import { UsageGraphSkeleton } from "./skeleton"
20 e6e6467 Dawsh 2y ago
21 e6e6467 Dawsh 2y ago export const UserNodesUsageWidget: FC<UserNodesUsageWidgetProps> = ({
22 e6e6467 Dawsh 2y ago user,
23 e6e6467 Dawsh 2y ago }) => {
24 e6e6467 Dawsh 2y ago const { t } = useTranslation();
25 e6e6467 Dawsh 2y ago const [timeRange, setTimeRange] = useState("1d")
26 e6e6467 Dawsh 2y ago const { start, end } = useFromNowInterval(timeRange as ChartDateInterval);
27 e6e6467 Dawsh 2y ago const { data, isPending } = useUserNodeUsagesQuery({ username: user.username, start, end })
28 e6e6467 Dawsh 2y ago const chartData = useTransformData(data);
29 e6e6467 Dawsh 2y ago const config = useChartConfig(data);
30 b15de9e Erfan 2y ago const [totalAmount, totalMetric] = formatByte(data.total);
31 e6e6467 Dawsh 2y ago
32 e6e6467 Dawsh 2y ago return (
33 e6e6467 Dawsh 2y ago <Awaiting
34 e6e6467 Dawsh 2y ago Component={
35 e6e6467 Dawsh 2y ago <SectionWidget
36 b15de9e Erfan 2y ago title={<div className="hstack justify-between w-full">{t("page.users.settings.nodes-usage.title")}</div>}
37 e6e6467 Dawsh 2y ago description={t("page.users.settings.nodes-usage.desc")}
38 b15de9e Erfan 2y ago options={
39 b15de9e Erfan 2y ago <div className="vstack justify-end w-full">
40 b15de9e Erfan 2y ago <span className="text-lg leading-none sm:text-2xl w-full">
41 b15de9e Erfan 2y ago {totalAmount} {totalMetric}
42 b15de9e Erfan 2y ago </span>
43 b15de9e Erfan 2y ago <span className="text-sm flex justify-end text-muted-foreground w-full">
44 b15de9e Erfan 2y ago Total
45 b15de9e Erfan 2y ago </span>
46 b15de9e Erfan 2y ago </div>
47 b15de9e Erfan 2y ago }
48 b15de9e Erfan 2y ago footer={
49 b15de9e Erfan 2y ago <SelectDateView timeRange={timeRange} setTimeRange={setTimeRange} />
50 b15de9e Erfan 2y ago }
51 e6e6467 Dawsh 2y ago >
52 e6e6467 Dawsh 2y ago <ChartContainer
53 e6e6467 Dawsh 2y ago className="aspect-auto h-[320px] w-full"
54 e6e6467 Dawsh 2y ago config={config}>
55 e6e6467 Dawsh 2y ago <AreaChart
56 e6e6467 Dawsh 2y ago accessibilityLayer
57 e6e6467 Dawsh 2y ago data={chartData}
58 e6e6467 Dawsh 2y ago margin={{
59 e6e6467 Dawsh 2y ago left: 13,
60 e6e6467 Dawsh 2y ago top: 13,
61 e6e6467 Dawsh 2y ago right: 12,
62 e6e6467 Dawsh 2y ago }}
63 e6e6467 Dawsh 2y ago >
64 e6e6467 Dawsh 2y ago <CartesianGrid vertical={false} />
65 e6e6467 Dawsh 2y ago <YAxis
66 e6e6467 Dawsh 2y ago tickLine={false}
67 e6e6467 Dawsh 2y ago axisLine={false}
68 e6e6467 Dawsh 2y ago tickMargin={8}
69 e6e6467 Dawsh 2y ago tickFormatter={(value) => {
70 e6e6467 Dawsh 2y ago const [amount, metric] = formatByte(value)
71 e6e6467 Dawsh 2y ago return `${amount} ${metric}`
72 e6e6467 Dawsh 2y ago }}
73 e6e6467 Dawsh 2y ago />
74 e6e6467 Dawsh 2y ago <XAxis
75 e6e6467 Dawsh 2y ago dataKey="datetime"
76 e6e6467 Dawsh 2y ago tickLine={false}
77 e6e6467 Dawsh 2y ago axisLine={false}
78 e6e6467 Dawsh 2y ago tickMargin={8}
79 6a4fee1 Dawsh 2y ago tickFormatter={(value) => dateXAxisTicks(value, timeRange as ChartDateInterval)}
80 e6e6467 Dawsh 2y ago />
81 e6e6467 Dawsh 2y ago <ChartTooltip
82 e6e6467 Dawsh 2y ago cursor={false}
83 e6e6467 Dawsh 2y ago content={
84 e6e6467 Dawsh 2y ago <ChartTooltipContent
85 e6e6467 Dawsh 2y ago indicator='line'
86 e6e6467 Dawsh 2y ago labelFormatter={(value) => {
87 e6e6467 Dawsh 2y ago return new Date(value).toLocaleDateString("en-US", {
88 e6e6467 Dawsh 2y ago month: "short",
89 e6e6467 Dawsh 2y ago day: "numeric",
90 e6e6467 Dawsh 2y ago year: "numeric",
91 e6e6467 Dawsh 2y ago hour: "numeric"
92 e6e6467 Dawsh 2y ago })
93 e6e6467 Dawsh 2y ago }}
94 e6e6467 Dawsh 2y ago valueFormatter={(value) => {
95 e6e6467 Dawsh 2y ago const [amount, metric] = formatByte(value as number)
96 e6e6467 Dawsh 2y ago return `${amount} ${metric}`
97 e6e6467 Dawsh 2y ago }}
98 e6e6467 Dawsh 2y ago />
99 e6e6467 Dawsh 2y ago }
100 e6e6467 Dawsh 2y ago />
101 e6e6467 Dawsh 2y ago <defs>
102 e6e6467 Dawsh 2y ago {data.node_usages.map(node =>
103 e6e6467 Dawsh 2y ago <linearGradient key={node.node_name} id={node.node_name} x1="0" y1="0" x2="0" y2="1">
104 e6e6467 Dawsh 2y ago <stop
105 e6e6467 Dawsh 2y ago offset="5%"
106 e6e6467 Dawsh 2y ago stopColor={config[node.node_name].color}
107 e6e6467 Dawsh 2y ago stopOpacity={0.1}
108 e6e6467 Dawsh 2y ago />
109 e6e6467 Dawsh 2y ago <stop
110 e6e6467 Dawsh 2y ago offset="95%"
111 e6e6467 Dawsh 2y ago stopColor={config[node.node_name].color}
112 e6e6467 Dawsh 2y ago stopOpacity={0.8}
113 e6e6467 Dawsh 2y ago />
114 e6e6467 Dawsh 2y ago </linearGradient>
115 e6e6467 Dawsh 2y ago )}
116 e6e6467 Dawsh 2y ago </defs>
117 e6e6467 Dawsh 2y ago {data.node_usages.map(node =>
118 e6e6467 Dawsh 2y ago <Area
119 e6e6467 Dawsh 2y ago dataKey={node.node_name}
120 e6e6467 Dawsh 2y ago key={node.node_name}
121 e6e6467 Dawsh 2y ago type="natural"
122 e6e6467 Dawsh 2y ago fill={config[node.node_name].color}
123 e6e6467 Dawsh 2y ago fillOpacity={0.4}
124 e6e6467 Dawsh 2y ago stackId={node.node_id}
125 e6e6467 Dawsh 2y ago stroke={config[node.node_name].color}
126 e6e6467 Dawsh 2y ago />
127 e6e6467 Dawsh 2y ago )}
128 e6e6467 Dawsh 2y ago <ChartLegend content={<ChartLegendContent />} />
129 e6e6467 Dawsh 2y ago </AreaChart>
130 e6e6467 Dawsh 2y ago </ChartContainer>
131 e6e6467 Dawsh 2y ago </SectionWidget>
132 e6e6467 Dawsh 2y ago }
133 e6e6467 Dawsh 2y ago Skeleton={<UsageGraphSkeleton />}
134 e6e6467 Dawsh 2y ago isFetching={isPending}
135 e6e6467 Dawsh 2y ago />
136 e6e6467 Dawsh 2y ago );
137 e6e6467 Dawsh 2y ago };