From e42e8cc7666658a5380cc4c740c076447fd55dd3 Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Mon, 29 Apr 2024 17:49:31 +0300 Subject: [PATCH 1/2] refactor: statistics --- src/api/quizStatistic.ts | 50 ---- src/api/quizStatistic/index.ts | 61 +++++ src/api/quizStatistic/types.ts | 21 ++ src/index.tsx | 6 +- .../Content/QuizStatistic/StatisticSchild.tsx | 245 ----------------- .../dashboard/Content/QuizStatistic/index.tsx | 172 ------------ .../Content/QuizStatistics/QuizInfo.tsx | 148 ++++++++++ .../QuizStatistics/StatisticSchild.tsx | 256 ++++++++++++++++++ .../Content/QuizStatistics/index.tsx | 12 + src/utils/hooks/useQuizStatistic.ts | 22 +- src/utils/hooks/useSchildStatistic.ts | 17 -- src/utils/hooks/useSchildStatistics.ts | 27 ++ tsconfig.json | 4 +- 13 files changed, 541 insertions(+), 500 deletions(-) delete mode 100644 src/api/quizStatistic.ts create mode 100644 src/api/quizStatistic/index.ts create mode 100644 src/api/quizStatistic/types.ts delete mode 100644 src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx delete mode 100644 src/pages/dashboard/Content/QuizStatistic/index.tsx create mode 100644 src/pages/dashboard/Content/QuizStatistics/QuizInfo.tsx create mode 100644 src/pages/dashboard/Content/QuizStatistics/StatisticSchild.tsx create mode 100644 src/pages/dashboard/Content/QuizStatistics/index.tsx delete mode 100644 src/utils/hooks/useSchildStatistic.ts create mode 100644 src/utils/hooks/useSchildStatistics.ts diff --git a/src/api/quizStatistic.ts b/src/api/quizStatistic.ts deleted file mode 100644 index 0551ada..0000000 --- a/src/api/quizStatistic.ts +++ /dev/null @@ -1,50 +0,0 @@ -import makeRequest from "@root/api/makeRequest"; -import {parseAxiosError} from "@root/utils/parse-error"; - -export type QuizStatisticResponse = { - Registrations: number; - Quizes: number; - Results: number -}; - -type TRequest = { - to: number; - from: number; -}; - -export const getStatistic = async ( - to: number, - from: number, -): Promise => { - try { - const generalResponse = await makeRequest({ - url: `${process.env.REACT_APP_DOMAIN}/squiz/statistic`, - body: { to, from } - }) - return generalResponse; - } catch (nativeError) { - - return { Registrations: 0, Quizes: 0, Results: 0 }; - } -}; - -export const getStatisticSchild = async ( - from: any, to: any): Promise => { - 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": 100 - }, - }); - return StatisticResponse; - } catch (nativeError) { - - return [{ID: 0, Regs: 0, Money: 0, Quizes:[{QuizID: 0, Regs: 0, Money: 0}]}]; - } -}; diff --git a/src/api/quizStatistic/index.ts b/src/api/quizStatistic/index.ts new file mode 100644 index 0000000..308bb46 --- /dev/null +++ b/src/api/quizStatistic/index.ts @@ -0,0 +1,61 @@ +import makeRequest from "@root/api/makeRequest"; + +import type { GetStatisticSchildBody, QuizStatisticsItem } from "./types"; + +export type QuizStatisticResponse = { + Registrations: number; + Quizes: number; + Results: number; +}; + +type TRequest = { + to: number; + from: number; +}; + +export const getStatistic = async ( + to: number, + from: number +): Promise => { + try { + const generalResponse = await makeRequest({ + url: `${process.env.REACT_APP_DOMAIN}/squiz/statistic`, + body: { to, from }, + }); + return generalResponse; + } catch (nativeError) { + return { Registrations: 0, Quizes: 0, Results: 0 }; + } +}; + +export const getStatisticSchild = async ( + from: number, + to: number +): Promise => { + try { + const StatisticResponse = await makeRequest< + GetStatisticSchildBody, + QuizStatisticsItem[] + >({ + url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat", + method: "post", + useToken: true, + body: { to, from, page: 0, limit: 100 }, + }); + + if (!StatisticResponse) { + throw new Error("Статистика не найдена"); + } + + return StatisticResponse; + } catch (nativeError) { + return [ + { + ID: "0", + Regs: 0, + Money: 0, + Quizes: [{ QuizID: "0", Regs: 0, Money: 0 }], + }, + ]; + } +}; diff --git a/src/api/quizStatistic/types.ts b/src/api/quizStatistic/types.ts new file mode 100644 index 0000000..7aaf69d --- /dev/null +++ b/src/api/quizStatistic/types.ts @@ -0,0 +1,21 @@ +import { Moment } from "moment"; + +export type GetStatisticSchildBody = { + to: Moment | null; + from: Moment | null; + page: number; + limit: number; +}; + +type StatisticsQuizes = { + QuizID: string; + Money: number; + Regs: number; +}; + +export type QuizStatisticsItem = { + ID: string; + Money: number; + Quizes: StatisticsQuizes[]; + Regs: number; +}; diff --git a/src/index.tsx b/src/index.tsx index 5959a90..ed8ace0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -24,7 +24,7 @@ import { PromocodeManagement } from "@root/pages/dashboard/Content/PromocodeMana import { SettingRoles } from "@pages/Setting/SettingRoles"; import Support from "@pages/dashboard/Content/Support/Support"; import ChatImageNewWindow from "@pages/dashboard/Content/Support/ChatImageNewWindow"; -import QuizStatistic from "@pages/dashboard/Content/QuizStatistic"; +import { QuizStatistics } from "@root/pages/dashboard/Content/QuizStatistics"; import theme from "./theme"; import "./index.css"; @@ -109,7 +109,7 @@ root.render( path="/quizStatistic" element={ - + } /> @@ -121,7 +121,7 @@ root.render( /> ))} - } /> + } /> } /> diff --git a/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx b/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx deleted file mode 100644 index 74087a0..0000000 --- a/src/pages/dashboard/Content/QuizStatistic/StatisticSchild.tsx +++ /dev/null @@ -1,245 +0,0 @@ -import {useEffect, useState} from "react"; -import moment, {Moment} from "moment"; -import { - Accordion, - AccordionDetails, AccordionSummary, - Box, - Button, - Table, - TableBody, - TableCell, - TableHead, - TableRow, - TextField, - Typography, - useTheme -} from "@mui/material"; -import {AdapterMoment} from "@mui/x-date-pickers/AdapterMoment"; -import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; -import ModalUser from "@pages/dashboard/ModalUser"; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import useSchildStatistic from "@root/utils/hooks/useSchildStatistic"; - -export default function StatisticSchild() { - const theme = useTheme() - const [isOpen, setOpen] = useState(false); - const [isOpenEnd, setOpenEnd] = useState(false); - - const [openUserModal, setOpenUserModal] = useState(false); - const [activeUserId, setActiveUserId] = useState(""); - - const [from, setFrom] = useState(moment("01.01.2023")); - 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(""); - } - }, [openUserModal]); - - useEffect(() => { - if (activeUserId) { - setOpenUserModal(true); - - return; - } - - setOpenUserModal(false); - }, [activeUserId]); - - 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, - }, - }, - }} - /> - - - - - Пользователь - Регистраций - Деньги - Квизы - - - {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 deleted file mode 100644 index 172aeba..0000000 --- a/src/pages/dashboard/Content/QuizStatistic/index.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import { Table, TableBody, TableCell, TableHead, TableRow, useTheme, Typography, Box, TextField, Button } from '@mui/material'; -import { useState } from 'react'; -import moment from "moment"; -import type { Moment } from "moment"; -import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; -import { useQuizStatistic } from '@root/utils/hooks/useQuizStatistic'; -import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment' -import StatisticSchild from "./StatisticSchild"; - -export default () => { - const theme = useTheme() - - const [isOpen, setOpen] = useState(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, - }); - - const resetTime = () => { - setFrom(moment(0)); - setTo(moment(Date.now())); - }; - - const handleClose = () => { - setOpen(false); - }; - - const handleOpen = () => { - setOpen(true); - }; - - const onAdornmentClick = () => { - setOpen((old) => !old); - if (isOpenEnd) { - handleCloseEnd(); - } - }; - - const handleCloseEnd = () => { - setOpenEnd(false); - }; - - const handleOpenEnd = () => { - setOpenEnd(true); - }; - - const onAdornmentClickEnd = () => { - setOpenEnd((old) => !old); - if (isOpen) { - handleClose(); - } - }; - - return <> - - - - Дата начала - - 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 6d67a11265a9287958bbe9541d7bf67b0c3365ba Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Tue, 30 Apr 2024 13:34:29 +0300 Subject: [PATCH 2/2] 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} + /> ); };