refactor: statistics
This commit is contained in:
parent
8f7e0bfbdf
commit
e42e8cc766
@ -1,50 +0,0 @@
|
||||
import makeRequest from "@root/api/makeRequest";
|
||||
import {parseAxiosError} from "@root/utils/parse-error";
|
||||
|
||||
export type QuizStatisticResponse = {
|
||||
Registrations: number;
|
||||
Quizes: number;
|
||||
Results: number
|
||||
};
|
||||
|
||||
type TRequest = {
|
||||
to: number;
|
||||
from: number;
|
||||
};
|
||||
|
||||
export const getStatistic = async (
|
||||
to: number,
|
||||
from: number,
|
||||
): Promise<QuizStatisticResponse> => {
|
||||
try {
|
||||
const generalResponse = await makeRequest<TRequest, QuizStatisticResponse>({
|
||||
url: `${process.env.REACT_APP_DOMAIN}/squiz/statistic`,
|
||||
body: { to, from }
|
||||
})
|
||||
return generalResponse;
|
||||
} catch (nativeError) {
|
||||
|
||||
return { Registrations: 0, Quizes: 0, Results: 0 };
|
||||
}
|
||||
};
|
||||
|
||||
export const getStatisticSchild = async (
|
||||
from: any, to: any): Promise<unknown> => {
|
||||
try {
|
||||
const StatisticResponse = await makeRequest<unknown, unknown>({
|
||||
url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" ,
|
||||
method: "post",
|
||||
useToken: true,
|
||||
body: {
|
||||
"to": to,
|
||||
"from": from,
|
||||
"page": 0,
|
||||
"limit": 100
|
||||
},
|
||||
});
|
||||
return StatisticResponse;
|
||||
} catch (nativeError) {
|
||||
|
||||
return [{ID: 0, Regs: 0, Money: 0, Quizes:[{QuizID: 0, Regs: 0, Money: 0}]}];
|
||||
}
|
||||
};
|
61
src/api/quizStatistic/index.ts
Normal file
61
src/api/quizStatistic/index.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import makeRequest from "@root/api/makeRequest";
|
||||
|
||||
import type { GetStatisticSchildBody, QuizStatisticsItem } from "./types";
|
||||
|
||||
export type QuizStatisticResponse = {
|
||||
Registrations: number;
|
||||
Quizes: number;
|
||||
Results: number;
|
||||
};
|
||||
|
||||
type TRequest = {
|
||||
to: number;
|
||||
from: number;
|
||||
};
|
||||
|
||||
export const getStatistic = async (
|
||||
to: number,
|
||||
from: number
|
||||
): Promise<QuizStatisticResponse> => {
|
||||
try {
|
||||
const generalResponse = await makeRequest<TRequest, QuizStatisticResponse>({
|
||||
url: `${process.env.REACT_APP_DOMAIN}/squiz/statistic`,
|
||||
body: { to, from },
|
||||
});
|
||||
return generalResponse;
|
||||
} catch (nativeError) {
|
||||
return { Registrations: 0, Quizes: 0, Results: 0 };
|
||||
}
|
||||
};
|
||||
|
||||
export const getStatisticSchild = async (
|
||||
from: number,
|
||||
to: number
|
||||
): Promise<QuizStatisticsItem[]> => {
|
||||
try {
|
||||
const StatisticResponse = await makeRequest<
|
||||
GetStatisticSchildBody,
|
||||
QuizStatisticsItem[]
|
||||
>({
|
||||
url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat",
|
||||
method: "post",
|
||||
useToken: true,
|
||||
body: { to, from, page: 0, limit: 100 },
|
||||
});
|
||||
|
||||
if (!StatisticResponse) {
|
||||
throw new Error("Статистика не найдена");
|
||||
}
|
||||
|
||||
return StatisticResponse;
|
||||
} catch (nativeError) {
|
||||
return [
|
||||
{
|
||||
ID: "0",
|
||||
Regs: 0,
|
||||
Money: 0,
|
||||
Quizes: [{ QuizID: "0", Regs: 0, Money: 0 }],
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
21
src/api/quizStatistic/types.ts
Normal file
21
src/api/quizStatistic/types.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Moment } from "moment";
|
||||
|
||||
export type GetStatisticSchildBody = {
|
||||
to: Moment | null;
|
||||
from: Moment | null;
|
||||
page: number;
|
||||
limit: number;
|
||||
};
|
||||
|
||||
type StatisticsQuizes = {
|
||||
QuizID: string;
|
||||
Money: number;
|
||||
Regs: number;
|
||||
};
|
||||
|
||||
export type QuizStatisticsItem = {
|
||||
ID: string;
|
||||
Money: number;
|
||||
Quizes: StatisticsQuizes[];
|
||||
Regs: number;
|
||||
};
|
@ -24,7 +24,7 @@ import { PromocodeManagement } from "@root/pages/dashboard/Content/PromocodeMana
|
||||
import { SettingRoles } from "@pages/Setting/SettingRoles";
|
||||
import Support from "@pages/dashboard/Content/Support/Support";
|
||||
import ChatImageNewWindow from "@pages/dashboard/Content/Support/ChatImageNewWindow";
|
||||
import QuizStatistic from "@pages/dashboard/Content/QuizStatistic";
|
||||
import { QuizStatistics } from "@root/pages/dashboard/Content/QuizStatistics";
|
||||
|
||||
import theme from "./theme";
|
||||
import "./index.css";
|
||||
@ -109,7 +109,7 @@ root.render(
|
||||
path="/quizStatistic"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<QuizStatistic />
|
||||
<QuizStatistics />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
@ -121,7 +121,7 @@ root.render(
|
||||
/>
|
||||
))}
|
||||
</Route>
|
||||
<Route path={"/image/:srcImage"} element={<ChatImageNewWindow />} />
|
||||
<Route path={"/image/:srcImage"} element={<ChatImageNewWindow />} />
|
||||
|
||||
<Route path="*" element={<Error404 />} />
|
||||
</Routes>
|
||||
|
@ -1,245 +0,0 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import moment, {Moment} from "moment";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionDetails, AccordionSummary,
|
||||
Box,
|
||||
Button,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TextField,
|
||||
Typography,
|
||||
useTheme
|
||||
} from "@mui/material";
|
||||
import {AdapterMoment} from "@mui/x-date-pickers/AdapterMoment";
|
||||
import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
||||
import ModalUser from "@pages/dashboard/ModalUser";
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import useSchildStatistic from "@root/utils/hooks/useSchildStatistic";
|
||||
|
||||
export default function StatisticSchild() {
|
||||
const theme = useTheme()
|
||||
const [isOpen, setOpen] = useState<boolean>(false);
|
||||
const [isOpenEnd, setOpenEnd] = useState<boolean>(false);
|
||||
|
||||
const [openUserModal, setOpenUserModal] = useState<boolean>(false);
|
||||
const [activeUserId, setActiveUserId] = useState<string>("");
|
||||
|
||||
const [from, setFrom] = useState<Moment | null>(moment("01.01.2023"));
|
||||
const [to, setTo] = useState<Moment | null>(moment(Date.now()));
|
||||
|
||||
const statistic = useSchildStatistic(from, to)
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onAdornmentClick = () => {
|
||||
setOpen((old) => !old);
|
||||
if (isOpenEnd) {
|
||||
handleCloseEnd();
|
||||
}
|
||||
};
|
||||
|
||||
const handleCloseEnd = () => {
|
||||
setOpenEnd(false);
|
||||
};
|
||||
|
||||
const handleOpenEnd = () => {
|
||||
setOpenEnd(true);
|
||||
};
|
||||
|
||||
const onAdornmentClickEnd = () => {
|
||||
setOpenEnd((old) => !old);
|
||||
if (isOpen) {
|
||||
handleClose();
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!openUserModal) {
|
||||
setActiveUserId("");
|
||||
}
|
||||
}, [openUserModal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeUserId) {
|
||||
setOpenUserModal(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setOpenUserModal(false);
|
||||
}, [activeUserId]);
|
||||
|
||||
console.log(statistic)
|
||||
|
||||
return(
|
||||
<LocalizationProvider dateAdapter={AdapterMoment}>
|
||||
<Typography sx={{mt: "20px", mb: "20px"}}>Статистика переходов с шильдика</Typography>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата начала
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={from}
|
||||
onChange={(date) => date && setFrom(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата окончания
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={to}
|
||||
onChange={(date) => date && setTo(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Table
|
||||
sx={{
|
||||
width: "80%",
|
||||
border: "2px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
bgcolor: theme.palette.content.main,
|
||||
color: "white",
|
||||
mt: "20px"
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
borderBottom: "2px solid",
|
||||
borderColor: theme.palette.grayLight.main,
|
||||
height: "100px",
|
||||
}}
|
||||
>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Пользователь</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Регистраций</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Деньги</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Квизы</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
{statistic.map((stat: any) => (
|
||||
<TableBody>
|
||||
<TableCell
|
||||
sx={{color: "inherit"}} align="center"
|
||||
onClick={()=> setActiveUserId(stat?.ID)}
|
||||
>{stat?.ID}</TableCell>
|
||||
<ModalUser
|
||||
open={openUserModal}
|
||||
onClose={() => setOpenUserModal(false)}
|
||||
userId={activeUserId}
|
||||
/>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{stat?.Regs}</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{stat?.Money}</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">
|
||||
<Accordion>
|
||||
<AccordionSummary
|
||||
sx={{backgroundColor: "#26272c", color: "#FFFFFF"}}
|
||||
expandIcon={<ExpandMoreIcon sx={{color: "#FFFFFF"}}/>}
|
||||
aria-controls="panel1-content"
|
||||
id="panel1-header"
|
||||
>
|
||||
Статистика по квизам
|
||||
</AccordionSummary>
|
||||
<AccordionDetails sx={{backgroundColor: "#26272c",}}>
|
||||
<Table
|
||||
sx={{
|
||||
width: "80%",
|
||||
border: "2px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
bgcolor: theme.palette.content.main,
|
||||
color: "white"
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
borderBottom: "2px solid",
|
||||
borderColor: theme.palette.grayLight.main,
|
||||
height: "100px",
|
||||
}}
|
||||
>
|
||||
<TableCell sx={{color: "inherit"}} align="center">QuizID</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Регистрации</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Деньги</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
{stat?.Quizes.map((quiz:any)=> (
|
||||
<TableBody>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{quiz?.QuizID}</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{quiz?.Regs}</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{quiz?.Money}</TableCell>
|
||||
</TableBody>
|
||||
))}
|
||||
|
||||
|
||||
</Table>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</TableCell>
|
||||
</TableBody>
|
||||
))
|
||||
}
|
||||
|
||||
</Table>
|
||||
</LocalizationProvider>
|
||||
)
|
||||
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
import { Table, TableBody, TableCell, TableHead, TableRow, useTheme, Typography, Box, TextField, Button } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import moment from "moment";
|
||||
import type { Moment } from "moment";
|
||||
import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
||||
import { useQuizStatistic } from '@root/utils/hooks/useQuizStatistic';
|
||||
import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'
|
||||
import StatisticSchild from "./StatisticSchild";
|
||||
|
||||
export default () => {
|
||||
const theme = useTheme()
|
||||
|
||||
const [isOpen, setOpen] = useState<boolean>(false);
|
||||
const [isOpenEnd, setOpenEnd] = useState<boolean>(false);
|
||||
|
||||
const [from, setFrom] = useState<Moment | null>(null);
|
||||
const [to, setTo] = useState<Moment | null>(moment(Date.now()));
|
||||
|
||||
|
||||
|
||||
const { Registrations, Quizes, Results } = useQuizStatistic({
|
||||
from,
|
||||
to,
|
||||
});
|
||||
|
||||
const resetTime = () => {
|
||||
setFrom(moment(0));
|
||||
setTo(moment(Date.now()));
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const onAdornmentClick = () => {
|
||||
setOpen((old) => !old);
|
||||
if (isOpenEnd) {
|
||||
handleCloseEnd();
|
||||
}
|
||||
};
|
||||
|
||||
const handleCloseEnd = () => {
|
||||
setOpenEnd(false);
|
||||
};
|
||||
|
||||
const handleOpenEnd = () => {
|
||||
setOpenEnd(true);
|
||||
};
|
||||
|
||||
const onAdornmentClickEnd = () => {
|
||||
setOpenEnd((old) => !old);
|
||||
if (isOpen) {
|
||||
handleClose();
|
||||
}
|
||||
};
|
||||
|
||||
return <>
|
||||
<LocalizationProvider dateAdapter={AdapterMoment}>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата начала
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={from}
|
||||
onChange={(date) => date && setFrom(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата окончания
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={to}
|
||||
onChange={(date) => date && setTo(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
sx={{
|
||||
m: '10px 0'
|
||||
}}
|
||||
onClick={resetTime}
|
||||
>
|
||||
Сбросить даты
|
||||
</Button>
|
||||
<Table
|
||||
sx={{
|
||||
width: "80%",
|
||||
border: "2px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
bgcolor: theme.palette.content.main,
|
||||
color: "white"
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
borderBottom: "2px solid",
|
||||
borderColor: theme.palette.grayLight.main,
|
||||
height: "100px",
|
||||
}}
|
||||
>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Регистраций</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Quiz</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">Результаты</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{Registrations}</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{Quizes}</TableCell>
|
||||
<TableCell sx={{color: "inherit"}} align="center">{Results}</TableCell>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
<StatisticSchild/>
|
||||
|
||||
</LocalizationProvider>
|
||||
</>
|
||||
}
|
148
src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx
Normal file
148
src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx
Normal file
@ -0,0 +1,148 @@
|
||||
import { useState } from "react";
|
||||
import moment from "moment";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Typography,
|
||||
Box,
|
||||
TextField,
|
||||
Button,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
|
||||
import { useQuizStatistic } from "@root/utils/hooks/useQuizStatistic";
|
||||
|
||||
import type { Moment } from "moment";
|
||||
|
||||
export const QuizInfo = () => {
|
||||
const [from, setFrom] = useState<Moment | null>(null);
|
||||
const [to, setTo] = useState<Moment | null>(moment(Date.now()));
|
||||
const theme = useTheme();
|
||||
const { Registrations, Quizes, Results } = useQuizStatistic({
|
||||
from,
|
||||
to,
|
||||
});
|
||||
|
||||
const resetTime = () => {
|
||||
setFrom(moment());
|
||||
setTo(moment(Date.now()));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата начала
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={from}
|
||||
onChange={(date) => date && setFrom(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата окончания
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={to}
|
||||
onChange={(date) => date && setTo(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Button sx={{ m: "10px 0" }} onClick={resetTime}>
|
||||
Сбросить даты
|
||||
</Button>
|
||||
<Table
|
||||
sx={{
|
||||
width: "80%",
|
||||
border: "2px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
bgcolor: theme.palette.content.main,
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
borderBottom: "2px solid",
|
||||
borderColor: theme.palette.grayLight.main,
|
||||
height: "100px",
|
||||
}}
|
||||
>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Регистраций
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Quiz
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Результаты
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Registrations}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Quizes}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Results}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
};
|
256
src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx
Normal file
256
src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx
Normal file
@ -0,0 +1,256 @@
|
||||
import moment from "moment";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Box,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TextField,
|
||||
Typography,
|
||||
Button,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
import ModalUser from "@pages/dashboard/ModalUser";
|
||||
|
||||
import { useSchildStatistics } from "@root/utils/hooks/useSchildStatistics";
|
||||
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import type { Moment } from "moment";
|
||||
|
||||
export const StatisticSchild = () => {
|
||||
const [openUserModal, setOpenUserModal] = useState<boolean>(false);
|
||||
const [activeUserId, setActiveUserId] = useState<string>("");
|
||||
|
||||
const [from, setFrom] = useState<Moment | null>(
|
||||
moment(new Date("01.01.2023"))
|
||||
);
|
||||
const [to, setTo] = useState<Moment | null>(moment(Date.now()));
|
||||
|
||||
const theme = useTheme();
|
||||
const statistics = useSchildStatistics(from, to);
|
||||
|
||||
useEffect(() => {
|
||||
if (!openUserModal) {
|
||||
setActiveUserId("");
|
||||
}
|
||||
}, [openUserModal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeUserId) {
|
||||
setOpenUserModal(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setOpenUserModal(false);
|
||||
}, [activeUserId]);
|
||||
|
||||
const copyQuizLink = (quizId: string) => {
|
||||
navigator.clipboard.writeText(
|
||||
`https://${
|
||||
window.location.href.includes("/admin.") ? "" : "s."
|
||||
}hbpn.link/${quizId}`
|
||||
);
|
||||
|
||||
enqueueSnackbar("Ссылка успешно скопирована");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography sx={{ mt: "20px", mb: "20px" }}>
|
||||
Статистика переходов с шильдика
|
||||
</Typography>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата начала
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={from}
|
||||
onChange={(date) => date && setFrom(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
marginBottom: "5px",
|
||||
fontWeight: 500,
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
Дата окончания
|
||||
</Typography>
|
||||
<DatePicker
|
||||
inputFormat="DD/MM/YYYY"
|
||||
value={to}
|
||||
onChange={(date) => date && setTo(date)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{ background: "#1F2126", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "40px",
|
||||
color: theme.palette.secondary.main,
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Table
|
||||
sx={{
|
||||
width: "80%",
|
||||
border: "2px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
bgcolor: theme.palette.content.main,
|
||||
color: "white",
|
||||
mt: "20px",
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
borderBottom: "2px solid",
|
||||
borderColor: theme.palette.grayLight.main,
|
||||
height: "100px",
|
||||
}}
|
||||
>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Пользователь
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Регистраций
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Деньги
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Квизы
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{statistics.map(({ ID, Regs, Money, Quizes }) => (
|
||||
<TableRow key={ID}>
|
||||
<TableCell
|
||||
sx={{ color: "inherit" }}
|
||||
align="center"
|
||||
onClick={() => setActiveUserId(ID)}
|
||||
>
|
||||
{ID}
|
||||
</TableCell>
|
||||
<ModalUser
|
||||
open={openUserModal}
|
||||
onClose={() => setOpenUserModal(false)}
|
||||
userId={activeUserId}
|
||||
/>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Regs}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Money}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
<Accordion>
|
||||
<AccordionSummary
|
||||
sx={{ backgroundColor: "#26272c", color: "#FFFFFF" }}
|
||||
expandIcon={<ExpandMoreIcon sx={{ color: "#FFFFFF" }} />}
|
||||
aria-controls="panel1-content"
|
||||
id="panel1-header"
|
||||
>
|
||||
Статистика по квизам
|
||||
</AccordionSummary>
|
||||
<AccordionDetails sx={{ backgroundColor: "#26272c" }}>
|
||||
<Table
|
||||
sx={{
|
||||
width: "80%",
|
||||
border: "2px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
bgcolor: theme.palette.content.main,
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
borderBottom: "2px solid",
|
||||
borderColor: theme.palette.grayLight.main,
|
||||
height: "100px",
|
||||
}}
|
||||
>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
QuizID
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Регистрации
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
Деньги
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{Quizes.map(({ QuizID, Regs, Money }) => (
|
||||
<TableRow key={QuizID}>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
<Button onClick={() => copyQuizLink(QuizID)}>
|
||||
{QuizID}
|
||||
</Button>
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Regs}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: "inherit" }} align="center">
|
||||
{Money}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
};
|
12
src/pages/dashboard/Content/QuizStatistics/index.tsx
Normal file
12
src/pages/dashboard/Content/QuizStatistics/index.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import { LocalizationProvider } from "@mui/x-date-pickers";
|
||||
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
|
||||
|
||||
import { QuizInfo } from "./QuizInfo";
|
||||
import { StatisticSchild } from "./StatisticSchild";
|
||||
|
||||
export const QuizStatistics = () => (
|
||||
<LocalizationProvider dateAdapter={AdapterMoment}>
|
||||
<QuizInfo />
|
||||
<StatisticSchild />
|
||||
</LocalizationProvider>
|
||||
);
|
@ -1,8 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
QuizStatisticResponse,
|
||||
getStatistic
|
||||
} from "@root/api/quizStatistic";
|
||||
import { QuizStatisticResponse, getStatistic } from "@root/api/quizStatistic";
|
||||
|
||||
import type { Moment } from "moment";
|
||||
|
||||
@ -15,15 +12,20 @@ export function useQuizStatistic({ to, from }: useQuizStatisticProps) {
|
||||
const formatTo = to?.unix();
|
||||
const formatFrom = from?.unix();
|
||||
|
||||
const [data, setData] = useState<QuizStatisticResponse | null>({ Registrations: 0, Quizes: 0, Results: 0 });
|
||||
const [data, setData] = useState<QuizStatisticResponse | null>({
|
||||
Registrations: 0,
|
||||
Quizes: 0,
|
||||
Results: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const requestStatistics = async () => {
|
||||
|
||||
const gottenData = await getStatistic(Number(formatTo), Number(formatFrom));
|
||||
setData(gottenData)
|
||||
}
|
||||
const gottenData = await getStatistic(
|
||||
Number(formatTo),
|
||||
Number(formatFrom)
|
||||
);
|
||||
setData(gottenData);
|
||||
};
|
||||
|
||||
requestStatistics();
|
||||
}, [to, from]);
|
||||
|
@ -1,17 +0,0 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {getStatisticSchild} from "@root/api/quizStatistic";
|
||||
|
||||
|
||||
export default function useSchildStatistic (from: any, to: any){
|
||||
const formatTo = to?.unix();
|
||||
const formatFrom = from?.unix();
|
||||
const [statistic, setStatistic] = useState<any>([])
|
||||
useEffect(() => {
|
||||
const StatisticsShild = async () => {
|
||||
const gottenData = await getStatisticSchild(Number(formatFrom), Number(formatTo));
|
||||
setStatistic(gottenData)
|
||||
}
|
||||
StatisticsShild()
|
||||
}, []);
|
||||
return statistic
|
||||
}
|
27
src/utils/hooks/useSchildStatistics.ts
Normal file
27
src/utils/hooks/useSchildStatistics.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { getStatisticSchild } from "@root/api/quizStatistic";
|
||||
|
||||
import type { Moment } from "moment";
|
||||
|
||||
import type { QuizStatisticsItem } from "@root/api/quizStatistic/types";
|
||||
|
||||
export const useSchildStatistics = (from: Moment | null, to: Moment | null) => {
|
||||
const formatTo = to?.unix();
|
||||
const formatFrom = from?.unix();
|
||||
const [statistics, setStatistics] = useState<QuizStatisticsItem[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const StatisticsShild = async () => {
|
||||
const gottenData = await getStatisticSchild(
|
||||
Number(formatFrom),
|
||||
Number(formatTo)
|
||||
);
|
||||
|
||||
setStatistics(gottenData);
|
||||
};
|
||||
|
||||
StatisticsShild();
|
||||
}, [formatTo, formatFrom]);
|
||||
|
||||
return statistics;
|
||||
};
|
@ -16,9 +16,7 @@
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"types": ["node"],
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src", "**/*.ts"]
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user