frontPanel/src/pages/Analytics/Devices.tsx

155 lines
3.9 KiB
TypeScript
Raw Normal View History

2024-04-01 18:09:26 +00:00
import { FC } from "react";
2024-03-21 14:24:56 +00:00
import { Box, Paper, Typography, useMediaQuery, useTheme } from "@mui/material";
2024-03-20 14:44:51 +00:00
import { PieChart } from "@mui/x-charts";
2024-03-21 14:24:56 +00:00
import type { DevicesResponse } from "@api/statistic";
2024-03-20 14:44:51 +00:00
type DeviceProps = {
title: string;
2024-04-01 18:09:26 +00:00
devices: Record<string, number> | null;
};
type DevicesProps = {
data: DevicesResponse | null;
2024-03-20 14:44:51 +00:00
};
2024-03-21 14:24:56 +00:00
const COLORS: Record<number, string> = {
0: "#7E2AEA",
1: "#FA7738",
2: "#62BB1C",
3: "#0886FB",
};
2024-03-20 14:44:51 +00:00
const Device = ({ title, devices }: DeviceProps) => {
2024-03-21 14:24:56 +00:00
const theme = useTheme();
2024-04-05 11:27:52 +00:00
if (!devices || !Object.keys(devices ?? {}).length) {
return <Typography>{title} - нет данных</Typography>;
2024-04-01 18:09:26 +00:00
}
2024-03-21 14:24:56 +00:00
const data = Object.entries(devices).map(([id, value], index) => ({
id,
value,
color: COLORS[index],
}));
2024-03-20 14:44:51 +00:00
return (
2024-03-21 14:24:56 +00:00
<Paper
sx={{
overflow: "hidden",
minHeight: "500px",
display: "flex",
flexDirection: "column",
gap: "30px",
borderRadius: "12px",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
}}
>
<Typography sx={{ margin: "20px" }}>{title}</Typography>
<Box sx={{ flexGrow: 1 }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<PieChart
height={245}
width={245}
margin={{ right: 0 }}
series={[{ data, innerRadius: 50 }]}
/>
</Box>
</Box>
<Box
sx={{ background: theme.palette.background.default, padding: "20px" }}
>
{data.map(({ id, value, color }) => (
<Box
2024-03-22 14:29:51 +00:00
key={id}
2024-03-21 14:24:56 +00:00
sx={{
display: "flex",
marginBottom: "10px",
"&:last-child": { margin: 0 },
}}
>
<Typography
sx={{
flexGrow: 1,
position: "relative",
paddingLeft: "30px",
"&::before": {
content: "''",
display: "block",
position: "absolute",
left: "0",
background: color,
height: "20px",
width: "20px",
borderRadius: "6px",
},
}}
>
{id ? id : "Неопределено"}
2024-03-21 14:24:56 +00:00
</Typography>
<Typography>{value.toFixed(1)} %</Typography>
2024-03-21 14:24:56 +00:00
</Box>
))}
2024-03-20 14:44:51 +00:00
</Box>
</Paper>
);
};
2024-04-01 18:09:26 +00:00
export const Devices: FC<DevicesProps> = ({ data }) => {
2024-03-20 14:44:51 +00:00
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
2024-03-21 14:24:56 +00:00
const isMobile = useMediaQuery(theme.breakpoints.down(700));
2024-03-29 06:10:33 +00:00
// useEffect(() => {
// const requestDevices = async () => {
// const [devicesResponse, devicesError] = await getDevices("14761");
2024-03-21 14:24:56 +00:00
2024-03-29 06:10:33 +00:00
// if (devicesError) {
// enqueueSnackbar(devicesError);
2024-03-21 14:24:56 +00:00
2024-03-29 06:10:33 +00:00
// return;
// }
2024-03-21 14:24:56 +00:00
2024-03-29 06:10:33 +00:00
// if (!devicesResponse) {
// enqueueSnackbar("Список девайсов пуст.");
2024-03-21 14:24:56 +00:00
2024-03-29 06:10:33 +00:00
// return;
// }
2024-03-21 14:24:56 +00:00
2024-03-29 06:10:33 +00:00
// setDevices(devicesResponse);
// };
2024-03-21 14:24:56 +00:00
2024-03-29 06:10:33 +00:00
// // requestDevices();
// }, []);
2024-03-20 14:44:51 +00:00
return (
2024-03-21 14:24:56 +00:00
<Box sx={{ marginTop: "120px" }}>
<Typography
component="h3"
sx={{
fontSize: "24px",
fontWeight: "bold",
color: theme.palette.text.primary,
}}
>
Статистика пользователей
</Typography>
<Box
sx={{
display: "grid",
gridTemplateColumns: isTablet
? isMobile
? "1fr"
: "1fr 1fr"
: "1fr 1fr 1fr",
gap: "20px",
marginTop: "30px",
}}
>
2024-04-03 14:22:51 +00:00
<Device title="Устройства" devices={data?.Device || null} />
<Device title="Операционные системы" devices={data?.OS || null} />
<Device title="Браузеры" devices={data?.Browser || null} />
2024-03-21 14:24:56 +00:00
</Box>
2024-03-20 14:44:51 +00:00
</Box>
);
};