Merge branch 'promo-stat' into 'statistics-refactoring'
Promo stat See merge request frontend/admin!80
This commit is contained in:
commit
9fea38098b
@ -59,3 +59,24 @@ export const getStatisticSchild = async (
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
@ -106,7 +106,7 @@ root.render(
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/quizStatistic"
|
||||
path="/quizStatistics"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<QuizStatistics />
|
||||
|
||||
122
src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx
Normal file
122
src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx
Normal file
@ -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,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>
|
||||
);
|
||||
};
|
||||
@ -1,378 +0,0 @@
|
||||
import moment from "moment";
|
||||
import { ReactNode, useEffect, useState } from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Box,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TextField,
|
||||
Typography,
|
||||
Button,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { GridToolbar } from "@mui/x-data-grid";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import DataGrid from "@kitUI/datagrid";
|
||||
|
||||
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";
|
||||
import type { QuizStatisticsItem } from "@root/api/quizStatistic/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 StatisticSchild = () => {
|
||||
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>
|
||||
<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> */}
|
||||
<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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
195
src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx
Normal file
195
src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx
Normal file
@ -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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -2,11 +2,11 @@ import { LocalizationProvider } from "@mui/x-date-pickers";
|
||||
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
|
||||
|
||||
import { QuizInfo } from "./QuizInfo";
|
||||
import { StatisticSchild } from "./StatisticSchild";
|
||||
import { StatisticsSchild } from "./StatisticsSchild";
|
||||
|
||||
export const QuizStatistics = () => (
|
||||
<LocalizationProvider dateAdapter={AdapterMoment}>
|
||||
<QuizInfo />
|
||||
<StatisticSchild />
|
||||
<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" },
|
||||
|
||||
36
src/utils/hooks/usePromocodeStatistics.ts
Normal file
36
src/utils/hooks/usePromocodeStatistics.ts
Normal file
@ -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,5 +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";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { getStatisticSchild } from "@root/api/quizStatistic";
|
||||
import { getStatisticSchild } from "@root/api/quizStatistics";
|
||||
|
||||
import type { Moment } from "moment";
|
||||
|
||||
import type { QuizStatisticsItem } from "@root/api/quizStatistic/types";
|
||||
import type { QuizStatisticsItem } from "@root/api/quizStatistics/types";
|
||||
|
||||
export const useSchildStatistics = (from: Moment | null, to: Moment | null) => {
|
||||
const formatTo = to?.unix();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user