From 3f8301c4fe7e740bd401176361c060a80971268a Mon Sep 17 00:00:00 2001 From: Nastya Date: Fri, 19 Apr 2024 19:49:34 +0300 Subject: [PATCH 01/20] =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=BB=D0=BE=D0=B3=D0=B8=20=D0=BF=D1=80=D0=B8=20=D0=B2?= =?UTF-8?q?=D1=8B=D0=B1=D0=BE=D1=80=D0=B5=20=D0=BF=D1=80=D0=B8=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=D0=B5=D0=B3=D0=B8=D0=B8=20=D0=B2=20=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D1=84=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Content/Tariffs/CreateTariff.tsx | 491 +++++++++--------- 1 file changed, 247 insertions(+), 244 deletions(-) diff --git a/src/pages/dashboard/Content/Tariffs/CreateTariff.tsx b/src/pages/dashboard/Content/Tariffs/CreateTariff.tsx index fad5d30..d96d06d 100644 --- a/src/pages/dashboard/Content/Tariffs/CreateTariff.tsx +++ b/src/pages/dashboard/Content/Tariffs/CreateTariff.tsx @@ -52,19 +52,19 @@ export default function CreateTariff() { }; - const initialValues: Values = { - nameField: "", - descriptionField: "", - amountField: "", - customPriceField: "", - privilegeIdField: "", - orderField: 0, - privilege: null - }; + const initialValues: Values = { + nameField: "", + descriptionField: "", + amountField: "", + customPriceField: "", + privilegeIdField: "", + orderField: 0, + privilege: null + }; const createTariffBackend = async ( - values: Values, - formikHelpers: FormikHelpers + values: Values, + formikHelpers: FormikHelpers ) => { if (values.privilege !== null) { const [, createdTariffError] = await createTariff({ @@ -111,241 +111,244 @@ export default function CreateTariff() { // } return ( - - {(props) => ( -
- + {(props) => ( + + - - Создание тарифа - - + + Создание тарифа + + + + Привилегия + + { - props.setFieldValue("privilegeIdField", e.target.value) - props.setFieldValue("privilege", findPrivilegeById(e.target.value)) - if (props.values.privilege === null) - return enqueueSnackbar("Привилегия не найдена"); - }} - onBlur={props.handleBlur} - sx={{ - color: theme.palette.secondary.main, - borderColor: theme.palette.secondary.main, - "&.Mui-focused .MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.secondary.main, - border: "1px solid", - }, - ".MuiSvgIcon-root ": { - fill: theme.palette.secondary.main, - }, - }} - inputProps={{ sx: { pt: "12px" } }} - > - {privileges.map((privilege) => ( - - {privilege.serviceKey}:{privilege.description} - - ))} - - - {props.values.privilege && ( - - - Имя: {props.values.privilege.name} - - - Сервис: {props.values.privilege.serviceKey} - - - Единица: {props.values.privilege.type} - - - Стандартная цена за единицу: {currencyFormatter.format(props.values.privilege.price / 100)} - - - )} - - {props.errors.nameField} - - } - InputProps={{ - style: { - backgroundColor: theme.palette.content.main, - color: theme.palette.secondary.main, - } - }} - InputLabelProps={{ - style: { - color: theme.palette.secondary.main - } - }} - /> - { - props.setFieldValue("amountField", e.target.value.replace(/[^\d]/g,'')) - }} - value={props.values.amountField} - onBlur={props.handleBlur} - label="Кол-во единиц привилегии" - error={props.touched.amountField && !!props.errors.amountField} - helperText={ - - {props.errors.amountField} - - } - InputProps={{ - style: { - backgroundColor: theme.palette.content.main, - color: theme.palette.secondary.main, - } - }} - InputLabelProps={{ - style: { - color: theme.palette.secondary.main - } - }} - /> - { - props.setFieldValue("customPriceField", e.target.value.replace(/[^\d]/g,'')) - }} - value={props.values.customPriceField} - onBlur={props.handleBlur} - label="Кастомная цена (не обязательно)" - InputProps={{ - style: { - backgroundColor: theme.palette.content.main, - color: theme.palette.secondary.main, - } - }} - InputLabelProps={{ - style: { - color: theme.palette.secondary.main - } - }} - /> - { - props.setFieldValue("descriptionField", e.target.value) - }} - value={props.values.descriptionField} - onBlur={props.handleBlur} - label="Описание" - multiline={true} - InputProps={{ - style: { - backgroundColor: theme.palette.content.main, - color: theme.palette.secondary.main, - } - }} - InputLabelProps={{ - style: { - color: theme.palette.secondary.main - } - }} - /> - { - props.setFieldValue("orderField", e.target.value) - }} - value={props.values.orderField} - onBlur={props.handleBlur} - label="порядковый номер" - InputProps={{ - style: { - backgroundColor: theme.palette.content.main, - color: theme.palette.secondary.main, - } - }} - type={'number'} - InputLabelProps={{ - style: { - color: theme.palette.secondary.main - } - }} - /> - - - - )} -
+ {privilege.serviceKey}:{privilege.description} + + ))} + + + {props.values.privilege && ( + + + Имя: {props.values.privilege.name} + + + Сервис: {props.values.privilege.serviceKey} + + + Единица: {props.values.privilege.type} + + + Стандартная цена за единицу: {currencyFormatter.format(props.values.privilege.price / 100)} + + + )} + + {props.errors.nameField} + + } + InputProps={{ + style: { + backgroundColor: theme.palette.content.main, + color: theme.palette.secondary.main, + } + }} + InputLabelProps={{ + style: { + color: theme.palette.secondary.main + } + }} + /> + { + props.setFieldValue("amountField", e.target.value.replace(/[^\d]/g, '')) + }} + value={props.values.amountField} + onBlur={props.handleBlur} + label="Кол-во единиц привилегии" + error={props.touched.amountField && !!props.errors.amountField} + helperText={ + + {props.errors.amountField} + + } + InputProps={{ + style: { + backgroundColor: theme.palette.content.main, + color: theme.palette.secondary.main, + } + }} + InputLabelProps={{ + style: { + color: theme.palette.secondary.main + } + }} + /> + { + props.setFieldValue("customPriceField", e.target.value.replace(/[^\d]/g, '')) + }} + value={props.values.customPriceField} + onBlur={props.handleBlur} + label="Кастомная цена (не обязательно)" + InputProps={{ + style: { + backgroundColor: theme.palette.content.main, + color: theme.palette.secondary.main, + } + }} + InputLabelProps={{ + style: { + color: theme.palette.secondary.main + } + }} + /> + { + props.setFieldValue("descriptionField", e.target.value) + }} + value={props.values.descriptionField} + onBlur={props.handleBlur} + label="Описание" + multiline={true} + InputProps={{ + style: { + backgroundColor: theme.palette.content.main, + color: theme.palette.secondary.main, + } + }} + InputLabelProps={{ + style: { + color: theme.palette.secondary.main + } + }} + /> + { + props.setFieldValue("orderField", e.target.value) + }} + value={props.values.orderField} + onBlur={props.handleBlur} + label="порядковый номер" + InputProps={{ + style: { + backgroundColor: theme.palette.content.main, + color: theme.palette.secondary.main, + } + }} + type={'number'} + InputLabelProps={{ + style: { + color: theme.palette.secondary.main + } + }} + /> + + + + )} + ); } From 3fc5fc14906f9f656d8858aaae7c90937ab2cebf Mon Sep 17 00:00:00 2001 From: skeris Date: Mon, 22 Apr 2024 11:58:36 +0300 Subject: [PATCH 02/20] ci: remove from external interface --- admin.conf | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/admin.conf b/admin.conf index d1bdfe0..b3a31f2 100644 --- a/admin.conf +++ b/admin.conf @@ -21,10 +21,10 @@ server { return 200; } if ($host = sadmin.pena) { - proxy_pass http://10.6.0.11:59301; + proxy_pass http://10.8.0.6:59301; } if ($host != sadmin.pena) { - proxy_pass http://10.6.0.11:59300; + proxy_pass http://10.8.0.6:59300; } proxy_hide_header Access-Control-Allow-Origin; add_header Access-Control-Allow-Origin $http_origin always; @@ -42,7 +42,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.11:59300; + proxy_pass http://10.8.0.6:59300; } location /manager/ { if ($request_method = OPTIONS) { @@ -56,11 +56,11 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.11:59301/; + proxy_pass http://10.8.0.6:59301/; } location /swagger/ { - proxy_pass http://10.6.0.11:59300/; + proxy_pass http://10.8.0.6:59300/; } location /heruvym/ { @@ -75,7 +75,7 @@ server { chunked_transfer_encoding off; proxy_buffering off; proxy_cache off; - proxy_pass https://10.6.0.11:1488/; + proxy_pass https://10.8.0.6:1488/; } location /strator/ { @@ -90,7 +90,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.11:59303/; + proxy_pass http://10.8.0.6:59303/; } location /customer/ { @@ -105,7 +105,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.11:8065/; + proxy_pass http://10.8.0.6:8065/; } location /codeword/ { @@ -120,7 +120,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.11:59664/; + proxy_pass http://10.8.0.6:59664/; } location /answer/ { @@ -135,7 +135,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.23:1490/; + proxy_pass http://10.8.0.5:1490/; } location /squiz/ { @@ -150,7 +150,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.23:1488/; + proxy_pass http://10.8.0.5:1488/; } location /squizstorer/ { @@ -172,7 +172,7 @@ server { chunked_transfer_encoding off; proxy_buffering off; proxy_cache off; - proxy_pass http://10.6.0.23:1489/; + proxy_pass http://10.8.0.5:1489/; } location /price/ { @@ -187,7 +187,7 @@ server { add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers content-type,authorization always; add_header Access-Control-Allow-Methods OPTIONS,GET,POST,PATCH,PUT,DELETE; - proxy_pass http://10.6.0.11:8001/; + proxy_pass http://10.8.0.6:8001/; } location /feedback/ { if ($request_method = OPTIONS) { @@ -257,7 +257,7 @@ server { chunked_transfer_encoding off; proxy_buffering off; proxy_cache off; - proxy_pass http://10.6.0.17:7035/; + proxy_pass http://10.8.0.6:7035/; } From 9fcadcfe597a6ebec6c0c8ae8cdcef2abc575303 Mon Sep 17 00:00:00 2001 From: Tamara Date: Tue, 23 Apr 2024 10:12:01 +0300 Subject: [PATCH 03/20] =?UTF-8?q?=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=8B=20=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D1=82?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=82=D0=B8=D0=BA=D0=B5=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B8=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BF=D0=BE=D1=81=20=D0=BD=D0=B0=20=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D0=BA=D1=83=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D1=85=D0=BE=D0=B4=D0=BE=D0=B2=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D1=88=D0=B8=D0=BB=D1=8C=D0=B4=D0=B8=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/Content/QuizStatistic/index.tsx | 33 +++++++++++++++++++ .../Content/Support/TicketList/TicketList.tsx | 22 +++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/pages/dashboard/Content/QuizStatistic/index.tsx b/src/pages/dashboard/Content/QuizStatistic/index.tsx index 4c2b5e2..0a18d45 100644 --- a/src/pages/dashboard/Content/QuizStatistic/index.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/index.tsx @@ -5,6 +5,9 @@ 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 makeRequest from "@root/api/makeRequest"; +import {Discount} from "@frontend/kitui"; +import {parseAxiosError} from "@root/utils/parse-error"; export default () => { const theme = useTheme() @@ -56,6 +59,28 @@ export default () => { } }; + const StatisticsShild = async (from: any, to: any) => { + try { + const StatisticResponse = await makeRequest({ + url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" , + method: "post", + useToken: true, + body: { + "to": to, + "from": from, + "page": 0, + "limit": 0 + }, + }); + + return [StatisticResponse]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, `Ошибка запроса статистики. ${error}`]; + } + } + return <> @@ -135,6 +160,14 @@ export default () => { > Сбросить даты + void; @@ -21,6 +24,7 @@ export default function TicketList({ const tickets = useTicketStore((state) => state.tickets); const ticketsFetchState = useTicketStore((state) => state.ticketsFetchState); const ticketsBoxRef = useRef(null); + const ticketId = useParams().ticketId; useEffect( function updateCurrentPageOnScroll() { @@ -91,6 +95,24 @@ export default function TicketList({ + + + + + ) +} \ No newline at end of file diff --git a/src/pages/dashboard/Content/Support/TicketList/TicketList.tsx b/src/pages/dashboard/Content/Support/TicketList/TicketList.tsx index d4c712b..433a7ac 100644 --- a/src/pages/dashboard/Content/Support/TicketList/TicketList.tsx +++ b/src/pages/dashboard/Content/Support/TicketList/TicketList.tsx @@ -3,12 +3,13 @@ import SearchOutlinedIcon from "@mui/icons-material/SearchOutlined"; import { Box, Button, useMediaQuery, useTheme } from "@mui/material"; import { Ticket } from "@root/model/ticket"; import { incrementTicketsApiPage, useTicketStore } from "@root/stores/tickets"; -import { useEffect, useRef } from "react"; +import {useEffect, useRef, useState} from "react"; import TicketItem from "./TicketItem"; import { throttle } from "@frontend/kitui"; import makeRequest from "@root/api/makeRequest"; import {parseAxiosError} from "@root/utils/parse-error"; import {useParams} from "react-router-dom"; +import CloseTicketModal from "@pages/dashboard/Content/Support/TicketList/CloseTicketModal"; type TicketListProps = { closeCollapse?: () => void; @@ -25,6 +26,7 @@ export default function TicketList({ const ticketsFetchState = useTicketStore((state) => state.ticketsFetchState); const ticketsBoxRef = useRef(null); const ticketId = useParams().ticketId; + const [openModal, setOpenModal] = useState(false) useEffect( function updateCurrentPageOnScroll() { @@ -95,24 +97,7 @@ export default function TicketList({ + Date: Thu, 25 Apr 2024 02:29:39 +0300 Subject: [PATCH 05/20] =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B0=20=D1=88=D0=B8=D0=BB=D1=8C=D0=B4=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Content/QuizStatistic/StatisticSchild.tsx | 192 ++++++++++++++++++ .../dashboard/Content/QuizStatistic/index.tsx | 65 +++--- .../Support/TicketList/CloseTicketModal.tsx | 5 +- 3 files changed, 231 insertions(+), 31 deletions(-) create mode 100644 src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx diff --git a/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx b/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx new file mode 100644 index 0000000..8bd15c1 --- /dev/null +++ b/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx @@ -0,0 +1,192 @@ +import {useState} from "react"; +import moment, {Moment} from "moment"; +import { + Box, + Button, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + TextField, + Typography, + useTheme +} from "@mui/material"; +import makeRequest from "@root/api/makeRequest"; +import {parseAxiosError} from "@root/utils/parse-error"; +import {AdapterMoment} from "@mui/x-date-pickers/AdapterMoment"; +import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; + +export default function StatisticSchild() { + const theme = useTheme() + const [isOpen, setOpen] = useState(false); + const [isOpenEnd, setOpenEnd] = useState(false); + + const [from, setFrom] = useState(null); + const [to, setTo] = useState(moment(Date.now())); + + const [statistic, setStatistic] = useState([]) + 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(); + } + }; + + const StatisticsShild = async (from: any, to: any) => { + try { + const StatisticResponse = await makeRequest({ + url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" , + method: "post", + useToken: true, + body: { + "to": to.unix(), + "from": from.unix(), + "page": 0, + "limit": 100 + }, + }); + setStatistic(StatisticResponse) + return [StatisticResponse]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, `Ошибка запроса статистики. ${error}`]; + } + } + console.log(statistic) + + return( + + Статистика переходов с шильдика + + + Дата начала + + date && setFrom(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { + color: theme.palette.secondary.main, + }, + }, + }} + /> + + + + Дата окончания + + date && setTo(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { + color: theme.palette.secondary.main, + }, + }, + }} + /> + + +
+ + + ID + Регистраций + Money + + + + {statistic[0].ID} + {statistic[0].Regs} + {statistic[0].Money} + +
+
+ ) + +} diff --git a/src/pages/dashboard/Content/QuizStatistic/index.tsx b/src/pages/dashboard/Content/QuizStatistic/index.tsx index 9e93461..57d9b25 100644 --- a/src/pages/dashboard/Content/QuizStatistic/index.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/index.tsx @@ -8,6 +8,7 @@ import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment' import makeRequest from "@root/api/makeRequest"; import {Discount} from "@frontend/kitui"; import {parseAxiosError} from "@root/utils/parse-error"; +import StatisticSchild from "./StatisticSchild"; export default () => { const theme = useTheme() @@ -19,6 +20,7 @@ export default () => { const [to, setTo] = useState(moment(Date.now())); + const { Registrations, Quizes, Results } = useQuizStatistic({ from, to, @@ -59,28 +61,28 @@ export default () => { } }; - const StatisticsShild = async (from: any, to: any) => { - try { - const StatisticResponse = await makeRequest({ - url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" , - method: "post", - useToken: true, - body: { - "to": to.unix(), - "from": from.unix(), - "page": 0, - "limit": 100 - }, - }); - - return [StatisticResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); - - return [null, `Ошибка запроса статистики. ${error}`]; - } - } - + // const StatisticsShild = async (from: any, to: any) => { + // try { + // const StatisticResponse = await makeRequest({ + // url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" , + // method: "post", + // useToken: true, + // body: { + // "to": to.unix(), + // "from": from.unix(), + // "page": 0, + // "limit": 100 + // }, + // }); + // + // return [StatisticResponse]; + // } catch (nativeError) { + // const [error] = parseAxiosError(nativeError); + // + // return [null, `Ошибка запроса статистики. ${error}`]; + // } + // } + // return <> @@ -160,14 +162,14 @@ export default () => { > Сбросить даты - + {/*StatisticsShild(from, to)}*/} + {/*>*/} + {/* Запросить статистику(тест)*/} + {/**/} { {Results}
+ + +
} \ No newline at end of file diff --git a/src/pages/dashboard/Content/Support/TicketList/CloseTicketModal.tsx b/src/pages/dashboard/Content/Support/TicketList/CloseTicketModal.tsx index 450d49c..1c12a27 100644 --- a/src/pages/dashboard/Content/Support/TicketList/CloseTicketModal.tsx +++ b/src/pages/dashboard/Content/Support/TicketList/CloseTicketModal.tsx @@ -66,7 +66,10 @@ export default function CloseTicketModal({ticketId, openModal, setOpenModal}: Pr }} > @@ -175,16 +168,76 @@ export default function StatisticSchild() { height: "100px", }} > - ID + Пользователь Регистраций - Money + Деньги + Квизы - - {statistic[0]?.ID} - {statistic[0]?.Regs} - {statistic[0]?.Money} - + {statistic.map((stat: any) => ( + + setActiveUserId(stat?.ID)} + >{stat?.ID} + setOpenUserModal(false)} + userId={activeUserId} + /> + {stat?.Regs} + {stat?.Money} + + + } + aria-controls="panel1-content" + id="panel1-header" + > + Статистика по квизам + + +
+ + + QuizID + Регистрации + Деньги + + + + {stat?.Quizes.map((quiz:any)=> ( + + {quiz?.QuizID} + {quiz?.Regs} + {quiz?.Money} + + ))} + + +
+ + + + + )) + } + ) diff --git a/src/pages/dashboard/Content/QuizStatistic/index.tsx b/src/pages/dashboard/Content/QuizStatistic/index.tsx index 57d9b25..172aeba 100644 --- a/src/pages/dashboard/Content/QuizStatistic/index.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/index.tsx @@ -5,9 +5,6 @@ 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 makeRequest from "@root/api/makeRequest"; -import {Discount} from "@frontend/kitui"; -import {parseAxiosError} from "@root/utils/parse-error"; import StatisticSchild from "./StatisticSchild"; export default () => { @@ -61,29 +58,6 @@ export default () => { } }; - // const StatisticsShild = async (from: any, to: any) => { - // try { - // const StatisticResponse = await makeRequest({ - // url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" , - // method: "post", - // useToken: true, - // body: { - // "to": to.unix(), - // "from": from.unix(), - // "page": 0, - // "limit": 100 - // }, - // }); - // - // return [StatisticResponse]; - // } catch (nativeError) { - // const [error] = parseAxiosError(nativeError); - // - // return [null, `Ошибка запроса статистики. ${error}`]; - // } - // } - // - return <> @@ -162,15 +136,6 @@ export default () => { > Сбросить даты - {/*StatisticsShild(from, to)}*/} - {/*>*/} - {/* Запросить статистику(тест)*/} - {/**/} - { Email - {user?.email} + {user?.email || user?.login} diff --git a/src/utils/hooks/useSchildStatistic.ts b/src/utils/hooks/useSchildStatistic.ts new file mode 100644 index 0000000..4167d25 --- /dev/null +++ b/src/utils/hooks/useSchildStatistic.ts @@ -0,0 +1,17 @@ +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([]) + useEffect(() => { + const StatisticsShild = async () => { + const gottenData = await getStatisticSchild(Number(formatFrom), Number(formatTo)); + setStatistic(gottenData) + } + StatisticsShild() + }, []); + return statistic +} From 1dc7a83ac229ed4a50bebd41c441d2866a8f6182 Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Fri, 26 Apr 2024 14:12:51 +0300 Subject: [PATCH 08/20] feat: promocodes description --- .../usePromocodeGridColDef.tsx | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/pages/dashboard/Content/PromocodeManagement/usePromocodeGridColDef.tsx b/src/pages/dashboard/Content/PromocodeManagement/usePromocodeGridColDef.tsx index 2bd6da9..707e7f2 100644 --- a/src/pages/dashboard/Content/PromocodeManagement/usePromocodeGridColDef.tsx +++ b/src/pages/dashboard/Content/PromocodeManagement/usePromocodeGridColDef.tsx @@ -4,14 +4,20 @@ import { Promocode } from "@root/model/promocodes"; import { useMemo, useState } from "react"; import { BarChart, Delete } from "@mui/icons-material"; -import {promocodeApi} from "@root/api/promocode/requests"; +import { promocodeApi } from "@root/api/promocode/requests"; export function usePromocodeGridColDef( setStatistics: (id: string) => void, deletePromocode: (id: string) => void ) { - const validity = (value:string|number) => {if(value===0){return "неоганичен"}else {return new Date(value).toLocaleString()}} - return useMemo[]>( + const validity = (value: string | number) => { + if (value === 0) { + return "неоганичен"; + } else { + return new Date(value).toLocaleString(); + } + }; + return useMemo[]>( () => [ { field: "id", @@ -50,6 +56,14 @@ export function usePromocodeGridColDef( valueGetter: ({ row }) => row.dueTo * 1000, valueFormatter: ({ value }) => `${validity(value)}`, }, + { + field: "description", + headerName: "Описание", + minWidth: 200, + flex: 1, + sortable: false, + valueGetter: ({ row }) => row.description, + }, { field: "settings", headerName: "", @@ -57,10 +71,12 @@ export function usePromocodeGridColDef( sortable: false, renderCell: (params) => { return ( - { - setStatistics(params.row.id,) - promocodeApi.getPromocodeStatistics(params.row.id, 0, 0) - }}> + { + setStatistics(params.row.id); + promocodeApi.getPromocodeStatistics(params.row.id, 0, 0); + }} + > ); From ddd345b0d12ef120054574eb0b353d8c468653ee Mon Sep 17 00:00:00 2001 From: Tamara Date: Mon, 29 Apr 2024 16:29:52 +0300 Subject: [PATCH 09/20] =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B0=20=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=D0=B0(=D0=B1=D0=B5=D0=B7=20=D0=B2=D1=8B=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=D0=B0=20=D0=B2=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D1=86=D1=83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/quizStatistic.ts | 19 ++- .../Content/QuizStatistic/StatisticSchild.tsx | 102 +-------------- .../QuizStatistic/StstisticPromocode.tsx | 50 ++++++++ .../Content/QuizStatistic/dateFilter.tsx | 119 ++++++++++++++++++ .../dashboard/Content/QuizStatistic/index.tsx | 111 +--------------- src/utils/hooks/usePromocodeStatistic.ts | 29 +++++ 6 files changed, 224 insertions(+), 206 deletions(-) create mode 100644 src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx create mode 100644 src/pages/dashboard/Content/QuizStatistic/dateFilter.tsx create mode 100644 src/utils/hooks/usePromocodeStatistic.ts diff --git a/src/api/quizStatistic.ts b/src/api/quizStatistic.ts index 0551ada..217e300 100644 --- a/src/api/quizStatistic.ts +++ b/src/api/quizStatistic.ts @@ -29,7 +29,7 @@ export const getStatistic = async ( }; export const getStatisticSchild = async ( - from: any, to: any): Promise => { + from: number, to: number): Promise => { try { const StatisticResponse = await makeRequest({ url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat" , @@ -48,3 +48,20 @@ export const getStatisticSchild = async ( return [{ID: 0, Regs: 0, Money: 0, Quizes:[{QuizID: 0, Regs: 0, Money: 0}]}]; } }; + export const getStatisticPromocode = async (from: number, to: number): Promise => { + try { + const StatisticPromo = await makeRequest({ + 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) + } + } \ No newline at end of file diff --git a/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx b/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx index 74087a0..7694877 100644 --- a/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx @@ -19,12 +19,10 @@ 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 [isOpen, setOpen] = useState(false); - const [isOpenEnd, setOpenEnd] = useState(false); - const [openUserModal, setOpenUserModal] = useState(false); const [activeUserId, setActiveUserId] = useState(""); @@ -32,35 +30,6 @@ export default function StatisticSchild() { const [to, setTo] = useState(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(""); @@ -82,74 +51,7 @@ export default function StatisticSchild() { return( Статистика переходов с шильдика - - - Дата начала - - date && setFrom(date)} - renderInput={(params) => ( - - )} - InputProps={{ - sx: { - height: "40px", - color: theme.palette.secondary.main, - border: "1px solid", - borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { - color: theme.palette.secondary.main, - }, - }, - }} - /> - - - - Дата окончания - - date && setTo(date)} - renderInput={(params) => ( - - )} - InputProps={{ - sx: { - height: "40px", - color: theme.palette.secondary.main, - border: "1px solid", - borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { - color: theme.palette.secondary.main, - }, - }, - }} - /> - +
(moment("01.01.2023")); + const [to, setTo] = useState(moment(Date.now())); + + const statisticPromo = usePromocodeStatistic({to, from}) + + return( + + Статистика промокодов + +
+ + + Промокод + Регистации + Внесено + + + + {/*{Registrations}*/} + {/*{Quizes}*/} + {/*{Results}*/} + +
+
+ ) +} \ No newline at end of file diff --git a/src/pages/dashboard/Content/QuizStatistic/dateFilter.tsx b/src/pages/dashboard/Content/QuizStatistic/dateFilter.tsx new file mode 100644 index 0000000..9d8339e --- /dev/null +++ b/src/pages/dashboard/Content/QuizStatistic/dateFilter.tsx @@ -0,0 +1,119 @@ +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(false); + const [isOpenEnd, setOpenEnd] = useState(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( + <> + + + Дата начала + + date && setFrom(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { + color: theme.palette.secondary.main, + }, + }, + }} + /> + + + + Дата окончания + + date && setTo(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { + color: theme.palette.secondary.main, + }, + }, + }} + /> + + + + ) +} \ No newline at end of file diff --git a/src/pages/dashboard/Content/QuizStatistic/index.tsx b/src/pages/dashboard/Content/QuizStatistic/index.tsx index 172aeba..2dbbcea 100644 --- a/src/pages/dashboard/Content/QuizStatistic/index.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/index.tsx @@ -6,18 +6,16 @@ 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 [isOpen, setOpen] = useState(false); - const [isOpenEnd, setOpenEnd] = useState(false); - const [from, setFrom] = useState(null); const [to, setTo] = useState(moment(Date.now())); - - const { Registrations, Quizes, Results } = useQuizStatistic({ from, to, @@ -28,106 +26,9 @@ export default () => { 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 <> - - - Дата начала - - date && setFrom(date)} - renderInput={(params) => ( - - )} - InputProps={{ - sx: { - height: "40px", - color: theme.palette.secondary.main, - border: "1px solid", - borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { - color: theme.palette.secondary.main, - }, - }, - }} - /> - - - - Дата окончания - - date && setTo(date)} - renderInput={(params) => ( - - )} - InputProps={{ - sx: { - height: "40px", - color: theme.palette.secondary.main, - border: "1px solid", - borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { - color: theme.palette.secondary.main, - }, - }, - }} - /> - + - - - - Регистраций - Quiz - Результаты - - - - {Registrations} - {Quizes} - {Results} - -
- - - -
- -} \ No newline at end of file diff --git a/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx b/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx new file mode 100644 index 0000000..5bde905 --- /dev/null +++ b/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx @@ -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(null); + const [to, setTo] = useState(moment(Date.now())); + const theme = useTheme(); + const { Registrations, Quizes, Results } = useQuizStatistic({ + from, + to, + }); + + const resetTime = () => { + setFrom(moment()); + setTo(moment(Date.now())); + }; + + return ( + <> + + + Дата начала + + date && setFrom(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, + }, + }} + /> + + + + Дата окончания + + date && setTo(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, + }, + }} + /> + + + + + + + Регистраций + + + Quiz + + + Результаты + + + + + + + {Registrations} + + + {Quizes} + + + {Results} + + + +
+ + ); +}; diff --git a/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx b/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx new file mode 100644 index 0000000..df90247 --- /dev/null +++ b/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx @@ -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(false); + const [activeUserId, setActiveUserId] = useState(""); + + const [from, setFrom] = useState( + moment(new Date("01.01.2023")) + ); + const [to, setTo] = useState(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 ( + <> + + Статистика переходов с шильдика + + + + Дата начала + + date && setFrom(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, + }, + }} + /> + + + + Дата окончания + + date && setTo(date)} + renderInput={(params) => ( + + )} + InputProps={{ + sx: { + height: "40px", + color: theme.palette.secondary.main, + border: "1px solid", + borderColor: theme.palette.secondary.main, + "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, + }, + }} + /> + + + + + + Пользователь + + + Регистраций + + + Деньги + + + Квизы + + + + + {statistics.map(({ ID, Regs, Money, Quizes }) => ( + + setActiveUserId(ID)} + > + {ID} + + setOpenUserModal(false)} + userId={activeUserId} + /> + + {Regs} + + + {Money} + + + + } + aria-controls="panel1-content" + id="panel1-header" + > + Статистика по квизам + + +
+ + + + QuizID + + + Регистрации + + + Деньги + + + + + + {Quizes.map(({ QuizID, Regs, Money }) => ( + + + + + + {Regs} + + + {Money} + + + ))} + +
+ + + + + ))} + + + + ); +}; diff --git a/src/pages/dashboard/Content/QuizStatistics/index.tsx b/src/pages/dashboard/Content/QuizStatistics/index.tsx new file mode 100644 index 0000000..86e860d --- /dev/null +++ b/src/pages/dashboard/Content/QuizStatistics/index.tsx @@ -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 = () => ( + + + + +); diff --git a/src/utils/hooks/useQuizStatistic.ts b/src/utils/hooks/useQuizStatistic.ts index 22458a7..25b1ed8 100644 --- a/src/utils/hooks/useQuizStatistic.ts +++ b/src/utils/hooks/useQuizStatistic.ts @@ -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({ Registrations: 0, Quizes: 0, Results: 0 }); + const [data, setData] = useState({ + 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]); diff --git a/src/utils/hooks/useSchildStatistic.ts b/src/utils/hooks/useSchildStatistic.ts deleted file mode 100644 index 4167d25..0000000 --- a/src/utils/hooks/useSchildStatistic.ts +++ /dev/null @@ -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([]) - useEffect(() => { - const StatisticsShild = async () => { - const gottenData = await getStatisticSchild(Number(formatFrom), Number(formatTo)); - setStatistic(gottenData) - } - StatisticsShild() - }, []); - return statistic -} diff --git a/src/utils/hooks/useSchildStatistics.ts b/src/utils/hooks/useSchildStatistics.ts new file mode 100644 index 0000000..6915b02 --- /dev/null +++ b/src/utils/hooks/useSchildStatistics.ts @@ -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([]); + + useEffect(() => { + const StatisticsShild = async () => { + const gottenData = await getStatisticSchild( + Number(formatFrom), + Number(formatTo) + ); + + setStatistics(gottenData); + }; + + StatisticsShild(); + }, [formatTo, formatFrom]); + + return statistics; +}; diff --git a/tsconfig.json b/tsconfig.json index 64018cf..fe01ca0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,9 +16,7 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", - "types": ["node"], + "types": ["node"] }, "include": ["src", "**/*.ts"] } - - From 56f1a2f7ab428dec4422a6f835dd9a3ff5089f20 Mon Sep 17 00:00:00 2001 From: Tamara Date: Tue, 30 Apr 2024 03:25:46 +0300 Subject: [PATCH 11/20] =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B0=20=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=D0=B0(=D0=B1=D0=B5=D0=B7=20=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=D0=B2=D0=BE=D1=80=D0=B4=D0=BE=D0=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QuizStatistic/StstisticPromocode.tsx | 44 ++++++++++++++++--- src/utils/hooks/usePromocodeStatistic.ts | 2 +- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx b/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx index 7ab1072..14d6dfc 100644 --- a/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx @@ -1,21 +1,34 @@ -import {Table, TableBody, TableCell, TableHead, TableRow, Typography, useTheme} from "@mui/material"; +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 {useEffect, useState} from "react"; import moment, {Moment} from "moment"; import {usePromocodeStatistic} from "@root/utils/hooks/usePromocodeStatistic"; +import {promocodeApi} from "@root/api/promocode/requests"; +import {useAllPromocodes} from "@root/api/promocode/swr"; export default function StstisticPromocode() { const theme = useTheme() const [from, setFrom] = useState(moment("01.01.2023")); const [to, setTo] = useState(moment(Date.now())); + const promocodes = useAllPromocodes(); const statisticPromo = usePromocodeStatistic({to, from}) + for (statisticPromo.key in statisticPromo) { + const codewordSearch = promocodes.find(obj => obj.id === statisticPromo.key) + let codeword = codewordSearch?.codeword + console.log( "xnj 'nj", codeword) + } + + return( Статистика промокодов + Внесено - - {/*{Registrations}*/} - {/*{Quizes}*/} - {/*{Results}*/} - + + {Object.values(statisticPromo).map((sPromo:any)=> { + let codeword + let listPromo = promocodes + let statisticP = statisticPromo + console.log("in map", sPromo.key) + + for (statisticP.key in statisticP) { + const codewordSearch = listPromo.find(obj => obj.id === statisticP.key) + codeword = codewordSearch?.codeword + console.log(codeword) + } + + return( + + {codeword} + {sPromo.Regs} + {sPromo.Money} + + ) + }) + }
) diff --git a/src/utils/hooks/usePromocodeStatistic.ts b/src/utils/hooks/usePromocodeStatistic.ts index b876579..b881980 100644 --- a/src/utils/hooks/usePromocodeStatistic.ts +++ b/src/utils/hooks/usePromocodeStatistic.ts @@ -18,7 +18,7 @@ export function usePromocodeStatistic({ to, from }: useStatisticProps) { const requestStatistics = async () => { - const gottenData = await getStatisticPromocode(Number(formatTo), Number(formatFrom)); + const gottenData = await getStatisticPromocode(Number(formatFrom), Number(formatTo)); setStatisticPromo(gottenData) } From eb6cd2face7571fa852ef25b56ba612a68d9e1e4 Mon Sep 17 00:00:00 2001 From: Tamara Date: Tue, 30 Apr 2024 04:20:34 +0300 Subject: [PATCH 12/20] =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B0=20=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=D0=B0(=D0=B1=D0=B5=D0=B7=20=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=D0=B2=D0=BE=D1=80=D0=B4=D0=BE=D0=B2,=20=D0=BF=D0=BE=D1=87?= =?UTF-8?q?=D0=B8=D1=89=D0=B5=D0=BD=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QuizStatistic/StstisticPromocode.tsx | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx b/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx index 14d6dfc..edd80a3 100644 --- a/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx +++ b/src/pages/dashboard/Content/QuizStatistic/StstisticPromocode.tsx @@ -2,10 +2,9 @@ import {Button, Table, TableBody, TableCell, TableHead, TableRow, Typography, us 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 {useEffect, useState} from "react"; +import {useState} from "react"; import moment, {Moment} from "moment"; import {usePromocodeStatistic} from "@root/utils/hooks/usePromocodeStatistic"; -import {promocodeApi} from "@root/api/promocode/requests"; import {useAllPromocodes} from "@root/api/promocode/swr"; export default function StstisticPromocode() { @@ -16,19 +15,9 @@ export default function StstisticPromocode() { const statisticPromo = usePromocodeStatistic({to, from}) - for (statisticPromo.key in statisticPromo) { - const codewordSearch = promocodes.find(obj => obj.id === statisticPromo.key) - let codeword = codewordSearch?.codeword - console.log( "xnj 'nj", codeword) - } - - return( Статистика промокодов - - {Object.values(statisticPromo).map((sPromo:any)=> { + {Object.values(statisticPromo || {}).map((sPromo:any)=> { let codeword let listPromo = promocodes let statisticP = statisticPromo - console.log("in map", sPromo.key) - for (statisticP.key in statisticP) { - const codewordSearch = listPromo.find(obj => obj.id === statisticP.key) + for (let key in statisticP) { + const codewordSearch = listPromo.find(obj => obj.id === key) codeword = codewordSearch?.codeword - console.log(codeword) + // console.log(codeword) } return( From 6d67a11265a9287958bbe9541d7bf67b0c3365ba Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Tue, 30 Apr 2024 13:34:29 +0300 Subject: [PATCH 13/20] feat: schild pagination --- .../QuizStatistics/StatisticSchild.tsx | 128 +++++++++++++++++- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx b/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx index df90247..8a00cde 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx @@ -1,5 +1,5 @@ import moment from "moment"; -import { useEffect, useState } from "react"; +import { ReactNode, useEffect, useState } from "react"; import { Accordion, AccordionDetails, @@ -15,8 +15,10 @@ import { 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"; @@ -25,10 +27,35 @@ 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[] = [ + { + 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(false); const [activeUserId, setActiveUserId] = useState(""); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(10); const [from, setFrom] = useState( moment(new Date("01.01.2023")) @@ -133,7 +160,7 @@ export const StatisticSchild = () => { }} /> -
{ ))} -
+ */} + 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 }) => ( + + } + aria-controls="panel1-content" + id="panel1-header" + > + Статистика по квизам + + + + + + + QuizID + + + Регистрации + + + Деньги + + + + + + {row.Quizes.map(({ QuizID, Regs, Money }) => ( + + + + + + {Regs} + + + {Money} + + + ))} + +
+
+
+ ), + }, + ]} + /> + setOpenUserModal(false)} + userId={activeUserId} + /> ); }; From 9e4d13303e8748dac8c2293ad2c582c4f6647b2b Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Tue, 30 Apr 2024 18:30:24 +0300 Subject: [PATCH 14/20] refactor: promocode statistics --- src/api/quizStatistics/index.ts | 21 ++++-- src/api/quizStatistics/types.ts | 10 +++ .../Content/QuizStatistics/DateFilter.tsx | 48 ++----------- .../Content/QuizStatistics/QuizInfo.tsx | 71 +------------------ .../QuizStatistics/StastisticsPromocode.tsx | 47 ++++++------ .../Content/QuizStatistics/index.tsx | 2 + src/utils/hooks/usePromocodeStatistics.ts | 18 +++-- src/utils/hooks/useQuizStatistic.ts | 2 +- 8 files changed, 65 insertions(+), 154 deletions(-) diff --git a/src/api/quizStatistics/index.ts b/src/api/quizStatistics/index.ts index f2cc2f7..5cd9ff6 100644 --- a/src/api/quizStatistics/index.ts +++ b/src/api/quizStatistics/index.ts @@ -1,6 +1,11 @@ import makeRequest from "@root/api/makeRequest"; -import type { GetStatisticSchildBody, QuizStatisticsItem } from "./types"; +import type { + GetStatisticSchildBody, + QuizStatisticsItem, + GetPromocodeStatisticsBody, + AllPromocodeStatistics, +} from "./types"; export type QuizStatisticResponse = { Registrations: number; @@ -63,20 +68,22 @@ export const getStatisticSchild = async ( export const getStatisticPromocode = async ( from: number, to: number -): Promise => { +): Promise> => { try { - const StatisticPromo = await makeRequest({ + const StatisticPromo = await makeRequest< + GetPromocodeStatisticsBody, + Record + >({ url: process.env.REACT_APP_DOMAIN + "/customer/promocode/ltv", method: "post", useToken: true, - body: { - to: to, - from: from, - }, + body: { to, from }, }); return StatisticPromo; } catch (nativeError) { console.log(nativeError); + + return {}; } }; diff --git a/src/api/quizStatistics/types.ts b/src/api/quizStatistics/types.ts index 7aaf69d..284b7c8 100644 --- a/src/api/quizStatistics/types.ts +++ b/src/api/quizStatistics/types.ts @@ -19,3 +19,13 @@ export type QuizStatisticsItem = { Quizes: StatisticsQuizes[]; Regs: number; }; + +export type GetPromocodeStatisticsBody = { + from: number; + to: number; +}; + +export type AllPromocodeStatistics = { + Money: number; + Regs: number; +}; diff --git a/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx b/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx index e664b8a..c2b7fff 100644 --- a/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx @@ -1,51 +1,18 @@ 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 { +type DateFilterProps = { from: Moment | null; to: Moment | null; - setFrom: (a: Moment | null) => void; - setTo: (a: Moment | null) => void; -} + setFrom: (date: Moment | null) => void; + setTo: (date: Moment | null) => void; +}; -export const DateFilter = ({ to, setTo, from, setFrom }: Props) => { +export const DateFilter = ({ to, setTo, from, setFrom }: DateFilterProps) => { const theme = useTheme(); - const [isOpen, setOpen] = useState(false); - const [isOpenEnd, setOpenEnd] = useState(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 ( <> @@ -75,9 +42,7 @@ export const DateFilter = ({ to, setTo, from, setFrom }: Props) => { color: theme.palette.secondary.main, border: "1px solid", borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { - color: theme.palette.secondary.main, - }, + "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, }, }} /> @@ -115,7 +80,6 @@ export const DateFilter = ({ to, setTo, from, setFrom }: Props) => { }, }} /> - ); diff --git a/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx b/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx index 5bde905..7ee5adb 100644 --- a/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx @@ -6,13 +6,11 @@ import { TableCell, TableHead, TableRow, - Typography, - Box, - TextField, Button, useTheme, } from "@mui/material"; -import { DatePicker } from "@mui/x-date-pickers"; + +import { DateFilter } from "./DateFilter"; import { useQuizStatistic } from "@root/utils/hooks/useQuizStatistic"; @@ -34,70 +32,7 @@ export const QuizInfo = () => { return ( <> - - - Дата начала - - date && setFrom(date)} - renderInput={(params) => ( - - )} - InputProps={{ - sx: { - height: "40px", - color: theme.palette.secondary.main, - border: "1px solid", - borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, - }, - }} - /> - - - - Дата окончания - - date && setTo(date)} - renderInput={(params) => ( - - )} - InputProps={{ - sx: { - height: "40px", - color: theme.palette.secondary.main, - border: "1px solid", - borderColor: theme.palette.secondary.main, - "& .MuiSvgIcon-root": { color: theme.palette.secondary.main }, - }, - }} - /> - + diff --git a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx index 5f596e8..d62c139 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx @@ -1,3 +1,5 @@ +import { useState } from "react"; +import moment from "moment"; import { Table, TableBody, @@ -7,25 +9,26 @@ import { 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"; +import { usePromocodeStatistics } from "@root/utils/hooks/usePromocodeStatistics"; + +import type { Moment } from "moment"; export const StatisticsPromocode = () => { - const [from, setFrom] = useState(moment("01.01.2023")); + const [from, setFrom] = useState( + moment(new Date("01.01.2023")) + ); const [to, setTo] = useState(moment(Date.now())); const promocodes = useAllPromocodes(); const promocodeStatistics = usePromocodeStatistics({ to, from }); const theme = useTheme(); return ( - - Статистика промокодов + <> + Статистика промокодов { borderColor: theme.palette.secondary.main, bgcolor: theme.palette.content.main, color: "white", + marginTop: "30px", }} > @@ -55,20 +59,11 @@ export const StatisticsPromocode = () => { - - {/* {Object.values(promocodeStatistics).map(({ Regs, Money }) => { - let codeword = ""; - - for (let value in promocodeStatistics) { - const codewordSearch = promocodes.find(({ id }) => id === value); - - codeword = codewordSearch?.codeword ?? ""; - } - - return ( - + {Object.entries(promocodeStatistics).map(([key, { Regs, Money }]) => ( + + - {codeword} + {promocodes.find(({ id }) => id === key)?.codeword ?? ""} {Regs} @@ -76,10 +71,10 @@ export const StatisticsPromocode = () => { {Money} - - ); - })} */} + + + ))}
-
+ ); }; diff --git a/src/pages/dashboard/Content/QuizStatistics/index.tsx b/src/pages/dashboard/Content/QuizStatistics/index.tsx index b060d99..968cba0 100644 --- a/src/pages/dashboard/Content/QuizStatistics/index.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/index.tsx @@ -3,10 +3,12 @@ import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; import { QuizInfo } from "./QuizInfo"; import { StatisticsSchild } from "./StatisticsSchild"; +import { StatisticsPromocode } from "./StastisticsPromocode"; export const QuizStatistics = () => ( + ); diff --git a/src/utils/hooks/usePromocodeStatistics.ts b/src/utils/hooks/usePromocodeStatistics.ts index 91420ce..7669907 100644 --- a/src/utils/hooks/usePromocodeStatistics.ts +++ b/src/utils/hooks/usePromocodeStatistics.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { getStatisticPromocode } from "@root/api/quizStatistics"; import type { Moment } from "moment"; -import type { QuizStatisticsItem } from "@root/api/quizStatistics/types"; +import type { AllPromocodeStatistics } from "@root/api/quizStatistics/types"; interface useStatisticProps { to: Moment | null; @@ -13,12 +13,9 @@ export function usePromocodeStatistics({ to, from }: useStatisticProps) { const formatTo = to?.unix(); const formatFrom = from?.unix(); - const [statisticPromo, setStatisticPromo] = useState({ - ID: "0", - Regs: 0, - Money: 0, - Quizes: [{ QuizID: "0", Regs: 0, Money: 0 }], - }); + const [promocodeStatistics, setPromocodeStatistics] = useState< + Record + >({}); useEffect(() => { const requestStatistics = async () => { @@ -26,11 +23,12 @@ export function usePromocodeStatistics({ to, from }: useStatisticProps) { Number(formatFrom), Number(formatTo) ); - setStatisticPromo(gottenData); + + setPromocodeStatistics(gottenData); }; requestStatistics(); - }, []); + }, [formatTo, formatFrom]); - return statisticPromo; + return promocodeStatistics; } diff --git a/src/utils/hooks/useQuizStatistic.ts b/src/utils/hooks/useQuizStatistic.ts index 605b485..8164965 100644 --- a/src/utils/hooks/useQuizStatistic.ts +++ b/src/utils/hooks/useQuizStatistic.ts @@ -28,7 +28,7 @@ export function useQuizStatistic({ to, from }: useQuizStatisticProps) { }; requestStatistics(); - }, [to, from]); + }, [formatTo, formatFrom]); return { ...data }; } From 12435b69b10af13849b566386bd7bf609b27bc17 Mon Sep 17 00:00:00 2001 From: Nastya Date: Wed, 1 May 2024 01:27:57 +0300 Subject: [PATCH 15/20] =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B0,=20=D1=84=D1=80=D0=BE=D0=BC=20=3D=20?= =?UTF-8?q?=D0=B4=D0=B0=D1=82=D0=B0=20-=204=20=D0=BD=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/Content/QuizStatistics/StastisticsPromocode.tsx | 4 ++-- .../dashboard/Content/QuizStatistics/StatisticsSchild.tsx | 4 ++-- src/utils/hooks/usePromocodeStatistics.ts | 3 ++- src/utils/hooks/useSchildStatistics.ts | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx index d62c139..fb00be8 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx @@ -19,9 +19,9 @@ import type { Moment } from "moment"; export const StatisticsPromocode = () => { const [from, setFrom] = useState( - moment(new Date("01.01.2023")) + moment(moment().subtract(4, "weeks")) ); - const [to, setTo] = useState(moment(Date.now())); + const [to, setTo] = useState(moment()); const promocodes = useAllPromocodes(); const promocodeStatistics = usePromocodeStatistics({ to, from }); const theme = useTheme(); diff --git a/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx b/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx index 6e0d494..3e0751c 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx @@ -56,9 +56,9 @@ export const StatisticsSchild = () => { const [pageSize, setPageSize] = useState(10); const [from, setFrom] = useState( - moment(new Date("01.01.2023")) + moment(moment().subtract(4, "weeks")) ); - const [to, setTo] = useState(moment(Date.now())); + const [to, setTo] = useState(moment()); const theme = useTheme(); const statistics = useSchildStatistics(from, to); diff --git a/src/utils/hooks/usePromocodeStatistics.ts b/src/utils/hooks/usePromocodeStatistics.ts index 7669907..eece16b 100644 --- a/src/utils/hooks/usePromocodeStatistics.ts +++ b/src/utils/hooks/usePromocodeStatistics.ts @@ -3,6 +3,7 @@ import { getStatisticPromocode } from "@root/api/quizStatistics"; import type { Moment } from "moment"; import type { AllPromocodeStatistics } from "@root/api/quizStatistics/types"; +import moment from "moment"; interface useStatisticProps { to: Moment | null; @@ -11,7 +12,7 @@ interface useStatisticProps { export function usePromocodeStatistics({ to, from }: useStatisticProps) { const formatTo = to?.unix(); - const formatFrom = from?.unix(); + const formatFrom = from?.unix() || moment().unix() - 604800; const [promocodeStatistics, setPromocodeStatistics] = useState< Record diff --git a/src/utils/hooks/useSchildStatistics.ts b/src/utils/hooks/useSchildStatistics.ts index 4bcba2c..44dd2a8 100644 --- a/src/utils/hooks/useSchildStatistics.ts +++ b/src/utils/hooks/useSchildStatistics.ts @@ -4,10 +4,11 @@ import { getStatisticSchild } from "@root/api/quizStatistics"; import type { Moment } from "moment"; import type { QuizStatisticsItem } from "@root/api/quizStatistics/types"; +import moment from "moment"; export const useSchildStatistics = (from: Moment | null, to: Moment | null) => { const formatTo = to?.unix(); - const formatFrom = from?.unix(); + const formatFrom = from?.unix() || moment().unix() - 604800; const [statistics, setStatistics] = useState([]); useEffect(() => { From a8182b1ab81c4f1bc652d73d63facc3b369943dd Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Wed, 1 May 2024 15:13:08 +0300 Subject: [PATCH 16/20] fix: statistics error --- src/api/promocode/swr.ts | 4 ++-- src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx | 4 ++-- src/pages/dashboard/Content/QuizStatistics/index.tsx | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/api/promocode/swr.ts b/src/api/promocode/swr.ts index c11016c..2e58d67 100644 --- a/src/api/promocode/swr.ts +++ b/src/api/promocode/swr.ts @@ -136,7 +136,7 @@ export function usePromocodes( } export function useAllPromocodes() { - const swrResponse = useSwr("allPromocodes", promocodeApi.getAllPromocodes, { + const { data } = useSwr("allPromocodes", promocodeApi.getAllPromocodes, { keepPreviousData: true, suspense: true, onError(err) { @@ -145,5 +145,5 @@ export function useAllPromocodes() { }, }); - return swrResponse.data; + return data; } diff --git a/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx b/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx index 7ee5adb..3c0c492 100644 --- a/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx @@ -18,7 +18,7 @@ import type { Moment } from "moment"; export const QuizInfo = () => { const [from, setFrom] = useState(null); - const [to, setTo] = useState(moment(Date.now())); + const [to, setTo] = useState(moment()); const theme = useTheme(); const { Registrations, Quizes, Results } = useQuizStatistic({ from, @@ -27,7 +27,7 @@ export const QuizInfo = () => { const resetTime = () => { setFrom(moment()); - setTo(moment(Date.now())); + setTo(moment()); }; return ( diff --git a/src/pages/dashboard/Content/QuizStatistics/index.tsx b/src/pages/dashboard/Content/QuizStatistics/index.tsx index 968cba0..5c256a4 100644 --- a/src/pages/dashboard/Content/QuizStatistics/index.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/index.tsx @@ -1,3 +1,5 @@ +import { Suspense } from "react"; +import { Box } from "@mui/material"; import { LocalizationProvider } from "@mui/x-date-pickers"; import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; @@ -9,6 +11,8 @@ export const QuizStatistics = () => ( - + Loading...}> + + ); From f073adc767b07ee90c9c68c6e233a05343172b93 Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Wed, 1 May 2024 17:22:08 +0300 Subject: [PATCH 17/20] fix: tariff price --- .../CreatePromocodeForm.tsx | 149 +++++++++--------- .../dashboard/Content/Tariffs/EditModal.tsx | 17 +- 2 files changed, 84 insertions(+), 82 deletions(-) diff --git a/src/pages/dashboard/Content/PromocodeManagement/CreatePromocodeForm.tsx b/src/pages/dashboard/Content/PromocodeManagement/CreatePromocodeForm.tsx index 657ef7a..8bc598a 100644 --- a/src/pages/dashboard/Content/PromocodeManagement/CreatePromocodeForm.tsx +++ b/src/pages/dashboard/Content/PromocodeManagement/CreatePromocodeForm.tsx @@ -21,6 +21,7 @@ import theme from "@root/theme"; import type { TextFieldProps } from "@mui/material"; import { CreatePromocodeBody } from "@root/model/promocodes"; import type { ChangeEvent } from "react"; +import { enqueueSnackbar } from "notistack"; type BonusType = "discount" | "privilege"; @@ -74,24 +75,34 @@ export const CreatePromocodeForm = ({ createPromocode }: Props) => { }, []); const submitForm = (values: FormValues) => { - const currentPrivilege = privileges.find( (item) => item.privilegeId === values.privilegeId ); - const body = { - ...values, - }; + const body = { ...values }; - if ((body.layer === 1 && bonusType === "discount") || bonusType === "privilege") { - if (currentPrivilege === undefined) return; - body.serviceKey = currentPrivilege?.serviceKey - body.target = body.privilegeId - } - if ((body.layer === 2 && bonusType === "discount")) { - if (body.serviceKey === undefined) return; - body.target = body.serviceKey - } + if ( + (body.layer === 1 && bonusType === "discount") || + bonusType === "privilege" + ) { + if (currentPrivilege === undefined) { + enqueueSnackbar("Привилегия не выбрана"); + + return; + } + + body.serviceKey = currentPrivilege?.serviceKey; + body.target = body.privilegeId; + } + if (body.layer === 2 && bonusType === "discount") { + if (!body.serviceKey) { + enqueueSnackbar("Сервис не выбран"); + + return; + } + + body.target = body.serviceKey; + } const factorFromDiscountValue = 1 - body.factor / 100; @@ -178,6 +189,7 @@ export const CreatePromocodeForm = ({ createPromocode }: Props) => { setFieldValue( "activationCount", @@ -253,64 +265,57 @@ export const CreatePromocodeForm = ({ createPromocode }: Props) => { > {values.layer === 1 ? "Выбор привилегии" : "Выбор сервиса"} - { - values.layer === 1 ? - - { - setFieldValue("target", target.value) - setFieldValue("privilegeId", target.value) - }} - children={ - privileges.map(({ name, privilegeId }) => ( - - {name} - - )) - } - /> - : - { - setFieldValue("target", target.value) - setFieldValue("serviceKey", target.value) - }} - children={ - SERVICE_LIST.map(({ displayName, serviceKey }) => ( - - {displayName} - - )) - } - /> - - } + {values.layer === 1 ? ( + { + setFieldValue("target", target.value); + setFieldValue("privilegeId", target.value); + }} + children={privileges.map(({ name, privilegeId }) => ( + + {name} + + ))} + /> + ) : ( + { + setFieldValue("target", target.value); + setFieldValue("serviceKey", target.value); + }} + children={SERVICE_LIST.map(({ displayName, serviceKey }) => ( + + {displayName} + + ))} + /> + )} { }} type="submit" > - Cоздать + Создать )} diff --git a/src/pages/dashboard/Content/Tariffs/EditModal.tsx b/src/pages/dashboard/Content/Tariffs/EditModal.tsx index 627e0d0..fd16621 100644 --- a/src/pages/dashboard/Content/Tariffs/EditModal.tsx +++ b/src/pages/dashboard/Content/Tariffs/EditModal.tsx @@ -45,7 +45,6 @@ export default function EditModal() { updatedTariff.price = price; updatedTariff.description = descriptionField; updatedTariff.order = parseInt(orderField); - const [_, putedTariffError] = await putTariff(updatedTariff); @@ -99,20 +98,20 @@ export default function EditModal() { sx={{ marginBottom: "10px" }} /> - Цена: {tariff.price} + Цена: {Math.trunc((tariff.price ?? 0) / 100)} setPriceField(event.target.value)} + onChange={({ target }) => + setPriceField(String(+target.value * 100)) + } label="Цена" name="price" - value={priceField} + value={Math.trunc(Number(priceField) / 100)} sx={{ marginBottom: "10px" }} /> - - Описание: {tariff.description} - + Описание: {tariff.description} - - Порядок: {tariff.order} - + Порядок: {tariff.order} setOrderField(event.target.value)} From d3c72f2e0bec8a320f917e9391b9de7cca1ec7aa Mon Sep 17 00:00:00 2001 From: Nastya Date: Sat, 4 May 2024 02:29:04 +0300 Subject: [PATCH 18/20] =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B0=20=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=D0=BE=D0=B2=20=D1=80=D1=83=D0=B1=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B2=20=D0=BA=D0=BE=D0=BF=D0=B5=D0=B9=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/Content/QuizStatistics/StastisticsPromocode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx index fb00be8..5223fd7 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx @@ -69,7 +69,7 @@ export const StatisticsPromocode = () => { {Regs} - {Money} + {(Money / 100).toFixed(2)} From 56a3a6396012180e2210c0e5861751d4a2d9e4ed Mon Sep 17 00:00:00 2001 From: Nastya Date: Sun, 5 May 2024 03:55:29 +0300 Subject: [PATCH 19/20] =?UTF-8?q?=D1=88=D0=B8=D0=BB=D1=8C=D0=B4=D0=B8?= =?UTF-8?q?=D0=BA=20=D0=B2=20=D1=80=D1=83=D0=B1=D0=BB=D1=8F=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/Content/QuizStatistics/StastisticsPromocode.tsx | 2 +- src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx index fb00be8..5223fd7 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StastisticsPromocode.tsx @@ -69,7 +69,7 @@ export const StatisticsPromocode = () => { {Regs} - {Money} + {(Money / 100).toFixed(2)} diff --git a/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx b/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx index 3e0751c..ee1a630 100644 --- a/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/StatisticsSchild.tsx @@ -173,7 +173,7 @@ export const StatisticsSchild = () => { {Regs} - {Money} + {(Money / 100).toFixed(2)} ))} From b99f41439387b7ae0f8786f68aced19f8b79ab44 Mon Sep 17 00:00:00 2001 From: Nastya Date: Mon, 6 May 2024 01:47:46 +0300 Subject: [PATCH 20/20] =?UTF-8?q?=D1=88=D0=B8=D0=BB=D1=8C=D0=B4=D0=B8?= =?UTF-8?q?=D0=BA=20=D0=B2=20=D1=80=D1=83=D0=B1=D0=BB=D1=8F=D1=85=20=D1=85?= =?UTF-8?q?2,=20to=20=D1=8D=D1=82=D0=BE=20=D0=BA=D0=BE=D0=BD=D0=B5=D1=86?= =?UTF-8?q?=20=D0=B4=D0=BD=D1=8F,=20from=20=D1=8D=D1=82=D0=BE=20=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B0=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx | 4 ++-- .../dashboard/Content/QuizStatistics/StatisticsSchild.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx b/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx index c2b7fff..93d052c 100644 --- a/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx +++ b/src/pages/dashboard/Content/QuizStatistics/DateFilter.tsx @@ -29,7 +29,7 @@ export const DateFilter = ({ to, setTo, from, setFrom }: DateFilterProps) => { date && setFrom(date)} + onChange={(date) => date && setFrom(date.startOf('day'))} renderInput={(params) => ( { date && setTo(date)} + onChange={(date) => date && setTo(date.endOf('day'))} renderInput={(params) => ( { const [to, setTo] = useState(moment()); const theme = useTheme(); - const statistics = useSchildStatistics(from, to); + const statistics = useSchildStatistics(from, to) + .map((obj) => ({...obj, Money: Number((obj.Money / 100).toFixed(2))})); useEffect(() => { if (!openUserModal) {