fix: question store interaction
This commit is contained in:
parent
365287d446
commit
2575d776a4
@ -1,22 +1,51 @@
|
|||||||
import { Box, useTheme } from "@mui/material";
|
import { Box, useTheme } from "@mui/material";
|
||||||
|
|
||||||
|
import type { SxProps } from "@mui/material";
|
||||||
|
|
||||||
export default function InfoIcon() {
|
type InfoIconProps = {
|
||||||
const theme = useTheme();
|
sx?: SxProps;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
export default function InfoIcon({ sx }: InfoIconProps) {
|
||||||
<Box sx={{
|
const theme = useTheme();
|
||||||
height: "24px",
|
|
||||||
width: "24px",
|
return (
|
||||||
display: "flex",
|
<Box
|
||||||
alignItems: "center",
|
sx={{
|
||||||
justifyContent: "center",
|
height: "24px",
|
||||||
}}>
|
width: "24px",
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
display: "flex",
|
||||||
<path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke={theme.palette.brightPurple.main} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
alignItems: "center",
|
||||||
<path d="M11.25 11.25H12V16.5H12.75" stroke={theme.palette.brightPurple.main} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
justifyContent: "center",
|
||||||
<path d="M11.8125 9C12.4338 9 12.9375 8.49632 12.9375 7.875C12.9375 7.25368 12.4338 6.75 11.8125 6.75C11.1912 6.75 10.6875 7.25368 10.6875 7.875C10.6875 8.49632 11.1912 9 11.8125 9Z" fill={theme.palette.brightPurple.main} />
|
...sx,
|
||||||
</svg>
|
}}
|
||||||
</Box>
|
>
|
||||||
);
|
<svg
|
||||||
}
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
|
||||||
|
stroke={theme.palette.brightPurple.main}
|
||||||
|
strokeWidth="1.5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M11.25 11.25H12V16.5H12.75"
|
||||||
|
stroke={theme.palette.brightPurple.main}
|
||||||
|
strokeWidth="1.5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M11.8125 9C12.4338 9 12.9375 8.49632 12.9375 7.875C12.9375 7.25368 12.4338 6.75 11.8125 6.75C11.1912 6.75 10.6875 7.25368 10.6875 7.875C10.6875 8.49632 11.1912 9 11.8125 9Z"
|
||||||
|
fill={theme.palette.brightPurple.main}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export const AnswerItem = ({
|
|||||||
|
|
||||||
const addNewAnswer = () => {
|
const addNewAnswer = () => {
|
||||||
const answerNew = variants.slice();
|
const answerNew = variants.slice();
|
||||||
answerNew.push({ answer: "", answerLong: "", hints: "" });
|
answerNew.push({ answer: "", hints: "" });
|
||||||
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
content: {
|
content: {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export default function DropDown({ totalIndex }: Props) {
|
|||||||
|
|
||||||
const addNewAnswer = () => {
|
const addNewAnswer = () => {
|
||||||
const answerNew = variants.slice();
|
const answerNew = variants.slice();
|
||||||
answerNew.push({ answer: "", answerLong: "", hints: "" });
|
answerNew.push({ answer: "", hints: "" });
|
||||||
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
content: {
|
content: {
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export default function Emoji({ totalIndex }: Props) {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const answerNew =
|
const answerNew =
|
||||||
listQuestions[quizId][totalIndex].content.variants.slice();
|
listQuestions[quizId][totalIndex].content.variants.slice();
|
||||||
answerNew.push({ answer: "", answerLong: "", hints: "" });
|
answerNew.push({ answer: "", hints: "" });
|
||||||
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
content: {
|
content: {
|
||||||
|
|||||||
@ -79,11 +79,7 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
|||||||
sx={{ color: theme.palette.brightPurple.main }}
|
sx={{ color: theme.palette.brightPurple.main }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
clonContent.variants.push({
|
clonContent.variants.push({ answer: "", hints: "" });
|
||||||
answer: "",
|
|
||||||
answerLong: "",
|
|
||||||
hints: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,25 +1,106 @@
|
|||||||
import {Box, Typography} from "@mui/material";
|
import { useParams } from "react-router-dom";
|
||||||
|
import { Box, Typography } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
|
|
||||||
export default function SettingOptionsAndPict() {
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
return(
|
|
||||||
<>
|
|
||||||
<Box sx={{display: 'flex', width: '100%', justifyContent: 'space-between'}}>
|
|
||||||
<Box sx={{padding: '20px', width: '100%'}}>
|
|
||||||
<Typography sx={{marginBottom: '15px'}}>Настройки ответов</Typography>
|
|
||||||
<CustomCheckbox label={'Вариант "свой ответ"'}/>
|
|
||||||
|
|
||||||
<Typography sx={{marginBottom: '15px'}}>Текст-заглушка на картинке</Typography>
|
type SettingOptionsAndPictProps = {
|
||||||
<CustomTextField placeholder={'Пример текста'} text={''}/>
|
totalIndex: number;
|
||||||
</Box>
|
};
|
||||||
<Box sx={{padding: '20px'}}>
|
|
||||||
<Typography sx={{marginBottom: '15px'}}>Настройки вопросов</Typography>
|
export default function SettingOptionsAndPict({
|
||||||
<CustomCheckbox label={'Необязательный вопрос'}/>
|
totalIndex,
|
||||||
<CustomCheckbox label={'Внутреннее название вопроса'}/> <InfoIcon />
|
}: SettingOptionsAndPictProps) {
|
||||||
</Box>
|
const quizId = Number(useParams().quizId);
|
||||||
</Box>
|
const { listQuestions } = questionStore();
|
||||||
</>
|
|
||||||
)
|
return (
|
||||||
}
|
<>
|
||||||
|
<Box
|
||||||
|
sx={{ display: "flex", width: "100%", justifyContent: "space-between" }}
|
||||||
|
>
|
||||||
|
<Box sx={{ padding: "20px", width: "100%" }}>
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Настройки ответов
|
||||||
|
</Typography>
|
||||||
|
<CustomCheckbox
|
||||||
|
label={'Вариант "свой ответ"'}
|
||||||
|
checked={listQuestions[quizId][totalIndex].content.own}
|
||||||
|
handleChange={({ target }) => {
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
own: target.checked,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Текст-заглушка на картинке
|
||||||
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
placeholder={"Пример текста"}
|
||||||
|
text={listQuestions[quizId][totalIndex].content.replText}
|
||||||
|
onChange={({ target }) => {
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
replText: target.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ padding: "20px", width: "100%" }}>
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Настройки вопросов
|
||||||
|
</Typography>
|
||||||
|
<CustomCheckbox
|
||||||
|
label={"Необязательный вопрос"}
|
||||||
|
checked={listQuestions[quizId][totalIndex].content.required}
|
||||||
|
handleChange={({ target }) => {
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
required: target.checked,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<CustomCheckbox
|
||||||
|
sx={{ width: "100%" }}
|
||||||
|
label={"Внутреннее название вопроса"}
|
||||||
|
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
||||||
|
handleChange={({ target }) => {
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
innerNameCheck: target.checked,
|
||||||
|
innerName: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>{" "}
|
||||||
|
<InfoIcon />
|
||||||
|
</Box>
|
||||||
|
{listQuestions[quizId][totalIndex].content.innerNameCheck && (
|
||||||
|
<CustomTextField
|
||||||
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
|
onChange={({ target }) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = target.value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: clonContent,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export default function SwitchOptionsAndPict({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
switch (switchState) {
|
switch (switchState) {
|
||||||
case "setting":
|
case "setting":
|
||||||
return <SettingOptionsAndPict />;
|
return <SettingOptionsAndPict totalIndex={totalIndex} />;
|
||||||
break;
|
break;
|
||||||
case "help":
|
case "help":
|
||||||
return <HelpQuestions totalIndex={totalIndex} />;
|
return <HelpQuestions totalIndex={totalIndex} />;
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Box, Button, Typography, useTheme } from "@mui/material";
|
import { Box, Button, Typography, useTheme } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
@ -114,13 +115,14 @@ export default function SettingOpytionsPict({
|
|||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<CustomCheckbox
|
<CustomCheckbox
|
||||||
|
sx={{ display: "block" }}
|
||||||
label={"Можно несколько"}
|
label={"Можно несколько"}
|
||||||
checked={listQuestions[quizId][totalIndex].content.multi}
|
checked={listQuestions[quizId][totalIndex].content.multi}
|
||||||
handleChange={() =>
|
handleChange={({ target }) =>
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
content: {
|
content: {
|
||||||
...listQuestions[quizId][totalIndex].content,
|
...listQuestions[quizId][totalIndex].content,
|
||||||
multi: !listQuestions[quizId][totalIndex].content.multi,
|
multi: target.checked,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -128,17 +130,27 @@ export default function SettingOpytionsPict({
|
|||||||
<CustomCheckbox
|
<CustomCheckbox
|
||||||
label={"Большие картинки"}
|
label={"Большие картинки"}
|
||||||
checked={listQuestions[quizId][totalIndex].content.largeCheck}
|
checked={listQuestions[quizId][totalIndex].content.largeCheck}
|
||||||
handleChange={() =>
|
handleChange={({ target }) =>
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
content: {
|
content: {
|
||||||
...listQuestions[quizId][totalIndex].content,
|
...listQuestions[quizId][totalIndex].content,
|
||||||
largeCheck:
|
largeCheck: target.checked,
|
||||||
!listQuestions[quizId][totalIndex].content.largeCheck,
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<CustomCheckbox
|
||||||
|
label={'Вариант "свой ответ"'}
|
||||||
|
checked={listQuestions[quizId][totalIndex].content.own}
|
||||||
|
handleChange={({ target }) =>
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
own: target.checked,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<CustomCheckbox label={'Вариант "свой ответ"'} />
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Форма</Typography>
|
<Typography sx={{ marginBottom: "15px" }}>Форма</Typography>
|
||||||
@ -181,8 +193,48 @@ export default function SettingOpytionsPict({
|
|||||||
<Typography sx={{ marginBottom: "15px" }}>
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
Настройки вопросов
|
Настройки вопросов
|
||||||
</Typography>
|
</Typography>
|
||||||
<CustomCheckbox label={"Необязательный вопрос"} />
|
<CustomCheckbox
|
||||||
<CustomCheckbox label={"Внутреннее название вопроса"} /> <InfoIcon />
|
label={"Необязательный вопрос"}
|
||||||
|
checked={listQuestions[quizId][totalIndex].content.required}
|
||||||
|
handleChange={({ target }) =>
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
required: target.checked,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Box sx={{ display: "flex" }}>
|
||||||
|
<CustomCheckbox
|
||||||
|
sx={{ width: "100%" }}
|
||||||
|
label={"Внутреннее название вопроса"}
|
||||||
|
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
||||||
|
handleChange={({ target }) =>
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
innerNameCheck: target.checked,
|
||||||
|
innerName: "",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<InfoIcon />
|
||||||
|
</Box>
|
||||||
|
{listQuestions[quizId][totalIndex].content.innerNameCheck && (
|
||||||
|
<CustomTextField
|
||||||
|
placeholder={"Внутреннее описание вопроса"}
|
||||||
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
|
onChange={({ target }) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = target.value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: clonContent,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export default function AnswerOptions({ totalIndex }: Props) {
|
|||||||
|
|
||||||
const addNewAnswer = () => {
|
const addNewAnswer = () => {
|
||||||
const answerNew = variants.slice(); // Create a shallow copy of the array
|
const answerNew = variants.slice(); // Create a shallow copy of the array
|
||||||
answerNew.push({ answer: "", answerLong: "", hints: "" });
|
answerNew.push({ answer: "", hints: "" });
|
||||||
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
content: {
|
content: {
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import { persist } from "zustand/middleware";
|
|||||||
|
|
||||||
export type Variants = {
|
export type Variants = {
|
||||||
answer: string;
|
answer: string;
|
||||||
answerLong: string;
|
|
||||||
hints: string;
|
hints: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,6 +62,8 @@ export interface Question {
|
|||||||
start: number;
|
start: number;
|
||||||
step: number;
|
step: number;
|
||||||
chooseRange: boolean;
|
chooseRange: boolean;
|
||||||
|
required: boolean;
|
||||||
|
replText: string;
|
||||||
};
|
};
|
||||||
version: number;
|
version: number;
|
||||||
parent_ids: number[];
|
parent_ids: number[];
|
||||||
@ -167,10 +168,11 @@ export const createQuestion = (quizId: number) => {
|
|||||||
start: 50,
|
start: 50,
|
||||||
step: 1,
|
step: 1,
|
||||||
chooseRange: false,
|
chooseRange: false,
|
||||||
|
required: false,
|
||||||
|
replText: "",
|
||||||
variants: [
|
variants: [
|
||||||
{
|
{
|
||||||
answer: "",
|
answer: "",
|
||||||
answerLong: "",
|
|
||||||
hints: "",
|
hints: "",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import { FormControlLabel, Checkbox, useTheme, Box } from "@mui/material";
|
import { FormControlLabel, Checkbox, useTheme, Box } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import type { SxProps } from "@mui/material";
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
label: string;
|
label: string;
|
||||||
handleChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
handleChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
|
sx?: SxProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CustomCheckbox({ label, handleChange, checked}: Props) {
|
export default function CustomCheckbox({ label, handleChange, checked, sx}: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -25,6 +28,7 @@ export default function CustomCheckbox({ label, handleChange, checked}: Props) {
|
|||||||
color: theme.palette.grey2.main,
|
color: theme.palette.grey2.main,
|
||||||
ml: "-9px",
|
ml: "-9px",
|
||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
|
...sx,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user