frontPanel/src/ui_kit/QuizPreview/QuizPreviewLayout.tsx

245 lines
7.8 KiB
TypeScript
Raw Normal View History

2023-12-20 22:59:28 +00:00
import {
Box,
Button,
LinearProgress,
Paper,
Typography,
FormControl,
Select as MuiSelect,
MenuItem,
useTheme,
} from "@mui/material";
2023-11-20 17:22:13 +00:00
import { useQuestionsStore } from "@root/questions/store";
2023-10-17 13:24:37 +00:00
import {
2023-12-20 22:59:28 +00:00
decrementCurrentQuestionIndex,
incrementCurrentQuestionIndex,
useQuizPreviewStore,
setCurrentQuestionIndex,
2023-10-17 13:24:37 +00:00
} from "@root/quizPreview";
2023-11-29 13:49:52 +00:00
import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "model/questionTypes/shared";
2023-11-13 18:04:51 +00:00
import { useEffect } from "react";
2023-10-09 12:33:45 +00:00
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
import Date from "./QuizPreviewQuestionTypes/Date";
2023-10-09 16:04:12 +00:00
import Emoji from "./QuizPreviewQuestionTypes/Emoji";
2023-10-09 12:33:45 +00:00
import File from "./QuizPreviewQuestionTypes/File";
2023-10-09 16:04:12 +00:00
import Images from "./QuizPreviewQuestionTypes/Images";
import Number from "./QuizPreviewQuestionTypes/Number";
2023-10-09 12:33:45 +00:00
import Page from "./QuizPreviewQuestionTypes/Page";
import Rating from "./QuizPreviewQuestionTypes/Rating";
2023-10-09 16:04:12 +00:00
import Select from "./QuizPreviewQuestionTypes/Select";
import Text from "./QuizPreviewQuestionTypes/Text";
import Variant from "./QuizPreviewQuestionTypes/Variant";
import Varimg from "./QuizPreviewQuestionTypes/Varimg";
2023-11-20 17:22:13 +00:00
import { notReachable } from "../../utils/notReachable";
import ArrowDownIcon from "@icons/ArrowDownIcon";
2023-10-09 12:33:45 +00:00
export default function QuizPreviewLayout() {
2023-12-20 22:59:28 +00:00
const theme = useTheme();
const questions = useQuestionsStore((state) => state.questions);
const currentQuizStep = useQuizPreviewStore((state) => state.currentQuestionIndex);
2023-10-09 12:33:45 +00:00
2023-12-20 22:59:28 +00:00
const nonDeletedQuizQuestions = questions.filter((question) => !question.deleted);
const maxCurrentQuizStep = nonDeletedQuizQuestions.length > 0 ? nonDeletedQuizQuestions.length - 1 : 0;
const currentProgress = Math.floor((currentQuizStep / maxCurrentQuizStep) * 100);
2023-10-09 16:04:12 +00:00
2023-12-20 22:59:28 +00:00
const currentQuestion = nonDeletedQuizQuestions[currentQuizStep];
2023-10-09 12:33:45 +00:00
2023-12-20 22:59:28 +00:00
useEffect(
function resetCurrentQuizStep() {
if (currentQuizStep > maxCurrentQuizStep) {
decrementCurrentQuestionIndex();
}
},
[currentQuizStep, maxCurrentQuizStep]
);
2023-10-09 12:33:45 +00:00
2023-12-20 22:59:28 +00:00
return (
<Paper
className="quiz-preview-draghandle"
data-cy="quiz-preview-layout"
sx={{
height: "100%",
display: "flex",
flexDirection: "column",
flexGrow: 1,
borderRadius: "12px",
pointerEvents: "auto",
}}
>
<Box
sx={{
p: "40px 20px 20px",
whiteSpace: "break-spaces",
overflowY: "auto",
flexGrow: 1,
"&::-webkit-scrollbar": { width: 0, display: "none" },
msOverflowStyle: "none",
scrollbarWidth: "none",
}}
>
<QuestionPreviewComponent question={currentQuestion} />
</Box>
<Box
sx={{
mt: "auto",
p: "16px",
borderTop: "1px solid #E3E3E3",
}}
>
<Box sx={{ marginBottom: "10px" }}>
<FormControl fullWidth size="small" sx={{ width: "100%", minWidth: "200px", height: "48px" }}>
<MuiSelect
id="category-select"
variant="outlined"
value={currentQuizStep}
placeholder="Заголовок вопроса"
onChange={({ target }) => setCurrentQuestionIndex(window.Number(target.value))}
sx={{
height: "48px",
borderRadius: "8px",
"& .MuiOutlinedInput-notchedOutline": {
border: `1px solid ${theme.palette.brightPurple.main} !important`,
},
}}
MenuProps={{
PaperProps: {
sx: {
mt: "8px",
p: "4px",
borderRadius: "8px",
border: "1px solid #EEE4FC",
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
},
},
MenuListProps: {
sx: {
py: 0,
display: "flex",
flexDirection: "column",
gap: "8px",
"& .Mui-selected": {
backgroundColor: theme.palette.background.default,
color: theme.palette.brightPurple.main,
},
},
},
}}
inputProps={{
sx: {
color: theme.palette.brightPurple.main,
display: "flex",
alignItems: "center",
px: "9px",
gap: "20px",
},
}}
IconComponent={(props) => <ArrowDownIcon {...props} />}
>
{Object.values(questions).map(({ id, title }, index) => (
<MenuItem
key={id}
value={index}
sx={{
display: "flex",
alignItems: "center",
gap: "20px",
p: "4px",
borderRadius: "5px",
color: theme.palette.grey2.main,
}}
>
{`${index + 1}. ${title}`}
</MenuItem>
))}
</MuiSelect>
</FormControl>
</Box>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Box
2023-11-13 18:04:51 +00:00
sx={{
2023-12-20 22:59:28 +00:00
flexGrow: 1,
display: "flex",
flexDirection: "column",
gap: 1,
2023-11-13 18:04:51 +00:00
}}
2023-12-20 22:59:28 +00:00
>
<Typography>
{nonDeletedQuizQuestions.length > 0
? `Вопрос ${currentQuizStep + 1} из ${nonDeletedQuizQuestions.length}`
: "Нет вопросов"}
</Typography>
{nonDeletedQuizQuestions.length > 0 && (
<LinearProgress
variant="determinate"
value={currentProgress}
2023-11-13 18:04:51 +00:00
sx={{
2023-12-20 22:59:28 +00:00
"&.MuiLinearProgress-colorPrimary": {
backgroundColor: "fadePurple.main",
},
"& .MuiLinearProgress-barColorPrimary": {
backgroundColor: "brightPurple.main",
},
2023-11-13 18:04:51 +00:00
}}
2023-12-20 22:59:28 +00:00
/>
)}
</Box>
<Box
sx={{
ml: 2,
display: "flex",
gap: 1,
}}
>
<Button
variant="outlined"
onClick={decrementCurrentQuestionIndex}
disabled={currentQuizStep === 0}
sx={{ px: 1, minWidth: 0 }}
2023-11-13 18:04:51 +00:00
>
2023-12-20 22:59:28 +00:00
<ArrowLeft />
</Button>
<Button
variant="contained"
onClick={() => incrementCurrentQuestionIndex(maxCurrentQuizStep)}
disabled={currentQuizStep >= maxCurrentQuizStep}
2023-11-13 18:04:51 +00:00
>
2023-12-20 22:59:28 +00:00
Далее
</Button>
</Box>
</Box>
</Box>
</Paper>
);
2023-11-13 18:04:51 +00:00
}
2023-12-20 22:59:28 +00:00
function QuestionPreviewComponent({ question }: { question: AnyTypedQuizQuestion | UntypedQuizQuestion | undefined }) {
if (!question || question.type === null) return null;
2023-11-29 13:49:52 +00:00
2023-12-20 22:59:28 +00:00
switch (question.type) {
case "variant":
return <Variant question={question} />;
case "images":
return <Images question={question} />;
case "varimg":
return <Varimg question={question} />;
case "emoji":
return <Emoji question={question} />;
case "text":
return <Text question={question} />;
case "select":
return <Select question={question} />;
case "date":
return <Date question={question} />;
case "number":
return <Number question={question} />;
case "file":
return <File question={question} />;
case "page":
return <Page question={question} />;
case "rating":
return <Rating question={question} />;
default:
notReachable(question);
}
2023-10-09 12:33:45 +00:00
}