memo question card parts with textfields

This commit is contained in:
nflnkr 2024-02-29 14:23:52 +03:00
parent a58af46dac
commit c531b16131
32 changed files with 488 additions and 1065 deletions

@ -19,38 +19,46 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
import { updateDesireToOpenABranchingModal } from "@root/uiTools/actions"; import { updateDesireToOpenABranchingModal } from "@root/uiTools/actions";
import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
import { DeleteFunction } from "@utils/deleteFunc"; import { DeleteFunction } from "@utils/deleteFunc";
import { useState } from "react"; import { memo, useState } from "react";
import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon"; import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
import Branching from "../../assets/icons/questionsPage/branching"; import Branching from "../../assets/icons/questionsPage/branching";
import SettingIcon from "../../assets/icons/questionsPage/settingIcon"; import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared"; import { QuestionType } from "@model/question/question";
interface Props { interface Props {
switchState: string; switchState: string;
SSHC: (data: string) => void; SSHC: (data: string) => void;
question: AnyTypedQuizQuestion; questionId: string;
sx?: SxProps; questionContentId: string;
openBranchingPage: boolean; questionType: QuestionType;
questionHasParent: boolean;
setOpenBranchingPage: (a: boolean) => void; setOpenBranchingPage: (a: boolean) => void;
sx?: SxProps;
} }
export default function ButtonsOptions({ const ButtonsOptions = memo<Props>(function ({
SSHC, SSHC,
switchState, switchState,
question, questionId,
openBranchingPage, questionContentId,
questionType,
questionHasParent,
setOpenBranchingPage, setOpenBranchingPage,
}: Props) { }) {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920)); const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { questions } = useQuestionsStore.getState();
const [openDelete, setOpenDelete] = useState<boolean>(false); const [openDelete, setOpenDelete] = useState<boolean>(false);
const isQuestionFirst = useQuestionsStore(
(state) => state.questions[0]?.id === questionId,
);
if (!quiz) return null;
const openedModal = () => { const openedModal = () => {
setOpenBranchingPage(true); setOpenBranchingPage(true);
updateDesireToOpenABranchingModal(question.content.id); updateDesireToOpenABranchingModal(questionContentId);
}; };
const buttonSetting: { const buttonSetting: {
@ -70,15 +78,6 @@ export default function ButtonsOptions({
title: "Настройки", title: "Настройки",
value: "setting", value: "setting",
}, },
// {
// icon: (
// <Clue
// color={switchState === "help" ? "#ffffff" : theme.palette.grey3.main}
// />
// ),
// title: "Подсказка",
// value: "help",
// },
{ {
icon: ( icon: (
<Branching <Branching
@ -89,6 +88,7 @@ export default function ButtonsOptions({
), ),
title: "Ветвление", title: "Ветвление",
value: "branching", value: "branching",
// @ts-ignore
myFunc: (question) => { myFunc: (question) => {
setOpenBranchingPage(true); setOpenBranchingPage(true);
updateDesireToOpenABranchingModal(question.content.id); updateDesireToOpenABranchingModal(question.content.id);
@ -118,64 +118,13 @@ export default function ButtonsOptions({
{buttonSetting.map(({ icon, title, value, myFunc }) => ( {buttonSetting.map(({ icon, title, value, myFunc }) => (
<Box key={value}> <Box key={value}>
{value === "branching" ? ( {value === "branching" ? (
question.type === "page" || ["page", "text", "date", "number"].includes(
question.type === "text" || questionType,
question.type === "date" || ) ? null : (
question.type === "number" ? (
<></>
) : (
// <Tooltip
// arrow
// placement="right"
// componentsProps={{
// tooltip: {
// sx: {
// background: "#fff",
// borderRadius: "6px",
// color: "#9A9AAF",
// boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
// "& .MuiTooltip-arrow": {
// color: "#FFF",
// },
// },
// },
// }}
// title={
// <Box>
// <Typography
// sx={{
// color: "#4D4D4D",
// fontWeight: "bold",
// fontSize: "14px",
// marginBottom: "10px",
// }}
// >
// Будет показан при условии
// </Typography>
// <Typography sx={{ fontWeight: "bold", fontSize: "12px" }}>
// Название
// </Typography>
// <Typography
// sx={{
// fontWeight: "bold",
// fontSize: "12px",
// marginBottom: "10px",
// }}
// >
// Условие 1, Условие 2
// </Typography>
// <Typography sx={{ color: "#7E2AEA", fontSize: "12px" }}>
// Все условия обязательны
// </Typography>
// </Box>
// }
// >
<MiniButtonSetting <MiniButtonSetting
key={title} key={title}
onClick={() => { onClick={() => {
openedModal(); openedModal();
// SSHC(value);
// myFunc(question);
}} }}
sx={{ sx={{
display: quiz.config.type === "form" ? "none" : "flex", display: quiz.config.type === "form" ? "none" : "flex",
@ -198,72 +147,37 @@ export default function ButtonsOptions({
{icon} {icon}
{isWrappMiniButtonSetting ? null : title} {isWrappMiniButtonSetting ? null : title}
</MiniButtonSetting> </MiniButtonSetting>
// </Tooltip>
) )
) : ( ) : (
<> <MiniButtonSetting
<MiniButtonSetting key={title}
key={title} onClick={() => {
onClick={() => { SSHC(value);
SSHC(value); myFunc();
myFunc(); }}
}} sx={{
sx={{ backgroundColor:
backgroundColor: switchState === value
switchState === value ? theme.palette.brightPurple.main
? theme.palette.brightPurple.main : "transparent",
: "transparent", color:
color: switchState === value
switchState === value ? "#ffffff"
? "#ffffff" : theme.palette.grey3.main,
: theme.palette.grey3.main, minWidth: isWrappMiniButtonSetting ? "30px" : "64px",
minWidth: isWrappMiniButtonSetting ? "30px" : "64px", height: "30px",
height: "30px", "&:hover": {
"&:hover": { color: theme.palette.grey3.main,
color: theme.palette.grey3.main, "& path": { stroke: theme.palette.grey3.main },
"& path": { stroke: theme.palette.grey3.main }, },
}, }}
}} >
> {icon}
{icon} {isWrappMiniButtonSetting ? null : title}
{isWrappMiniButtonSetting ? null : title} </MiniButtonSetting>
</MiniButtonSetting>
</>
)} )}
</Box> </Box>
))} ))}
{/* <>
<MiniButtonSetting
onClick={undefined} // TODO
sx={{
minWidth: "30px",
height: "30px",
backgroundColor: "#FEDFD0",
}}
>
<DoubleTick style={{ color: "#FC712F", fontSize: "9px" }} />
</MiniButtonSetting>
<MiniButtonSetting
onClick={undefined} // TODO
sx={{
minWidth: "30px",
height: "30px",
backgroundColor: "#FEDFD0",
}}
>
<DoubleArrowRight style={{ color: "#FC712F", fontSize: "9px" }} />
</MiniButtonSetting>
<MiniButtonSetting
onClick={undefined} // TODO
sx={{
minWidth: "30px",
height: "30px",
backgroundColor: "#FEDFD0",
}}
>
<VectorQuestions style={{ color: "#FC712F", fontSize: "9px" }} />
</MiniButtonSetting>
</> */}
</Box> </Box>
<Box <Box
sx={{ sx={{
@ -272,27 +186,24 @@ export default function ButtonsOptions({
gap: "6px", gap: "6px",
}} }}
> >
{/* <IconButton sx={{ borderRadius: "6px", padding: "2px" }}>
<HideIcon style={{ color: "#4D4D4D" }} />
</IconButton> */}
<IconButton <IconButton
sx={{ borderRadius: "6px", padding: "2px" }} sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => copyQuestion(question.id, question.quizId)} onClick={() => copyQuestion(questionId, quiz.backendId)}
> >
<CopyIcon color={"#4D4D4D"} /> <CopyIcon color={"#4D4D4D"} />
</IconButton> </IconButton>
{(quiz?.config.type !== "form" || question.id !== questions[0].id) && ( {(quiz?.config.type !== "form" || !isQuestionFirst) && (
<IconButton <IconButton
sx={{ borderRadius: "6px", padding: "2px" }} sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => { onClick={() => {
if (question.type === null) { if (questionType === null) {
deleteQuestion(question.id); deleteQuestion(questionId);
} }
if (question.content.rule.parentId.length !== 0) { if (questionHasParent) {
setOpenDelete(true); setOpenDelete(true);
} else { } else {
deleteQuestionWithTimeout(question.id, () => deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(question.id), DeleteFunction(questionId),
); );
} }
}} }}
@ -336,8 +247,8 @@ export default function ButtonsOptions({
variant="contained" variant="contained"
sx={{ minWidth: "150px" }} sx={{ minWidth: "150px" }}
onClick={() => { onClick={() => {
deleteQuestionWithTimeout(question.id, () => deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(question.id), DeleteFunction(questionId),
); );
}} }}
> >
@ -349,4 +260,8 @@ export default function ButtonsOptions({
</Box> </Box>
</Box> </Box>
); );
} });
ButtonsOptions.displayName = "ButtonsOptions";
export default ButtonsOptions;

@ -1,7 +1,7 @@
import { QuizQuestionVarImg } from "@model/questionTypes/varimg"; import { QuizQuestionVarImg } from "@model/questionTypes/varimg";
import UploadImage from "../UploadImage"; import UploadImage from "../UploadImage";
import HelpQuestions from "../helpQuestions"; import HelpQuestions from "../helpQuestions";
import SettingOptionsAndPict from "./SettingOptionsAndPict"; import SettingOptionsAndPict from "../OptionsAndPicture/SettingOptionsAndPict";
interface Props { interface Props {
switchState: string; switchState: string;
@ -14,9 +14,21 @@ export default function SwitchOptionsAndPict({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <SettingOptionsAndPict question={question} />; return (
<SettingOptionsAndPict
questionId={question.id}
isRequired={question.content.required}
replText={question.content.replText}
/>
);
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
case "image": case "image":
return <UploadImage question={question} />; return <UploadImage question={question} />;
default: default:

@ -1,5 +1,4 @@
import { QuizQuestionVariant } from "@model/questionTypes/variant"; import { QuestionType } from "@model/question/question";
import { QuizQuestionVarImg } from "@model/questionTypes/varimg";
import { import {
Box, Box,
Button, Button,
@ -20,7 +19,7 @@ import { updateDesireToOpenABranchingModal } from "@root/uiTools/actions";
import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
import { ReallyChangingModal } from "@ui_kit/Modal/ReallyChangingModal/ReallyChangingModal"; import { ReallyChangingModal } from "@ui_kit/Modal/ReallyChangingModal/ReallyChangingModal";
import { DeleteFunction } from "@utils/deleteFunc"; import { DeleteFunction } from "@utils/deleteFunc";
import { useEffect, useState } from "react"; import { memo, useState } from "react";
import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon"; import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
import Branching from "../../assets/icons/questionsPage/branching"; import Branching from "../../assets/icons/questionsPage/branching";
import { DeleteIcon } from "../../assets/icons/questionsPage/deleteIcon"; import { DeleteIcon } from "../../assets/icons/questionsPage/deleteIcon";
@ -30,34 +29,37 @@ import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
interface Props { interface Props {
switchState: string; switchState: string;
SSHC: (data: string) => void; SSHC: (data: string) => void;
question: QuizQuestionVariant | QuizQuestionVarImg;
openBranchingPage: boolean; openBranchingPage: boolean;
setOpenBranchingPage: (a: boolean) => void; setOpenBranchingPage: (a: boolean) => void;
questionId: string;
questionType: QuestionType;
questionContentId: string;
questionHasParent: boolean;
} }
export default function ButtonsOptionsAndPict({ const ButtonsOptionsAndPict = memo<Props>(function ({
SSHC, SSHC,
switchState, switchState,
question,
openBranchingPage, openBranchingPage,
setOpenBranchingPage, setOpenBranchingPage,
}: Props) { questionId,
questionType,
questionContentId,
questionHasParent,
}) {
const [buttonHover, setButtonHover] = useState<string>(""); const [buttonHover, setButtonHover] = useState<string>("");
const [openedReallyChangingModal, setOpenedReallyChangingModal] = const [openedReallyChangingModal, setOpenedReallyChangingModal] =
useState<boolean>(false); useState<boolean>(false);
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isIconMobile = useMediaQuery(theme.breakpoints.down(1050)); const isIconMobile = useMediaQuery(theme.breakpoints.down(1050));
const { questions } = useQuestionsStore.getState();
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const [openDelete, setOpenDelete] = useState<boolean>(false); const [openDelete, setOpenDelete] = useState<boolean>(false);
const isQuestionFirst = useQuestionsStore(
(state) => state.questions[0]?.id === questionId,
);
useEffect(() => { if (!quiz) return null;
if (question.deleteTimeoutId) {
clearTimeout(question.deleteTimeoutId);
}
}, [question]);
return ( return (
<Box <Box
@ -112,218 +114,102 @@ export default function ButtonsOptionsAndPict({
/> />
{isIconMobile ? null : "Настройки"} {isIconMobile ? null : "Настройки"}
</MiniButtonSetting> </MiniButtonSetting>
{/*<MiniButtonSetting*/} {questionType !== "text" && (
{/* onMouseEnter={() => setButtonHover("help")}*/}
{/* onMouseLeave={() => setButtonHover("")}*/}
{/* onClick={() => {*/}
{/* SSHC("help");*/}
{/* }}*/}
{/* sx={{*/}
{/* minWidth: isIconMobile ? "30px" : "64px",*/}
{/* maxWidth: "102px",*/}
{/* height: "30px",*/}
{/* backgroundColor:*/}
{/* switchState === "help"*/}
{/* ? theme.palette.brightPurple.main*/}
{/* : "transparent",*/}
{/* color:*/}
{/* switchState === "help" ? "#ffffff" : theme.palette.grey3.main,*/}
{/* "&:hover": {*/}
{/* color: switchState === "help" ? theme.palette.grey3.main : null,*/}
{/* },*/}
{/* }}*/}
{/*>*/}
{/* <Clue*/}
{/* color={*/}
{/* buttonHover === "help"*/}
{/* ? theme.palette.grey3.main*/}
{/* : switchState === "help"*/}
{/* ? "#ffffff"*/}
{/* : theme.palette.grey3.main*/}
{/* }*/}
{/* />*/}
{/* {isIconMobile ? null : "Подсказка"}*/}
{/*</MiniButtonSetting>*/}
<>
{/* <Tooltip
arrow
placement="right"
componentsProps={{
tooltip: {
sx: {
background: "#fff",
borderRadius: "6px",
color: "#9A9AAF",
boxShadow: "0px 8px 24px rgba(210, 208, 225, 0.4)",
"& .MuiTooltip-arrow": {
color: "#FFF",
},
},
},
}}
title={
<Box>
<Typography
sx={{
color: "#4D4D4D",
fontWeight: "bold",
fontSize: "14px",
marginBottom: "10px",
}}
>
Будет показан при условии
</Typography>
<Typography sx={{ fontWeight: "bold", fontSize: "12px" }}>
Название
</Typography>
<Typography
sx={{
fontWeight: "bold",
fontSize: "12px",
marginBottom: "10px",
}}
>
Условие 1, Условие 2
</Typography>
<Typography sx={{ color: "#7E2AEA", fontSize: "12px" }}>
Все условия обязательны
</Typography>
</Box>
}
> */}
{question.type !== "text" && (
<MiniButtonSetting
onMouseEnter={() => setButtonHover("branching")}
onMouseLeave={() => setButtonHover("")}
onClick={() => {
setOpenBranchingPage(true);
updateDesireToOpenABranchingModal(question.content.id);
}}
sx={{
display: quiz.config.type === "form" ? "none" : "flex",
height: "30px",
maxWidth: "103px",
minWidth: isIconMobile ? "30px" : "64px",
backgroundColor:
switchState === "branching"
? theme.palette.brightPurple.main
: "transparent",
color:
switchState === "branching"
? "#ffffff"
: theme.palette.grey3.main,
"&:hover": {
color:
switchState === "branching"
? theme.palette.grey3.main
: null,
},
}}
>
<Branching
color={
buttonHover === "branching"
? theme.palette.grey3.main
: switchState === "branching"
? "#ffffff"
: theme.palette.grey3.main
}
/>
{isIconMobile ? null : "Ветвление"}
</MiniButtonSetting>
)}
{/* </Tooltip> */}
<MiniButtonSetting <MiniButtonSetting
onMouseEnter={() => setButtonHover("image")} onMouseEnter={() => setButtonHover("branching")}
onMouseLeave={() => setButtonHover("")} onMouseLeave={() => setButtonHover("")}
onClick={() => { onClick={() => {
SSHC("image"); setOpenBranchingPage(true);
updateDesireToOpenABranchingModal(questionContentId);
}} }}
sx={{ sx={{
display: quiz.config.type === "form" ? "none" : "flex",
height: "30px", height: "30px",
maxWidth: "123px", maxWidth: "103px",
minWidth: isIconMobile ? "30px" : "64px", minWidth: isIconMobile ? "30px" : "64px",
backgroundColor: backgroundColor:
switchState === "image" switchState === "branching"
? theme.palette.brightPurple.main ? theme.palette.brightPurple.main
: "transparent", : "transparent",
color: color:
switchState === "image" ? "#ffffff" : theme.palette.grey3.main, switchState === "branching"
? "#ffffff"
: theme.palette.grey3.main,
"&:hover": { "&:hover": {
color: color:
switchState === "image" ? theme.palette.grey3.main : null, switchState === "branching" ? theme.palette.grey3.main : null,
}, },
}} }}
> >
<ImgIcon <Branching
color={ color={
buttonHover === "image" buttonHover === "branching"
? theme.palette.grey3.main ? theme.palette.grey3.main
: switchState === "image" : switchState === "branching"
? "#ffffff" ? "#ffffff"
: theme.palette.grey3.main : theme.palette.grey3.main
} }
/> />
{isIconMobile ? null : "Изображение"} {isIconMobile ? null : "Ветвление"}
</MiniButtonSetting> </MiniButtonSetting>
{/* <MiniButtonSetting )}
onClick={() => setOpenedReallyChangingModal(true)} {/* </Tooltip> */}
sx={{ <MiniButtonSetting
minWidth: "30px", onMouseEnter={() => setButtonHover("image")}
height: "30px", onMouseLeave={() => setButtonHover("")}
backgroundColor: "#FEDFD0", onClick={() => {
}} SSHC("image");
> }}
<DoubleTick style={{ color: "#FC712F", fontSize: "9px" }} /> sx={{
</MiniButtonSetting> height: "30px",
<MiniButtonSetting maxWidth: "123px",
onClick={() => setOpenedReallyChangingModal(true)} minWidth: isIconMobile ? "30px" : "64px",
sx={{ backgroundColor:
minWidth: "30px", switchState === "image"
height: "30px", ? theme.palette.brightPurple.main
backgroundColor: "#FEDFD0", : "transparent",
}} color:
> switchState === "image" ? "#ffffff" : theme.palette.grey3.main,
<DoubleArrowRight style={{ color: "#FC712F", fontSize: "9px" }} /> "&:hover": {
</MiniButtonSetting> color: switchState === "image" ? theme.palette.grey3.main : null,
<MiniButtonSetting },
onClick={() => setOpenedReallyChangingModal(true)} }}
sx={{ >
minWidth: "30px", <ImgIcon
height: "30px", color={
backgroundColor: "#FEDFD0", buttonHover === "image"
}} ? theme.palette.grey3.main
> : switchState === "image"
<VectorQuestions style={{ color: "#FC712F", fontSize: "9px" }} /> ? "#ffffff"
</MiniButtonSetting> */} : theme.palette.grey3.main
</> }
/>
{isIconMobile ? null : "Изображение"}
</MiniButtonSetting>
</Box> </Box>
<Box <Box
sx={{ sx={{
padding: "20px", padding: "20px",
}} }}
> >
{/* <IconButton sx={{ borderRadius: "6px", padding: "0px 2px" }}>
<HideIcon style={{ color: "#4D4D4D" }} />
</IconButton> */}
<IconButton <IconButton
sx={{ borderRadius: "6px" }} sx={{ borderRadius: "6px" }}
onClick={() => copyQuestion(question.id, question.quizId)} onClick={() => copyQuestion(questionId, quiz.backendId)}
> >
<CopyIcon style={{ color: "#4D4D4D" }} /> <CopyIcon style={{ color: "#4D4D4D" }} />
</IconButton> </IconButton>
{(quiz?.config.type !== "form" || question.id !== questions[0].id) && ( {(quiz?.config.type !== "form" || !isQuestionFirst) && (
<IconButton <IconButton
sx={{ borderRadius: "6px", padding: "2px" }} sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => { onClick={() => {
if (question.type === null) { if (questionType === null) {
deleteQuestion(question.id); deleteQuestion(questionId);
} }
if (question.content.rule.parentId.length !== 0) { if (questionHasParent) {
setOpenDelete(true); setOpenDelete(true);
} else { } else {
deleteQuestionWithTimeout(question.id, () => deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(question.id), DeleteFunction(questionId),
); );
} }
}} }}
@ -367,8 +253,8 @@ export default function ButtonsOptionsAndPict({
variant="contained" variant="contained"
sx={{ minWidth: "150px" }} sx={{ minWidth: "150px" }}
onClick={() => { onClick={() => {
deleteQuestionWithTimeout(question.id, () => deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(question.id), DeleteFunction(questionId),
); );
}} }}
> >
@ -384,4 +270,8 @@ export default function ButtonsOptionsAndPict({
/> />
</Box> </Box>
); );
} });
ButtonsOptionsAndPict.displayName = "ButtonsOptionsAndPict";
export default ButtonsOptionsAndPict;

@ -27,10 +27,6 @@ export default function DataOptions({
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const SSHC = (data: string) => {
setSwitchState(data);
};
return ( return (
<> <>
<Box <Box
@ -75,9 +71,11 @@ export default function DataOptions({
</Box> </Box>
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchData switchState={switchState} question={question} /> <SwitchData switchState={switchState} question={question} />

@ -15,7 +15,13 @@ export default function SwitchData({
case "setting": case "setting":
return <SettingData question={question} />; return <SettingData question={question} />;
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -1,5 +1,5 @@
import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material"; import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material";
import { useState } from "react"; import { useCallback, useState } from "react";
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon"; import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
import { useAddAnswer } from "../../../utils/hooks/useAddAnswer"; import { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
import { AnswerDraggableList } from "../AnswerDraggableList"; import { AnswerDraggableList } from "../AnswerDraggableList";
@ -25,10 +25,6 @@ export default function DropDown({
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const SSHC = (data: string) => {
setSwitchState(data);
};
return ( return (
<> <>
<Box <Box
@ -108,9 +104,11 @@ export default function DropDown({
</Box> </Box>
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchDropDown switchState={switchState} question={question} /> <SwitchDropDown switchState={switchState} question={question} />

@ -2,19 +2,26 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions"; import { updateQuestion } from "@root/questions/actions";
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 { memo } from "react";
import type { QuizQuestionSelect } from "../../../model/questionTypes/select"; import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
type SettingDropDownProps = { type SettingDropDownProps = {
question: QuizQuestionSelect; questionId: string;
questionContentDefault: string;
isRequired: boolean;
}; };
export default function SettingDropDown({ question }: SettingDropDownProps) { const SettingDropDown = memo<SettingDropDownProps>(function ({
questionId,
questionContentDefault,
isRequired,
}) {
const theme = useTheme(); const theme = useTheme();
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const setContentDefault = (value: string) => { const setContentDefault = (value: string) => {
updateQuestion(question.id, (question) => { updateQuestion(questionId, (question) => {
if (question.type !== "select") return; if (question.type !== "select") return;
question.content.default = value; question.content.default = value;
@ -45,28 +52,6 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
maxWidth: isFigmaTablte ? "297px" : "360px", maxWidth: isFigmaTablte ? "297px" : "360px",
}} }}
> >
{/* <Typography
sx={{
height: isMobile ? "18px" : "auto",
fontWeight: "500",
fontSize: "18px",
color: " #4D4D4D",
}}
>
Настройки ответов
</Typography>
<CustomCheckbox
label={"Можно несколько"}
checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) =>
updateQuestion(question.id, question => {
if (question.type !== "select") return;
question.content.multi = target.checked;
})
}
/> */}
<Box <Box
sx={{ sx={{
display: isMobile ? "none" : "block", display: isMobile ? "none" : "block",
@ -86,7 +71,7 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
</Typography> </Typography>
<CustomTextField <CustomTextField
placeholder={"Выберите вариант"} placeholder={"Выберите вариант"}
value={question.content.default} value={questionContentDefault}
maxLength={60} maxLength={60}
onChange={({ target }) => setContentDefault(target.value)} onChange={({ target }) => setContentDefault(target.value)}
/> />
@ -117,34 +102,13 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
<CustomCheckbox <CustomCheckbox
dataCy="checkbox-optional-question" dataCy="checkbox-optional-question"
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!question.content.required} checked={!isRequired}
handleChange={(e) => { handleChange={(e) => {
updateQuestion<QuizQuestionSelect>(question.id, (question) => { updateQuestion<QuizQuestionSelect>(questionId, (question) => {
question.content.required = !e.target.checked; question.content.required = !e.target.checked;
}); });
}} }}
/> />
{/*<Box sx={{ position: "relative", display: "flex", alignItems: "flex-start" }}>*/}
{/* <CustomCheckbox*/}
{/* sx={{ height: isMobile ? "100%" : "26px", alignItems: isMobile ? "flex-start" : "center" }}*/}
{/* label={"Внутреннее название вопроса"}*/}
{/* checked={question.content.innerNameCheck}*/}
{/* handleChange={({ target }) => {*/}
{/* updateQuestion<QuizQuestionSelect>(question.id, question => {*/}
{/* question.content.innerNameCheck = target.checked;*/}
{/* question.content.innerName = target.checked ? question.content.innerName : "";*/}
{/* });*/}
{/* }}*/}
{/* />*/}
{/* <Tooltip*/}
{/* title="Будет отображаться как заголовок вопроса в приходящих заявках."*/}
{/* placement="top"*/}
{/* >*/}
{/* <Box>*/}
{/* <InfoIcon />*/}
{/* </Box>*/}
{/* </Tooltip>*/}
{/*</Box>*/}
<Box <Box
sx={{ sx={{
width: "100%", width: "100%",
@ -165,19 +129,16 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
</Typography> </Typography>
<CustomTextField <CustomTextField
placeholder={"Выберите вариант"} placeholder={"Выберите вариант"}
value={question.content.default} value={questionContentDefault}
onChange={({ target }) => setContentDefault(target.value)} onChange={({ target }) => setContentDefault(target.value)}
/> />
</Box> </Box>
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* placeholder={"Развёрнутое описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => debounced(target.value || " ")}*/}
{/* />*/}
{/*)}*/}
</Box> </Box>
</Box> </Box>
</> </>
); );
} });
SettingDropDown.displayName = "SettingDropDown";
export default SettingDropDown;

@ -13,10 +13,22 @@ export default function SwitchDropDown({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <SettingDropDown question={question} />; return (
<SettingDropDown
questionId={question.id}
questionContentDefault={question.content.default}
isRequired={question.content.required}
/>
);
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintVideo={question.content.hint.video}
hintText={question.content.hint.text}
/>
);
default: default:
return <></>; return null;
} }
} }

@ -39,10 +39,6 @@ export default function Emoji({
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const SSHC = (data: string) => {
setSwitchState(data);
};
return ( return (
<> <>
<Box sx={{ padding: "20px" }}> <Box sx={{ padding: "20px" }}>
@ -134,9 +130,11 @@ export default function Emoji({
</Box> </Box>
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchEmoji switchState={switchState} question={question} /> <SwitchEmoji switchState={switchState} question={question} />

@ -2,12 +2,17 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions"; import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox"; import CustomCheckbox from "@ui_kit/CustomCheckbox";
import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji"; import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
import { memo } from "react";
type SettingEmojiProps = { type SettingEmojiProps = {
question: QuizQuestionEmoji; questionId: string;
isRequired: boolean;
}; };
export default function SettingEmoji({ question }: SettingEmojiProps) { const SettingEmoji = memo<SettingEmojiProps>(function ({
questionId,
isRequired,
}) {
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
@ -21,43 +26,6 @@ export default function SettingEmoji({ question }: SettingEmojiProps) {
flexDirection: isWrappColumn ? "column" : "none", flexDirection: isWrappColumn ? "column" : "none",
}} }}
> >
{/* <Box
sx={{
pt: isMobile ? "25px" : "20px",
pb: isMobile ? "25px" : "20px",
pl: "20px",
pr: isFigmaTablte ? (isWrappColumn ? "20px" : "0px") : "0px",
display: "flex",
flexDirection: "column",
gap: "14px",
width: "100%",
}}
>
<Typography sx={{ height: isMobile ? "18px" : "auto", fontWeight: "500", fontSize: "18px", color: " #4D4D4D" }}>
Настройки ответов
</Typography>
<CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"}
checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "emoji") return;
question.content.multi = target.checked;
})}
/>
<CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={'Вариант "свой ответ"'}
checked={question.content.own}
handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "emoji") return;
question.content.own = target.checked;
})}
/>
</Box> */}
<Box <Box
sx={{ sx={{
pt: "20px", pt: "20px",
@ -84,49 +52,20 @@ export default function SettingEmoji({ question }: SettingEmojiProps) {
dataCy="checkbox-optional-question" dataCy="checkbox-optional-question"
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!question.content.required} checked={!isRequired}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestion<QuizQuestionEmoji>(question.id, (question) => { updateQuestion<QuizQuestionEmoji>(questionId, (question) => {
if (question.type !== "emoji") return; if (question.type !== "emoji") return;
question.content.required = !target.checked; question.content.required = !target.checked;
}) })
} }
/> />
{/*<Box*/}
{/* sx={{*/}
{/* width: isMobile ? "90%" : "auto",*/}
{/* display: "flex",*/}
{/* alignItems: "center",*/}
{/* }}*/}
{/*>*/}
{/* <CustomCheckbox*/}
{/* sx={{*/}
{/* mr: isMobile ? "0px" : "16px",*/}
{/* height: isMobile ? "100%" : "26px",*/}
{/* alignItems: isMobile ? "flex-start" : "center",*/}
{/* }}*/}
{/* label={"Внутреннее название вопроса"}*/}
{/* checked={question.content.innerNameCheck}*/}
{/* handleChange={({ target }) => updateQuestion<QuizQuestionEmoji>(question.id, question => {*/}
{/* question.content.innerNameCheck = target.checked;*/}
{/* question.content.innerName = target.checked ? question.content.innerName : "";*/}
{/* })}*/}
{/* />*/}
{/* <Tooltip title="Будет отображаться как заголовок вопроса в приходящих заявках." placement="top">*/}
{/* <Box>*/}
{/* <InfoIcon />*/}
{/* </Box>*/}
{/* </Tooltip>*/}
{/*</Box>*/}
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* placeholder={"Развёрнутое описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => setInnerName(target.value)}*/}
{/* />*/}
{/*)}*/}
</Box> </Box>
</Box> </Box>
); );
} });
SettingEmoji.displayName = "SettingEmoji";
export default SettingEmoji;

@ -13,9 +13,20 @@ export default function SwitchEmoji({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <SettingEmoji question={question} />; return (
<SettingEmoji
questionId={question.id}
isRequired={question.content.required}
/>
);
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -5,7 +5,7 @@ import {
} from "@root/questions/actions"; } from "@root/questions/actions";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal"; import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
import { useState } from "react"; import { useEffect, useState } from "react";
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon"; import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg"; import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
import { useDisclosure } from "../../../utils/useDisclosure"; import { useDisclosure } from "../../../utils/useDisclosure";
@ -44,10 +44,6 @@ export default function OptionsAndPicture({
setCropModalImageBlob, setCropModalImageBlob,
} = useCropModalState(); } = useCropModalState();
const SSHC = (data: string) => {
setSwitchState(data);
};
const handleImageUpload = async (file: File) => { const handleImageUpload = async (file: File) => {
if (!selectedVariantId) return; if (!selectedVariantId) return;
@ -90,6 +86,12 @@ export default function OptionsAndPicture({
}); });
} }
useEffect(() => {
if (question.deleteTimeoutId) {
clearTimeout(question.deleteTimeoutId);
}
}, [question]);
return ( return (
<> <>
<Box sx={{ pl: "20px", pr: "20px" }}> <Box sx={{ pl: "20px", pr: "20px" }}>
@ -172,8 +174,11 @@ export default function OptionsAndPicture({
</Box> </Box>
<ButtonsOptionsAndPict <ButtonsOptionsAndPict
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
questionContentId={question.content.id}
questionHasParent={question.content.rule.parentId.length !== 0}
questionType={question.type}
openBranchingPage={false} openBranchingPage={false}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />

@ -3,21 +3,26 @@ import { updateQuestion } from "@root/questions/actions";
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 type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg"; import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
import { memo } from "react";
type SettingOptionsAndPictProps = { type SettingOptionsAndPictProps = {
question: QuizQuestionVarImg; questionId: string;
replText: string;
isRequired: boolean;
}; };
export default function SettingOptionsAndPict({ const SettingOptionsAndPict = memo<SettingOptionsAndPictProps>(function ({
question, questionId,
}: SettingOptionsAndPictProps) { replText,
isRequired,
}) {
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(680)); const isMobile = useMediaQuery(theme.breakpoints.down(680));
const setReplText = (replText: string) => { const setReplText = (replText: string) => {
updateQuestion(question.id, (question) => { updateQuestion(questionId, (question) => {
if (question.type !== "varimg") return; if (question.type !== "varimg") return;
question.content.replText = replText; question.content.replText = replText;
@ -55,18 +60,6 @@ export default function SettingOptionsAndPict({
> >
Настройки ответов Настройки ответов
</Typography> </Typography>
{/*<CustomCheckbox*/}
{/* sx={{ mr: isMobile ? "0px" : "16px" }}*/}
{/* label={'Вариант "свой ответ"'}*/}
{/* checked={question.content.own}*/}
{/* handleChange={({ target }) =>*/}
{/* updateQuestion(question.id, (question) => {*/}
{/* if (question.type !== "varimg") return;*/}
{/* question.content.own = target.checked;*/}
{/* })*/}
{/* }*/}
{/*/>*/}
{!isWrappColumn && ( {!isWrappColumn && (
<Box sx={{ mt: isMobile ? "11px" : "6px", width: "100%" }}> <Box sx={{ mt: isMobile ? "11px" : "6px", width: "100%" }}>
<Typography <Typography
@ -88,7 +81,7 @@ export default function SettingOptionsAndPict({
}} }}
maxLength={60} maxLength={60}
placeholder={"Пример текста"} placeholder={"Пример текста"}
value={question.content.replText} value={replText}
onChange={({ target }) => setReplText(target.value)} onChange={({ target }) => setReplText(target.value)}
/> />
</Box> </Box>
@ -120,41 +113,15 @@ export default function SettingOptionsAndPict({
dataCy="checkbox-optional-question" dataCy="checkbox-optional-question"
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!question.content.required} checked={!isRequired}
handleChange={({ target }) => handleChange={({ target }) =>
updateQuestion<QuizQuestionVarImg>(question.id, (question) => { updateQuestion<QuizQuestionVarImg>(questionId, (question) => {
if (question.type !== "varimg") return; if (question.type !== "varimg") return;
question.content.required = !target.checked; question.content.required = !target.checked;
}) })
} }
/> />
{/*<Box sx={{ display: "flex", alignItems: "center" }}>*/}
{/* <CustomCheckbox*/}
{/* sx={{*/}
{/* width: isMobile ? "90%" : "auto",*/}
{/* mr: isMobile ? "0px" : "16px",*/}
{/* }}*/}
{/* label={"Внутреннее название вопроса"}*/}
{/* checked={question.content.innerNameCheck}*/}
{/* handleChange={({ target }) => updateQuestion<QuizQuestionVarImg>(question.id, question => {*/}
{/* question.content.innerNameCheck = target.checked;*/}
{/* question.content.innerName = "";*/}
{/* })}*/}
{/* />*/}
{/* <Tooltip title="Будет отображаться как заголовок вопроса в приходящих заявках." placement="top">*/}
{/* <Box>*/}
{/* <InfoIcon />*/}
{/* </Box>*/}
{/* </Tooltip>*/}
{/*</Box>*/}
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* placeholder={"Развёрнутое описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => setDescription(target.value)}*/}
{/* />*/}
{/*)}*/}
{isWrappColumn && ( {isWrappColumn && (
<> <>
<Typography <Typography
@ -170,7 +137,7 @@ export default function SettingOptionsAndPict({
<CustomTextField <CustomTextField
sx={{ maxWidth: "360px", width: "100%" }} sx={{ maxWidth: "360px", width: "100%" }}
placeholder={"Пример текста"} placeholder={"Пример текста"}
value={question.content.replText} value={replText}
maxLength={60} maxLength={60}
onChange={({ target }) => setReplText(target.value)} onChange={({ target }) => setReplText(target.value)}
/> />
@ -180,4 +147,8 @@ export default function SettingOptionsAndPict({
</Box> </Box>
</> </>
); );
} });
SettingOptionsAndPict.displayName = "SettingOptionsAndPict";
export default SettingOptionsAndPict;

@ -14,12 +14,24 @@ export default function SwitchOptionsAndPict({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <SettingOptionsAndPict question={question} />; return (
<SettingOptionsAndPict
questionId={question.id}
replText={question.content.replText}
isRequired={question.content.required}
/>
);
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
case "image": case "image":
return <UploadImage question={question} />; return <UploadImage question={question} />;
default: default:
return <></>; return null;
} }
} }

@ -44,10 +44,6 @@ export default function OptionsPicture({
setCropModalImageBlob, setCropModalImageBlob,
} = useCropModalState(); } = useCropModalState();
const SSHC = (data: string) => {
setSwitchState(data);
};
const handleImageUpload = async (file: File) => { const handleImageUpload = async (file: File) => {
if (!selectedVariantId) return; if (!selectedVariantId) return;
@ -159,9 +155,11 @@ export default function OptionsPicture({
</Box> </Box>
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchAnswerOptionsPict switchState={switchState} question={question} /> <SwitchAnswerOptionsPict switchState={switchState} question={question} />

@ -11,6 +11,7 @@ import ProportionsIcon11 from "../../../assets/icons/questionsPage/ProportionsIc
import ProportionsIcon12 from "../../../assets/icons/questionsPage/ProportionsIcon12"; import ProportionsIcon12 from "../../../assets/icons/questionsPage/ProportionsIcon12";
import ProportionsIcon21 from "../../../assets/icons/questionsPage/ProportionsIcon21"; import ProportionsIcon21 from "../../../assets/icons/questionsPage/ProportionsIcon21";
import type { QuizQuestionImages } from "../../../model/questionTypes/images"; import type { QuizQuestionImages } from "../../../model/questionTypes/images";
import { memo } from "react";
type Proportion = "1:1" | "2:1" | "1:2"; type Proportion = "1:1" | "2:1" | "1:2";
@ -26,227 +27,66 @@ const PROPORTIONS: ProportionItem[] = [
]; ];
type SettingOpytionsPictProps = { type SettingOpytionsPictProps = {
question: QuizQuestionImages; questionId: string;
isRequired: boolean;
}; };
export default function SettingOpytionsPict({ const SettingOptionsPict = memo<SettingOpytionsPictProps>(function ({
question, questionId,
}: SettingOpytionsPictProps) { isRequired,
}) {
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(985)); const isTablet = useMediaQuery(theme.breakpoints.down(985));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
return ( return (
<> <Box
sx={{
display: "flex",
justifyContent: "space-between",
flexDirection: isTablet ? "column" : null,
marginRight: isFigmaTablte ? (isMobile ? "0" : "0px") : "30px",
}}
>
<Box <Box
sx={{ sx={{
pt: isMobile ? "25px" : "20px",
pb: isMobile ? "25px" : "20px",
pl: "20px",
pr: isFigmaTablte ? (isMobile ? "20px" : "0px") : "28px",
display: "flex", display: "flex",
justifyContent: "space-between", flexDirection: "column",
flexDirection: isTablet ? "column" : null, gap: "14px",
marginRight: isFigmaTablte ? (isMobile ? "0" : "0px") : "30px", width: "100%",
}} }}
> >
{/* <Box <Typography
sx={{ sx={{ fontWeight: "500", fontSize: "18px", color: " #4D4D4D" }}
pt: isMobile ? "25px" : "20px",
pb: isMobile ? "25px" : "20px",
pl: "20px",
pr: isFigmaTablte ? (isMobile ? "20px" : "0px") : "28px",
display: "flex",
flexDirection: "column",
gap: "14px",
width: "100%",
}}
>
<Box sx={{ pb: isMobile ? "11px" : "6px" }}>
<Typography
sx={{
fontWeight: "500",
fontSize: "18px",
color: " #4D4D4D",
mb: isMobile ? "10px" : "14px",
}}
>
Пропорции
</Typography>
<Box
sx={{
display: "flex",
gap: "10px",
}}
>
{PROPORTIONS.map(({ value, icon }, index) => (
<SelectIconButton
key={index}
onClick={() => updateProportions(value)}
isActive={question.content.xy === value}
Icon={icon}
/>
))}
</Box>
</Box>
<Typography
sx={{ fontWeight: "500", fontSize: "18px", color: " #4D4D4D" }}
>
Настройки ответов
</Typography>
<CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Можно несколько"}
checked={question.content.multi}
dataCy="multiple-answers-checkbox"
handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "images") return;
question.content.multi = target.checked;
})
}
/>
{question.content.xy !== "1:1" &&
question.content.format !== "masonry" && (
<CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={"Большие картинки"}
checked={question.content.largeCheck}
handleChange={({ target }) =>
updateQuestion(question.id, question => {
if (question.type !== "images") return;
question.content.largeCheck = target.checked;
})
}
/>
)}
<CustomCheckbox
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
label={'Вариант "свой ответ"'}
checked={question.content.own}
handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "images") return;
question.content.own = target.checked;
})
}
/>
</Box> */}
<Box
sx={{
pt: isMobile ? "25px" : "20px",
pb: isMobile ? "25px" : "20px",
pl: "20px",
pr: isFigmaTablte ? (isMobile ? "20px" : "0px") : "28px",
display: "flex",
flexDirection: "column",
gap: "14px",
width: "100%",
}}
> >
{/* <Box Настройки вопросов
sx={{ </Typography>
marginBottom: "5px", <CustomCheckbox
opacity: question.content.xy !== "1:1" ? 1 : 0, dataCy="checkbox-optional-question"
display: isTablet sx={{ alignItems: isMobile ? "flex-start" : "" }}
? question.content.xy === "1:1" label={"Необязательный вопрос"}
? "none" checked={!isRequired}
: "block" handleChange={({ target }) =>
: "block", updateQuestion<QuizQuestionImages>(questionId, (question) => {
}} if (question.type !== "images") return;
>
<Typography
sx={{
marginBottom: "15px",
fontWeight: "500",
fontSize: "18px",
color: " #4D4D4D",
}}
>
Формат
</Typography>
<SelectIconButton
onClick={() => updateQuestion(question.id, question => {
if (question.type !== "images") return;
question.content.format = "carousel"; question.content.required = !target.checked;
}) })
} }
isActive={question.content.format === "carousel"} />
Icon={FormatIcon2}
/>
<SelectIconButton
onClick={() => updateQuestion(question.id, question => {
if (question.type !== "images") return;
question.content.format = "masonry";
})
}
isActive={question.content.format === "masonry"}
Icon={FormatIcon1}
/>
</Box> */}
<Typography
sx={{ fontWeight: "500", fontSize: "18px", color: " #4D4D4D" }}
>
Настройки вопросов
</Typography>
<CustomCheckbox
dataCy="checkbox-optional-question"
sx={{ alignItems: isMobile ? "flex-start" : "" }}
label={"Необязательный вопрос"}
checked={!question.content.required}
handleChange={({ target }) =>
updateQuestion<QuizQuestionImages>(question.id, (question) => {
if (question.type !== "images") return;
question.content.required = !target.checked;
})
}
/>
{/*<Box*/}
{/* sx={{*/}
{/* width: isMobile ? "90%" : "auto",*/}
{/* display: "flex",*/}
{/* alignItems: "center",*/}
{/* }}*/}
{/*>*/}
{/* <CustomCheckbox*/}
{/* sx={{*/}
{/* height: isMobile ? "100%" : "26px",*/}
{/* alignItems: isMobile ? "flex-start" : "center",*/}
{/* }}*/}
{/* label={"Внутреннее название вопроса"}*/}
{/* checked={question.content.innerNameCheck}*/}
{/* handleChange={({ target }) => updateQuestion(question.id, question => {*/}
{/* if (question.type !== "images") return;*/}
{/* question.content.innerNameCheck = target.checked;*/}
{/* question.content.innerName = "";*/}
{/* })*/}
{/* }*/}
{/* />*/}
{/* <Tooltip*/}
{/* title="Будет отображаться как заголовок вопроса в приходящих заявках."*/}
{/* placement="top"*/}
{/* >*/}
{/* <Box>*/}
{/* <InfoIcon />*/}
{/* </Box>*/}
{/* </Tooltip>*/}
{/*</Box>*/}
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* placeholder={"Внутреннее описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => debounced(target.value)}*/}
{/* />*/}
{/*)}*/}
</Box>
</Box> </Box>
</> </Box>
); );
} });
SettingOptionsPict.displayName = "SettingOptionsPict";
export default SettingOptionsPict;
interface Props { interface Props {
Icon: (props: { color: string }) => JSX.Element; Icon: (props: { color: string }) => JSX.Element;

@ -1,7 +1,6 @@
import * as React from "react";
import SettingOpytionsPict from "./settingOpytionsPict";
import HelpQuestions from "../helpQuestions";
import { QuizQuestionImages } from "@model/questionTypes/images"; import { QuizQuestionImages } from "@model/questionTypes/images";
import HelpQuestions from "../helpQuestions";
import SettingOpytionsPict from "./settingOpytionsPict";
interface Props { interface Props {
switchState: string; switchState: string;
@ -14,9 +13,20 @@ export default function SwitchAnswerOptionsPict({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <SettingOpytionsPict question={question} />; return (
<SettingOpytionsPict
questionId={question.id}
isRequired={question.content.required}
/>
);
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -8,7 +8,7 @@ import {
import { updateQuestion } from "@root/questions/actions"; import { updateQuestion } from "@root/questions/actions";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
import TooltipClickInfo from "@ui_kit/Toolbars/TooltipClickInfo"; import TooltipClickInfo from "@ui_kit/Toolbars/TooltipClickInfo";
import { useState } from "react"; import { useEffect, useState } from "react";
import InfoIcon from "../../../assets/icons/InfoIcon"; import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionText } from "../../../model/questionTypes/text"; import type { QuizQuestionText } from "../../../model/questionTypes/text";
import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict"; import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
@ -38,9 +38,11 @@ export default function OwnTextField({
}); });
}; };
const SSHC = (data: string) => { useEffect(() => {
setSwitchState(data); if (question.deleteTimeoutId) {
}; clearTimeout(question.deleteTimeoutId);
}
}, [question]);
return ( return (
<> <>
@ -102,8 +104,11 @@ export default function OwnTextField({
</Box> </Box>
<ButtonsOptionsAndPict <ButtonsOptionsAndPict
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
questionContentId={question.content.id}
questionHasParent={question.content.rule.parentId.length !== 0}
questionType={question.type}
openBranchingPage={openBranchingPage} openBranchingPage={openBranchingPage}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />

@ -2,9 +2,11 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions"; import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox"; import CustomCheckbox from "@ui_kit/CustomCheckbox";
import type { QuizQuestionText } from "../../../model/questionTypes/text"; import type { QuizQuestionText } from "../../../model/questionTypes/text";
import { memo } from "react";
type SettingTextFieldProps = { type SettingTextFieldProps = {
question: QuizQuestionText; questionId: string;
isRequired: boolean;
}; };
type Answer = { type Answer = {
@ -17,7 +19,10 @@ const ANSWER_TYPES: Answer[] = [
{ name: "Многострочное", value: "multi" }, { name: "Многострочное", value: "multi" },
]; ];
export default function SettingTextField({ question }: SettingTextFieldProps) { const SettingTextField = memo<SettingTextFieldProps>(function ({
questionId,
isRequired,
}) {
const theme = useTheme(); const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -32,79 +37,6 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
marginRight: isFigmaTablte ? "0px" : "32px", marginRight: isFigmaTablte ? "0px" : "32px",
}} }}
> >
{/* <Box
sx={{
pt: isMobile ? "25px" : "20px",
pb: isMobile ? "25px" : "20px",
pl: "20px",
}}
>
<Typography
sx={{
fontWeight: "500",
fontSize: "18px",
color: " #4D4D4D",
marginBottom: "14px",
}}
>
Настройки ответов
</Typography>
<FormControl>
<RadioGroup
sx={{
display: "flex",
flexDirection: "column",
gap: "14px",
width: "100%",
}}
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={ANSWER_TYPES.findIndex(
({ value }) => question.content.answerType === value
)}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
updateQuestion(question.id, question => {
if (question.type !== "text") return;
question.content.answerType = ANSWER_TYPES[Number(target.value)].value;
});
}}
>
{ANSWER_TYPES.map(({ name }, index) => (
<FormControlLabel
key={index}
sx={{
height: "26px",
color: theme.palette.grey2.main,
"& .MuiRadio-root": { padding: "8px 9px" },
}}
value={index}
control={
<Radio icon={<CheckIcon />} checkedIcon={<CheckedIcon />} />
}
label={name}
/>
))}
</RadioGroup>
</FormControl>
<CustomCheckbox
sx={{
display: isMobile ? "flex" : "block",
mr: isMobile ? "0px" : "16px",
marginTop: "15px",
alignItems: isMobile ? "flex-end" : "center",
}}
label={"Только числа"}
checked={question.content.onlyNumbers}
handleChange={({ target }) => {
updateQuestion(question.id, question => {
if (question.type !== "text") return;
question.content.onlyNumbers = target.checked;
});
}}
/>
</Box> */}
<Box <Box
sx={{ sx={{
pt: "20px", pt: "20px",
@ -126,20 +58,6 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
> >
Настройки вопросов Настройки вопросов
</Typography> </Typography>
{/* <CustomCheckbox
sx={{
display: isMobile ? "flex" : "block",
mr: isMobile ? "0px" : "16px",
alignItems: isMobile ? "flex-end" : "center",
}}
label={"Автозаполнение адреса"}
checked={question.content.autofill}
handleChange={({ target }) => {
updateQuestion(question.id, question => {
question.content.autofill = target.checked;
});
}}
/> */}
<CustomCheckbox <CustomCheckbox
dataCy="checkbox-optional-question" dataCy="checkbox-optional-question"
sx={{ sx={{
@ -148,55 +66,18 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
alignItems: isMobile ? "flex-end" : "center", alignItems: isMobile ? "flex-end" : "center",
}} }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!question.content.required} checked={!isRequired}
handleChange={(e) => { handleChange={(e) => {
updateQuestion<QuizQuestionText>(question.id, (question) => { updateQuestion<QuizQuestionText>(questionId, (question) => {
question.content.required = !e.target.checked; question.content.required = !e.target.checked;
}); });
}} }}
/> />
{/*<Box*/}
{/* sx={{*/}
{/* width: isMobile ? "90%" : "auto",*/}
{/* display: "flex",*/}
{/* alignItems: "center",*/}
{/* }}*/}
{/*>*/}
{/* <CustomCheckbox*/}
{/* sx={{*/}
{/* alignItems: isMobile ? "flex-start" : "center",*/}
{/* display: isMobile ? "flex" : "block",*/}
{/* mr: isMobile ? "0px" : "16px",*/}
{/* height: isMobile ? "100%" : "26px",*/}
{/* }}*/}
{/* label={"Внутреннее название вопроса"}*/}
{/* checked={question.content.innerNameCheck}*/}
{/* handleChange={({ target }) => {*/}
{/* updateQuestion<QuizQuestionText>(question.id, question => {*/}
{/* question.content.innerNameCheck = target.checked;*/}
{/* question.content.innerName = target.checked*/}
{/* ? question.content.innerName*/}
{/* : "";*/}
{/* });*/}
{/* }}*/}
{/* />*/}
{/* <Tooltip*/}
{/* title="Будет отображаться как заголовок вопроса в приходящих заявках."*/}
{/* placement="top"*/}
{/* >*/}
{/* <Box>*/}
{/* <InfoIcon />*/}
{/* </Box>*/}
{/* </Tooltip>*/}
{/*</Box>*/}
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* placeholder={"Развёрнутое описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => debounced(target.value)}*/}
{/* />*/}
{/*)}*/}
</Box> </Box>
</Box> </Box>
); );
} });
SettingTextField.displayName = "SettingTextField";
export default SettingTextField;

@ -14,11 +14,22 @@ export default function SwitchTextField({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <SettingTextField question={question} />; return (
<SettingTextField
questionId={question.id}
isRequired={question.content.required}
/>
);
case "image": case "image":
return <UploadImage question={question} />; return <UploadImage question={question} />;
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -15,7 +15,13 @@ export default function SwitchPageOptions({
case "setting": case "setting":
return <SettingPageOptions question={question} />; return <SettingPageOptions question={question} />;
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -135,10 +135,6 @@ export default function RatingOptions({
}, },
]; ];
const SSHC = (data: string) => {
setSwitchState(data);
};
return ( return (
<> <>
<Box <Box
@ -311,9 +307,11 @@ export default function RatingOptions({
</Box> </Box>
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchRating switchState={switchState} question={question} /> <SwitchRating switchState={switchState} question={question} />

@ -15,7 +15,13 @@ export default function SwitchRating({
case "setting": case "setting":
return <SettingRating question={question} />; return <SettingRating question={question} />;
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -224,8 +224,10 @@ export default function SliderOptions({
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={setSwitchState} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchSlider switchState={switchState} question={question} /> <SwitchSlider switchState={switchState} question={question} />

@ -15,7 +15,13 @@ export default function SwitchSlider({
case "setting": case "setting":
return <SettingSlider question={question} />; return <SettingSlider question={question} />;
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -51,10 +51,6 @@ export default function UploadFile({
const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const SSHC = (data: string) => {
setSwitchState(data);
};
const handleChange = ({ target }: SelectChangeEvent) => { const handleChange = ({ target }: SelectChangeEvent) => {
updateQuestion(question.id, (question) => { updateQuestion(question.id, (question) => {
if (question.type !== "file") return; if (question.type !== "file") return;
@ -205,9 +201,11 @@ export default function UploadFile({
</Box> </Box>
<ButtonsOptions <ButtonsOptions
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
openBranchingPage={openBranchingPage} questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />
<SwitchUpload switchState={switchState} question={question} /> <SwitchUpload switchState={switchState} question={question} />

@ -15,7 +15,13 @@ export default function SwitchUpload({
case "setting": case "setting":
return <SettingsUpload question={question} />; return <SettingsUpload question={question} />;
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default: default:
return <></>; return <></>;
} }

@ -1,5 +1,5 @@
import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material"; import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material";
import { useState } from "react"; import { useEffect, useState } from "react";
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon"; import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant"; import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
import { useAddAnswer } from "../../../utils/hooks/useAddAnswer"; import { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
@ -24,9 +24,11 @@ export default function AnswerOptions({
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const SSHC = (data: string) => { useEffect(() => {
setSwitchState(data); if (question.deleteTimeoutId) {
}; clearTimeout(question.deleteTimeoutId);
}
}, [question]);
return ( return (
<> <>
@ -104,8 +106,11 @@ export default function AnswerOptions({
</Box> </Box>
<ButtonsOptionsAndPict <ButtonsOptionsAndPict
switchState={switchState} switchState={switchState}
SSHC={SSHC} SSHC={setSwitchState}
question={question} questionId={question.id}
questionContentId={question.content.id}
questionHasParent={question.content.rule.parentId.length !== 0}
questionType={question.type}
openBranchingPage={openBranchingPage} openBranchingPage={openBranchingPage}
setOpenBranchingPage={setOpenBranchingPage} setOpenBranchingPage={setOpenBranchingPage}
/> />

@ -2,15 +2,16 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions"; import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox"; import CustomCheckbox from "@ui_kit/CustomCheckbox";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant"; import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
import { memo } from "react";
interface Props { interface Props {
question: QuizQuestionVariant; questionId: string;
isRequired: boolean;
} }
export default function ResponseSettings({ question }: Props) { const ResponseSettings = memo<Props>(function ({ questionId, isRequired }) {
const theme = useTheme(); const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(900)); const isTablet = useMediaQuery(theme.breakpoints.down(900));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -23,65 +24,6 @@ export default function ResponseSettings({ question }: Props) {
marginRight: isFigmaTablte ? (isMobile ? "0" : "0px") : "30px", marginRight: isFigmaTablte ? (isMobile ? "0" : "0px") : "30px",
}} }}
> >
{/*<Box*/}
{/* sx={{*/}
{/* pt: isMobile ? "25px" : "20px",*/}
{/* pb: isMobile ? "25px" : "20px",*/}
{/* pl: "20px",*/}
{/* display: "flex",*/}
{/* flexDirection: "column",*/}
{/* gap: "14px",*/}
{/* width: "100%",*/}
{/* }}*/}
{/*>*/}
{/* <Typography*/}
{/* sx={{*/}
{/* height: isMobile ? "18px" : "auto",*/}
{/* fontWeight: "500",*/}
{/* fontSize: "18px",*/}
{/* color: " #4D4D4D",*/}
{/* }}*/}
{/* >*/}
{/* Настройки ответов*/}
{/* </Typography>*/}
{/* <CustomCheckbox*/}
{/* sx={{ mr: isMobile ? "0px" : "16px" }}*/}
{/* label={"Длинный текстовый ответ"}*/}
{/* checked={question.content.largeCheck}*/}
{/* handleChange={({ target }) => {*/}
{/* updateQuestion(question.id, (question) => {*/}
{/* if (!("largeCheck" in question.content)) return;*/}
{/* */}
{/* question.content.largeCheck = target.checked;*/}
{/* });*/}
{/* }}*/}
{/* />*/}
{/* <CustomCheckbox*/}
{/* sx={{ mr: isMobile ? "0px" : "16px" }}*/}
{/* label={"Можно несколько"}*/}
{/* checked={question.content.multi}*/}
{/* dataCy="multiple-answers-checkbox"*/}
{/* handleChange={({ target }) => {*/}
{/* updateQuestion(question.id, (question) => {*/}
{/* if (!("multi" in question.content)) return;*/}
{/* */}
{/* question.content.multi = target.checked;*/}
{/* });*/}
{/* }}*/}
{/* />*/}
{/* <CustomCheckbox*/}
{/* sx={{ mr: isMobile ? "0px" : "16px" }}*/}
{/* label={'Вариант "свой ответ"'}*/}
{/* checked={question.content.own}*/}
{/* handleChange={({ target }) => {*/}
{/* updateQuestion(question.id, (question) => {*/}
{/* if (!("own" in question.content)) return;*/}
{/* */}
{/* question.content.own = target.checked;*/}
{/* });*/}
{/* }}*/}
{/* /> */}
{/*</Box>*/}
<Box <Box
sx={{ sx={{
boxSizing: "border-box", boxSizing: "border-box",
@ -109,57 +51,18 @@ export default function ResponseSettings({ question }: Props) {
dataCy="checkbox-optional-question" dataCy="checkbox-optional-question"
sx={{ mr: isMobile ? "0px" : "16px" }} sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"} label={"Необязательный вопрос"}
checked={!question.content.required} checked={!isRequired}
handleChange={({ target }) => { handleChange={({ target }) => {
updateQuestion<QuizQuestionVariant>(question.id, (question) => { updateQuestion<QuizQuestionVariant>(questionId, (question) => {
question.content.required = !target.checked; question.content.required = !target.checked;
}); });
}} }}
/> />
{/*<Box*/}
{/* sx={{*/}
{/* width: isMobile ? "90%" : "auto",*/}
{/* display: "flex",*/}
{/* alignItems: "center",*/}
{/* }}*/}
{/*>*/}
{/* <CustomCheckbox*/}
{/* sx={{*/}
{/* mr: isMobile ? "0px" : "9px",*/}
{/* height: isMobile ? "42px" : "26px",*/}
{/* alignItems: "start",*/}
{/* }}*/}
{/* label={"Внутреннее название вопроса"}*/}
{/* checked={question.content.innerNameCheck}*/}
{/* handleChange={({ target }) => {*/}
{/* updateQuestion<QuizQuestionVariant>(question.id, (question) => {*/}
{/* question.content.innerNameCheck = target.checked;*/}
{/* question.content.innerName = target.checked*/}
{/* ? question.content.innerName*/}
{/* : "";*/}
{/* });*/}
{/* }}*/}
{/* />*/}
{/* {isMobile && (*/}
{/* <Tooltip*/}
{/* title="Будет отображаться как заголовок вопроса в приходящих заявках."*/}
{/* placement="top"*/}
{/* >*/}
{/* <Box>*/}
{/* <InfoIcon />*/}
{/* </Box>*/}
{/* </Tooltip>*/}
{/* )}*/}
{/*</Box>*/}
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* sx={{ mr: isMobile ? "0px" : "16px" }}*/}
{/* placeholder={"Развёрнутое описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => updateQuestionInnerName(target.value || " ")}*/}
{/* />*/}
{/*)}*/}
</Box> </Box>
</Box> </Box>
); );
} });
ResponseSettings.displayName = "ResponseSettings";
export default ResponseSettings;

@ -14,12 +14,23 @@ export default function SwitchAnswerOptions({
}: Props) { }: Props) {
switch (switchState) { switch (switchState) {
case "setting": case "setting":
return <ResponseSettings question={question} />; return (
<ResponseSettings
questionId={question.id}
isRequired={question.content.required}
/>
);
case "help": case "help":
return <HelpQuestions question={question} />; return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
case "image": case "image":
return <UploadImage question={question} />; return <UploadImage question={question} />;
default: default:
return <></>; return null;
} }
} }

@ -1,25 +1,30 @@
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { Box, ButtonBase, Typography } from "@mui/material"; import { Box, ButtonBase, Typography } from "@mui/material";
import { updateQuestion } from "@root/questions/actions"; import { updateQuestion } from "@root/questions/actions";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
import SelectableButton from "@ui_kit/SelectableButton"; import SelectableButton from "@ui_kit/SelectableButton";
import UploadBox from "@ui_kit/UploadBox"; import UploadBox from "@ui_kit/UploadBox";
import { useState } from "react"; import { memo, useState } from "react";
import UploadIcon from "../../assets/icons/UploadIcon"; import UploadIcon from "../../assets/icons/UploadIcon";
import { UploadVideoModal } from "./UploadVideoModal"; import { UploadVideoModal } from "./UploadVideoModal";
type BackgroundType = "text" | "video"; type BackgroundType = "text" | "video";
type HelpQuestionsProps = { type HelpQuestionsProps = {
question: AnyTypedQuizQuestion; questionId: string;
hintVideo: string;
hintText: string;
}; };
export default function HelpQuestions({ question }: HelpQuestionsProps) { const HelpQuestions = memo<HelpQuestionsProps>(function ({
questionId,
hintVideo,
hintText,
}) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [backgroundType, setBackgroundType] = useState<BackgroundType>("text"); const [backgroundType, setBackgroundType] = useState<BackgroundType>("text");
const updateQuestionHint = (value: string) => { const updateQuestionHint = (value: string) => {
updateQuestion(question.id, (question) => { updateQuestion(questionId, (question) => {
question.content.hint.text = value; question.content.hint.text = value;
}); });
}; };
@ -59,7 +64,7 @@ export default function HelpQuestions({ question }: HelpQuestionsProps) {
<> <>
<CustomTextField <CustomTextField
placeholder={"Текст консультанта"} placeholder={"Текст консультанта"}
value={question.content.hint.text} value={hintText}
onChange={({ target }) => updateQuestionHint(target.value || " ")} onChange={({ target }) => updateQuestionHint(target.value || " ")}
maxLength={100} maxLength={100}
/> />
@ -73,8 +78,8 @@ export default function HelpQuestions({ question }: HelpQuestionsProps) {
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
sx={{ justifyContent: "flex-start" }} sx={{ justifyContent: "flex-start" }}
> >
{question.content.hint.video ? ( {hintVideo ? (
<video src={question.content.hint.video} width="400" controls /> <video src={hintVideo} width="400" controls />
) : ( ) : (
<> <>
<UploadBox <UploadBox
@ -90,9 +95,9 @@ export default function HelpQuestions({ question }: HelpQuestionsProps) {
<UploadVideoModal <UploadVideoModal
open={open} open={open}
onClose={() => setOpen(false)} onClose={() => setOpen(false)}
video={question.content.hint.video} video={hintVideo}
onUpload={(url) => onUpload={(url) =>
updateQuestion(question.id, (question) => { updateQuestion(questionId, (question) => {
question.content.hint.video = url; question.content.hint.video = url;
}) })
} }
@ -101,4 +106,8 @@ export default function HelpQuestions({ question }: HelpQuestionsProps) {
)} )}
</Box> </Box>
); );
} });
HelpQuestions.displayName = "HelpQuestions";
export default HelpQuestions;

@ -2,7 +2,7 @@ import { Button, ClickAwayListener, IconButton, Tooltip } from "@mui/material";
import InfoIcon from "@icons/InfoIcon"; import InfoIcon from "@icons/InfoIcon";
import { useState } from "react"; import { useState } from "react";
export default function TooltipClickInfo({ title }: string) { export default function TooltipClickInfo({ title }: { title: string }) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const handleTooltipClose = () => { const handleTooltipClose = () => {