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-12-31 02:53:25 +00:00
|
|
|
|
import {
|
|
|
|
|
AnyTypedQuizQuestion,
|
|
|
|
|
UntypedQuizQuestion,
|
|
|
|
|
} from "model/questionTypes/shared";
|
|
|
|
|
import { useEffect, useRef, useState } 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-12-31 02:53:25 +00:00
|
|
|
|
import Select, { ArrowDownTheme } from "./QuizPreviewQuestionTypes/Select";
|
2023-10-09 16:04:12 +00:00
|
|
|
|
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";
|
2023-11-30 06:27:15 +00:00
|
|
|
|
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);
|
2023-12-31 02:53:25 +00:00
|
|
|
|
const currentQuizStep = useQuizPreviewStore(
|
|
|
|
|
(state) => state.currentQuestionIndex,
|
|
|
|
|
);
|
|
|
|
|
const [widthPreview, setWidthPreview] = useState(null);
|
|
|
|
|
const nonDeletedQuizQuestions = questions.filter(
|
|
|
|
|
(question) => !question.deleted && question.type !== "result",
|
|
|
|
|
);
|
|
|
|
|
const maxCurrentQuizStep =
|
|
|
|
|
nonDeletedQuizQuestions.length > 0 ? nonDeletedQuizQuestions.length - 1 : 0;
|
|
|
|
|
const currentProgress = Math.floor(
|
|
|
|
|
(currentQuizStep / maxCurrentQuizStep) * 100,
|
|
|
|
|
);
|
2023-12-29 04:10:08 +00:00
|
|
|
|
const PreviewWin = useRef(0);
|
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();
|
|
|
|
|
}
|
|
|
|
|
},
|
2023-12-31 02:53:25 +00:00
|
|
|
|
[currentQuizStep, maxCurrentQuizStep],
|
2023-12-20 22:59:28 +00:00
|
|
|
|
);
|
2023-10-09 12:33:45 +00:00
|
|
|
|
|
2023-12-29 04:10:08 +00:00
|
|
|
|
const observer = useRef(
|
2023-12-31 02:53:25 +00:00
|
|
|
|
new ResizeObserver((entries) => {
|
|
|
|
|
const { width } = entries[0].contentRect;
|
|
|
|
|
setWidthPreview(width);
|
|
|
|
|
}),
|
2023-12-29 04:10:08 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2023-12-31 02:53:25 +00:00
|
|
|
|
observer.current.observe(PreviewWin.current);
|
|
|
|
|
}, [PreviewWin, observer]);
|
2023-12-29 04:10:08 +00:00
|
|
|
|
|
2023-12-20 22:59:28 +00:00
|
|
|
|
return (
|
|
|
|
|
<Paper
|
2023-12-31 02:53:25 +00:00
|
|
|
|
ref={PreviewWin}
|
2023-12-20 22:59:28 +00:00
|
|
|
|
className="quiz-preview-draghandle"
|
|
|
|
|
data-cy="quiz-preview-layout"
|
|
|
|
|
sx={{
|
|
|
|
|
height: "100%",
|
|
|
|
|
display: "flex",
|
|
|
|
|
flexDirection: "column",
|
|
|
|
|
flexGrow: 1,
|
|
|
|
|
borderRadius: "12px",
|
|
|
|
|
pointerEvents: "auto",
|
2023-12-31 02:53:25 +00:00
|
|
|
|
backgroundColor: theme.palette.background.default,
|
2023-12-20 22:59:28 +00:00
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
p: "40px 20px 20px",
|
|
|
|
|
whiteSpace: "break-spaces",
|
|
|
|
|
overflowY: "auto",
|
|
|
|
|
flexGrow: 1,
|
|
|
|
|
"&::-webkit-scrollbar": { width: 0, display: "none" },
|
|
|
|
|
msOverflowStyle: "none",
|
|
|
|
|
scrollbarWidth: "none",
|
|
|
|
|
}}
|
|
|
|
|
>
|
2023-12-31 02:53:25 +00:00
|
|
|
|
<QuestionPreviewComponent
|
|
|
|
|
question={currentQuestion}
|
|
|
|
|
widthPreview={widthPreview}
|
|
|
|
|
/>
|
2023-12-20 22:59:28 +00:00
|
|
|
|
</Box>
|
|
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
mt: "auto",
|
|
|
|
|
p: "16px",
|
|
|
|
|
borderTop: "1px solid #E3E3E3",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Box sx={{ marginBottom: "10px" }}>
|
2023-12-31 02:53:25 +00:00
|
|
|
|
<FormControl
|
|
|
|
|
fullWidth
|
|
|
|
|
size="small"
|
|
|
|
|
sx={{ width: "100%", minWidth: "200px", height: "48px" }}
|
|
|
|
|
>
|
2023-12-20 22:59:28 +00:00
|
|
|
|
<MuiSelect
|
|
|
|
|
id="category-select"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
value={currentQuizStep}
|
|
|
|
|
placeholder="Заголовок вопроса"
|
2023-12-31 02:53:25 +00:00
|
|
|
|
onChange={({ target }) =>
|
|
|
|
|
setCurrentQuestionIndex(window.Number(target.value))
|
|
|
|
|
}
|
2023-12-20 22:59:28 +00:00
|
|
|
|
sx={{
|
|
|
|
|
height: "48px",
|
|
|
|
|
borderRadius: "8px",
|
|
|
|
|
"& .MuiOutlinedInput-notchedOutline": {
|
2023-12-29 04:10:08 +00:00
|
|
|
|
border: `1px solid ${theme.palette.primary.main} !important`,
|
2023-12-20 22:59:28 +00:00
|
|
|
|
},
|
2023-12-31 02:53:25 +00:00
|
|
|
|
"& .MuiSelect-icon": {
|
|
|
|
|
color: theme.palette.primary.main,
|
|
|
|
|
},
|
2023-12-20 22:59:28 +00:00
|
|
|
|
}}
|
|
|
|
|
MenuProps={{
|
|
|
|
|
PaperProps: {
|
|
|
|
|
sx: {
|
|
|
|
|
mt: "8px",
|
|
|
|
|
p: "4px",
|
|
|
|
|
borderRadius: "8px",
|
|
|
|
|
border: "1px solid #EEE4FC",
|
|
|
|
|
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
|
2023-12-31 02:53:25 +00:00
|
|
|
|
backgroundColor: theme.palette.background.default,
|
2023-12-20 22:59:28 +00:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
MenuListProps: {
|
|
|
|
|
sx: {
|
|
|
|
|
py: 0,
|
|
|
|
|
display: "flex",
|
|
|
|
|
flexDirection: "column",
|
|
|
|
|
gap: "8px",
|
|
|
|
|
"& .Mui-selected": {
|
|
|
|
|
backgroundColor: theme.palette.background.default,
|
2023-12-29 04:10:08 +00:00
|
|
|
|
color: theme.palette.primary.main,
|
2023-12-20 22:59:28 +00:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
inputProps={{
|
|
|
|
|
sx: {
|
2023-12-29 04:10:08 +00:00
|
|
|
|
color: theme.palette.primary.main,
|
2023-12-20 22:59:28 +00:00
|
|
|
|
display: "flex",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
px: "9px",
|
|
|
|
|
gap: "20px",
|
|
|
|
|
},
|
|
|
|
|
}}
|
2023-12-29 04:10:08 +00:00
|
|
|
|
IconComponent={ArrowDownTheme}
|
2023-12-20 22:59:28 +00:00
|
|
|
|
>
|
2023-12-31 02:53:25 +00:00
|
|
|
|
{Object.values(questions.filter((q) => q.type !== "result")).map(
|
|
|
|
|
({ id, title }, index) => (
|
|
|
|
|
<MenuItem
|
|
|
|
|
key={id}
|
|
|
|
|
value={index}
|
|
|
|
|
sx={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
gap: "20px",
|
|
|
|
|
p: "4px",
|
|
|
|
|
borderRadius: "5px",
|
|
|
|
|
color: "#9A9AAF",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{`${index + 1}. ${title}`}
|
|
|
|
|
</MenuItem>
|
|
|
|
|
),
|
|
|
|
|
)}
|
2023-12-20 22:59:28 +00:00
|
|
|
|
</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
|
2023-12-31 02:53:25 +00:00
|
|
|
|
? `Вопрос ${currentQuizStep + 1} из ${
|
|
|
|
|
nonDeletedQuizQuestions.length
|
|
|
|
|
}`
|
2023-12-20 22:59:28 +00:00
|
|
|
|
: "Нет вопросов"}
|
|
|
|
|
</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-31 02:53:25 +00:00
|
|
|
|
<ArrowLeft color={theme.palette.primary.main} />
|
2023-12-20 22:59:28 +00:00
|
|
|
|
</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-31 02:53:25 +00:00
|
|
|
|
function QuestionPreviewComponent({
|
|
|
|
|
question,
|
|
|
|
|
widthPreview,
|
|
|
|
|
}: {
|
|
|
|
|
question: AnyTypedQuizQuestion | UntypedQuizQuestion | undefined;
|
|
|
|
|
widthPreview?: number;
|
|
|
|
|
}) {
|
2023-12-20 22:59:28 +00:00
|
|
|
|
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":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Variant question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "images":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Images question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "varimg":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Varimg question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "emoji":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Emoji question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "text":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Text question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "select":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Select question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "date":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Date question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "number":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Number question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "file":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <File question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "page":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Page question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
case "rating":
|
2023-12-31 02:53:25 +00:00
|
|
|
|
return <Rating question={question} widthPreview={widthPreview} />;
|
2023-12-20 22:59:28 +00:00
|
|
|
|
default:
|
|
|
|
|
notReachable(question);
|
|
|
|
|
}
|
2023-10-09 12:33:45 +00:00
|
|
|
|
}
|