260 lines
6.9 KiB
TypeScript
260 lines
6.9 KiB
TypeScript
![]() |
import { useState } from "react";
|
|||
|
import {
|
|||
|
Box,
|
|||
|
Paper,
|
|||
|
Typography,
|
|||
|
LinearProgress,
|
|||
|
Pagination as MuiPagination,
|
|||
|
PaginationItem,
|
|||
|
Input,
|
|||
|
ButtonBase,
|
|||
|
useTheme,
|
|||
|
useMediaQuery,
|
|||
|
} from "@mui/material";
|
|||
|
|
|||
|
import { ReactComponent as DoubleCheckIcon } from "@icons/Analytics/doubleCheck.svg";
|
|||
|
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;
|
|||
|
highlight?: boolean;
|
|||
|
};
|
|||
|
|
|||
|
const ANSWERS_MOCK: Record<string, number> = {
|
|||
|
"Добавьте ответ": 67,
|
|||
|
"Вопрос пропущен": 7,
|
|||
|
Другое: 27,
|
|||
|
};
|
|||
|
|
|||
|
const Answer = ({ title, percent, highlight }: AnswerProps) => {
|
|||
|
const theme = useTheme();
|
|||
|
|
|||
|
return (
|
|||
|
<Box sx={{ padding: "15px 25px" }}>
|
|||
|
<Box
|
|||
|
sx={{
|
|||
|
position: "relative",
|
|||
|
display: "flex",
|
|||
|
gap: "15px",
|
|||
|
alignItems: "center",
|
|||
|
flexGrow: 1,
|
|||
|
}}
|
|||
|
>
|
|||
|
<LinearProgress
|
|||
|
variant="determinate"
|
|||
|
title={title}
|
|||
|
value={percent}
|
|||
|
sx={{
|
|||
|
width: "100%",
|
|||
|
height: "44px",
|
|||
|
background: theme.palette.background.default,
|
|||
|
borderRadius: "10px",
|
|||
|
border: `1px solid ${highlight ? theme.palette.brightPurple.main : theme.palette.grey2.main}`,
|
|||
|
"& > span": { background: highlight ? "#D9C0F9" : "#9A9AAF1A" },
|
|||
|
"&::before": {
|
|||
|
content: `"${title}"`,
|
|||
|
position: "absolute",
|
|||
|
zIndex: 1,
|
|||
|
left: "20px",
|
|||
|
top: "50%",
|
|||
|
transform: "translateY(-50%)",
|
|||
|
color: highlight
|
|||
|
? theme.palette.brightPurple.main
|
|||
|
: theme.palette.grey3.main,
|
|||
|
},
|
|||
|
}}
|
|||
|
/>
|
|||
|
<Box sx={{ minWidth: 35 }}>
|
|||
|
<Typography
|
|||
|
sx={{
|
|||
|
minWidth: "45px",
|
|||
|
fontWeight: highlight ? "bold" : "normal",
|
|||
|
color: highlight
|
|||
|
? theme.palette.brightPurple.main
|
|||
|
: theme.palette.text.primary,
|
|||
|
}}
|
|||
|
>{`${percent}%`}</Typography>
|
|||
|
</Box>
|
|||
|
</Box>
|
|||
|
</Box>
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
const Pagination = () => {
|
|||
|
const [count, setCount] = useState<number>(50);
|
|||
|
const [page, setPage] = useState<number>(1);
|
|||
|
const theme = useTheme();
|
|||
|
const isMobile = useMediaQuery(theme.breakpoints.down(855));
|
|||
|
|
|||
|
const getPaginationItem = (props: PaginationRenderItemParams) => {
|
|||
|
if (props.type === "start-ellipsis" || props.type === "end-ellipsis") {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (props.type !== "previous" && props.type !== "next" && props.page) {
|
|||
|
if (isMobile) {
|
|||
|
const allowedPages = [
|
|||
|
page - 1 < 1 ? page + 2 : page - 1,
|
|||
|
page,
|
|||
|
page + 1 > count ? page - 2 : page + 1,
|
|||
|
];
|
|||
|
|
|||
|
if (!allowedPages.includes(props.page)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const allowedPages = [
|
|||
|
page - 2 < 1 ? page + 3 : page - 2,
|
|||
|
page - 1 < 1 ? page + 4 : page - 1,
|
|||
|
page,
|
|||
|
page + 1 > count ? page - 4 : page + 1,
|
|||
|
page + 2 > count ? page - 3 : page + 2,
|
|||
|
];
|
|||
|
|
|||
|
if (!allowedPages.includes(props.page)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return (
|
|||
|
<PaginationItem
|
|||
|
component="div"
|
|||
|
slots={{ previous: LeftArrowIcon, next: RightArrowIcon }}
|
|||
|
{...{ ...props, variant: undefined }}
|
|||
|
/>
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
return (
|
|||
|
<Box
|
|||
|
sx={{
|
|||
|
display: "flex",
|
|||
|
alignItems: "center",
|
|||
|
justifyContent: "center",
|
|||
|
marginTop: "30px",
|
|||
|
}}
|
|||
|
>
|
|||
|
<Input
|
|||
|
disableUnderline
|
|||
|
placeholder="1"
|
|||
|
value={page}
|
|||
|
onChange={({ target }) =>
|
|||
|
setPage(Number(target.value.replace(/\D/, "")))
|
|||
|
}
|
|||
|
sx={{
|
|||
|
height: "30px",
|
|||
|
width: "65px",
|
|||
|
borderRadius: "5px",
|
|||
|
padding: "10px",
|
|||
|
marginRight: "5px",
|
|||
|
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
|
|||
|
backgroundColor: theme.palette.background.paper,
|
|||
|
}}
|
|||
|
/>
|
|||
|
<MuiPagination
|
|||
|
page={page}
|
|||
|
count={count}
|
|||
|
siblingCount={isMobile ? 1 : 2}
|
|||
|
boundaryCount={isMobile ? 1 : 2}
|
|||
|
onChange={(_, page) => setPage(page)}
|
|||
|
renderItem={getPaginationItem}
|
|||
|
sx={{
|
|||
|
"& .MuiButtonBase-root": {
|
|||
|
borderRadius: "5px",
|
|||
|
margin: "0 5px",
|
|||
|
height: "30px",
|
|||
|
background: theme.palette.background.paper,
|
|||
|
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
|
|||
|
"&.Mui-selected": {
|
|||
|
background: theme.palette.background.paper,
|
|||
|
color: theme.palette.brightPurple.main,
|
|||
|
},
|
|||
|
"&.MuiPaginationItem-previousNext": {
|
|||
|
margin: "0 15px",
|
|||
|
background: theme.palette.brightPurple.main,
|
|||
|
},
|
|||
|
},
|
|||
|
}}
|
|||
|
/>
|
|||
|
</Box>
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
export const Answers = () => {
|
|||
|
const [answers, setAnswers] = useState<Record<string, number>>(ANSWERS_MOCK);
|
|||
|
const theme = useTheme();
|
|||
|
|
|||
|
return (
|
|||
|
<Box sx={{ flexGrow: 1 }}>
|
|||
|
<Paper
|
|||
|
sx={{
|
|||
|
borderRadius: "12px",
|
|||
|
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
|
|||
|
marginTop: "20px",
|
|||
|
}}
|
|||
|
>
|
|||
|
<Box
|
|||
|
sx={{
|
|||
|
display: "flex",
|
|||
|
gap: "10px",
|
|||
|
alignItems: "center",
|
|||
|
padding: "25px",
|
|||
|
}}
|
|||
|
>
|
|||
|
<Typography
|
|||
|
component="h3"
|
|||
|
sx={{
|
|||
|
flexGrow: 1,
|
|||
|
position: "relative",
|
|||
|
fontSize: "18px",
|
|||
|
fontWeight: "bold",
|
|||
|
paddingLeft: "40px",
|
|||
|
color: theme.palette.text.primary,
|
|||
|
"&::before": {
|
|||
|
content: "'1'",
|
|||
|
position: "absolute",
|
|||
|
top: "50%",
|
|||
|
left: "0",
|
|||
|
transform: "translateY(-50%)",
|
|||
|
display: "flex",
|
|||
|
alignItems: "center",
|
|||
|
justifyContent: "center",
|
|||
|
width: "30px",
|
|||
|
height: "30px",
|
|||
|
borderRadius: "50%",
|
|||
|
fontSize: "14px",
|
|||
|
fontWeight: "normal",
|
|||
|
background: "#EEE4FC",
|
|||
|
color: theme.palette.brightPurple.main,
|
|||
|
},
|
|||
|
}}
|
|||
|
>
|
|||
|
Заголовок вопроса. Варианты ответов
|
|||
|
</Typography>
|
|||
|
<ButtonBase>
|
|||
|
<DoubleCheckIcon />
|
|||
|
</ButtonBase>
|
|||
|
<ButtonBase>
|
|||
|
<NextIcon />
|
|||
|
</ButtonBase>
|
|||
|
</Box>
|
|||
|
{Object.entries(answers).map(([title, percent], index) => (
|
|||
|
<Answer
|
|||
|
key={title}
|
|||
|
title={title}
|
|||
|
percent={percent}
|
|||
|
highlight={!index}
|
|||
|
/>
|
|||
|
))}
|
|||
|
</Paper>
|
|||
|
<Pagination />
|
|||
|
</Box>
|
|||
|
);
|
|||
|
};
|