2023-11-14 20:15:52 +00:00
|
|
|
import { CrossedEyeIcon } from "@icons/CrossedEyeIcon";
|
|
|
|
import { ArrowDownIcon } from "@icons/questionsPage/ArrowDownIcon";
|
|
|
|
import { CopyIcon } from "@icons/questionsPage/CopyIcon";
|
2023-09-25 13:43:15 +00:00
|
|
|
import { OneIcon } from "@icons/questionsPage/OneIcon";
|
|
|
|
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
2023-07-06 15:54:12 +00:00
|
|
|
import Answer from "@icons/questionsPage/answer";
|
|
|
|
import Date from "@icons/questionsPage/date";
|
2023-11-14 20:15:52 +00:00
|
|
|
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
2023-07-06 15:54:12 +00:00
|
|
|
import Download from "@icons/questionsPage/download";
|
2023-11-14 20:15:52 +00:00
|
|
|
import DropDown from "@icons/questionsPage/drop_down";
|
|
|
|
import Emoji from "@icons/questionsPage/emoji";
|
|
|
|
import { HideIcon } from "@icons/questionsPage/hideIcon";
|
|
|
|
import Input from "@icons/questionsPage/input";
|
|
|
|
import OptionsAndPict from "@icons/questionsPage/options_and_pict";
|
|
|
|
import OptionsPict from "@icons/questionsPage/options_pict";
|
2023-07-06 15:54:12 +00:00
|
|
|
import Page from "@icons/questionsPage/page";
|
|
|
|
import RatingIcon from "@icons/questionsPage/rating";
|
2023-11-14 20:15:52 +00:00
|
|
|
import Slider from "@icons/questionsPage/slider";
|
|
|
|
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
2023-11-17 15:42:49 +00:00
|
|
|
import {
|
|
|
|
Box,
|
|
|
|
Checkbox,
|
|
|
|
FormControl,
|
|
|
|
FormControlLabel,
|
|
|
|
IconButton,
|
|
|
|
InputAdornment,
|
|
|
|
Paper,
|
|
|
|
TextField,
|
|
|
|
useMediaQuery,
|
|
|
|
useTheme,
|
|
|
|
} from "@mui/material";
|
2023-11-29 13:49:52 +00:00
|
|
|
import { copyQuestion, createUntypedQuestion, deleteQuestion, toggleExpandQuestion, updateQuestion, updateUntypedQuestion } from "@root/questions/actions";
|
2023-11-17 15:42:49 +00:00
|
|
|
import { useRef, useState } from "react";
|
2023-11-14 20:15:52 +00:00
|
|
|
import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
|
2023-11-17 15:42:49 +00:00
|
|
|
import { useDebouncedCallback } from "use-debounce";
|
2023-09-13 10:58:07 +00:00
|
|
|
import { ReactComponent as PlusIcon } from "../../../assets/icons/plus.svg";
|
2023-11-29 13:49:52 +00:00
|
|
|
import type { AnyTypedQuizQuestion, UntypedQuizQuestion } from "../../../model/questionTypes/shared";
|
2023-11-15 18:38:02 +00:00
|
|
|
import SwitchQuestionsPage from "../SwitchQuestionsPage";
|
|
|
|
import { ChooseAnswerModal } from "./ChooseAnswerModal";
|
2023-11-29 13:49:52 +00:00
|
|
|
import TypeQuestions from "../TypeQuestions";
|
|
|
|
import { QuestionType } from "@model/question/question";
|
2023-06-28 23:32:43 +00:00
|
|
|
|
2023-08-08 11:01:37 +00:00
|
|
|
|
2023-06-28 23:32:43 +00:00
|
|
|
interface Props {
|
2023-11-29 13:49:52 +00:00
|
|
|
question: AnyTypedQuizQuestion | UntypedQuizQuestion;
|
2023-11-14 20:15:52 +00:00
|
|
|
draggableProps: DraggableProvidedDragHandleProps | null | undefined;
|
|
|
|
isDragging: boolean;
|
2023-11-30 06:27:15 +00:00
|
|
|
index: number;
|
2023-06-28 23:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 06:27:15 +00:00
|
|
|
export default function QuestionsPageCard({ question, draggableProps, isDragging, index }: Props) {
|
2023-11-14 20:15:52 +00:00
|
|
|
const [plusVisible, setPlusVisible] = useState<boolean>(false);
|
|
|
|
const [open, setOpen] = useState<boolean>(false);
|
|
|
|
const theme = useTheme();
|
|
|
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
|
|
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
|
|
|
const anchorRef = useRef(null);
|
2023-11-17 15:42:49 +00:00
|
|
|
|
|
|
|
const setTitle = useDebouncedCallback((title) => {
|
2023-11-29 13:49:52 +00:00
|
|
|
const updateQuestionFn = question.type === null ? updateUntypedQuestion : updateQuestion;
|
|
|
|
|
|
|
|
updateQuestionFn(question.id, question => {
|
2023-11-17 15:42:49 +00:00
|
|
|
question.title = title;
|
|
|
|
});
|
2023-11-14 20:15:52 +00:00
|
|
|
}, 200);
|
2023-09-27 14:14:48 +00:00
|
|
|
|
2023-11-14 20:15:52 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Paper
|
|
|
|
data-cy="quiz-question-card"
|
2023-10-09 14:39:40 +00:00
|
|
|
sx={{
|
2023-11-14 20:15:52 +00:00
|
|
|
maxWidth: "796px",
|
|
|
|
width: "100%",
|
|
|
|
borderRadius: "12px",
|
|
|
|
backgroundColor: question.expanded ? "white" : "#EEE4FC",
|
|
|
|
border: question.expanded ? "none" : "1px solid #9A9AAF",
|
|
|
|
boxShadow: "0px 10px 30px #e7e7e7",
|
2023-10-09 14:39:40 +00:00
|
|
|
}}
|
2023-11-14 20:15:52 +00:00
|
|
|
>
|
|
|
|
<Box
|
|
|
|
sx={{
|
|
|
|
display: "flex",
|
|
|
|
alignItems: "center",
|
|
|
|
padding: isMobile ? "10px" : "20px 10px 20px 20px",
|
|
|
|
flexDirection: isMobile ? "column" : null,
|
|
|
|
}}
|
2023-10-09 14:39:40 +00:00
|
|
|
>
|
2023-11-14 20:15:52 +00:00
|
|
|
<FormControl
|
|
|
|
variant="standard"
|
|
|
|
sx={{
|
|
|
|
p: 0,
|
|
|
|
maxWidth: isTablet ? "549px" : "640px",
|
|
|
|
width: "100%",
|
|
|
|
marginRight: isMobile ? "0px" : "16.1px",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<TextField
|
|
|
|
defaultValue={question.title}
|
2023-11-23 19:07:57 +00:00
|
|
|
placeholder={"Заголовок вопроса"}
|
2023-11-30 06:27:15 +00:00
|
|
|
onChange={({ target }: { target: HTMLInputElement }) => setTitle(target.value)}
|
2023-11-14 20:15:52 +00:00
|
|
|
InputProps={{
|
|
|
|
startAdornment: (
|
|
|
|
<Box>
|
|
|
|
<InputAdornment
|
|
|
|
ref={anchorRef}
|
|
|
|
position="start"
|
|
|
|
sx={{ cursor: "pointer" }}
|
|
|
|
onClick={() => setOpen((isOpened) => !isOpened)}
|
|
|
|
>
|
|
|
|
{IconAndrom(question.expanded, question.type)}
|
|
|
|
</InputAdornment>
|
|
|
|
<ChooseAnswerModal
|
|
|
|
open={open}
|
|
|
|
onClose={() => setOpen(false)}
|
|
|
|
anchorRef={anchorRef}
|
|
|
|
question={question}
|
2023-11-29 13:49:52 +00:00
|
|
|
questionType={question.type}
|
2023-11-14 20:15:52 +00:00
|
|
|
/>
|
|
|
|
</Box>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
sx={{
|
|
|
|
margin: isMobile ? "10px 0" : 0,
|
|
|
|
"& .MuiInputBase-root": {
|
|
|
|
color: "#000000",
|
|
|
|
backgroundColor: question.expanded
|
|
|
|
? theme.palette.background.default
|
|
|
|
: "transparent",
|
|
|
|
height: "48px",
|
|
|
|
borderRadius: "10px",
|
|
|
|
".MuiOutlinedInput-notchedOutline": {
|
|
|
|
borderWidth: "1px !important",
|
|
|
|
border: !question.expanded ? "none" : null,
|
|
|
|
},
|
|
|
|
"& .MuiInputBase-input::placeholder": {
|
|
|
|
color: "#4D4D4D",
|
|
|
|
opacity: 0.8,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputProps={{
|
|
|
|
sx: {
|
|
|
|
fontSize: "18px",
|
|
|
|
lineHeight: "21px",
|
|
|
|
py: 0,
|
2023-11-29 13:49:52 +00:00
|
|
|
paddingLeft: question.type === null ? 0 : "18px",
|
2023-11-14 20:15:52 +00:00
|
|
|
},
|
|
|
|
"data-cy": "quiz-question-title",
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</FormControl>
|
|
|
|
<Box
|
|
|
|
sx={{
|
|
|
|
display: "flex",
|
|
|
|
alignItems: "center",
|
|
|
|
justifyContent: "flex-end",
|
|
|
|
width: isMobile ? "100%" : "auto",
|
|
|
|
position: "relative",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<IconButton
|
|
|
|
sx={{ padding: "0", margin: "5px" }}
|
|
|
|
disableRipple
|
|
|
|
data-cy="expand-question"
|
2023-11-15 18:38:02 +00:00
|
|
|
onClick={() => toggleExpandQuestion(question.id)}
|
2023-11-14 20:15:52 +00:00
|
|
|
>
|
|
|
|
{question.expanded ? (
|
|
|
|
<ArrowDownIcon
|
|
|
|
style={{
|
|
|
|
width: "18px",
|
|
|
|
color: "#4D4D4D",
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<ExpandLessIcon
|
|
|
|
sx={{
|
|
|
|
boxSizing: "border-box",
|
|
|
|
fill: theme.palette.brightPurple.main,
|
|
|
|
background: "#FFF",
|
|
|
|
borderRadius: "6px",
|
|
|
|
height: "30px",
|
|
|
|
width: "30px",
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</IconButton>
|
|
|
|
{question.expanded ? (
|
|
|
|
<></>
|
|
|
|
) : (
|
|
|
|
<Box
|
|
|
|
sx={{
|
|
|
|
display: "flex",
|
|
|
|
height: "30px",
|
|
|
|
borderRight: "solid 1px #4D4D4D",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<FormControlLabel
|
|
|
|
control={
|
|
|
|
<Checkbox
|
|
|
|
icon={
|
|
|
|
<HideIcon
|
|
|
|
style={{
|
|
|
|
boxSizing: "border-box",
|
|
|
|
color: "#7E2AEA",
|
|
|
|
background: "#FFF",
|
|
|
|
borderRadius: "6px",
|
|
|
|
height: "30px",
|
|
|
|
width: "30px",
|
|
|
|
padding: "3px",
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
checkedIcon={<CrossedEyeIcon />}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
label={""}
|
|
|
|
sx={{
|
|
|
|
color: theme.palette.grey2.main,
|
|
|
|
ml: "-9px",
|
|
|
|
mr: 0,
|
|
|
|
userSelect: "none",
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
<IconButton
|
|
|
|
sx={{ padding: "0" }}
|
2023-11-15 18:38:02 +00:00
|
|
|
onClick={() => copyQuestion(question.id, question.quizId)}
|
2023-11-14 20:15:52 +00:00
|
|
|
>
|
|
|
|
<CopyIcon
|
|
|
|
style={{ color: theme.palette.brightPurple.main }}
|
|
|
|
/>
|
|
|
|
</IconButton>
|
|
|
|
<IconButton
|
|
|
|
sx={{
|
|
|
|
cursor: "pointer",
|
|
|
|
borderRadius: "6px",
|
|
|
|
padding: "0",
|
|
|
|
margin: "0 5px 0 10px",
|
|
|
|
}}
|
2023-11-15 18:38:02 +00:00
|
|
|
onClick={() => { // TODO
|
|
|
|
// const removedId = question.id;
|
|
|
|
// if (question.deleteTimeoutId) {
|
|
|
|
// clearTimeout(question.deleteTimeoutId);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// removeQuestion(quizId, totalIndex);
|
2023-09-27 14:14:48 +00:00
|
|
|
|
2023-11-15 18:38:02 +00:00
|
|
|
// const newTimeoutId = window.setTimeout(() => {
|
|
|
|
// removeQuestionForce(quizId, removedId);
|
|
|
|
// }, 5000);
|
2023-09-27 14:14:48 +00:00
|
|
|
|
2023-11-15 18:38:02 +00:00
|
|
|
// updateQuestionsList<AnyQuizQuestion>(quizId, totalIndex, {
|
|
|
|
// ...question,
|
|
|
|
// deleteTimeoutId: newTimeoutId,
|
|
|
|
// });
|
2023-09-27 14:14:48 +00:00
|
|
|
|
2023-11-15 18:38:02 +00:00
|
|
|
deleteQuestion(question.id);
|
2023-11-14 20:15:52 +00:00
|
|
|
}}
|
2023-11-27 23:07:24 +00:00
|
|
|
data-cy="delete-question"
|
2023-11-14 20:15:52 +00:00
|
|
|
>
|
|
|
|
<DeleteIcon
|
|
|
|
style={{ color: theme.palette.brightPurple.main }}
|
|
|
|
/>
|
|
|
|
</IconButton>
|
|
|
|
</Box>
|
|
|
|
)}
|
2023-11-30 06:27:15 +00:00
|
|
|
<Box
|
2023-11-14 20:15:52 +00:00
|
|
|
style={{
|
2023-11-30 06:27:15 +00:00
|
|
|
display: "flex",
|
|
|
|
alignItems: "center",
|
|
|
|
justifyContent: "center",
|
|
|
|
height: "30px",
|
|
|
|
width: "30px",
|
2023-11-14 20:15:52 +00:00
|
|
|
marginLeft: "3px",
|
2023-11-30 06:27:15 +00:00
|
|
|
borderRadius: "50%",
|
|
|
|
fontSize: "16px",
|
|
|
|
color: question.expanded
|
|
|
|
? theme.palette.brightPurple.main
|
|
|
|
: "#FFF",
|
|
|
|
background: question.expanded
|
2023-11-14 20:15:52 +00:00
|
|
|
? "#EEE4FC"
|
|
|
|
: theme.palette.brightPurple.main,
|
|
|
|
}}
|
2023-11-30 06:27:15 +00:00
|
|
|
>
|
|
|
|
{index + 1}
|
|
|
|
</Box>
|
2023-11-14 20:15:52 +00:00
|
|
|
<IconButton
|
|
|
|
disableRipple
|
|
|
|
sx={{
|
|
|
|
padding: isMobile ? "0" : "0 5px",
|
|
|
|
right: isMobile ? "0" : null,
|
|
|
|
bottom: isMobile ? "0" : null,
|
|
|
|
}}
|
|
|
|
{...draggableProps}
|
|
|
|
>
|
|
|
|
<PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
|
|
|
|
</IconButton>
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
{question.expanded && (
|
|
|
|
<Box
|
|
|
|
sx={{
|
|
|
|
display: "flex",
|
|
|
|
flexDirection: "column",
|
|
|
|
padding: 0,
|
|
|
|
borderRadius: "12px",
|
|
|
|
}}
|
|
|
|
>
|
2023-11-29 13:49:52 +00:00
|
|
|
{question.type === null ? (
|
2023-11-14 20:15:52 +00:00
|
|
|
<TypeQuestions question={question} />
|
2023-11-29 13:49:52 +00:00
|
|
|
) : (
|
|
|
|
<SwitchQuestionsPage question={question} />
|
|
|
|
)}
|
2023-11-14 20:15:52 +00:00
|
|
|
</Box>
|
|
|
|
)}
|
|
|
|
</Paper>
|
|
|
|
<Box
|
|
|
|
onMouseEnter={() => setPlusVisible(true)}
|
|
|
|
onMouseLeave={() => setPlusVisible(false)}
|
|
|
|
sx={{
|
|
|
|
maxWidth: "825px",
|
|
|
|
display: "flex",
|
|
|
|
alignItems: "center",
|
|
|
|
height: "40px",
|
|
|
|
cursor: "pointer",
|
|
|
|
}}
|
2023-09-15 12:37:12 +00:00
|
|
|
>
|
2023-11-14 20:15:52 +00:00
|
|
|
<Box
|
2023-11-29 13:49:52 +00:00
|
|
|
onClick={() => createUntypedQuestion(question.quizId)}
|
2023-11-14 20:15:52 +00:00
|
|
|
sx={{
|
|
|
|
display: plusVisible && !isDragging ? "flex" : "none",
|
|
|
|
width: "100%",
|
|
|
|
alignItems: "center",
|
|
|
|
columnGap: "10px",
|
|
|
|
}}
|
2023-11-27 23:07:24 +00:00
|
|
|
data-cy="create-question"
|
2023-11-14 20:15:52 +00:00
|
|
|
>
|
|
|
|
<Box
|
|
|
|
sx={{
|
|
|
|
boxSizing: "border-box",
|
|
|
|
width: "100%",
|
|
|
|
height: "1px",
|
|
|
|
backgroundPosition: "bottom",
|
|
|
|
backgroundRepeat: "repeat-x",
|
|
|
|
backgroundSize: "20px 1px",
|
|
|
|
backgroundImage:
|
|
|
|
"radial-gradient(circle, #7E2AEA 6px, #F2F3F7 1px)",
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
<PlusIcon />
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
</>
|
|
|
|
);
|
2023-08-08 11:01:37 +00:00
|
|
|
}
|
2023-11-14 20:15:52 +00:00
|
|
|
|
2023-11-29 13:49:52 +00:00
|
|
|
const IconAndrom = (isExpanded: boolean, questionType: QuestionType | null) => {
|
|
|
|
switch (questionType) {
|
2023-11-14 20:15:52 +00:00
|
|
|
case "variant":
|
|
|
|
return (
|
|
|
|
<Answer
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "images":
|
|
|
|
return (
|
|
|
|
<OptionsPict
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "varimg":
|
|
|
|
return (
|
|
|
|
<OptionsAndPict
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "emoji":
|
|
|
|
return (
|
|
|
|
<Emoji
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "text":
|
|
|
|
return (
|
|
|
|
<Input
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "select":
|
|
|
|
return (
|
|
|
|
<DropDown
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "date":
|
|
|
|
return (
|
|
|
|
<Date
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "number":
|
|
|
|
return (
|
|
|
|
<Slider
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "file":
|
|
|
|
return (
|
|
|
|
<Download
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "page":
|
|
|
|
return (
|
|
|
|
<Page
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
case "rating":
|
|
|
|
return (
|
|
|
|
<RatingIcon
|
|
|
|
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
|
|
sx={{ height: "22px", width: "20px" }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
default:
|
|
|
|
return <></>;
|
|
|
|
}
|
|
|
|
};
|