бек статистики
This commit is contained in:
parent
dd58065255
commit
93ddfb8570
@ -29,13 +29,16 @@ export default function Analytics() {
|
||||
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
const [isOpenEnd, setOpenEnd] = useState(false);
|
||||
const [to, setTo] = useState(0);
|
||||
const [from, setFrom] = useState(0);
|
||||
const [to, setTo] = useState(null);
|
||||
const [from, setFrom] = useState(null);
|
||||
|
||||
const { devices, general, questions } = useAnalytics({quizId: editQuizId?.toString(), to, from})
|
||||
|
||||
const resetTime = () => {
|
||||
setTo(null);
|
||||
setFrom(null);
|
||||
}
|
||||
useLayoutEffect(() => {
|
||||
console.log("editQuizId ", editQuizId)
|
||||
if (editQuizId === undefined) redirect("/list")
|
||||
}, [editQuizId])
|
||||
const theme = useTheme();
|
||||
@ -67,6 +70,9 @@ export default function Analytics() {
|
||||
handleClose();
|
||||
}
|
||||
};
|
||||
console.log("questions",questions)
|
||||
console.log("general",general)
|
||||
console.log("devices",devices)
|
||||
|
||||
const now = moment();
|
||||
return (
|
||||
@ -123,6 +129,8 @@ export default function Analytics() {
|
||||
},
|
||||
},
|
||||
}}
|
||||
value={to}
|
||||
onChange={(newValue) => setTo(newValue)}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
@ -134,6 +142,8 @@ export default function Analytics() {
|
||||
color: "4D4D4D",
|
||||
}}
|
||||
>
|
||||
value={from}
|
||||
onChange={(newValue) => setValue(setFrom)}
|
||||
Дата окончания
|
||||
</Typography>
|
||||
<DatePicker
|
||||
@ -167,6 +177,7 @@ export default function Analytics() {
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
onClick={resetTime}
|
||||
variant="outlined"
|
||||
sx={{
|
||||
minWidth: isMobile ? "144px" : "180px",
|
||||
@ -185,9 +196,9 @@ export default function Analytics() {
|
||||
Сбросить
|
||||
</Button>
|
||||
</Box>
|
||||
<General />
|
||||
<AnswersStatistics />
|
||||
<Devices />
|
||||
<General data={ general }/>
|
||||
<AnswersStatistics data={ questions }/>
|
||||
<Devices data={ devices }/>
|
||||
</SectionWrapper>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -186,10 +186,11 @@ const Pagination = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Answers = () => {
|
||||
const [answers, setAnswers] = useState<Record<string, number>>(ANSWERS_MOCK);
|
||||
export const Answers = (props) => {
|
||||
const theme = useTheme();
|
||||
console.log(props.data)
|
||||
|
||||
if (Object.keys(props.data).length === 0) return <Typography textAlign="center" m="10px 0">нет данных об ответах</Typography>
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Paper
|
||||
@ -244,7 +245,7 @@ export const Answers = () => {
|
||||
<NextIcon />
|
||||
</ButtonBase>
|
||||
</Box>
|
||||
{Object.entries(answers).map(([title, percent], index) => (
|
||||
{Object.entries(props.data).map(([title, percent], index) => (
|
||||
<Answer
|
||||
key={title}
|
||||
title={title}
|
||||
|
||||
@ -16,9 +16,9 @@ type FunnelItemProps = {
|
||||
|
||||
const FUNNEL_MOCK: Record<string, number> = {
|
||||
"Стартовая страница": 100,
|
||||
"Воронка квиза": 69,
|
||||
Заявки: 56,
|
||||
Результаты: 56,
|
||||
"Воронка квиза": 0,
|
||||
Заявки: 0,
|
||||
Результаты: 0,
|
||||
};
|
||||
|
||||
const FunnelItem = ({ title, percent }: FunnelItemProps) => {
|
||||
@ -100,12 +100,11 @@ const FunnelItem = ({ title, percent }: FunnelItemProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Funnel = () => {
|
||||
const [funnel, setFunnel] = useState<Record<string, number>>(FUNNEL_MOCK);
|
||||
export const Funnel = (props) => {
|
||||
const theme = useTheme();
|
||||
const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1150));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(850));
|
||||
|
||||
console.log(props)
|
||||
useEffect(() => {
|
||||
// const requestFunnel = async () => {
|
||||
// const [funnelResponse, funnelError] = await getGeneral("14761");
|
||||
@ -122,6 +121,7 @@ export const Funnel = () => {
|
||||
// requestFunnel();
|
||||
}, []);
|
||||
|
||||
if (Object.keys(props.data).length === 0) return <Typography textAlign="center" m="10px 0">нет данных о разделах</Typography>
|
||||
return (
|
||||
<Paper
|
||||
sx={{
|
||||
@ -132,8 +132,8 @@ export const Funnel = () => {
|
||||
maxWidth: isSmallMonitor && !isMobile ? "366px" : "none",
|
||||
}}
|
||||
>
|
||||
{Object.entries(funnel).map(([title, percent]) => (
|
||||
<FunnelItem key={title} title={title} percent={percent} />
|
||||
{Object.entries(FUNNEL_MOCK).map(([title, percent], index) => (
|
||||
<FunnelItem key={title} title={title} percent={index > 0 ? props.data[index-1] : percent} />
|
||||
))}
|
||||
</Paper>
|
||||
);
|
||||
|
||||
@ -69,10 +69,10 @@ const Result = ({ title, percent, highlight }: ResultProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Results = () => {
|
||||
const [results, setResults] = useState<Record<string, number>>(RESULTS_MOCK);
|
||||
export const Results = (props) => {
|
||||
const theme = useTheme();
|
||||
|
||||
if (Object.keys(props.data).length === 0) return <Typography margin="20px 0 0 0" textAlign="center" m="10px 0">нет данных о результатах</Typography>
|
||||
return (
|
||||
<Box>
|
||||
<Typography
|
||||
@ -93,7 +93,7 @@ export const Results = () => {
|
||||
marginTop: "30px",
|
||||
}}
|
||||
>
|
||||
{Object.entries(results).map(([title, percent], index) => (
|
||||
{Object.entries(props.data).map(([title, percent], index) => (
|
||||
<Result
|
||||
key={title}
|
||||
title={title}
|
||||
|
||||
@ -12,11 +12,13 @@ import { Results } from "./Results";
|
||||
|
||||
import { ReactComponent as OpenIcon } from "@icons/Analytics/open.svg";
|
||||
|
||||
export const AnswersStatistics = () => {
|
||||
export const AnswersStatistics = (props) => {
|
||||
const theme = useTheme();
|
||||
const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1150));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(850));
|
||||
|
||||
console.log(props)
|
||||
|
||||
return (
|
||||
<Box sx={{ marginTop: "120px" }}>
|
||||
<Typography
|
||||
@ -29,7 +31,7 @@ export const AnswersStatistics = () => {
|
||||
>
|
||||
Статистика по ответам
|
||||
</Typography>
|
||||
<ButtonBase
|
||||
{/* <ButtonBase
|
||||
sx={{
|
||||
marginTop: "35px",
|
||||
display: "flex",
|
||||
@ -50,17 +52,17 @@ export const AnswersStatistics = () => {
|
||||
<Box>
|
||||
<OpenIcon />
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
</ButtonBase> */}
|
||||
<Box
|
||||
sx={{
|
||||
display: isSmallMonitor && !isMobile ? "flex" : "block",
|
||||
gap: "40px",
|
||||
}}
|
||||
>
|
||||
<Answers />
|
||||
<Funnel />
|
||||
<Answers data={props.data?.Questions || {}}/>
|
||||
<Funnel data={props.data?.Funnel || {}}/>
|
||||
</Box>
|
||||
<Results />
|
||||
<Results data={props.data?.Results || {}}/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@ -27,6 +27,8 @@ const DEVICES_MOCK: DevicesResponse = {
|
||||
|
||||
const Device = ({ title, devices }: DeviceProps) => {
|
||||
const theme = useTheme();
|
||||
console.log("devices ", devices)
|
||||
if (devices === undefined || Object.keys(devices).length === 0) return <Typography>{title} - нет данных</Typography>
|
||||
const data = Object.entries(devices).map(([id, value], index) => ({
|
||||
id,
|
||||
value,
|
||||
@ -95,33 +97,33 @@ const Device = ({ title, devices }: DeviceProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Devices = () => {
|
||||
const [devices, setDevices] = useState<DevicesResponse>(DEVICES_MOCK);
|
||||
export const Devices = ({data = {}}) => {
|
||||
const [devices, setDevices] = useState<DevicesResponse>(data);
|
||||
const theme = useTheme();
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(700));
|
||||
|
||||
useEffect(() => {
|
||||
const requestDevices = async () => {
|
||||
const [devicesResponse, devicesError] = await getDevices("14761");
|
||||
// useEffect(() => {
|
||||
// const requestDevices = async () => {
|
||||
// const [devicesResponse, devicesError] = await getDevices("14761");
|
||||
|
||||
if (devicesError) {
|
||||
enqueueSnackbar(devicesError);
|
||||
// if (devicesError) {
|
||||
// enqueueSnackbar(devicesError);
|
||||
|
||||
return;
|
||||
}
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!devicesResponse) {
|
||||
enqueueSnackbar("Список девайсов пуст.");
|
||||
// if (!devicesResponse) {
|
||||
// enqueueSnackbar("Список девайсов пуст.");
|
||||
|
||||
return;
|
||||
}
|
||||
// return;
|
||||
// }
|
||||
|
||||
setDevices(devicesResponse);
|
||||
};
|
||||
// setDevices(devicesResponse);
|
||||
// };
|
||||
|
||||
// requestDevices();
|
||||
}, []);
|
||||
// // requestDevices();
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<Box sx={{ marginTop: "120px" }}>
|
||||
|
||||
@ -38,7 +38,10 @@ const GeneralItem = ({ title, general, color, numberType }: GeneralProps) => {
|
||||
: Object.entries(general).reduce(
|
||||
(total, [key, value]) => total + (value / Number(key)) * 100,
|
||||
0,
|
||||
) / Object.keys(general).length;
|
||||
) / Object.keys(general).length
|
||||
||
|
||||
Number(0)
|
||||
;
|
||||
|
||||
return (
|
||||
<Paper
|
||||
@ -66,34 +69,13 @@ const GeneralItem = ({ title, general, color, numberType }: GeneralProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const General = () => {
|
||||
const [general, setGeneral] = useState<GeneralResponse>(GENERAL_MOCK);
|
||||
export const General = (props:any) => {
|
||||
|
||||
const theme = useTheme();
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(700));
|
||||
|
||||
useEffect(() => {
|
||||
const requestGeneral = async () => {
|
||||
const [generalResponse, generalError] = await getGeneral("14761");
|
||||
|
||||
if (generalError) {
|
||||
enqueueSnackbar(generalError);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!generalResponse) {
|
||||
enqueueSnackbar("Список девайсов пуст.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setGeneral(generalResponse);
|
||||
};
|
||||
|
||||
// requestGeneral();
|
||||
}, []);
|
||||
|
||||
if (Object.keys(props.data).length === 0) return <Typography textAlign="center" m="10px 0">нет данных о ключевых метриках</Typography>
|
||||
return (
|
||||
<Box sx={{ marginTop: "45px" }}>
|
||||
<Typography
|
||||
@ -121,25 +103,25 @@ export const General = () => {
|
||||
<GeneralItem
|
||||
title="Открыли квиз"
|
||||
numberType="sum"
|
||||
general={general.open}
|
||||
general={props.data.open || {0:0}}
|
||||
color={COLORS[0]}
|
||||
/>
|
||||
<GeneralItem
|
||||
title="Получено заявок"
|
||||
numberType="sum"
|
||||
general={general.result}
|
||||
general={props.data.result || {0:0}}
|
||||
color={COLORS[1]}
|
||||
/>
|
||||
<GeneralItem
|
||||
title="Конверсия"
|
||||
numberType="percent"
|
||||
general={general.conversation}
|
||||
general={props.data.conversation || {0:0}}
|
||||
color={COLORS[2]}
|
||||
/>
|
||||
<GeneralItem
|
||||
title="Среднее время прохождения квиза"
|
||||
numberType="percent"
|
||||
general={general.avtime}
|
||||
general={props.data.avtime || {0:0}}
|
||||
color={COLORS[3]}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { getGeneral, getDevices, getQuestions } from "@api/statistic";
|
||||
import { useEffect, useState } from "react";
|
||||
import moment from "moment";
|
||||
|
||||
interface Props {
|
||||
quizId: string;
|
||||
@ -12,18 +13,24 @@ export function useAnalytics({
|
||||
to,
|
||||
from,
|
||||
}: Props) {
|
||||
const [devices, setDevices] = useState();
|
||||
const [general, setGeneral] = useState();
|
||||
const [questions, setQuestions] = useState();
|
||||
const formatTo = to === null ? 0 : moment(to).unix()
|
||||
const formatFrom = from === null ? 0 : moment(from).unix()
|
||||
console.log(
|
||||
to,
|
||||
from,)
|
||||
if (quizId === undefined) return {}
|
||||
const [devices, setDevices] = useState({});
|
||||
const [general, setGeneral] = useState({});
|
||||
const [questions, setQuestions] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const gottenGeneral = await getGeneral(quizId, to, from)
|
||||
const gottenDevices = await getDevices(quizId, to, from)
|
||||
const gottenQuestions = await getQuestions(quizId, to, from)
|
||||
setDevices(gottenGeneral)
|
||||
setGeneral(gottenDevices)
|
||||
setQuestions(gottenQuestions)
|
||||
const gottenGeneral = await getGeneral(quizId, formatTo, formatFrom)
|
||||
const gottenDevices = await getDevices(quizId, formatTo, formatFrom)
|
||||
const gottenQuestions = await getQuestions(quizId, formatTo, formatFrom)
|
||||
setDevices(gottenGeneral[0])
|
||||
setGeneral(gottenDevices[0])
|
||||
setQuestions(gottenQuestions[0])
|
||||
})()
|
||||
}, [to, from]);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user