feat: questions store new logic

This commit is contained in:
IlyaDoronin 2023-09-06 16:20:12 +03:00
parent 015717cc0c
commit 4a58ef2bfc
34 changed files with 470 additions and 332 deletions

@ -6,17 +6,14 @@ import "./index.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import lightTheme from "./utils/themes/light";
import { ThemeProvider } from "@mui/material";
import HorizontalLinearStepper from "./ui_kit/Stepper";
import StartPage from "./pages/startPage/StartPage";
import Main from "./pages/main";
import FirstQuiz from "./pages/createQuize/FirstQuiz";
import QuestionsPage from "./pages/Questions/QuestionsPage";
import ContactFormPage from "./pages/ContactFormPage/ContactFormPage";
import InstallQuiz from "./pages/InstallQuiz/InstallQuiz";
import { Result } from "./pages/Result/Result";
import { Setting } from "./pages/Result/Setting";
import MyQuizzes from "./pages/createQuize/MyQuizzes";
import MyQuizzesFull from "./pages/createQuize/MyQuizzesFull";
import ImageCrop from "@ui_kit/Modal/ImageCrop";

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Draggable } from "react-beautiful-dnd";
import {
Box,
@ -36,6 +37,7 @@ export const AnswerItem = ({
variant,
icon,
}: AnswerItemProps) => {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
@ -55,8 +57,11 @@ export const AnswerItem = ({
const answerNew = variants.slice();
answerNew[index].answer = event.target.value;
updateQuestionsList(totalIndex, {
content: { ...listQuestions[totalIndex].content, variants: answerNew },
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});
};
@ -64,8 +69,11 @@ export const AnswerItem = ({
const answerNew = variants.slice();
answerNew.push({ answer: "", answerLong: "", hints: "" });
updateQuestionsList(totalIndex, {
content: { ...listQuestions[totalIndex].content, variants: answerNew },
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});
};
@ -73,8 +81,11 @@ export const AnswerItem = ({
const answerNew = variants.slice();
answerNew.splice(index, 1);
updateQuestionsList(totalIndex, {
content: { ...listQuestions[totalIndex].content, variants: answerNew },
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});
};
@ -82,8 +93,11 @@ export const AnswerItem = ({
const answerNew = variants.slice();
answerNew[index].hints = event.target.value;
updateQuestionsList(totalIndex, {
content: { ...listQuestions[totalIndex].content, variants: answerNew },
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});
};

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box } from "@mui/material";
import { DragDropContext, Droppable } from "react-beautiful-dnd";
@ -22,11 +23,13 @@ export const AnswerDraggableList = ({
totalIndex,
icon,
}: AnswerDraggableListProps) => {
const quizId = Number(useParams().quizId);
const onDragEnd = ({ destination, source }: DropResult) => {
if (destination) {
const newItems = reorder(variants, source.index, destination.index);
updateVariants(totalIndex, newItems);
updateVariants(quizId, totalIndex, newItems);
}
};

@ -17,7 +17,7 @@ interface Props {
}
export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props) {
const params = Number(useParams().quizId);
const quizId = Number(useParams().quizId);
const {openedModalSettings} = questionStore()
const openedModal = () => {
resetSomeField({openedModalSettings: "open"})
@ -64,7 +64,7 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
key={title}
onClick={() => {
SSHC(value);
{myFunc()}
myFunc()
}}
sx={{
backgroundColor: switchState === value ? theme.palette.brightPurple.main : "transparent",
@ -87,7 +87,7 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
<IconButton sx={{ borderRadius: "6px", padding: "2px" }}>
<CopyIcon color={"#4D4D4D"}/>
</IconButton>
<IconButton sx={{ borderRadius: "6px", padding: "2px" }} onClick={() => removeQuestion(totalIndex)}>
<IconButton sx={{ borderRadius: "6px", padding: "2px" }} onClick={() => removeQuestion(quizId, totalIndex)}>
<DeleteIcon color={"#4D4D4D"}/>
</IconButton>
</Box>

@ -24,7 +24,7 @@ export default function ButtonsOptionsAndPict({
switchState,
totalIndex,
}: Props) {
const params = Number(useParams().quizId);
const quizId = Number(useParams().quizId);
const { openedModalSettings } = questionStore();
const theme = useTheme();
@ -181,7 +181,7 @@ export default function ButtonsOptionsAndPict({
</IconButton>
<IconButton
sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => removeQuestion(totalIndex)}
onClick={() => removeQuestion(quizId, totalIndex)}
>
<DeleteIcon color={"#4D4D4D"} />
</IconButton>

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography, useTheme } from "@mui/material";
import ButtonsOptions from "../ButtonsOptions";
import SwitchData from "./switchData";
@ -12,6 +13,7 @@ interface Props {
export default function DataOptions({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
@ -20,10 +22,10 @@ export default function DataOptions({ totalIndex }: Props) {
};
useEffect(() => {
if (listQuestions[totalIndex].content.type !== "mask") {
const clonContent = listQuestions[totalIndex].content;
if (listQuestions[quizId][totalIndex].content.type !== "mask") {
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.type = "calendar";
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}
}, []);
@ -41,21 +43,25 @@ export default function DataOptions({ totalIndex }: Props) {
>
<Box sx={{ gap: "10px", display: "flex" }}>
<SelectableButton
isSelected={listQuestions[totalIndex].content.type === "calendar"}
isSelected={
listQuestions[quizId][totalIndex].content.type === "calendar"
}
onClick={() => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.type = "calendar";
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
>
Использовать календарь
</SelectableButton>
<SelectableButton
isSelected={listQuestions[totalIndex].content.type === "mask"}
isSelected={
listQuestions[quizId][totalIndex].content.type === "mask"
}
onClick={() => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.type = "mask";
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
>
Использовать маску

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import InfoIcon from "../../../assets/icons/InfoIcon";
@ -8,6 +9,7 @@ type SettingsDataProps = {
};
export default function SettingsData({ totalIndex }: SettingsDataProps) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
return (
@ -16,20 +18,20 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
<Typography>Настройки календаря</Typography>
<CustomCheckbox
label={"Выбор диапозона дат"}
checked={listQuestions[totalIndex].content.dateRange}
checked={listQuestions[quizId][totalIndex].content.dateRange}
handleChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.dateRange = target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
<CustomCheckbox
label={"Выбор времени"}
checked={listQuestions[totalIndex].content.time}
checked={listQuestions[quizId][totalIndex].content.time}
handleChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.time = target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import {
Box,
Checkbox,
@ -133,9 +134,11 @@ export default function QuestionsPageCard({
totalIndex,
draggableProps,
}: Props) {
const quizId = Number(useParams().quizId);
const theme = useTheme();
const { listQuestions } = questionStore();
const { type: switchState, expanded: isExpanded } = listQuestions[totalIndex];
const { type: switchState, expanded: isExpanded } =
listQuestions[quizId][totalIndex];
return (
<Paper
@ -161,11 +164,13 @@ export default function QuestionsPageCard({
<FormControl fullWidth variant="standard" sx={{ p: 0 }}>
<TextField
fullWidth
value={listQuestions[totalIndex].title}
value={listQuestions[quizId][totalIndex].title}
placeholder={"Заголовок вопроса"}
onChange={(e) => {
updateQuestionsList(totalIndex, { title: e.target.value });
console.log(listQuestions[totalIndex].title);
updateQuestionsList(quizId, totalIndex, {
title: e.target.value,
});
console.log(listQuestions[quizId][totalIndex].title);
}}
InputProps={{
startAdornment: (
@ -198,7 +203,7 @@ export default function QuestionsPageCard({
<IconButton
onClick={() =>
updateQuestionsList(totalIndex, { expanded: !isExpanded })
updateQuestionsList(quizId, totalIndex, { expanded: !isExpanded })
}
>
{isExpanded ? <ExpandMoreIcon /> : <ExpandLessIcon fill="#7E2AEA" />}
@ -222,12 +227,12 @@ export default function QuestionsPageCard({
userSelect: "none",
}}
/>
<IconButton onClick={() => copyQuestion(totalIndex)}>
<IconButton onClick={() => copyQuestion(quizId, totalIndex)}>
<CopyIcon color={"white"} />
</IconButton>
<IconButton
sx={{ cursor: "pointer", borderRadius: "6px", padding: "2px" }}
onClick={() => removeQuestion(totalIndex)}
onClick={() => removeQuestion(quizId, totalIndex)}
>
<DeleteIcon color={"white"} />
</IconButton>

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box } from "@mui/material";
import { DragDropContext, Droppable } from "react-beautiful-dnd";
@ -13,6 +14,7 @@ import type { DropResult } from "react-beautiful-dnd";
export const DraggableList = () => {
const [draggableId, setDraggableId] = useState<number>(-1);
const [dropPlaceIndex, setDropPlaceIndex] = useState<number>(-1);
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const onDrop = () => {
@ -22,9 +24,13 @@ export const DraggableList = () => {
const onDragEnd = ({ destination, source }: DropResult) => {
if (destination) {
const newItems = reorder(listQuestions, source.index, destination.index);
const newItems = reorder(
listQuestions[quizId],
source.index,
destination.index
);
updateQuestionsListDragAndDrop(newItems);
updateQuestionsListDragAndDrop(quizId, newItems);
}
};
@ -43,7 +49,7 @@ export const DraggableList = () => {
{...provided.droppableProps}
onMouseUp={onDrop}
>
{listQuestions.map((_, index) => (
{listQuestions[quizId]?.map((_, index) => (
<DraggableListItem
key={index}
index={index}

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box, Typography, Link, useTheme } from "@mui/material";
import { AnswerDraggableList } from "../AnswerDraggableList";
@ -14,9 +15,10 @@ interface Props {
export default function DropDown({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
const variants = listQuestions[totalIndex].content.variants;
const variants = listQuestions[quizId][totalIndex].content.variants;
const SSHC = (data: string) => {
setSwitchState(data);
@ -26,8 +28,11 @@ export default function DropDown({ totalIndex }: Props) {
const answerNew = variants.slice();
answerNew.push({ answer: "", answerLong: "", hints: "" });
updateQuestionsList(totalIndex, {
content: { ...listQuestions[totalIndex].content, variants: answerNew },
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});
};

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import CustomTextField from "@ui_kit/CustomTextField";
@ -11,6 +12,7 @@ type SettingDropDownProps = {
};
export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
return (
@ -28,11 +30,11 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
</Typography>
<CustomTextField
placeholder={"Выберите вариант"}
text={listQuestions[totalIndex].content.default}
text={listQuestions[quizId][totalIndex].content.default}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.default = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Link, Typography, useTheme } from "@mui/material";
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
import ButtonsOptions from "../ButtonsOptions";
@ -13,6 +14,7 @@ interface Props {
export default function Emoji({ totalIndex }: Props) {
const [switchState, setSwitchState] = React.useState("setting");
const { listQuestions } = questionStore();
const quizId = Number(useParams().quizId);
const theme = useTheme();
const SSHC = (data: string) => {
@ -23,7 +25,7 @@ export default function Emoji({ totalIndex }: Props) {
<>
<Box sx={{ padding: "20px" }}>
<AnswerDraggableList
variants={listQuestions[totalIndex].content.variants}
variants={listQuestions[quizId][totalIndex].content.variants}
totalIndex={totalIndex}
icon={
<Box sx={{ margin: "0 15px 0 5px" }}>
@ -38,12 +40,12 @@ export default function Emoji({ totalIndex }: Props) {
sx={{ color: theme.palette.brightPurple.main }}
onClick={() => {
const answerNew =
listQuestions[totalIndex].content.variants.slice();
listQuestions[quizId][totalIndex].content.variants.slice();
answerNew.push({ answer: "", answerLong: "", hints: "" });
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[totalIndex].content,
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import InfoIcon from "../../../assets/icons/InfoIcon";
@ -8,6 +9,7 @@ type SettingEmojiProps = {
};
export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
return (
@ -16,20 +18,20 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
<Typography>Настройки ответов</Typography>
<CustomCheckbox
label={"Можно несколько"}
checked={listQuestions[totalIndex].content.multi}
checked={listQuestions[quizId][totalIndex].content.multi}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.multi = e.target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
<CustomCheckbox
label={'Вариант "свой ответ"'}
checked={listQuestions[totalIndex].content.own}
checked={listQuestions[quizId][totalIndex].content.own}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.own = e.target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>

@ -1,4 +1,5 @@
import { Box, Link, Typography, ButtonBase, useTheme } from "@mui/material";
import { useParams } from "react-router-dom";
import AddImage from "../../../assets/icons/questionsPage/addImage";
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
@ -13,6 +14,7 @@ interface Props {
export default function OptionsAndPicture({ totalIndex }: Props) {
const [switchState, setSwitchState] = React.useState("setting");
const { listQuestions } = questionStore();
const quizId = Number(useParams().quizId);
const theme = useTheme();
const SSHC = (data: string) => {
setSwitchState(data);
@ -22,48 +24,53 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
<>
<Box sx={{ padding: "20px" }}>
<Box sx={{ paddingBottom: "25px" }}>
{listQuestions[totalIndex].content.variants.map((_, index) => (
<ButtonBase
component="label"
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
marginBottom: "15px",
}}
>
<input
onChange={({ target }) => {
if (target.files?.length) {
const clonContent = listQuestions[totalIndex].content;
clonContent.variants[index].answer = URL.createObjectURL(
target.files[0]
);
updateQuestionsList(totalIndex, { content: clonContent });
}
}}
hidden
accept="image/*"
multiple
type="file"
/>
<AddImage />
<Typography
{listQuestions[quizId][totalIndex].content.variants.map(
(_, index) => (
<ButtonBase
component="label"
sx={{
padding: "0 0 0 20px",
fontWeight: 400,
fontSize: "18px",
lineHeight: "21.33px",
color: theme.palette.grey2.main,
cursor: "pointer",
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
marginBottom: "15px",
}}
>
Добавьте ответ
</Typography>
</ButtonBase>
))}
<input
onChange={({ target }) => {
if (target.files?.length) {
const clonContent =
listQuestions[quizId][totalIndex].content;
clonContent.variants[index].answer = URL.createObjectURL(
target.files[0]
);
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}
}}
hidden
accept="image/*"
multiple
type="file"
/>
<AddImage />
<Typography
sx={{
padding: "0 0 0 20px",
fontWeight: 400,
fontSize: "18px",
lineHeight: "21.33px",
color: theme.palette.grey2.main,
}}
>
Добавьте ответ
</Typography>
</ButtonBase>
)
)}
</Box>
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
<Link
@ -71,14 +78,14 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
variant="body2"
sx={{ color: theme.palette.brightPurple.main }}
onClick={() => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.variants.push({
answer: "",
answerLong: "",
hints: "",
});
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
>
Добавьте ответ

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box, Link, Typography, Button, useTheme } from "@mui/material";
import ButtonsOptions from "../ButtonsOptions";
@ -16,6 +17,7 @@ interface Props {
export default function OptionsPicture({ totalIndex }: Props) {
const theme = useTheme();
const quizId = Number(useParams().quizId);
const [switchState, setSwitchState] = useState("setting");
const { listQuestions } = questionStore();
@ -25,11 +27,11 @@ export default function OptionsPicture({ totalIndex }: Props) {
const addImage = ({ target }: ChangeEvent<HTMLInputElement>) => {
if (target.files?.length) {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.images.push(URL.createObjectURL(target.files[0]));
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}
};

@ -1,4 +1,5 @@
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { Box, Button, Typography, useTheme } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
@ -70,18 +71,19 @@ export function SelectIconButton({ Icon, isActive = false, onClick }: Props) {
export default function SettingOpytionsPict({
totalIndex,
}: SettingOpytionsPictProps) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
useEffect(() => {
if (!listQuestions[totalIndex].content.xy) {
if (!listQuestions[quizId][totalIndex].content.xy) {
updateProportions("1:1");
}
}, []);
const updateProportions = (proportions: string) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.xy = proportions;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
};
return (
@ -100,7 +102,9 @@ export default function SettingOpytionsPict({
<SelectIconButton
key={index}
onClick={() => updateProportions(value)}
isActive={listQuestions[totalIndex].content.xy === value}
isActive={
listQuestions[quizId][totalIndex].content.xy === value
}
Icon={icon}
/>
))}
@ -111,24 +115,25 @@ export default function SettingOpytionsPict({
<CustomCheckbox
label={"Можно несколько"}
checked={listQuestions[totalIndex].content.multi}
checked={listQuestions[quizId][totalIndex].content.multi}
handleChange={() =>
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[totalIndex].content,
multi: !listQuestions[totalIndex].content.multi,
...listQuestions[quizId][totalIndex].content,
multi: !listQuestions[quizId][totalIndex].content.multi,
},
})
}
/>
<CustomCheckbox
label={"Большие картинки"}
checked={listQuestions[totalIndex].content.largeCheck}
checked={listQuestions[quizId][totalIndex].content.largeCheck}
handleChange={() =>
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[totalIndex].content,
largeCheck: !listQuestions[totalIndex].content.largeCheck,
...listQuestions[quizId][totalIndex].content,
largeCheck:
!listQuestions[quizId][totalIndex].content.largeCheck,
},
})
}
@ -146,26 +151,30 @@ export default function SettingOpytionsPict({
>
<SelectIconButton
onClick={() =>
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[totalIndex].content,
...listQuestions[quizId][totalIndex].content,
format: "carousel",
},
})
}
isActive={listQuestions[totalIndex].content.format === "carousel"}
isActive={
listQuestions[quizId][totalIndex].content.format === "carousel"
}
Icon={FormatIcon2}
/>
<SelectIconButton
onClick={() =>
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[totalIndex].content,
...listQuestions[quizId][totalIndex].content,
format: "masonry",
},
})
}
isActive={listQuestions[totalIndex].content.format === "masonry"}
isActive={
listQuestions[quizId][totalIndex].content.format === "masonry"
}
Icon={FormatIcon1}
/>
</Box>

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box, Typography, useTheme } from "@mui/material";
import CustomTextField from "@ui_kit/CustomTextField";
@ -16,6 +17,7 @@ interface Props {
}
export default function OwnTextField({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
@ -37,11 +39,11 @@ export default function OwnTextField({ totalIndex }: Props) {
>
<CustomTextField
placeholder={"Пример ответа"}
text={listQuestions[totalIndex].content.placeholder}
text={listQuestions[quizId][totalIndex].content.placeholder}
onChange={({ target }: ChangeEvent<HTMLInputElement>) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.placeholder = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
<Box sx={{ display: "flex", alignItems: "center", gap: "12px" }}>

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import {
Box,
FormControl,
@ -32,6 +33,7 @@ export default function SettingTextField({
totalIndex,
}: SettingTextFieldProps) {
const { listQuestions } = questionStore();
const quizId = Number(useParams().quizId);
const theme = useTheme();
return (
@ -43,18 +45,18 @@ export default function SettingTextField({
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={ANSWER_TYPES.findIndex(
({ value }) => listQuestions[totalIndex].content[value]
({ value }) => listQuestions[quizId][totalIndex].content[value]
)}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
const clonContent = {
...listQuestions[totalIndex].content,
...listQuestions[quizId][totalIndex].content,
single: false,
multi: false,
number: false,
[ANSWER_TYPES[Number(target.value)].value]: true,
};
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
>
{ANSWER_TYPES.map(({ name }, index) => (

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box, Typography, useTheme } from "@mui/material";
import ButtonsOptions from "../ButtonsOptions";
import CustomTextField from "@ui_kit/CustomTextField";
@ -18,6 +19,7 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
const [openImageModal, setOpenImageModal] = useState<boolean>(false);
const [openVideoModal, setOpenVideoModal] = useState<boolean>(false);
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
@ -40,11 +42,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
<Box sx={{ display: disableInput ? "none" : "" }}>
<CustomTextField
placeholder={"Можно добавить текст"}
text={listQuestions[totalIndex].content.text}
text={listQuestions[quizId][totalIndex].content.text}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.text = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>
@ -75,9 +77,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
onClose={() => setOpenImageModal(false)}
imgHC={(fileList) => {
if (fileList?.length) {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.picture = URL.createObjectURL(fileList[0]);
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}
}}
/>
@ -106,11 +110,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
<UploadVideoModal
open={openVideoModal}
onClose={() => setOpenVideoModal(false)}
video={listQuestions[totalIndex].content.video}
video={listQuestions[quizId][totalIndex].content.video}
onUpload={(url) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.video = url;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>

@ -25,7 +25,7 @@ export default function QuestionsPage() {
const collapseEverything = () => {
listQuestions[quizId].forEach((item, index) => {
updateQuestionsList(quizId, { ...item, expanded: false });
updateQuestionsList(quizId, index, { ...item, expanded: false });
});
};

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box, Typography, useTheme } from "@mui/material";
import ButtonsOptions from "../ButtonsOptions";
import Rating from "@mui/material/Rating";
@ -12,6 +13,7 @@ interface Props {
export default function RatingOptions({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
@ -33,7 +35,7 @@ export default function RatingOptions({ totalIndex }: Props) {
>
<Rating
name="customized-color"
defaultValue={listQuestions[totalIndex].content.starts}
defaultValue={listQuestions[quizId][totalIndex].content.starts}
getLabelText={(value: number) =>
`${value} Heart${value !== 1 ? "s" : ""}`
}
@ -42,9 +44,9 @@ export default function RatingOptions({ totalIndex }: Props) {
emptyIcon={<RatingStar color={"#9A9AAF"} />}
sx={{ display: "flex", gap: "15px" }}
onChange={(_, value) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.starts = value || 0;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
<Box

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, ButtonBase, Slider, Typography, useTheme } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
@ -22,6 +23,7 @@ type ButtonRatingFrom = {
};
export default function SettingSlider({ totalIndex }: SettingSliderProps) {
const quizId = Number(useParams().quizId);
const theme = useTheme();
const { listQuestions } = questionStore();
@ -58,17 +60,19 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
<ButtonBase
key={index}
onClick={() => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.form = name;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
sx={{
backgroundColor:
listQuestions[totalIndex].content.form === name
listQuestions[quizId][totalIndex].content.form === name
? theme.palette.brightPurple.main
: "transparent",
color:
listQuestions[totalIndex].content.form === name
listQuestions[quizId][totalIndex].content.form === name
? "#ffffff"
: theme.palette.grey3.main,
width: "40px",
@ -90,16 +94,16 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
Количество
</Typography>
<Slider
value={listQuestions[totalIndex].content.steps}
value={listQuestions[quizId][totalIndex].content.steps}
min={1}
max={10}
aria-label="Default"
valueLabelDisplay="auto"
sx={{ color: theme.palette.brightPurple.main }}
onChange={(_, value) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.steps = Number(value) || 1;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>

@ -1,4 +1,5 @@
import { Box, Typography, useTheme } from "@mui/material";
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import ButtonsOptions from "../ButtonsOptions";
import React from "react";
import CustomTextField from "@ui_kit/CustomTextField";
@ -11,8 +12,9 @@ interface Props {
export default function SliderOptions({ totalIndex }: Props) {
const [switchState, setSwitchState] = React.useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
const SSHC = (data: string) => {
setSwitchState(data);
};
@ -34,25 +36,33 @@ export default function SliderOptions({ totalIndex }: Props) {
<Box sx={{ display: "flex", alignItems: "center", gap: "20px" }}>
<CustomTextField
placeholder={"0"}
text={listQuestions[totalIndex].content.range.split("—")[0]}
text={
listQuestions[quizId][totalIndex].content.range.split("—")[0]
}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.range = `${target.value}${
listQuestions[totalIndex].content.range.split("—")[1]
listQuestions[quizId][totalIndex].content.range.split("—")[1]
}`;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
/>
<Typography></Typography>
<CustomTextField
placeholder={"100"}
text={listQuestions[totalIndex].content.range.split("—")[1]}
text={
listQuestions[quizId][totalIndex].content.range.split("—")[1]
}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.range = `${
listQuestions[totalIndex].content.range.split("—")[0]
listQuestions[quizId][totalIndex].content.range.split("—")[0]
}${target.value}`;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
/>
</Box>
@ -68,11 +78,13 @@ export default function SliderOptions({ totalIndex }: Props) {
<Typography>Начальное значение</Typography>
<CustomTextField
placeholder={"50"}
text={String(listQuestions[totalIndex].content.start)}
text={String(listQuestions[quizId][totalIndex].content.start)}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.start = Number(target.value);
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
/>
</Box>
@ -80,11 +92,13 @@ export default function SliderOptions({ totalIndex }: Props) {
<Typography>Шаг</Typography>
<CustomTextField
placeholder={"1"}
text={String(listQuestions[totalIndex].content.step)}
text={String(listQuestions[quizId][totalIndex].content.step)}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.step = Number(target.value);
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
/>
</Box>

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import InfoIcon from "../../../assets/icons/InfoIcon";
@ -8,6 +9,7 @@ type SettingSliderProps = {
};
export default function SettingSlider({ totalIndex }: SettingSliderProps) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
return (
@ -16,11 +18,11 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
<Typography>Настройки ползунка</Typography>
<CustomCheckbox
label={"Выбор диапозона (два ползунка)"}
checked={listQuestions[totalIndex].content.chooseRange}
checked={listQuestions[quizId][totalIndex].content.chooseRange}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.chooseRange = e.target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>

@ -19,9 +19,10 @@ interface Props {
}
export default function SwitchQuestionsPage({ totalIndex }: Props) {
const params = Number(useParams().quizId);
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const switchState = listQuestions[totalIndex].type;
const switchState = listQuestions[quizId][totalIndex].type;
switch (switchState) {
case "variant":
return <AnswerOptions totalIndex={totalIndex} />;

@ -10,91 +10,101 @@ import Slider from "../../assets/icons/questionsPage/slider";
import Download from "../../assets/icons/questionsPage/download";
import Page from "../../assets/icons/questionsPage/page";
import RatingIcon from "../../assets/icons/questionsPage/rating";
import {Box, useTheme} from "@mui/material";
import { Box, useTheme } from "@mui/material";
import React from "react";
import {useParams} from "react-router-dom";
import {questionStore, updateQuestionsList} from "@root/questions";
import { useParams } from "react-router-dom";
import { questionStore, updateQuestionsList } from "@root/questions";
interface Props {
totalIndex: number
totalIndex: number;
}
export default function TypeQuestions({totalIndex }: Props) {
const theme = useTheme()
const params = Number(useParams().quizId);
const {listQuestions} = questionStore()
const switchState = listQuestions[totalIndex].type
const buttonTypeQuestions: { icon: JSX.Element; title: string; value: string }[] = [
{
icon: <Answer color={theme.palette.grey2.main}/>,
title: 'Варианты ответов',
value: 'variant',
},
{
icon: <OptionsPict color={theme.palette.grey2.main}/>,
title: 'Варианты с картинками',
value: 'images',
},
{
icon: <OptionsAndPict color={theme.palette.grey2.main}/>,
title: 'Варианты и картинка',
value: 'varimg',
},
{
icon: <Emoji color={theme.palette.grey2.main}/>,
title: 'Эмоджи',
value: 'emoji',
},
{
icon: <Input color={theme.palette.grey2.main}/>,
title: 'Своё поле для ввода',
value: 'text',
},
{
icon: <DropDown color={theme.palette.grey2.main}/>,
title: 'Выпадающий список',
value: 'select',
},
{
icon: <Date color={theme.palette.grey2.main}/>,
title: 'Дата',
value: 'date',
},
{
icon: <Slider color={theme.palette.grey2.main}/>,
title: 'Ползунок',
value: 'number',
},
{
icon: <Download color={theme.palette.grey2.main}/>,
title: 'Загрузка файла',
value: 'file',
},
{
icon: <Page color={theme.palette.grey2.main}/>,
title: 'Страница',
value: 'page',
},
{
icon: <RatingIcon color={theme.palette.grey2.main}/>,
title: 'Рейтинг',
value: 'rating',
},
];
return (
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: '20px', padding: '8px 20px 20px'}}>
{buttonTypeQuestions.map(({ icon, title, value }) => (
<QuestionsMiniButton
key={title}
onClick={() => {
console.log(value)
updateQuestionsList(totalIndex, {type: value})
}}
icon={icon}
text={title}
/>
))}
</Box>
)
export default function TypeQuestions({ totalIndex }: Props) {
const theme = useTheme();
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const switchState = listQuestions[quizId][totalIndex].type;
const buttonTypeQuestions: {
icon: JSX.Element;
title: string;
value: string;
}[] = [
{
icon: <Answer color={theme.palette.grey2.main} />,
title: "Варианты ответов",
value: "variant",
},
{
icon: <OptionsPict color={theme.palette.grey2.main} />,
title: "Варианты с картинками",
value: "images",
},
{
icon: <OptionsAndPict color={theme.palette.grey2.main} />,
title: "Варианты и картинка",
value: "varimg",
},
{
icon: <Emoji color={theme.palette.grey2.main} />,
title: "Эмоджи",
value: "emoji",
},
{
icon: <Input color={theme.palette.grey2.main} />,
title: "Своё поле для ввода",
value: "text",
},
{
icon: <DropDown color={theme.palette.grey2.main} />,
title: "Выпадающий список",
value: "select",
},
{
icon: <Date color={theme.palette.grey2.main} />,
title: "Дата",
value: "date",
},
{
icon: <Slider color={theme.palette.grey2.main} />,
title: "Ползунок",
value: "number",
},
{
icon: <Download color={theme.palette.grey2.main} />,
title: "Загрузка файла",
value: "file",
},
{
icon: <Page color={theme.palette.grey2.main} />,
title: "Страница",
value: "page",
},
{
icon: <RatingIcon color={theme.palette.grey2.main} />,
title: "Рейтинг",
value: "rating",
},
];
return (
<Box
sx={{
display: "flex",
flexWrap: "wrap",
gap: "20px",
padding: "8px 20px 20px",
}}
>
{buttonTypeQuestions.map(({ icon, title, value }) => (
<QuestionsMiniButton
key={title}
onClick={() => {
console.log(value);
updateQuestionsList(quizId, totalIndex, { type: value });
}}
icon={icon}
text={title}
/>
))}
</Box>
);
}

@ -1,4 +1,5 @@
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import {
Box,
FormControl,
@ -30,6 +31,7 @@ const DESIGN_TYPES = [
export default function UploadFile({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const theme = useTheme();
@ -38,20 +40,20 @@ export default function UploadFile({ totalIndex }: Props) {
};
const handleChange = ({ target }: SelectChangeEvent) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.type = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
};
useEffect(() => {
const isTypeSetted = DESIGN_TYPES.find(
({ value }) => value === listQuestions[totalIndex].content.type
({ value }) => value === listQuestions[quizId][totalIndex].content.type
);
if (!isTypeSetted) {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.type = DESIGN_TYPES[0].value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}
}, []);
@ -80,7 +82,7 @@ export default function UploadFile({ totalIndex }: Props) {
<Select
id="category-select"
variant="outlined"
value={listQuestions[totalIndex].content.type}
value={listQuestions[quizId][totalIndex].content.type}
displayEmpty
onChange={handleChange}
sx={{

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
@ -10,6 +11,7 @@ type SettingsUploadProps = {
};
export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
return (
@ -17,11 +19,11 @@ export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
<Typography>Настройки вопроса</Typography>
<CustomCheckbox
label={"Автозаполнение адреса"}
checked={listQuestions[totalIndex].content.autofill}
checked={listQuestions[quizId][totalIndex].content.autofill}
handleChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.autofill = target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
<CustomCheckbox label={"Необязательный вопрос"} />

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { useState } from "react";
import { Typography, Box, useTheme, ButtonBase } from "@mui/material";
import UploadBox from "@ui_kit/UploadBox";
@ -14,6 +15,7 @@ type UploadImageProps = {
};
export default function UploadImage({ totalIndex }: UploadImageProps) {
const quizId = Number(useParams().quizId);
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const { listQuestions } = questionStore();
@ -24,9 +26,9 @@ export default function UploadImage({ totalIndex }: UploadImageProps) {
if (files?.length) {
const [file] = Array.from(files);
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.back = URL.createObjectURL(file);
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
handleClose();
setOpened(true);
@ -68,7 +70,7 @@ export default function UploadImage({ totalIndex }: UploadImageProps) {
<CroppingModal
opened={opened}
onClose={() => setOpened(false)}
picture={listQuestions[totalIndex].content.back}
picture={listQuestions[quizId][totalIndex].content.back}
/>
</Box>
);

@ -1,4 +1,5 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { Box, Typography, Link, useTheme } from "@mui/material";
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
import SwitchAnswerOptions from "./switchAnswerOptions";
@ -14,8 +15,9 @@ interface Props {
export default function AnswerOptions({ totalIndex }: Props) {
const [switchState, setSwitchState] = useState("setting");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const variants = listQuestions[totalIndex].content.variants;
const variants = listQuestions[quizId][totalIndex].content.variants;
const theme = useTheme();
const SSHC = (data: string) => {
@ -26,8 +28,11 @@ export default function AnswerOptions({ totalIndex }: Props) {
const answerNew = variants.slice(); // Create a shallow copy of the array
answerNew.push({ answer: "", answerLong: "", hints: "" });
updateQuestionsList(totalIndex, {
content: { ...listQuestions[totalIndex].content, variants: answerNew },
updateQuestionsList(quizId, totalIndex, {
content: {
...listQuestions[quizId][totalIndex].content,
variants: answerNew,
},
});
};

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import { Box, Typography } from "@mui/material";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import InfoIcon from "../../../assets/icons/InfoIcon";
@ -9,6 +10,7 @@ interface Props {
}
export default function ResponseSettings({ totalIndex }: Props) {
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
return (
@ -17,45 +19,45 @@ export default function ResponseSettings({ totalIndex }: Props) {
<Typography>Настройки ответов</Typography>
<CustomCheckbox
label={"Длинный текстовый ответ"}
checked={listQuestions[totalIndex].content.largeCheck}
checked={listQuestions[quizId][totalIndex].content.largeCheck}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.largeCheck = e.target.checked;
if (!e.target.checked) {
clonContent.large = "";
}
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
{listQuestions[totalIndex].content.largeCheck && (
{listQuestions[quizId][totalIndex].content.largeCheck && (
<CustomTextField
placeholder={"Развёрнутый ответ"}
text={listQuestions[totalIndex].content.large}
text={listQuestions[quizId][totalIndex].content.large}
onChange={({ target }) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.large = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
)}
<CustomCheckbox
label={"Можно несколько"}
checked={listQuestions[totalIndex].content.multi}
checked={listQuestions[quizId][totalIndex].content.multi}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.multi = e.target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
<CustomCheckbox
label={'Вариант "свой ответ"'}
checked={listQuestions[totalIndex].content.own}
checked={listQuestions[quizId][totalIndex].content.own}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.own = e.target.checked;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</Box>
@ -63,36 +65,38 @@ export default function ResponseSettings({ totalIndex }: Props) {
<Typography>Настройки вопросов</Typography>
<CustomCheckbox
label={"Необязательный вопрос"}
checked={!listQuestions[totalIndex].required}
checked={!listQuestions[quizId][totalIndex].required}
handleChange={(e) => {
updateQuestionsList(totalIndex, { required: !e.target.checked });
updateQuestionsList(quizId, totalIndex, {
required: !e.target.checked,
});
}}
/>
<Box sx={{ display: "flex" }}>
<CustomCheckbox
label={"Внутреннее название вопроса"}
checked={listQuestions[totalIndex].content.innerNameCheck}
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
handleChange={(e) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.innerNameCheck = e.target.checked;
if (!e.target.checked) {
clonContent.innerName = "";
}
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>{" "}
<InfoIcon />
</Box>
{listQuestions[totalIndex].content.innerNameCheck && (
{listQuestions[quizId][totalIndex].content.innerNameCheck && (
<CustomTextField
placeholder={"Развёрнутое описание вопроса"}
text={listQuestions[totalIndex].content.innerName}
text={listQuestions[quizId][totalIndex].content.innerName}
onChange={({ target }) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.innerName = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
)}

@ -1,3 +1,4 @@
import { useParams } from "react-router-dom";
import {
Box,
Button,
@ -39,6 +40,7 @@ const CONDITIONS = [
export default function BranchingQuestions({
totalIndex,
}: BranchingQuestionsProps) {
const quizId = Number(useParams().quizId);
const { openedModalSettings, listQuestions } = questionStore();
const theme = useTheme();
@ -99,20 +101,22 @@ export default function BranchingQuestions({
<Select
items={ACTIONS}
activeItemIndex={
listQuestions[totalIndex].content.rule.show ? 0 : 1
listQuestions[quizId][totalIndex].content.rule.show ? 0 : 1
}
sx={{ maxWidth: "140px" }}
onChange={(action) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.rule.show = action === ACTIONS[0];
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
/>
<Typography sx={{ color: theme.palette.grey2.main }}>
если в ответе на вопрос
</Typography>
</Box>
{listQuestions[totalIndex].content.rule.reqs.map(
{listQuestions[quizId][totalIndex].content.rule.reqs.map(
(request, index) => (
<Box
key={index}
@ -137,10 +141,11 @@ export default function BranchingQuestions({
<IconButton
sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => {
const clonContent = listQuestions[totalIndex].content;
const clonContent =
listQuestions[quizId][totalIndex].content;
clonContent.rule.reqs.splice(index, 1);
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
@ -153,7 +158,8 @@ export default function BranchingQuestions({
activeItemIndex={request.id ? Number(request.id) : -1}
items={STIPULATIONS}
onChange={(stipulation) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent =
listQuestions[quizId][totalIndex].content;
clonContent.rule.reqs[index] = {
id: String(
@ -164,7 +170,9 @@ export default function BranchingQuestions({
vars: request.vars,
};
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
sx={{ marginBottom: "15px" }}
/>
@ -191,7 +199,8 @@ export default function BranchingQuestions({
activeItemIndex={-1}
items={ANSWERS}
onChange={(answer) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent =
listQuestions[quizId][totalIndex].content;
const answerItemIndex = ANSWERS.findIndex(
(answerItem) => answerItem === answer
);
@ -201,12 +210,12 @@ export default function BranchingQuestions({
answerItemIndex
)
) {
listQuestions[totalIndex].content.rule.reqs[
listQuestions[quizId][totalIndex].content.rule.reqs[
index
].vars.push(answerItemIndex);
}
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
@ -223,7 +232,7 @@ export default function BranchingQuestions({
gap: "10px",
}}
>
{listQuestions[totalIndex].content.rule.reqs[
{listQuestions[quizId][totalIndex].content.rule.reqs[
index
].vars.map((item, varIndex) => (
<Chip
@ -232,7 +241,7 @@ export default function BranchingQuestions({
variant="outlined"
onDelete={() => {
const clonContent =
listQuestions[totalIndex].content;
listQuestions[quizId][totalIndex].content;
const removedItemIndex = clonContent.rule.reqs[
index
].vars.findIndex((varItem) => varItem === item);
@ -242,7 +251,7 @@ export default function BranchingQuestions({
1
);
updateQuestionsList(totalIndex, {
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
@ -268,9 +277,11 @@ export default function BranchingQuestions({
marginBottom: "10px",
}}
onClick={() => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.rule.reqs.push({ id: "", vars: [] });
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
>
Добавить условие
@ -279,12 +290,15 @@ export default function BranchingQuestions({
<RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group"
defaultValue={
listQuestions[totalIndex].content.rule.or ? 0 : 1
listQuestions[quizId][totalIndex].content.rule.or ? 0 : 1
}
onChange={({ target }) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent =
listQuestions[quizId][totalIndex].content;
clonContent.rule.or = target.value === CONDITIONS[0];
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, {
content: clonContent,
});
}}
>
{CONDITIONS.map((condition, index) => (

@ -1,5 +1,5 @@
import { Box, ButtonBase, Typography } from "@mui/material";
import * as React from "react";
import { useParams } from "react-router-dom";
import SelectableButton from "@ui_kit/SelectableButton";
import CustomTextField from "@ui_kit/CustomTextField";
import { useState } from "react";
@ -17,12 +17,13 @@ type HelpQuestionsProps = {
export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
const [open, setOpen] = useState(false);
const [backgroundType, setBackgroundType] = useState<BackgroundType>("text");
const quizId = Number(useParams().quizId);
const { listQuestions } = questionStore();
const videoHC = (url: string) => {
const clonContent = listQuestions[totalIndex].content;
const clonContent = listQuestions[quizId][totalIndex].content;
clonContent.hint.video = url;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
};
return (
@ -60,11 +61,11 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
<>
<CustomTextField
placeholder={"Текст консультанта"}
text={listQuestions[totalIndex].content.hint.text}
text={listQuestions[quizId][totalIndex].content.hint.text}
onChange={({ target }) => {
let clonContent = listQuestions[totalIndex].content;
let clonContent = listQuestions[quizId][totalIndex].content;
clonContent.hint.text = target.value;
updateQuestionsList(totalIndex, { content: clonContent });
updateQuestionsList(quizId, totalIndex, { content: clonContent });
}}
/>
</>
@ -77,9 +78,9 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
onClick={() => setOpen(true)}
sx={{ justifyContent: "flex-start" }}
>
{listQuestions[totalIndex].content.hint.video ? (
{listQuestions[quizId][totalIndex].content.hint.video ? (
<video
src={listQuestions[totalIndex].content.hint.video}
src={listQuestions[quizId][totalIndex].content.hint.video}
width="400"
controls
/>
@ -98,7 +99,7 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
<UploadVideoModal
open={open}
onClose={() => setOpen(false)}
video={listQuestions[totalIndex].content.hint.video}
video={listQuestions[quizId][totalIndex].content.hint.video}
onUpload={videoHC}
/>
</Box>

@ -89,40 +89,48 @@ export const questionStore = create<QuestionStore>()(
)
);
export const updateQuestionsList = (
questionId: number,
quizId: number,
index: number,
data: Partial<Question>
) => {
const questionListClone = { ...questionStore.getState()["listQuestions"] };
questionListClone[questionId] = { ...questionListClone[questionId], ...data };
questionListClone[quizId][index] = {
...questionListClone[quizId][index],
...data,
};
questionStore.setState({ listQuestions: questionListClone });
};
export const updateQuestionsListDragAndDrop = (
questionId: number,
quizId: number,
updatedQuestions: Question[]
) => {
const questionListClone = { ...questionStore.getState()["listQuestions"] };
questionStore.setState({
listQuestions: { ...questionListClone, [questionId]: updatedQuestions },
listQuestions: { ...questionListClone, [quizId]: updatedQuestions },
});
};
export const updateVariants = (
questionId: number,
quizId: number,
index: number,
variants: Variants[]
) => {
const listQuestions = { ...questionStore.getState()["listQuestions"] };
listQuestions[questionId][index].content.variants = variants;
listQuestions[quizId][index].content.variants = variants;
questionStore.setState({ listQuestions });
};
export const createQuestion = (questionId: number) => {
export const createQuestion = (quizId: number) => {
const id = getRandom(1000000, 10000000);
const newData = { ...questionStore.getState()["listQuestions"] };
newData[questionId].push({
if (!newData[quizId]) {
newData[quizId] = [];
}
newData[quizId].push({
id,
title: "",
description: "",
@ -187,27 +195,24 @@ export const createQuestion = (questionId: number) => {
updated_at: "",
expanded: false,
});
questionStore.setState({ listQuestions: newData });
};
export const copyQuestion = (
questionId: number,
copiedQuestionIndex: number
) => {
export const copyQuestion = (quizId: number, copiedQuestionIndex: number) => {
const listQuestions = { ...questionStore.getState()["listQuestions"] };
listQuestions[questionId].push({
...listQuestions[questionId][copiedQuestionIndex],
listQuestions[quizId].push({
...listQuestions[quizId][copiedQuestionIndex],
});
questionStore.setState({ listQuestions });
};
export const removeQuestion = (questionId: number, index: number) => {
export const removeQuestion = (quizId: number, index: number) => {
const questionListClone = { ...questionStore.getState()["listQuestions"] };
questionListClone[questionId].splice(index, 1);
questionListClone[quizId].splice(index, 1);
questionStore.setState({ listQuestions: questionListClone });
};
@ -216,12 +221,12 @@ export const resetSomeField = (data: Record<string, string>) => {
questionStore.setState(data);
};
export const findQuestionById = (questionId: number) => {
export const findQuestionById = (quizId: number) => {
let found = null;
questionStore
.getState()
["listQuestions"][questionId].some((quiz: Question, index: number) => {
if (quiz.id === questionId) {
["listQuestions"][quizId].some((quiz: Question, index: number) => {
if (quiz.id === quizId) {
found = { quiz, index };
return true;
}