1import {
2 Box,
3 CircularProgress,
4 VStack,
5 chakra,
6 useColorMode,
7} from '@chakra-ui/react';
8import { ChartPieIcon } from '@heroicons/react/24/outline';
9import { FilterUsageType } from 'types/filter';
10import { useNodes } from 'stores';
11import dayjs from 'dayjs';
12import { FC, Suspense, useEffect, useState } from 'react';
13import ReactApexChart from 'react-apexcharts';
14import { useTranslation } from 'react-i18next';
15import { Icon } from 'components/icon';
16import { UsageFilter, createUsageConfig } from 'components/usage-filter';
17import { StatisticsCardWide } from 'components/statistics-card';
18
19const UsageIcon = chakra(ChartPieIcon, {
20 baseStyle: {
21 w: 5,
22 h: 5,
23 },
24});
25
26export type NodesUsageProps = {};
27
28export const NodesUsage: FC<NodesUsageProps> = () => {
29 const { isShowingNodesUsage } = useNodes();
30 const { fetchNodesUsage } = useNodes();
31 const { t } = useTranslation();
32 const { colorMode } = useColorMode();
33
34 const usageTitle = t('userDialog.total');
35 const [usage, setUsage] = useState(createUsageConfig(colorMode, usageTitle));
36 const [usageFilter, setUsageFilter] = useState('1m');
37 const fetchUsageWithFilter = (query: FilterUsageType) => {
38 fetchNodesUsage(query).then((data: any) => {
39 const labels = [];
40 const series = [];
41 for (const key in data.usages) {
42 const entry = data.usages[key];
43 series.push(entry.uplink + entry.downlink);
44 labels.push(entry.node_name);
45 }
46 setUsage(createUsageConfig(colorMode, usageTitle, series, labels));
47 });
48 };
49
50 useEffect(() => {
51 if (isShowingNodesUsage) {
52 fetchUsageWithFilter({
53 start: dayjs().utc().subtract(30, 'day').format('YYYY-MM-DDTHH:00:00'),
54 });
55 }
56 }, [isShowingNodesUsage]);
57
58 return (
59 <StatisticsCardWide
60 title={t('header.nodesUsage')}
61 icon={<Icon color="primary">
62 <UsageIcon color="white" /> </Icon>}
63 content={
64 <VStack gap={4}>
65 <UsageFilter
66 defaultValue={usageFilter}
67 onChange={(filter, query) => {
68 setUsageFilter(filter);
69 fetchUsageWithFilter(query);
70 }}
71 />
72 <Box justifySelf="center" w="full" maxW="300px" mt="4">
73 <Suspense fallback={<CircularProgress isIndeterminate />}>
74 <ReactApexChart
75 options={usage.options}
76 series={usage.series}
77 type="donut"
78 height="500px"
79 />
80 </Suspense>
81 </Box>
82 </VStack>
83
84 } />
85 );
86};