feat: updates from brunch dev
This commit is contained in:
commit
2a8dda2670
@ -0,0 +1,23 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Droppable } from "react-beautiful-dnd";
|
||||||
|
|
||||||
|
import type { DroppableProps } from "react-beautiful-dnd";
|
||||||
|
|
||||||
|
export const StrictModeDroppable = ({ children, ...props }: DroppableProps) => {
|
||||||
|
const [enabled, setEnabled] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const animation = requestAnimationFrame(() => setEnabled(true));
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
setEnabled(false);
|
||||||
|
cancelAnimationFrame(animation);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Droppable {...props}>{children}</Droppable>;
|
||||||
|
};
|
||||||
@ -10,7 +10,6 @@ import DeleteIcon from "../../assets/icons/questionsPage/deleteIcon";
|
|||||||
import ImgIcon from "../../assets/icons/questionsPage/imgIcon";
|
import ImgIcon from "../../assets/icons/questionsPage/imgIcon";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { questionStore, removeQuestion, resetSomeField } from "@root/questions";
|
import { questionStore, removeQuestion, resetSomeField } from "@root/questions";
|
||||||
import { branchStore } from "@root/branches";
|
|
||||||
|
|
||||||
import "./ButtonsOptionsAndPict.css";
|
import "./ButtonsOptionsAndPict.css";
|
||||||
|
|
||||||
@ -27,7 +26,6 @@ export default function ButtonsOptionsAndPict({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
const params = Number(useParams().quizId);
|
const params = Number(useParams().quizId);
|
||||||
const { openedModalSettings } = questionStore();
|
const { openedModalSettings } = questionStore();
|
||||||
const { branch } = branchStore();
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const openedModal = () => {
|
const openedModal = () => {
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { Box, Typography, Link, useTheme } from "@mui/material";
|
import { Box, Typography, Link, useTheme } from "@mui/material";
|
||||||
import React from "react";
|
import { AnswerDraggableList } from "../AnswerDraggableList";
|
||||||
|
|
||||||
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
|
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
|
||||||
import SwitchDropDown from "./switchDropDown";
|
import SwitchDropDown from "./switchDropDown";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
@ -9,16 +13,28 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function DropDown({ totalIndex }: Props) {
|
export default function DropDown({ totalIndex }: Props) {
|
||||||
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
|
const { listQuestions } = questionStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [switchState, setSwitchState] = React.useState("setting");
|
const variants = listQuestions[totalIndex].content.variants;
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addNewAnswer = () => {
|
||||||
|
const answerNew = variants.slice();
|
||||||
|
answerNew.push({ answer: "", answerLong: "", hints: "" });
|
||||||
|
|
||||||
|
updateQuestionsList(totalIndex, {
|
||||||
|
content: { ...listQuestions[totalIndex].content, variants: answerNew },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
|
{variants.length === 0 ? (
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
padding: "0 0 33px 80px",
|
padding: "0 0 33px 80px",
|
||||||
@ -30,14 +46,15 @@ export default function DropDown({ totalIndex }: Props) {
|
|||||||
>
|
>
|
||||||
Добавьте ответ
|
Добавьте ответ
|
||||||
</Typography>
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<AnswerDraggableList variants={variants} totalIndex={totalIndex} />
|
||||||
|
)}
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||||
<Link
|
<Link
|
||||||
component="button"
|
component="button"
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{ color: theme.palette.brightPurple.main }}
|
sx={{ color: theme.palette.brightPurple.main }}
|
||||||
// onClick={() => {
|
onClick={addNewAnswer}
|
||||||
// console.info("I'm a button.");
|
|
||||||
// }}
|
|
||||||
>
|
>
|
||||||
Добавьте ответ
|
Добавьте ответ
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -1,25 +1,49 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
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 { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
|
|
||||||
export default function SettingDropDown() {
|
type SettingDropDownProps = {
|
||||||
|
totalIndex: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
|
||||||
|
const { listQuestions } = questionStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{display: 'flex', width: '100%', justifyContent: 'space-between'}}>
|
<Box
|
||||||
<Box sx={{padding: '20px', width: '100%'}}>
|
sx={{ display: "flex", width: "100%", justifyContent: "space-between" }}
|
||||||
<Typography sx={{marginBottom: '15px'}}>Настройки ответов</Typography>
|
>
|
||||||
<CustomCheckbox label={'Можно несколько'}/>
|
<Box sx={{ padding: "20px", width: "100%" }}>
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
<Typography sx={{marginBottom: '15px'}}>Текст в выпадающем списке</Typography>
|
Настройки ответов
|
||||||
<CustomTextField placeholder={'Выберите вариант'} text={''}/>
|
</Typography>
|
||||||
|
<CustomCheckbox label={"Можно несколько"} />
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Текст в выпадающем списке
|
||||||
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
placeholder={"Выберите вариант"}
|
||||||
|
text={listQuestions[totalIndex].content.default}
|
||||||
|
onChange={({ target }) => {
|
||||||
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
|
clonContent.default = target.value;
|
||||||
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{padding: '20px'}}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<Typography sx={{marginBottom: '15px'}}>Настройки вопросов</Typography>
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
<CustomCheckbox label={'Необязательный вопрос'}/>
|
Настройки вопросов
|
||||||
<CustomCheckbox label={'Внутреннее название вопроса'}/> <InfoIcon />
|
</Typography>
|
||||||
|
<CustomCheckbox label={"Необязательный вопрос"} />
|
||||||
|
<CustomCheckbox label={"Внутреннее название вопроса"} /> <InfoIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@ -14,7 +14,7 @@ export default function SwitchDropDown({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
switch (switchState) {
|
switch (switchState) {
|
||||||
case "setting":
|
case "setting":
|
||||||
return <SettingDropDown />;
|
return <SettingDropDown totalIndex={totalIndex} />;
|
||||||
break;
|
break;
|
||||||
case "help":
|
case "help":
|
||||||
return <HelpQuestions totalIndex={totalIndex} />;
|
return <HelpQuestions totalIndex={totalIndex} />;
|
||||||
|
|||||||
@ -1,36 +1,48 @@
|
|||||||
import { Box, Link, Typography, useTheme } from "@mui/material";
|
import { useState } from "react";
|
||||||
import React from "react";
|
import { Box, Link, Typography, Button, useTheme } from "@mui/material";
|
||||||
|
|
||||||
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
|
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
|
||||||
import AddImage from "../../../assets/icons/questionsPage/addImage";
|
import AddImage from "../../../assets/icons/questionsPage/addImage";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
|
||||||
import SwitchAnswerOptionsPict from "./switchOptionsPict";
|
import SwitchAnswerOptionsPict from "./switchOptionsPict";
|
||||||
|
|
||||||
|
import type { ChangeEvent } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
totalIndex: number;
|
totalIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function OptionsPicture({ totalIndex }: Props) {
|
export default function OptionsPicture({ totalIndex }: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [switchState, setSwitchState] = React.useState("setting");
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
// const [addInput, setAddInput] = React.useState([
|
const { listQuestions } = questionStore();
|
||||||
// 0: {name: "распутье", variants: ["дорога влево", "дорога вправо"]};
|
|
||||||
// ]);
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const createCondition = (name) => {
|
const addImage = ({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
// addInput([...state, {name: name}])
|
if (target.files?.length) {
|
||||||
// }
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
//
|
|
||||||
// const deleteCondition = (index) => {
|
clonContent.images.push(URL.createObjectURL(target.files[0]));
|
||||||
//
|
|
||||||
// }
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<Box
|
<Box
|
||||||
sx={{ display: "flex", alignItems: "center", paddingBottom: "25px" }}
|
sx={{ display: "flex", alignItems: "center", paddingBottom: "25px" }}
|
||||||
>
|
>
|
||||||
|
<Button component="label" sx={{ padding: "0px" }}>
|
||||||
<AddImage />
|
<AddImage />
|
||||||
|
<input type="file" hidden onChange={addImage} />
|
||||||
|
</Button>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
padding: "0 0 0 20px",
|
padding: "0 0 0 20px",
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
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 { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
import { useState } from "react";
|
|
||||||
import FormatIcon2 from "../../../assets/icons/questionsPage/FormatIcon2";
|
import FormatIcon2 from "../../../assets/icons/questionsPage/FormatIcon2";
|
||||||
import FormatIcon1 from "../../../assets/icons/questionsPage/FormatIcon1";
|
import FormatIcon1 from "../../../assets/icons/questionsPage/FormatIcon1";
|
||||||
import ProportionsIcon11 from "../../../assets/icons/questionsPage/ProportionsIcon11";
|
import ProportionsIcon11 from "../../../assets/icons/questionsPage/ProportionsIcon11";
|
||||||
@ -14,18 +17,38 @@ interface Props {
|
|||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SettingOpytionsPictProps = {
|
||||||
|
totalIndex: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PROPORTIONS = [
|
||||||
|
{ value: "1:1", icon: ProportionsIcon11 },
|
||||||
|
{ value: "2:1", icon: ProportionsIcon21 },
|
||||||
|
{ value: "1:2", icon: ProportionsIcon12 },
|
||||||
|
];
|
||||||
|
|
||||||
export function SelectIconButton({ Icon, isActive = false, onClick }: Props) {
|
export function SelectIconButton({ Icon, isActive = false, onClick }: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
startIcon={<Icon color={isActive ? theme.palette.navbarbg.main : theme.palette.brightPurple.main} />}
|
startIcon={
|
||||||
|
<Icon
|
||||||
|
color={
|
||||||
|
isActive
|
||||||
|
? theme.palette.navbarbg.main
|
||||||
|
: theme.palette.brightPurple.main
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: isActive ? theme.palette.brightPurple.main : "#eee4fc",
|
backgroundColor: isActive ? theme.palette.brightPurple.main : "#eee4fc",
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
border: "none",
|
border: "none",
|
||||||
color: isActive ? theme.palette.brightPurple.main : theme.palette.grey2.main,
|
color: isActive
|
||||||
|
? theme.palette.brightPurple.main
|
||||||
|
: theme.palette.grey2.main,
|
||||||
p: "7px",
|
p: "7px",
|
||||||
width: "auto",
|
width: "auto",
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
@ -35,19 +58,31 @@ export function SelectIconButton({ Icon, isActive = false, onClick }: Props) {
|
|||||||
},
|
},
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
border: "none",
|
border: "none",
|
||||||
borderColor: isActive ? theme.palette.brightPurple.main : theme.palette.grey2.main,
|
borderColor: isActive
|
||||||
|
? theme.palette.brightPurple.main
|
||||||
|
: theme.palette.grey2.main,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type Proportions = "oneOne" | "twoOne" | "oneTwo";
|
export default function SettingOpytionsPict({
|
||||||
type AlignType = "left" | "right";
|
totalIndex,
|
||||||
|
}: SettingOpytionsPictProps) {
|
||||||
|
const { listQuestions } = questionStore();
|
||||||
|
|
||||||
export default function SettingOpytionsPict() {
|
useEffect(() => {
|
||||||
const [proportions, setProportions] = useState<Proportions>("oneOne");
|
if (!listQuestions[totalIndex].content.xy) {
|
||||||
const [alignType, setAlignType] = useState<AlignType>("left");
|
updateProportions("1:1");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const updateProportions = (proportions: string) => {
|
||||||
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
|
clonContent.xy = proportions;
|
||||||
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -61,25 +96,43 @@ export default function SettingOpytionsPict() {
|
|||||||
marginBottom: "20px",
|
marginBottom: "20px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{PROPORTIONS.map(({ value, icon }, index) => (
|
||||||
<SelectIconButton
|
<SelectIconButton
|
||||||
onClick={() => setProportions("oneOne")}
|
key={index}
|
||||||
isActive={proportions === "oneOne"}
|
onClick={() => updateProportions(value)}
|
||||||
Icon={ProportionsIcon11}
|
isActive={listQuestions[totalIndex].content.xy === value}
|
||||||
/>
|
Icon={icon}
|
||||||
<SelectIconButton
|
|
||||||
onClick={() => setProportions("twoOne")}
|
|
||||||
isActive={proportions === "twoOne"}
|
|
||||||
Icon={ProportionsIcon21}
|
|
||||||
/>
|
|
||||||
<SelectIconButton
|
|
||||||
onClick={() => setProportions("oneTwo")}
|
|
||||||
isActive={proportions === "oneTwo"}
|
|
||||||
Icon={ProportionsIcon12}
|
|
||||||
/>
|
/>
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Настройки ответов</Typography>
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
<CustomCheckbox label={"Можно несколько"} />
|
Настройки ответов
|
||||||
<CustomCheckbox label={"Большие картинки"} />
|
</Typography>
|
||||||
|
|
||||||
|
<CustomCheckbox
|
||||||
|
label={"Можно несколько"}
|
||||||
|
checked={listQuestions[totalIndex].content.multi}
|
||||||
|
handleChange={() =>
|
||||||
|
updateQuestionsList(totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[totalIndex].content,
|
||||||
|
multi: !listQuestions[totalIndex].content.multi,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<CustomCheckbox
|
||||||
|
label={"Большие картинки"}
|
||||||
|
checked={listQuestions[totalIndex].content.large}
|
||||||
|
handleChange={() =>
|
||||||
|
updateQuestionsList(totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[totalIndex].content,
|
||||||
|
large: !listQuestions[totalIndex].content.large,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
<CustomCheckbox label={'Вариант "свой ответ"'} />
|
<CustomCheckbox label={'Вариант "свой ответ"'} />
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
@ -91,14 +144,34 @@ export default function SettingOpytionsPict() {
|
|||||||
marginBottom: "20px",
|
marginBottom: "20px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectIconButton onClick={() => setAlignType("left")} isActive={alignType === "left"} Icon={FormatIcon2} />
|
|
||||||
<SelectIconButton
|
<SelectIconButton
|
||||||
onClick={() => setAlignType("right")}
|
onClick={() =>
|
||||||
isActive={alignType === "right"}
|
updateQuestionsList(totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[totalIndex].content,
|
||||||
|
format: "carousel",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isActive={listQuestions[totalIndex].content.format === "carousel"}
|
||||||
|
Icon={FormatIcon2}
|
||||||
|
/>
|
||||||
|
<SelectIconButton
|
||||||
|
onClick={() =>
|
||||||
|
updateQuestionsList(totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[totalIndex].content,
|
||||||
|
format: "masonry",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
isActive={listQuestions[totalIndex].content.format === "masonry"}
|
||||||
Icon={FormatIcon1}
|
Icon={FormatIcon1}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Настройки вопросов</Typography>
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Настройки вопросов
|
||||||
|
</Typography>
|
||||||
<CustomCheckbox label={"Необязательный вопрос"} />
|
<CustomCheckbox label={"Необязательный вопрос"} />
|
||||||
<CustomCheckbox label={"Внутреннее название вопроса"} /> <InfoIcon />
|
<CustomCheckbox label={"Внутреннее название вопроса"} /> <InfoIcon />
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export default function SwitchAnswerOptionsPict({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
switch (switchState) {
|
switch (switchState) {
|
||||||
case "setting":
|
case "setting":
|
||||||
return <SettingOpytionsPict />;
|
return <SettingOpytionsPict totalIndex={totalIndex} />;
|
||||||
break;
|
break;
|
||||||
case "help":
|
case "help":
|
||||||
return <HelpQuestions totalIndex={totalIndex} />;
|
return <HelpQuestions totalIndex={totalIndex} />;
|
||||||
|
|||||||
@ -13,15 +13,13 @@ import { questionStore, updateQuestionsList } from "@root/questions";
|
|||||||
|
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
|
|
||||||
import type { QuestionType } from "@root/questions";
|
|
||||||
|
|
||||||
type SettingTextFieldProps = {
|
type SettingTextFieldProps = {
|
||||||
totalIndex: number;
|
totalIndex: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Answer = {
|
type Answer = {
|
||||||
name: string;
|
name: string;
|
||||||
value: QuestionType;
|
value: "single" | "multi" | "number";
|
||||||
};
|
};
|
||||||
|
|
||||||
const ANSWER_TYPES: Answer[] = [
|
const ANSWER_TYPES: Answer[] = [
|
||||||
@ -45,11 +43,17 @@ export default function SettingTextField({
|
|||||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||||
name="controlled-radio-buttons-group"
|
name="controlled-radio-buttons-group"
|
||||||
value={ANSWER_TYPES.findIndex(
|
value={ANSWER_TYPES.findIndex(
|
||||||
({ value }) => value === listQuestions[totalIndex].content.type
|
({ value }) => listQuestions[totalIndex].content[value]
|
||||||
)}
|
)}
|
||||||
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
|
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const clonContent = listQuestions[totalIndex].content;
|
const clonContent = {
|
||||||
clonContent.type = ANSWER_TYPES[Number(target.value)].value;
|
...listQuestions[totalIndex].content,
|
||||||
|
single: false,
|
||||||
|
multi: false,
|
||||||
|
number: false,
|
||||||
|
[ANSWER_TYPES[Number(target.value)].value]: true,
|
||||||
|
};
|
||||||
|
|
||||||
updateQuestionsList(totalIndex, { content: clonContent });
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -8,7 +9,9 @@ import {
|
|||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
import React, { useState } from "react";
|
|
||||||
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
import ArrowDown from "../../../assets/icons/ArrowDownIcon";
|
import ArrowDown from "../../../assets/icons/ArrowDownIcon";
|
||||||
import SwitchUpload from "./switchUpload";
|
import SwitchUpload from "./switchUpload";
|
||||||
@ -17,25 +20,41 @@ interface Props {
|
|||||||
totalIndex: number;
|
totalIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DESIGN_TYPES = [
|
||||||
|
{ name: "Все типы файлов", value: "all" },
|
||||||
|
{ name: "Изображения", value: "picture" },
|
||||||
|
{ name: "Видео", value: "video" },
|
||||||
|
{ name: "Аудио", value: "audio" },
|
||||||
|
{ name: "Документ", value: "document" },
|
||||||
|
];
|
||||||
|
|
||||||
export default function UploadFile({ totalIndex }: Props) {
|
export default function UploadFile({ totalIndex }: Props) {
|
||||||
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
|
const { listQuestions } = questionStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [switchState, setSwitchState] = React.useState("setting");
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const designTypes = [
|
const handleChange = ({ target }: SelectChangeEvent) => {
|
||||||
["Все типы файлов"],
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
["Изображения"],
|
clonContent.type = target.value;
|
||||||
["Видео"],
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
["Аудио"],
|
|
||||||
["Документ"],
|
|
||||||
];
|
|
||||||
const [designType, setDesignType] = useState(designTypes[0][0]);
|
|
||||||
const handleChange = (event: SelectChangeEvent) => {
|
|
||||||
setDesignType(event.target.value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const isTypeSetted = DESIGN_TYPES.find(
|
||||||
|
({ value }) => value === listQuestions[totalIndex].content.type
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isTypeSetted) {
|
||||||
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
|
clonContent.type = DESIGN_TYPES[0].value;
|
||||||
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@ -61,7 +80,7 @@ export default function UploadFile({ totalIndex }: Props) {
|
|||||||
<Select
|
<Select
|
||||||
id="category-select"
|
id="category-select"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={designType}
|
value={listQuestions[totalIndex].content.type}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
sx={{
|
sx={{
|
||||||
@ -105,10 +124,10 @@ export default function UploadFile({ totalIndex }: Props) {
|
|||||||
}}
|
}}
|
||||||
IconComponent={(props) => <ArrowDown {...props} />}
|
IconComponent={(props) => <ArrowDown {...props} />}
|
||||||
>
|
>
|
||||||
{designTypes.map((type) => (
|
{DESIGN_TYPES.map(({ name, value }) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={type[0]}
|
key={value}
|
||||||
value={type[0]}
|
value={value}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@ -118,7 +137,7 @@ export default function UploadFile({ totalIndex }: Props) {
|
|||||||
color: theme.palette.grey2.main,
|
color: theme.palette.grey2.main,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{type[0]}
|
{name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@ -1,15 +1,31 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
|
|
||||||
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
|
|
||||||
|
type SettingsUploadProps = {
|
||||||
|
totalIndex: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
|
||||||
|
const { listQuestions } = questionStore();
|
||||||
|
|
||||||
export default function SettingsUpload() {
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{display: 'flex', flexDirection: 'column', padding: '20px'}}>
|
<Box sx={{ display: "flex", flexDirection: "column", padding: "20px" }}>
|
||||||
<Typography>Настройки вопроса</Typography>
|
<Typography>Настройки вопроса</Typography>
|
||||||
<CustomCheckbox label={'Автозаполнение адреса'}/>
|
<CustomCheckbox
|
||||||
<CustomCheckbox label={'Необязательный вопрос'}/>
|
label={"Автозаполнение адреса"}
|
||||||
<CustomCheckbox label={'Внутреннее название вопроса'}/> <InfoIcon />
|
checked={listQuestions[totalIndex].content.autofill}
|
||||||
|
handleChange={({ target }) => {
|
||||||
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
|
clonContent.autofill = target.checked;
|
||||||
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CustomCheckbox label={"Необязательный вопрос"} />
|
||||||
|
<CustomCheckbox label={"Внутреннее название вопроса"} /> <InfoIcon />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export default function SwitchUpload({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
switch (switchState) {
|
switch (switchState) {
|
||||||
case "setting":
|
case "setting":
|
||||||
return <SettingsUpload />;
|
return <SettingsUpload totalIndex={totalIndex} />;
|
||||||
break;
|
break;
|
||||||
case "help":
|
case "help":
|
||||||
return <HelpQuestions totalIndex={totalIndex} />;
|
return <HelpQuestions totalIndex={totalIndex} />;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useState } from "react";
|
|||||||
import { Box, Typography, Link, useTheme } from "@mui/material";
|
import { Box, Typography, Link, useTheme } from "@mui/material";
|
||||||
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
|
import EnterIcon from "../../../assets/icons/questionsPage/enterIcon";
|
||||||
import SwitchAnswerOptions from "./switchAnswerOptions";
|
import SwitchAnswerOptions from "./switchAnswerOptions";
|
||||||
import { AnswerDraggableList } from "./AnswerDraggableList";
|
import { AnswerDraggableList } from "../AnswerDraggableList";
|
||||||
import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
|
import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,31 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
|
import type { ChangeEvent } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
totalIndex: number;
|
totalIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ResponseSettings({ totalIndex }: Props) {
|
export default function ResponseSettings({ totalIndex }: Props) {
|
||||||
const params = Number(useParams().quizId);
|
const [checked, setChecked] = useState(false);
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
const [checked, setChecked] = React.useState([true, false]);
|
|
||||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setChecked([checked[0], event.target.checked]);
|
setChecked(event.target.checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (listQuestions[totalIndex].content.innerName.length) {
|
||||||
|
setChecked(true);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex" }}>
|
<Box sx={{ display: "flex" }}>
|
||||||
<Box sx={{ padding: "20px", display: "flex", flexDirection: "column" }}>
|
<Box sx={{ padding: "20px", display: "flex", flexDirection: "column" }}>
|
||||||
@ -62,18 +70,18 @@ export default function ResponseSettings({ totalIndex }: Props) {
|
|||||||
<Box sx={{ display: "flex" }}>
|
<Box sx={{ display: "flex" }}>
|
||||||
<CustomCheckbox
|
<CustomCheckbox
|
||||||
label={"Внутреннее название вопроса"}
|
label={"Внутреннее название вопроса"}
|
||||||
checked={checked[1]}
|
checked={checked}
|
||||||
handleChange={handleChange}
|
handleChange={handleChange}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
</Box>
|
</Box>
|
||||||
{checked[1] && (
|
{checked && (
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[totalIndex].description}
|
text={listQuestions[totalIndex].content.innerName}
|
||||||
onChange={(e) => {
|
onChange={({ target }) => {
|
||||||
let clonContent = listQuestions[totalIndex].content;
|
let clonContent = listQuestions[totalIndex].content;
|
||||||
clonContent.innerName = e.target.value;
|
clonContent.innerName = target.value;
|
||||||
updateQuestionsList(totalIndex, { content: clonContent });
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
@ -18,7 +17,6 @@ import {
|
|||||||
resetSomeField,
|
resetSomeField,
|
||||||
updateQuestionsList,
|
updateQuestionsList,
|
||||||
} from "@root/questions";
|
} from "@root/questions";
|
||||||
import { branchStore, updateBranchState } from "@root/branches";
|
|
||||||
import { Select } from "./Select";
|
import { Select } from "./Select";
|
||||||
|
|
||||||
import DeleteIcon from "@icons/questionsPage/deleteIcon";
|
import DeleteIcon from "@icons/questionsPage/deleteIcon";
|
||||||
@ -42,20 +40,8 @@ export default function BranchingQuestions({
|
|||||||
totalIndex,
|
totalIndex,
|
||||||
}: BranchingQuestionsProps) {
|
}: BranchingQuestionsProps) {
|
||||||
const { openedModalSettings, listQuestions } = questionStore();
|
const { openedModalSettings, listQuestions } = questionStore();
|
||||||
const { branch } = branchStore();
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
updateBranchState({
|
|
||||||
action: listQuestions[totalIndex].content.rule.show
|
|
||||||
? ACTIONS[0]
|
|
||||||
: ACTIONS[1],
|
|
||||||
condition: listQuestions[totalIndex].content.rule.or
|
|
||||||
? CONDITIONS[0]
|
|
||||||
: CONDITIONS[1],
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
resetSomeField({ openedModalSettings: "" });
|
resetSomeField({ openedModalSettings: "" });
|
||||||
};
|
};
|
||||||
@ -120,7 +106,6 @@ export default function BranchingQuestions({
|
|||||||
const clonContent = listQuestions[totalIndex].content;
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
clonContent.rule.show = action === ACTIONS[0];
|
clonContent.rule.show = action === ACTIONS[0];
|
||||||
updateQuestionsList(totalIndex, { content: clonContent });
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
updateBranchState({ action });
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography sx={{ color: theme.palette.grey2.main }}>
|
<Typography sx={{ color: theme.palette.grey2.main }}>
|
||||||
@ -165,7 +150,7 @@ export default function BranchingQuestions({
|
|||||||
</Box>
|
</Box>
|
||||||
<Select
|
<Select
|
||||||
empty
|
empty
|
||||||
activeItemIndex={Number(request.id) || -1}
|
activeItemIndex={request.id ? Number(request.id) : -1}
|
||||||
items={STIPULATIONS}
|
items={STIPULATIONS}
|
||||||
onChange={(stipulation) => {
|
onChange={(stipulation) => {
|
||||||
const clonContent = listQuestions[totalIndex].content;
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
@ -180,7 +165,6 @@ export default function BranchingQuestions({
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateQuestionsList(totalIndex, { content: clonContent });
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
updateBranchState({ stipulation });
|
|
||||||
}}
|
}}
|
||||||
sx={{ marginBottom: "15px" }}
|
sx={{ marginBottom: "15px" }}
|
||||||
/>
|
/>
|
||||||
@ -225,7 +209,6 @@ export default function BranchingQuestions({
|
|||||||
updateQuestionsList(totalIndex, {
|
updateQuestionsList(totalIndex, {
|
||||||
content: clonContent,
|
content: clonContent,
|
||||||
});
|
});
|
||||||
updateBranchState({ answer });
|
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
marginBottom: "10px",
|
marginBottom: "10px",
|
||||||
@ -295,14 +278,13 @@ export default function BranchingQuestions({
|
|||||||
<FormControl>
|
<FormControl>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
aria-labelledby="demo-controlled-radio-buttons-group"
|
aria-labelledby="demo-controlled-radio-buttons-group"
|
||||||
defaultValue={branch.condition === CONDITIONS[0] ? 0 : 1}
|
defaultValue={
|
||||||
|
listQuestions[totalIndex].content.rule.or ? 0 : 1
|
||||||
|
}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => {
|
||||||
const clonContent = listQuestions[totalIndex].content;
|
const clonContent = listQuestions[totalIndex].content;
|
||||||
clonContent.rule.or = target.value === CONDITIONS[0];
|
clonContent.rule.or = target.value === CONDITIONS[0];
|
||||||
updateQuestionsList(totalIndex, { content: clonContent });
|
updateQuestionsList(totalIndex, { content: clonContent });
|
||||||
updateBranchState({
|
|
||||||
condition: CONDITIONS[Number(target.value)],
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{CONDITIONS.map((condition, index) => (
|
{CONDITIONS.map((condition, index) => (
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
import { create } from "zustand";
|
|
||||||
|
|
||||||
export type Branch = {
|
|
||||||
action: string;
|
|
||||||
stipulation: string;
|
|
||||||
answer: string;
|
|
||||||
condition: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface BranchStore {
|
|
||||||
branch: Branch;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const branchStore = create<BranchStore>()(() => ({
|
|
||||||
branch: {
|
|
||||||
action: "",
|
|
||||||
stipulation: "",
|
|
||||||
answer: "",
|
|
||||||
condition: "",
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const updateBranchState = (data: Partial<Branch>) => {
|
|
||||||
const state = { ...branchStore.getState().branch };
|
|
||||||
|
|
||||||
branchStore.setState({ branch: { ...state, ...data } });
|
|
||||||
};
|
|
||||||
@ -7,8 +7,6 @@ export type Variants = {
|
|||||||
hints: string;
|
hints: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type QuestionType = "single" | "multi" | "number";
|
|
||||||
|
|
||||||
type Hint = {
|
type Hint = {
|
||||||
text: string;
|
text: string;
|
||||||
video: string;
|
video: string;
|
||||||
@ -37,13 +35,20 @@ export interface Question {
|
|||||||
variants: Variants[];
|
variants: Variants[];
|
||||||
hint: Hint;
|
hint: Hint;
|
||||||
rule: Rule;
|
rule: Rule;
|
||||||
|
images: string[];
|
||||||
large: boolean;
|
large: boolean;
|
||||||
multi: boolean;
|
multi: boolean;
|
||||||
own: boolean;
|
own: boolean;
|
||||||
innerName: string;
|
innerName: string;
|
||||||
back: string;
|
back: string;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
type: QuestionType;
|
type: string;
|
||||||
|
autofill: boolean;
|
||||||
|
default: string;
|
||||||
|
single: boolean;
|
||||||
|
number: boolean;
|
||||||
|
xy: string;
|
||||||
|
format: "carousel" | "masonry";
|
||||||
};
|
};
|
||||||
version: number;
|
version: number;
|
||||||
parent_ids: number[];
|
parent_ids: number[];
|
||||||
@ -107,7 +112,14 @@ export const createQuestion = (id: number) => {
|
|||||||
innerName: "",
|
innerName: "",
|
||||||
back: "",
|
back: "",
|
||||||
placeholder: "",
|
placeholder: "",
|
||||||
type: "single",
|
type: "all",
|
||||||
|
autofill: true,
|
||||||
|
default: "",
|
||||||
|
images: [],
|
||||||
|
number: false,
|
||||||
|
single: false,
|
||||||
|
xy: "",
|
||||||
|
format: "carousel",
|
||||||
variants: [
|
variants: [
|
||||||
{
|
{
|
||||||
answer: "",
|
answer: "",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user