feat: updates

This commit is contained in:
IlyaDoronin 2024-04-30 14:30:59 +03:00
commit e9ab16bd85
20 changed files with 746 additions and 538 deletions

@ -1,67 +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: number, to: number): 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}]}];
}
};
export const getStatisticPromocode = async (from: number, to: number): Promise<unknown> => {
try {
const StatisticPromo = await makeRequest<unknown, unknown>({
url: process.env.REACT_APP_DOMAIN + "/customer/promocode/ltv" ,
method: "post",
useToken: true,
body: {
"to": to,
"from": from,
},
});
return StatisticPromo;
} catch (nativeError) {
console.log(nativeError)
}
}

@ -0,0 +1,82 @@
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 }],
},
];
}
};
export const getStatisticPromocode = async (
from: number,
to: number
): Promise<unknown> => {
try {
const StatisticPromo = await makeRequest<unknown, unknown>({
url: process.env.REACT_APP_DOMAIN + "/customer/promocode/ltv",
method: "post",
useToken: true,
body: {
to: to,
from: from,
},
});
return StatisticPromo;
} catch (nativeError) {
console.log(nativeError);
}
};

@ -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";
@ -106,10 +106,10 @@ root.render(
}
/>
<Route
path="/quizStatistic"
path="/quizStatistics"
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,147 +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";
import DateFilter from "@pages/dashboard/Content/QuizStatistic/dateFilter";
export default function StatisticSchild() {
const theme = useTheme()
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)
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>
<DateFilter from={from} to={to} setFrom={setFrom} setTo={setTo}/>
<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,68 +0,0 @@
import {Button, Table, TableBody, TableCell, TableHead, TableRow, Typography, useTheme} from "@mui/material";
import {AdapterMoment} from "@mui/x-date-pickers/AdapterMoment";
import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
import DateFilter from "@pages/dashboard/Content/QuizStatistic/dateFilter";
import {useState} from "react";
import moment, {Moment} from "moment";
import {usePromocodeStatistic} from "@root/utils/hooks/usePromocodeStatistic";
import {useAllPromocodes} from "@root/api/promocode/swr";
export default function StstisticPromocode() {
const theme = useTheme()
const [from, setFrom] = useState<Moment | null>(moment("01.01.2023"));
const [to, setTo] = useState<Moment | null>(moment(Date.now()));
const promocodes = useAllPromocodes();
const statisticPromo = usePromocodeStatistic({to, from})
return(
<LocalizationProvider dateAdapter={AdapterMoment}>
<Typography>Статистика промокодов</Typography>
<DateFilter from={from} to={to} setFrom={setFrom} setTo={setTo}/>
<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">Регистации</TableCell>
<TableCell sx={{color: "inherit"}} align="center">Внесено</TableCell>
</TableRow>
</TableHead>
{Object.values(statisticPromo || {}).map((sPromo:any)=> {
let codeword
let listPromo = promocodes
let statisticP = statisticPromo
for (let key in statisticP) {
const codewordSearch = listPromo.find(obj => obj.id === key)
codeword = codewordSearch?.codeword
// console.log(codeword)
}
return(
<TableBody>
<TableCell sx={{color: "inherit"}} align="center">{codeword}</TableCell>
<TableCell sx={{color: "inherit"}} align="center">{sPromo.Regs}</TableCell>
<TableCell sx={{color: "inherit"}} align="center">{sPromo.Money}</TableCell>
</TableBody>
)
})
}
</Table>
</LocalizationProvider>
)
}

@ -1,119 +0,0 @@
import {Box, TextField, Typography, useTheme} from "@mui/material";
import {useState} from "react";
import moment, {Moment} from "moment";
import {DatePicker} from "@mui/x-date-pickers";
interface Props{
from: Moment | null,
to: Moment | null,
setFrom: (a: Moment | null) => void,
setTo: (a: Moment | null) => void,
}
export default function DateFilter({to, setTo, from, setFrom}: Props) {
const theme = useTheme()
const [isOpen, setOpen] = useState<boolean>(false);
const [isOpenEnd, setOpenEnd] = useState<boolean>(false);
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(
<>
<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>
</>
)
}

@ -1,73 +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";
import makeRequest from "@root/api/makeRequest";
import {parseAxiosError} from "@root/utils/parse-error";
import DateFilter from "@pages/dashboard/Content/QuizStatistic/dateFilter";
import StstisticPromocode from "@pages/dashboard/Content/QuizStatistic/StstisticPromocode";
export default () => {
const theme = useTheme()
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()));
};
return <>
<LocalizationProvider dateAdapter={AdapterMoment}>
<DateFilter from={from} to={to} setFrom={setFrom} setTo={setTo}/>
<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/>
<StstisticPromocode/>
</LocalizationProvider>
</>
}

@ -0,0 +1,122 @@
import { Box, TextField, Typography, useTheme } from "@mui/material";
import { useState } from "react";
import { DatePicker } from "@mui/x-date-pickers";
import { StatisticsPromocode } from "./StastisticsPromocode";
import type { Moment } from "moment";
interface Props {
from: Moment | null;
to: Moment | null;
setFrom: (a: Moment | null) => void;
setTo: (a: Moment | null) => void;
}
export const DateFilter = ({ to, setTo, from, setFrom }: Props) => {
const theme = useTheme();
const [isOpen, setOpen] = useState<boolean>(false);
const [isOpenEnd, setOpenEnd] = useState<boolean>(false);
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 (
<>
<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,
},
},
}}
/>
<StatisticsPromocode />
</Box>
</>
);
};

@ -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>
</>
);
};

@ -0,0 +1,85 @@
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Typography,
useTheme,
} from "@mui/material";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { DateFilter } from "./DateFilter";
import { useState } from "react";
import moment, { Moment } from "moment";
import { usePromocodeStatistics } from "@root/utils/hooks/usePromocodeStatistics";
import { useAllPromocodes } from "@root/api/promocode/swr";
import { QuizStatisticsItem } from "@root/api/quizStatistics/types";
export const StatisticsPromocode = () => {
const [from, setFrom] = useState<Moment | null>(moment("01.01.2023"));
const [to, setTo] = useState<Moment | null>(moment(Date.now()));
const promocodes = useAllPromocodes();
const promocodeStatistics = usePromocodeStatistics({ to, from });
const theme = useTheme();
return (
<LocalizationProvider dateAdapter={AdapterMoment}>
<Typography>Статистика промокодов</Typography>
<DateFilter from={from} to={to} setFrom={setFrom} setTo={setTo} />
<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">
Регистации
</TableCell>
<TableCell sx={{ color: "inherit" }} align="center">
Внесено
</TableCell>
</TableRow>
</TableHead>
{/* {Object.values(promocodeStatistics).map(({ Regs, Money }) => {
let codeword = "";
for (let value in promocodeStatistics) {
const codewordSearch = promocodes.find(({ id }) => id === value);
codeword = codewordSearch?.codeword ?? "";
}
return (
<TableBody>
<TableCell sx={{ color: "inherit" }} align="center">
{codeword}
</TableCell>
<TableCell sx={{ color: "inherit" }} align="center">
{Regs}
</TableCell>
<TableCell sx={{ color: "inherit" }} align="center">
{Money}
</TableCell>
</TableBody>
);
})} */}
</Table>
</LocalizationProvider>
);
};

@ -0,0 +1,195 @@
import moment from "moment";
import { useEffect, useState } from "react";
import {
Accordion,
AccordionDetails,
AccordionSummary,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Typography,
Button,
useTheme,
} from "@mui/material";
import { GridToolbar } from "@mui/x-data-grid";
import { enqueueSnackbar } from "notistack";
import DataGrid from "@kitUI/datagrid";
import ModalUser from "@pages/dashboard/ModalUser";
import { DateFilter } from "./DateFilter";
import { useSchildStatistics } from "@root/utils/hooks/useSchildStatistics";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import type { Moment } from "moment";
import type { QuizStatisticsItem } from "@root/api/quizStatistics/types";
import type { GridColDef } from "@mui/x-data-grid";
const COLUMNS: GridColDef<QuizStatisticsItem, string>[] = [
{
field: "user",
headerName: "Пользователь",
width: 250,
valueGetter: ({ row }) => row.ID,
},
{
field: "regs",
headerName: "Регистраций",
width: 200,
valueGetter: ({ row }) => String(row.Regs),
},
{
field: "money",
headerName: "Деньги",
width: 200,
valueGetter: ({ row }) => String(row.Money),
},
];
export const StatisticsSchild = () => {
const [openUserModal, setOpenUserModal] = useState<boolean>(false);
const [activeUserId, setActiveUserId] = useState<string>("");
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
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>
<DateFilter from={from} to={to} setFrom={setFrom} setTo={setTo} />
<DataGrid
sx={{ marginTop: "30px", width: "80%" }}
getRowId={({ ID }) => ID}
checkboxSelection={true}
rows={statistics}
components={{ Toolbar: GridToolbar }}
rowCount={statistics.length}
rowsPerPageOptions={[1, 10, 25, 50, 100]}
paginationMode="client"
disableSelectionOnClick
page={page}
pageSize={pageSize}
onPageChange={setPage}
onPageSizeChange={setPageSize}
onCellClick={({ id, field }) =>
field === "user" && setActiveUserId(String(id))
}
getRowHeight={() => "auto"}
columns={[
...COLUMNS,
{
field: "quizes",
headerName: "Квизы",
flex: 1,
minWidth: 220,
valueGetter: ({ row }) => String(row.Quizes.length),
renderCell: ({ row }) => (
<Accordion sx={{ width: "100%" }}>
<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>
{row.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>
),
},
]}
/>
<ModalUser
open={openUserModal}
onClose={() => setOpenUserModal(false)}
userId={activeUserId}
/>
</>
);
};

@ -0,0 +1,12 @@
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import { QuizInfo } from "./QuizInfo";
import { StatisticsSchild } from "./StatisticsSchild";
export const QuizStatistics = () => (
<LocalizationProvider dateAdapter={AdapterMoment}>
<QuizInfo />
<StatisticsSchild />
</LocalizationProvider>
);

@ -100,7 +100,7 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== "open"
}));
const links: { path: string; element: JSX.Element; title: string; className: string }[] = [
{ path: "/quizStatistic", element: <>📝</>, title: "Статистика Quiz", className: "menu" },
{ path: "/quizStatistics", element: <>📝</>, title: "Статистика Quiz", className: "menu" },
{ path: "/users", element: <PersonOutlineOutlinedIcon />, title: "Информация о проекте", className: "menu" },
{ path: "/entities", element: <SettingsOutlinedIcon />, title: "Юридические лица", className: "menu" },
{ path: "/tariffs", element: <BathtubOutlinedIcon />, title: "Тарифы", className: "menu" },

@ -1,29 +0,0 @@
import { useEffect, useState } from "react";
import type { Moment } from "moment";
import {getStatisticPromocode} from "@root/api/quizStatistic";
interface useStatisticProps {
to: Moment | null;
from: Moment | null;
}
export function usePromocodeStatistic({ to, from }: useStatisticProps) {
const formatTo = to?.unix();
const formatFrom = from?.unix();
const [statisticPromo, setStatisticPromo] = useState<any>([])
useEffect(() => {
const requestStatistics = async () => {
const gottenData = await getStatisticPromocode(Number(formatFrom), Number(formatTo));
setStatisticPromo(gottenData)
}
requestStatistics();
}, []);
return statisticPromo;
}

@ -0,0 +1,36 @@
import { useEffect, useState } from "react";
import { getStatisticPromocode } from "@root/api/quizStatistics";
import type { Moment } from "moment";
import type { QuizStatisticsItem } from "@root/api/quizStatistics/types";
interface useStatisticProps {
to: Moment | null;
from: Moment | null;
}
export function usePromocodeStatistics({ to, from }: useStatisticProps) {
const formatTo = to?.unix();
const formatFrom = from?.unix();
const [statisticPromo, setStatisticPromo] = useState<QuizStatisticsItem>({
ID: "0",
Regs: 0,
Money: 0,
Quizes: [{ QuizID: "0", Regs: 0, Money: 0 }],
});
useEffect(() => {
const requestStatistics = async () => {
const gottenData = await getStatisticPromocode(
Number(formatFrom),
Number(formatTo)
);
setStatisticPromo(gottenData);
};
requestStatistics();
}, []);
return statisticPromo;
}

@ -1,8 +1,5 @@
import { useEffect, useState } from "react";
import {
QuizStatisticResponse,
getStatistic
} from "@root/api/quizStatistic";
import { QuizStatisticResponse, getStatistic } from "@root/api/quizStatistics";
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
}

@ -0,0 +1,27 @@
import { useEffect, useState } from "react";
import { getStatisticSchild } from "@root/api/quizStatistics";
import type { Moment } from "moment";
import type { QuizStatisticsItem } from "@root/api/quizStatistics/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"]
}