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 MiniButtonSetting from "@ui_kit/MiniButtonSetting";
import { DeleteFunction } from "@utils/deleteFunc";
import { useState } from "react";
import { memo, useState } from "react";
import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
import Branching from "../../assets/icons/questionsPage/branching";
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import { QuestionType } from "@model/question/question";
interface Props {
switchState: string;
SSHC: (data: string) => void;
question: AnyTypedQuizQuestion;
sx?: SxProps;
openBranchingPage: boolean;
questionId: string;
questionContentId: string;
questionType: QuestionType;
questionHasParent: boolean;
setOpenBranchingPage: (a: boolean) => void;
sx?: SxProps;
}
export default function ButtonsOptions({
const ButtonsOptions = memo<Props>(function ({
SSHC,
switchState,
question,
openBranchingPage,
questionId,
questionContentId,
questionType,
questionHasParent,
setOpenBranchingPage,
}: Props) {
}) {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
const quiz = useCurrentQuiz();
const { questions } = useQuestionsStore.getState();
const [openDelete, setOpenDelete] = useState<boolean>(false);
const isQuestionFirst = useQuestionsStore(
(state) => state.questions[0]?.id === questionId,
);
if (!quiz) return null;
const openedModal = () => {
setOpenBranchingPage(true);
updateDesireToOpenABranchingModal(question.content.id);
updateDesireToOpenABranchingModal(questionContentId);
};
const buttonSetting: {
@ -70,15 +78,6 @@ export default function ButtonsOptions({
title: "Настройки",
value: "setting",
},
// {
// icon: (
// <Clue
// color={switchState === "help" ? "#ffffff" : theme.palette.grey3.main}
// />
// ),
// title: "Подсказка",
// value: "help",
// },
{
icon: (
<Branching
@ -89,6 +88,7 @@ export default function ButtonsOptions({
),
title: "Ветвление",
value: "branching",
// @ts-ignore
myFunc: (question) => {
setOpenBranchingPage(true);
updateDesireToOpenABranchingModal(question.content.id);
@ -118,64 +118,13 @@ export default function ButtonsOptions({
{buttonSetting.map(({ icon, title, value, myFunc }) => (
<Box key={value}>
{value === "branching" ? (
question.type === "page" ||
question.type === "text" ||
question.type === "date" ||
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>
// }
// >
["page", "text", "date", "number"].includes(
questionType,
) ? null : (
<MiniButtonSetting
key={title}
onClick={() => {
openedModal();
// SSHC(value);
// myFunc(question);
}}
sx={{
display: quiz.config.type === "form" ? "none" : "flex",
@ -198,72 +147,37 @@ export default function ButtonsOptions({
{icon}
{isWrappMiniButtonSetting ? null : title}
</MiniButtonSetting>
// </Tooltip>
)
) : (
<>
<MiniButtonSetting
key={title}
onClick={() => {
SSHC(value);
myFunc();
}}
sx={{
backgroundColor:
switchState === value
? theme.palette.brightPurple.main
: "transparent",
color:
switchState === value
? "#ffffff"
: theme.palette.grey3.main,
minWidth: isWrappMiniButtonSetting ? "30px" : "64px",
height: "30px",
"&:hover": {
color: theme.palette.grey3.main,
"& path": { stroke: theme.palette.grey3.main },
},
}}
>
{icon}
{isWrappMiniButtonSetting ? null : title}
</MiniButtonSetting>
</>
<MiniButtonSetting
key={title}
onClick={() => {
SSHC(value);
myFunc();
}}
sx={{
backgroundColor:
switchState === value
? theme.palette.brightPurple.main
: "transparent",
color:
switchState === value
? "#ffffff"
: theme.palette.grey3.main,
minWidth: isWrappMiniButtonSetting ? "30px" : "64px",
height: "30px",
"&:hover": {
color: theme.palette.grey3.main,
"& path": { stroke: theme.palette.grey3.main },
},
}}
>
{icon}
{isWrappMiniButtonSetting ? null : title}
</MiniButtonSetting>
)}
</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
sx={{
@ -272,27 +186,24 @@ export default function ButtonsOptions({
gap: "6px",
}}
>
{/* <IconButton sx={{ borderRadius: "6px", padding: "2px" }}>
<HideIcon style={{ color: "#4D4D4D" }} />
</IconButton> */}
<IconButton
sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => copyQuestion(question.id, question.quizId)}
onClick={() => copyQuestion(questionId, quiz.backendId)}
>
<CopyIcon color={"#4D4D4D"} />
</IconButton>
{(quiz?.config.type !== "form" || question.id !== questions[0].id) && (
{(quiz?.config.type !== "form" || !isQuestionFirst) && (
<IconButton
sx={{ borderRadius: "6px", padding: "2px" }}
onClick={() => {
if (question.type === null) {
deleteQuestion(question.id);
if (questionType === null) {
deleteQuestion(questionId);
}
if (question.content.rule.parentId.length !== 0) {
if (questionHasParent) {
setOpenDelete(true);
} else {
deleteQuestionWithTimeout(question.id, () =>
DeleteFunction(question.id),
deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(questionId),
);
}
}}
@ -336,8 +247,8 @@ export default function ButtonsOptions({
variant="contained"
sx={{ minWidth: "150px" }}
onClick={() => {
deleteQuestionWithTimeout(question.id, () =>
DeleteFunction(question.id),
deleteQuestionWithTimeout(questionId, () =>
DeleteFunction(questionId),
);
}}
>
@ -349,4 +260,8 @@ export default function ButtonsOptions({
</Box>
</Box>
);
}
});
ButtonsOptions.displayName = "ButtonsOptions";
export default ButtonsOptions;

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

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

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

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

@ -1,5 +1,5 @@
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 { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
import { AnswerDraggableList } from "../AnswerDraggableList";
@ -25,10 +25,6 @@ export default function DropDown({
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const SSHC = (data: string) => {
setSwitchState(data);
};
return (
<>
<Box
@ -108,9 +104,11 @@ export default function DropDown({
</Box>
<ButtonsOptions
switchState={switchState}
SSHC={SSHC}
question={question}
openBranchingPage={openBranchingPage}
SSHC={setSwitchState}
questionId={question.id}
questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId.length !== 0}
setOpenBranchingPage={setOpenBranchingPage}
/>
<SwitchDropDown switchState={switchState} question={question} />

@ -2,19 +2,26 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import CustomTextField from "@ui_kit/CustomTextField";
import { memo } from "react";
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
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 isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const setContentDefault = (value: string) => {
updateQuestion(question.id, (question) => {
updateQuestion(questionId, (question) => {
if (question.type !== "select") return;
question.content.default = value;
@ -45,28 +52,6 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
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
sx={{
display: isMobile ? "none" : "block",
@ -86,7 +71,7 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
</Typography>
<CustomTextField
placeholder={"Выберите вариант"}
value={question.content.default}
value={questionContentDefault}
maxLength={60}
onChange={({ target }) => setContentDefault(target.value)}
/>
@ -117,34 +102,13 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
<CustomCheckbox
dataCy="checkbox-optional-question"
label={"Необязательный вопрос"}
checked={!question.content.required}
checked={!isRequired}
handleChange={(e) => {
updateQuestion<QuizQuestionSelect>(question.id, (question) => {
updateQuestion<QuizQuestionSelect>(questionId, (question) => {
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
sx={{
width: "100%",
@ -165,19 +129,16 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
</Typography>
<CustomTextField
placeholder={"Выберите вариант"}
value={question.content.default}
value={questionContentDefault}
onChange={({ target }) => setContentDefault(target.value)}
/>
</Box>
{/*{question.content.innerNameCheck && (*/}
{/* <CustomTextField*/}
{/* placeholder={"Развёрнутое описание вопроса"}*/}
{/* text={question.content.innerName}*/}
{/* onChange={({ target }) => debounced(target.value || " ")}*/}
{/* />*/}
{/*)}*/}
</Box>
</Box>
</>
);
}
});
SettingDropDown.displayName = "SettingDropDown";
export default SettingDropDown;

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

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

@ -2,12 +2,17 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
import { memo } from "react";
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 isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
@ -21,43 +26,6 @@ export default function SettingEmoji({ question }: SettingEmojiProps) {
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
sx={{
pt: "20px",
@ -84,49 +52,20 @@ export default function SettingEmoji({ question }: SettingEmojiProps) {
dataCy="checkbox-optional-question"
sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"}
checked={!question.content.required}
checked={!isRequired}
handleChange={({ target }) =>
updateQuestion<QuizQuestionEmoji>(question.id, (question) => {
updateQuestion<QuizQuestionEmoji>(questionId, (question) => {
if (question.type !== "emoji") return;
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>
);
}
});
SettingEmoji.displayName = "SettingEmoji";
export default SettingEmoji;

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

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

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

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

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

@ -11,6 +11,7 @@ import ProportionsIcon11 from "../../../assets/icons/questionsPage/ProportionsIc
import ProportionsIcon12 from "../../../assets/icons/questionsPage/ProportionsIcon12";
import ProportionsIcon21 from "../../../assets/icons/questionsPage/ProportionsIcon21";
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
import { memo } from "react";
type Proportion = "1:1" | "2:1" | "1:2";
@ -26,227 +27,66 @@ const PROPORTIONS: ProportionItem[] = [
];
type SettingOpytionsPictProps = {
question: QuizQuestionImages;
questionId: string;
isRequired: boolean;
};
export default function SettingOpytionsPict({
question,
}: SettingOpytionsPictProps) {
const SettingOptionsPict = memo<SettingOpytionsPictProps>(function ({
questionId,
isRequired,
}) {
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(985));
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
return (
<>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
flexDirection: isTablet ? "column" : null,
marginRight: isFigmaTablte ? (isMobile ? "0" : "0px") : "30px",
}}
>
<Box
sx={{
pt: isMobile ? "25px" : "20px",
pb: isMobile ? "25px" : "20px",
pl: "20px",
pr: isFigmaTablte ? (isMobile ? "20px" : "0px") : "28px",
display: "flex",
justifyContent: "space-between",
flexDirection: isTablet ? "column" : null,
marginRight: isFigmaTablte ? (isMobile ? "0" : "0px") : "30px",
flexDirection: "column",
gap: "14px",
width: "100%",
}}
>
{/* <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={{ 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%",
}}
<Typography
sx={{ fontWeight: "500", fontSize: "18px", color: " #4D4D4D" }}
>
{/* <Box
sx={{
marginBottom: "5px",
opacity: question.content.xy !== "1:1" ? 1 : 0,
display: isTablet
? question.content.xy === "1:1"
? "none"
: "block"
: "block",
}}
>
<Typography
sx={{
marginBottom: "15px",
fontWeight: "500",
fontSize: "18px",
color: " #4D4D4D",
}}
>
Формат
</Typography>
<SelectIconButton
onClick={() => updateQuestion(question.id, question => {
if (question.type !== "images") return;
Настройки вопросов
</Typography>
<CustomCheckbox
dataCy="checkbox-optional-question"
sx={{ alignItems: isMobile ? "flex-start" : "" }}
label={"Необязательный вопрос"}
checked={!isRequired}
handleChange={({ target }) =>
updateQuestion<QuizQuestionImages>(questionId, (question) => {
if (question.type !== "images") return;
question.content.format = "carousel";
})
}
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>
question.content.required = !target.checked;
})
}
/>
</Box>
</>
</Box>
);
}
});
SettingOptionsPict.displayName = "SettingOptionsPict";
export default SettingOptionsPict;
interface Props {
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 HelpQuestions from "../helpQuestions";
import SettingOpytionsPict from "./settingOpytionsPict";
interface Props {
switchState: string;
@ -14,9 +13,20 @@ export default function SwitchAnswerOptionsPict({
}: Props) {
switch (switchState) {
case "setting":
return <SettingOpytionsPict question={question} />;
return (
<SettingOpytionsPict
questionId={question.id}
isRequired={question.content.required}
/>
);
case "help":
return <HelpQuestions question={question} />;
return (
<HelpQuestions
questionId={question.id}
hintText={question.content.hint.text}
hintVideo={question.content.hint.video}
/>
);
default:
return <></>;
}

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

@ -2,9 +2,11 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import type { QuizQuestionText } from "../../../model/questionTypes/text";
import { memo } from "react";
type SettingTextFieldProps = {
question: QuizQuestionText;
questionId: string;
isRequired: boolean;
};
type Answer = {
@ -17,7 +19,10 @@ const ANSWER_TYPES: Answer[] = [
{ name: "Многострочное", value: "multi" },
];
export default function SettingTextField({ question }: SettingTextFieldProps) {
const SettingTextField = memo<SettingTextFieldProps>(function ({
questionId,
isRequired,
}) {
const theme = useTheme();
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -32,79 +37,6 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
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
sx={{
pt: "20px",
@ -126,20 +58,6 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
>
Настройки вопросов
</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
dataCy="checkbox-optional-question"
sx={{
@ -148,55 +66,18 @@ export default function SettingTextField({ question }: SettingTextFieldProps) {
alignItems: isMobile ? "flex-end" : "center",
}}
label={"Необязательный вопрос"}
checked={!question.content.required}
checked={!isRequired}
handleChange={(e) => {
updateQuestion<QuizQuestionText>(question.id, (question) => {
updateQuestion<QuizQuestionText>(questionId, (question) => {
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>
);
}
});
SettingTextField.displayName = "SettingTextField";
export default SettingTextField;

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

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

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

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

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

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

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

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

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

@ -2,15 +2,16 @@ import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
import { memo } from "react";
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 isTablet = useMediaQuery(theme.breakpoints.down(900));
const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
const isMobile = useMediaQuery(theme.breakpoints.down(790));
@ -23,65 +24,6 @@ export default function ResponseSettings({ question }: Props) {
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
sx={{
boxSizing: "border-box",
@ -109,57 +51,18 @@ export default function ResponseSettings({ question }: Props) {
dataCy="checkbox-optional-question"
sx={{ mr: isMobile ? "0px" : "16px" }}
label={"Необязательный вопрос"}
checked={!question.content.required}
checked={!isRequired}
handleChange={({ target }) => {
updateQuestion<QuizQuestionVariant>(question.id, (question) => {
updateQuestion<QuizQuestionVariant>(questionId, (question) => {
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>
);
}
});
ResponseSettings.displayName = "ResponseSettings";
export default ResponseSettings;

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

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