use new question types
This commit is contained in:
parent
5fc077c884
commit
36c13f96e9
@ -1,4 +1,4 @@
|
|||||||
import PointsIcon from "@icons/questionsPage/PointsIcon";
|
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
||||||
import { Box, IconButton } from "@mui/material";
|
import { Box, IconButton } from "@mui/material";
|
||||||
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
|
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
|
||||||
import { useLayoutEffect, useRef } from "react";
|
import { useLayoutEffect, useRef } from "react";
|
||||||
@ -110,7 +110,7 @@ export default function QuizPreview() {
|
|||||||
cursor: "move",
|
cursor: "move",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PointsIcon />
|
<PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Rnd>
|
</Rnd>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +1,24 @@
|
|||||||
import { Box, Button, LinearProgress, Paper, Typography } from "@mui/material";
|
import { Box, Button, LinearProgress, Paper, Typography } from "@mui/material";
|
||||||
import { Question, questionStore } from "@root/questions";
|
import { questionStore } from "@root/questions";
|
||||||
import { decrementCurrentQuestionIndex, incrementCurrentQuestionIndex, useQuizPreviewStore } from "@root/quizPreview";
|
import { decrementCurrentQuestionIndex, incrementCurrentQuestionIndex, useQuizPreviewStore } from "@root/quizPreview";
|
||||||
|
import { AnyQuizQuestion, QuizQuestionType } from "model/questionTypes/shared";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
|
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
|
||||||
import Variant from "./QuizPreviewQuestionTypes/Variant";
|
|
||||||
import { FC, useEffect } from "react";
|
|
||||||
import Images from "./QuizPreviewQuestionTypes/Images";
|
|
||||||
import Varimg from "./QuizPreviewQuestionTypes/Varimg";
|
|
||||||
import Emoji from "./QuizPreviewQuestionTypes/Emoji";
|
|
||||||
import Text from "./QuizPreviewQuestionTypes/Text";
|
|
||||||
import Select from "./QuizPreviewQuestionTypes/Select";
|
|
||||||
import Date from "./QuizPreviewQuestionTypes/Date";
|
import Date from "./QuizPreviewQuestionTypes/Date";
|
||||||
import Number from "./QuizPreviewQuestionTypes/Number";
|
import Emoji from "./QuizPreviewQuestionTypes/Emoji";
|
||||||
import File from "./QuizPreviewQuestionTypes/File";
|
import File from "./QuizPreviewQuestionTypes/File";
|
||||||
|
import Images from "./QuizPreviewQuestionTypes/Images";
|
||||||
|
import Number from "./QuizPreviewQuestionTypes/Number";
|
||||||
import Page from "./QuizPreviewQuestionTypes/Page";
|
import Page from "./QuizPreviewQuestionTypes/Page";
|
||||||
import Rating from "./QuizPreviewQuestionTypes/Rating";
|
import Rating from "./QuizPreviewQuestionTypes/Rating";
|
||||||
|
import Select from "./QuizPreviewQuestionTypes/Select";
|
||||||
|
import Text from "./QuizPreviewQuestionTypes/Text";
|
||||||
|
import Variant from "./QuizPreviewQuestionTypes/Variant";
|
||||||
|
import Varimg from "./QuizPreviewQuestionTypes/Varimg";
|
||||||
|
|
||||||
|
|
||||||
type QuizQuestionType = "variant" | "images" | "varimg" | "emoji" | "text" | "select" | "date" | "number" | "file" | "page" | "rating";
|
const QuestionPreviewComponentByType: Record<QuizQuestionType, FC<any>> = {
|
||||||
|
|
||||||
const QuestionPreviewComponentByType: Record<QuizQuestionType, FC<{ question: Question; }>> = {
|
|
||||||
variant: Variant,
|
variant: Variant,
|
||||||
images: Images,
|
images: Images,
|
||||||
varimg: Varimg,
|
varimg: Varimg,
|
||||||
@ -38,11 +37,12 @@ export default function QuizPreviewLayout() {
|
|||||||
const listQuestions = questionStore(state => state.listQuestions);
|
const listQuestions = questionStore(state => state.listQuestions);
|
||||||
const currentQuizStep = useQuizPreviewStore(state => state.currentQuestionIndex);
|
const currentQuizStep = useQuizPreviewStore(state => state.currentQuestionIndex);
|
||||||
|
|
||||||
const quizQuestions: Question[] | undefined = listQuestions[quizId];
|
const quizQuestions: AnyQuizQuestion[] | undefined = listQuestions[quizId];
|
||||||
const maxCurrentQuizStep = quizQuestions?.length > 0 ? quizQuestions.length - 1 : 0;
|
const nonDeletedQuizQuestions = quizQuestions?.filter(question => !question.deleted);
|
||||||
|
const maxCurrentQuizStep = nonDeletedQuizQuestions?.length > 0 ? nonDeletedQuizQuestions.length - 1 : 0;
|
||||||
const currentProgress = Math.floor((currentQuizStep / maxCurrentQuizStep) * 100);
|
const currentProgress = Math.floor((currentQuizStep / maxCurrentQuizStep) * 100);
|
||||||
|
|
||||||
const currentQuestion = quizQuestions[currentQuizStep];
|
const currentQuestion = nonDeletedQuizQuestions[currentQuizStep];
|
||||||
const QuestionComponent = currentQuestion
|
const QuestionComponent = currentQuestion
|
||||||
? QuestionPreviewComponentByType[currentQuestion.type as QuizQuestionType]
|
? QuestionPreviewComponentByType[currentQuestion.type as QuizQuestionType]
|
||||||
: null;
|
: null;
|
||||||
@ -88,12 +88,12 @@ export default function QuizPreviewLayout() {
|
|||||||
gap: 1,
|
gap: 1,
|
||||||
}}>
|
}}>
|
||||||
<Typography>
|
<Typography>
|
||||||
{quizQuestions.length > 0
|
{nonDeletedQuizQuestions.length > 0
|
||||||
? `Вопрос ${currentQuizStep + 1} из ${quizQuestions.length}`
|
? `Вопрос ${currentQuizStep + 1} из ${nonDeletedQuizQuestions.length}`
|
||||||
: "Нет вопросов"
|
: "Нет вопросов"
|
||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
{quizQuestions.length > 0 &&
|
{nonDeletedQuizQuestions.length > 0 &&
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
variant="determinate"
|
variant="determinate"
|
||||||
value={currentProgress}
|
value={currentProgress}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
|
||||||
import LabeledDatePicker from "@ui_kit/LabeledDatePicker";
|
import LabeledDatePicker from "@ui_kit/LabeledDatePicker";
|
||||||
|
import { QuizQuestionDate } from "model/questionTypes/date";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Date({ question }: Props) {
|
export default function Date({ question }: Props) {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import InfoIcon from "@icons/InfoIcon";
|
import InfoIcon from "@icons/InfoIcon";
|
||||||
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionEmoji } from "model/questionTypes/emoji";
|
||||||
import { useState, ChangeEvent } from "react";
|
import { useState, ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionEmoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Emoji({ question }: Props) {
|
export default function Emoji({ question }: Props) {
|
||||||
@ -26,7 +26,7 @@ export default function Emoji({ question }: Props) {
|
|||||||
{question.content.variants.map((variant, index) => (
|
{question.content.variants.map((variant, index) => (
|
||||||
<FormControlLabel key={index} value={variant.answer} control={<Radio />} label={
|
<FormControlLabel key={index} value={variant.answer} control={<Radio />} label={
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||||
<Typography>{`${variant.emoji} ${variant.answer}`}</Typography>
|
<Typography>{`${variant.extendedText} ${variant.answer}`}</Typography>
|
||||||
<Tooltip title={variant.hints} placement="right">
|
<Tooltip title={variant.hints} placement="right">
|
||||||
<Box><InfoIcon /></Box>
|
<Box><InfoIcon /></Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { Box, Button, Typography } from "@mui/material";
|
import { Box, Button, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionFile } from "model/questionTypes/file";
|
||||||
import { ChangeEvent, useRef, useState } from "react";
|
import { ChangeEvent, useRef, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function File({ question }: Props) {
|
export default function File({ question }: Props) {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import InfoIcon from "@icons/InfoIcon";
|
import InfoIcon from "@icons/InfoIcon";
|
||||||
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionImages } from "model/questionTypes/images";
|
||||||
import { ChangeEvent, useState } from "react";
|
import { ChangeEvent, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Images({ question }: Props) {
|
export default function Images({ question }: Props) {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
|
||||||
import { CustomSlider } from "@ui_kit/CustomSlider";
|
import { CustomSlider } from "@ui_kit/CustomSlider";
|
||||||
|
import { QuizQuestionNumber } from "model/questionTypes/number";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Number({ question }: Props) {
|
export default function Number({ question }: Props) {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionPage } from "model/questionTypes/page";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Page({ question }: Props) {
|
export default function Page({ question }: Props) {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import FlagIcon from "../../../assets/icons/questionsPage/FlagIcon";
|
import FlagIcon from "../../../assets/icons/questionsPage/FlagIcon";
|
||||||
import StarIconMini from "../../../assets/icons/questionsPage/StarIconMini";
|
import StarIconMini from "../../../assets/icons/questionsPage/StarIconMini";
|
||||||
@ -8,6 +7,7 @@ import HeartIcon from "../../../assets/icons/questionsPage/heartIcon";
|
|||||||
import LightbulbIcon from "../../../assets/icons/questionsPage/lightbulbIcon";
|
import LightbulbIcon from "../../../assets/icons/questionsPage/lightbulbIcon";
|
||||||
import LikeIcon from "../../../assets/icons/questionsPage/likeIcon";
|
import LikeIcon from "../../../assets/icons/questionsPage/likeIcon";
|
||||||
import TropfyIcon from "../../../assets/icons/questionsPage/tropfyIcon";
|
import TropfyIcon from "../../../assets/icons/questionsPage/tropfyIcon";
|
||||||
|
import { QuizQuestionRating } from "model/questionTypes/rating";
|
||||||
|
|
||||||
|
|
||||||
type RatingIconType = "star" | "trophie" | "flag" | "heart" | "like" | "bubble" | "hashtag";
|
type RatingIconType = "star" | "trophie" | "flag" | "heart" | "like" | "bubble" | "hashtag";
|
||||||
@ -23,7 +23,7 @@ const ratingIconComponentByType: Record<RatingIconType, FC<{ color: string; }>>
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionRating;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Rating({ question }: Props) {
|
export default function Rating({ question }: Props) {
|
||||||
@ -31,6 +31,8 @@ export default function Rating({ question }: Props) {
|
|||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const [selectedRating, setSelectedRating] = useState<number>(0);
|
const [selectedRating, setSelectedRating] = useState<number>(0);
|
||||||
|
|
||||||
|
console.log(question);
|
||||||
|
|
||||||
const RatingIconComponent = ratingIconComponentByType[question.content.form as RatingIconType];
|
const RatingIconComponent = ratingIconComponentByType[question.content.form as RatingIconType];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -42,32 +44,47 @@ export default function Rating({ question }: Props) {
|
|||||||
<Typography variant="h6">{question.title}</Typography>
|
<Typography variant="h6">{question.title}</Typography>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
gap: isMobile ? "10px" : "15px",
|
flexDirection: "column",
|
||||||
flexWrap: "wrap",
|
gap: 1,
|
||||||
|
width: "fit-content",
|
||||||
}}>
|
}}>
|
||||||
{Array.from(
|
<Box sx={{
|
||||||
{ length: question.content.steps },
|
display: "flex",
|
||||||
(_, index) => index
|
gap: isMobile ? "10px" : "15px",
|
||||||
).map((itemNumber) => (
|
flexWrap: "wrap",
|
||||||
<Box
|
}}>
|
||||||
key={itemNumber}
|
{Array.from(
|
||||||
onClick={() => setSelectedRating(itemNumber + 1)}
|
{ length: question.content.steps },
|
||||||
sx={{
|
(_, index) => index
|
||||||
cursor: "pointer",
|
).map((itemNumber) => (
|
||||||
transform: "scale(1.5)",
|
<Box
|
||||||
":hover": {
|
key={itemNumber}
|
||||||
transform: "scale(1.7)",
|
onClick={() => setSelectedRating(itemNumber + 1)}
|
||||||
transition: "0.2s",
|
sx={{
|
||||||
},
|
cursor: "pointer",
|
||||||
}}
|
transform: "scale(1.5)",
|
||||||
>
|
":hover": {
|
||||||
<RatingIconComponent color={
|
transform: "scale(1.7)",
|
||||||
selectedRating > itemNumber
|
transition: "0.2s",
|
||||||
? theme.palette.brightPurple.main
|
},
|
||||||
: theme.palette.grey2.main
|
}}
|
||||||
} />
|
>
|
||||||
</Box>
|
<RatingIconComponent color={
|
||||||
))}
|
selectedRating > itemNumber
|
||||||
|
? theme.palette.brightPurple.main
|
||||||
|
: theme.palette.grey2.main
|
||||||
|
} />
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
<Box sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
gap: 2,
|
||||||
|
}}>
|
||||||
|
<Typography>{question.content.ratingNegativeDescription}</Typography>
|
||||||
|
<Typography>{question.content.ratingPositiveDescription}</Typography>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import ArrowDownIcon from "@icons/ArrowDownIcon";
|
import ArrowDownIcon from "@icons/ArrowDownIcon";
|
||||||
import { Box, FormControl, MenuItem, Select, SelectChangeEvent, Typography, useTheme } from "@mui/material";
|
import { Box, FormControl, MenuItem, Select, SelectChangeEvent, Typography, useTheme } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionSelect } from "model/questionTypes/select";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Text({ question }: Props) {
|
export default function Text({ question }: Props) {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
import { QuizQuestionText } from "model/questionTypes/text";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionText;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Text({ question }: Props) {
|
export default function Text({ question }: Props) {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import InfoIcon from "@icons/InfoIcon";
|
import InfoIcon from "@icons/InfoIcon";
|
||||||
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionVariant } from "model/questionTypes/variant";
|
||||||
import { ChangeEvent, useState } from "react";
|
import { ChangeEvent, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionVariant;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Variant({ question }: Props) {
|
export default function Variant({ question }: Props) {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import InfoIcon from "@icons/InfoIcon";
|
import InfoIcon from "@icons/InfoIcon";
|
||||||
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
import { Box, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Tooltip, Typography } from "@mui/material";
|
||||||
import { Question } from "@root/questions";
|
import { QuizQuestionVarImg } from "model/questionTypes/varimg";
|
||||||
import { useState, ChangeEvent } from "react";
|
import { useState, ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: Question;
|
question: QuizQuestionVarImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Varimg({ question }: Props) {
|
export default function Varimg({ question }: Props) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user