Merge branch 'dev' into 'staging'

Dev

See merge request frontend/squiz!236
This commit is contained in:
Nastya 2024-04-05 18:24:26 +00:00
commit 3149250dae
7 changed files with 95 additions and 61 deletions

@ -58,7 +58,7 @@ export default function Analytics() {
useEffect(() => {
if (quizes.length > 0) {
const quiz = quizes.find((q) => q.backendId === editQuizId);
if (quiz === undefined) throw new Error("Не удалось получить квиз")
if (quiz === undefined) throw new Error("Не удалось получить квиз");
setQuiz(quiz);
setFrom(moment(new Date(quiz.created_at)));
}
@ -68,10 +68,8 @@ export default function Analytics() {
const getData = async (): Promise<void> => {
try {
if (editQuizId !== null) {
const gottenQuizes = await quizApi.getList();
setQuizes(gottenQuizes)
setQuizes(gottenQuizes);
}
} catch (error) {
console.error("Не удалось получить квизы", error);

@ -1,5 +1,4 @@
import { FC, useState } from "react";
import type { PaginationRenderItemParams } from "@mui/material";
import { FC, useEffect, useMemo, useState } from "react";
import {
Box,
ButtonBase,
@ -18,6 +17,8 @@ import { ReactComponent as NextIcon } from "@icons/Analytics/next.svg";
import { ReactComponent as LeftArrowIcon } from "@icons/Analytics/leftArrow.svg";
import { ReactComponent as RightArrowIcon } from "@icons/Analytics/rightArrow.svg";
import type { PaginationRenderItemParams } from "@mui/material";
type AnswerProps = {
title: string;
percent: number;
@ -28,12 +29,14 @@ type AnswersProps = {
data: Record<string, Record<string, number>> | null;
};
const ANSWERS_MOCK: Record<string, number> = {
"Добавьте ответ": 67,
"Вопрос пропущен": 7,
Другое: 27,
type PaginationProps = {
page: number;
pagesAmount: number;
setPage: (page: number) => void;
};
const ANSWERS_PER_PAGE = 5;
const Answer = ({ title, percent, highlight }: AnswerProps) => {
const theme = useTheme();
@ -60,7 +63,7 @@ const Answer = ({ title, percent, highlight }: AnswerProps) => {
border: `1px solid ${highlight ? theme.palette.brightPurple.main : theme.palette.grey2.main}`,
"& > span": { background: highlight ? "#D9C0F9" : "#9A9AAF1A" },
"&::before": {
content: `"${title}"`,
content: title ? `"${title}"` : `"Без имени"`,
position: "absolute",
zIndex: 1,
left: "20px",
@ -88,12 +91,15 @@ const Answer = ({ title, percent, highlight }: AnswerProps) => {
);
};
const Pagination = () => {
const [count, setCount] = useState<number>(50);
const [page, setPage] = useState<number>(1);
const Pagination = ({ page, setPage, pagesAmount }: PaginationProps) => {
const [count, setCount] = useState<number>(0);
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(855));
useEffect(() => {
setCount(pagesAmount);
}, [pagesAmount]);
const getPaginationItem = (props: PaginationRenderItemParams) => {
if (props.type === "start-ellipsis" || props.type === "end-ellipsis") {
return;
@ -147,9 +153,13 @@ const Pagination = () => {
disableUnderline
placeholder="1"
value={page}
onChange={({ target }) =>
setPage(Number(target.value.replace(/\D/, "")))
}
onChange={({ target }) => {
const newPage = Number(target.value.replace(/\D/, ""));
if (newPage <= count) {
setPage(newPage);
}
}}
sx={{
height: "30px",
width: "65px",
@ -190,7 +200,27 @@ const Pagination = () => {
};
export const Answers: FC<AnswersProps> = ({ data }) => {
const [page, setPage] = useState<number>(1);
const theme = useTheme();
const answers = useMemo(
() =>
data === null ?
[]
:
Object.keys(data ?? {})
.map((key) =>
Object.entries(data[key]).map(([title, percent]) => ({
title,
percent,
key,
})),
)
.flat(),
[data],
);
console.log(answers)
console.log(page)
if (!data) {
return (
<Typography textAlign="center" m="10px 0">
@ -244,7 +274,7 @@ export const Answers: FC<AnswersProps> = ({ data }) => {
},
}}
>
Заголовок вопроса. Варианты ответов
Заголовок вопроса. {answers.slice(ANSWERS_PER_PAGE * (page - 1), ANSWERS_PER_PAGE * page)[0]?.key}
</Typography>
<ButtonBase>
<DoubleCheckIcon />
@ -253,26 +283,22 @@ export const Answers: FC<AnswersProps> = ({ data }) => {
<NextIcon />
</ButtonBase>
</Box>
{/*{Object.entries(data).map(([title, percent], index) => (*/}
{/* <Answer*/}
{/* key={title}*/}
{/* title={title}*/}
{/* percent={percent}*/}
{/* highlight={!index}*/}
{/* />*/}
{/*))}*/}
{Object.entries(data).map(([title, values], index) =>
Object.entries(values).map(([subTitle, percent]) => (
{answers
.slice(ANSWERS_PER_PAGE * (page - 1), ANSWERS_PER_PAGE * page)
.map(({ title, percent }, index) => (
<Answer
key={subTitle}
title={subTitle}
key={index}
title={title}
percent={percent}
highlight={!index}
/>
)),
)}
))}
</Paper>
<Pagination />
<Pagination
page={page}
setPage={setPage}
pagesAmount={Math.ceil(answers.length / ANSWERS_PER_PAGE)}
/>
</Box>
);
};

@ -5,7 +5,8 @@ import {
Typography,
useTheme,
} from "@mui/material";
import { FC } from "react";
import type { FC } from "react";
type ResultProps = {
title: string;
@ -17,12 +18,6 @@ type ResultsProps = {
data: Record<string, number> | null;
};
const RESULTS_MOCK: Record<string, number> = {
"Заголовок результата": 100,
"Результат пропущен": 7,
Другое: 27,
};
const Result = ({ title, percent, highlight }: ResultProps) => {
const theme = useTheme();
@ -76,12 +71,13 @@ const Result = ({ title, percent, highlight }: ResultProps) => {
export const Results: FC<ResultsProps> = ({ data }) => {
const theme = useTheme();
if (!data)
if (!data || !Object.keys(data).length)
return (
<Typography margin="20px 0 0 0" textAlign="center" m="10px 0">
нет данных о результатах
</Typography>
);
return (
<Box>
<Typography

@ -22,7 +22,7 @@ const COLORS: Record<number, string> = {
const Device = ({ title, devices }: DeviceProps) => {
const theme = useTheme();
if (!devices) {
if (!devices || !Object.keys(devices ?? {}).length) {
return <Typography>{title} - нет данных</Typography>;
}
@ -84,7 +84,7 @@ const Device = ({ title, devices }: DeviceProps) => {
},
}}
>
{id}
{id ? id : "Неопределено"}
</Typography>
<Typography>{value.toFixed(1)} %</Typography>
</Box>

@ -9,7 +9,7 @@ type GeneralItemsProps = {
title: string;
general: Record<string, number>;
color: string;
numberType: "sum" | "percent";
numberType: "sum" | "percent" | "time";
};
type GeneralProps = {
@ -24,13 +24,13 @@ const COLORS: Record<number, string> = {
};
const dateParser = (object: Record<string, number>): Record<string, number> => {
const result = {} as Record<string, number>
const result = {} as Record<string, number>;
for (var key in object) {
result[moment.utc(Number(key)*1000).format('MM/DD/YYYY')] = object[key]
console.log(result)
result[moment.utc(Number(key) * 1000).format("DD/MM/YYYY")] = object[key];
console.log(result);
}
return result;
}
};
const GeneralItem = ({
title,
@ -44,10 +44,15 @@ const GeneralItem = ({
const numberValue =
numberType === "sum"
? Object.values(general).reduce((total, item) => total + item, 0)
: Object.entries(general).reduce(
: 0
Object.entries(general).reduce(
(total, [key, value]) => total + (value / Number(key)) * 100,
0,
) / Object.keys(general).length || Number(0);
console.log("general" , general)
console.log(Object.keys(general).length === 0)
if (Object.keys(general).length === 0) return <Typography textAlign="center">{`${title} - нет данных`}</Typography>
return (
<Paper
sx={{
@ -61,8 +66,16 @@ const GeneralItem = ({
{numberType === "sum" ? numberValue : `${numberValue.toFixed()}%`}
</Typography>
<LineChart
xAxis={[{ data: Object.keys(general), valueFormatter: (value) => moment.utc(Number(value)*1000).format('MM/DD/YYYY') }]}
xAxis={[
{
data: Object.keys(general),
valueFormatter: (value) =>
moment.utc(Number(value) * 1000).format("DD/MM/YYYY"),
},
]}
series={[{ data: Object.values(general) }]}
// dataset={Object.entries(general).map(([, v]) => moment.unix(v).format("ss/mm/HH")).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {})}
height={220}
colors={[color]}
sx={{
@ -113,25 +126,25 @@ export const General: FC<GeneralProps> = ({ data }) => {
<GeneralItem
title="Открыли квиз"
numberType="sum"
general={data.Open || { 0: 0 }}
general={ Object.entries(data.Open).filter(([, v]) => v > 0).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}) || { 0: 0 }}
color={COLORS[0]}
/>
<GeneralItem
title="Получено заявок"
numberType="sum"
general={data.Result || { 0: 0 }}
general={ Object.entries(data.Result).filter(([, v]) => v > 0).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}) || { 0: 0 }}
color={COLORS[1]}
/>
<GeneralItem
title="Конверсия"
numberType="percent"
general={data.Conversion || { 0: 0 }}
general={ Object.entries(data.Conversion).filter(([, v]) => v > 0).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}) || { 0: 0 }}
color={COLORS[2]}
/>
<GeneralItem
title="Среднее время прохождения квиза"
numberType="percent"
general={data.AvTime || { 0: 0 }}
numberType="time"
general={Object.entries(data.AvTime).filter(([, v]) => v > 0).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}) || { 0: 0 }}
color={COLORS[3]}
/>
</Box>

@ -4,8 +4,8 @@ import { CustomTab } from "./CustomTab";
type TabsProps = {
names: string[];
items: string[];
selectedItem: "count" | "day" | "dop";
setSelectedItem: (num: "count" | "day" | "dop") => void;
selectedItem: "day" | "count" | "dop";
setSelectedItem: (num: "day" | "count" | "dop") => void;
};
export const Tabs = ({
@ -18,7 +18,7 @@ export const Tabs = ({
sx={{ m: "25px" }}
TabIndicatorProps={{ sx: { display: "none" } }}
value={selectedItem}
onChange={(event, newValue: "count" | "day" | "dop") => {
onChange={(event, newValue: "day" | "count" | "dop") => {
setSelectedItem(newValue);
}}
variant="scrollable"

@ -32,8 +32,8 @@ import { createTariffElements } from "./tariffsUtils/createTariffElements";
import { currencyFormatter } from "./tariffsUtils/currencyFormatter";
const StepperText: Record<string, string> = {
count: "Тарифы на объём",
day: "Тарифы на время",
count: "Тарифы на объём",
dop: "Доп. услуги",
};
@ -50,7 +50,9 @@ function TariffPage() {
const [discounts, setDiscounts] = useState();
const [openModal, setOpenModal] = useState({});
const [cash, setCash] = useState("0");
const [selectedItem, setSelectedItem] = useState<"count" | "day">("count");
const [selectedItem, setSelectedItem] = useState<"count" | "day" | "dop">(
"day",
);
const { isTestServer } = useDomainDefine();
const [promocodeField, setPromocodeField] = useState<string>("");
@ -297,7 +299,6 @@ function TariffPage() {
justifyContent: "left",
display: "grid",
gap: "40px",
p: "20px",
gridTemplateColumns: `repeat(auto-fit, minmax(300px, ${
isTablet ? "436px" : "360px"
}))`,