fix: text inputs debounce
This commit is contained in:
parent
879f206d8f
commit
10f9a5adb1
@ -32,6 +32,7 @@
|
|||||||
"react-router-dom": "^6.6.2",
|
"react-router-dom": "^6.6.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"typescript": "^4.4.2",
|
"typescript": "^4.4.2",
|
||||||
|
"use-debounce": "^9.0.4",
|
||||||
"web-vitals": "^2.1.0",
|
"web-vitals": "^2.1.0",
|
||||||
"zustand": "^4.3.8"
|
"zustand": "^4.3.8"
|
||||||
},
|
},
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
useTheme,
|
useTheme,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
@ -42,6 +43,17 @@ export const AnswerItem = ({
|
|||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
const answerNew = variants.slice();
|
||||||
|
answerNew[index].answer = value;
|
||||||
|
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
variants: answerNew,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
||||||
@ -55,18 +67,6 @@ export const AnswerItem = ({
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onChangeText = (event: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const answerNew = variants.slice();
|
|
||||||
answerNew[index].answer = event.target.value;
|
|
||||||
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: {
|
|
||||||
...listQuestions[quizId][totalIndex].content,
|
|
||||||
variants: answerNew,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const addNewAnswer = () => {
|
const addNewAnswer = () => {
|
||||||
const answerNew = variants.slice();
|
const answerNew = variants.slice();
|
||||||
answerNew.push({ answer: "", hints: "" });
|
answerNew.push({ answer: "", hints: "" });
|
||||||
@ -114,12 +114,12 @@ export const AnswerItem = ({
|
|||||||
sx={{ padding: isMobile ? " 15px 0 20px 0" : "0 0 20px 0" }}
|
sx={{ padding: isMobile ? " 15px 0 20px 0" : "0 0 20px 0" }}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
value={variant.answer}
|
defaultValue={variant.answer}
|
||||||
fullWidth
|
fullWidth
|
||||||
focused={false}
|
focused={false}
|
||||||
placeholder={"Добавьте ответ"}
|
placeholder={"Добавьте ответ"}
|
||||||
multiline={listQuestions[quizId][totalIndex].content.largeCheck}
|
multiline={listQuestions[quizId][totalIndex].content.largeCheck}
|
||||||
onChange={onChangeText}
|
onChange={({ target }) => debounced(target.value)}
|
||||||
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
|
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
|
||||||
if (
|
if (
|
||||||
event.code === "Enter" &&
|
event.code === "Enter" &&
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
@ -20,6 +21,11 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
|
|||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
|
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -98,11 +104,7 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -12,10 +12,17 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import TypeQuestions from "../TypeQuestions";
|
import TypeQuestions from "../TypeQuestions";
|
||||||
import SwitchQuestionsPage from "../SwitchQuestionsPage";
|
import SwitchQuestionsPage from "../SwitchQuestionsPage";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList, createQuestion, copyQuestion, removeQuestion } from "@root/questions";
|
import {
|
||||||
|
questionStore,
|
||||||
|
updateQuestionsList,
|
||||||
|
createQuestion,
|
||||||
|
copyQuestion,
|
||||||
|
removeQuestion,
|
||||||
|
} from "@root/questions";
|
||||||
|
|
||||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
||||||
@ -49,39 +56,102 @@ interface Props {
|
|||||||
const IconAndrom = (isExpanded: boolean, switchState: string) => {
|
const IconAndrom = (isExpanded: boolean, switchState: string) => {
|
||||||
switch (switchState) {
|
switch (switchState) {
|
||||||
case "variant":
|
case "variant":
|
||||||
return <Answer color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Answer
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "images":
|
case "images":
|
||||||
return <OptionsPict color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<OptionsPict
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "varimg":
|
case "varimg":
|
||||||
return <OptionsAndPict color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<OptionsAndPict
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "emoji":
|
case "emoji":
|
||||||
return <Emoji color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Emoji
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "text":
|
case "text":
|
||||||
return <Input color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Input
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "select":
|
case "select":
|
||||||
return <DropDown color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<DropDown
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "date":
|
case "date":
|
||||||
return <Date color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Date
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "number":
|
case "number":
|
||||||
return <Slider color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Slider
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "file":
|
case "file":
|
||||||
return <Download color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Download
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "page":
|
case "page":
|
||||||
return <Page color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<Page
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "rating":
|
case "rating":
|
||||||
return <RatingIcon color={isExpanded ? "#9A9AAF" : "white"} sx={{ height: "22px", width: "20px" }} />;
|
return (
|
||||||
|
<RatingIcon
|
||||||
|
color={isExpanded ? "#9A9AAF" : "white"}
|
||||||
|
sx={{ height: "22px", width: "20px" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export default function QuestionsPageCard({ totalIndex, draggableProps, isDragging }: Props) {
|
export default function QuestionsPageCard({
|
||||||
|
totalIndex,
|
||||||
|
draggableProps,
|
||||||
|
isDragging,
|
||||||
|
}: Props) {
|
||||||
const [plusVisible, setPlusVisible] = useState<boolean>(false);
|
const [plusVisible, setPlusVisible] = useState<boolean>(false);
|
||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
const { type: switchState, expanded: isExpanded } = listQuestions[quizId][totalIndex];
|
const { type: switchState, expanded: isExpanded } =
|
||||||
|
listQuestions[quizId][totalIndex];
|
||||||
|
const debounced = useDebouncedCallback((title) => {
|
||||||
|
updateQuestionsList(quizId, totalIndex, { title });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -106,24 +176,29 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
|||||||
>
|
>
|
||||||
<FormControl
|
<FormControl
|
||||||
variant="standard"
|
variant="standard"
|
||||||
sx={{ p: 0, maxWidth: isTablet ? (isMobile ? "100%" : "640px") : "100%", width: "100%" }}
|
sx={{
|
||||||
|
p: 0,
|
||||||
|
maxWidth: isTablet ? (isMobile ? "100%" : "640px") : "100%",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
value={listQuestions[quizId][totalIndex].title}
|
defaultValue={listQuestions[quizId][totalIndex].title}
|
||||||
placeholder={"Заголовок вопроса"}
|
placeholder={"Заголовок вопроса"}
|
||||||
onChange={(e) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
title: e.target.value,
|
|
||||||
});
|
|
||||||
console.log(listQuestions[quizId][totalIndex].title);
|
|
||||||
}}
|
|
||||||
InputProps={{
|
InputProps={{
|
||||||
startAdornment: <InputAdornment position="start">{IconAndrom(isExpanded, switchState)}</InputAdornment>,
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">
|
||||||
|
{IconAndrom(isExpanded, switchState)}
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
"& .MuiInputBase-root": {
|
"& .MuiInputBase-root": {
|
||||||
color: isExpanded ? "#9A9AAF" : "white",
|
color: isExpanded ? "#9A9AAF" : "white",
|
||||||
backgroundColor: isExpanded ? theme.palette.background.default : "transparent",
|
backgroundColor: isExpanded
|
||||||
|
? theme.palette.background.default
|
||||||
|
: "transparent",
|
||||||
height: "48px",
|
height: "48px",
|
||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
".MuiOutlinedInput-notchedOutline": {
|
".MuiOutlinedInput-notchedOutline": {
|
||||||
@ -141,17 +216,45 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", width: isMobile ? "100%" : "auto", position: "relative" }}>
|
<Box
|
||||||
<Box sx={{ display: "flex", alignItems: "center", marginLeft: isMobile ? "auto" : "0px" }}>
|
sx={{
|
||||||
<IconButton onClick={() => updateQuestionsList(quizId, totalIndex, { expanded: !isExpanded })}>
|
display: "flex",
|
||||||
{isExpanded ? <ExpandMoreIcon /> : <ExpandLessIcon fill="#7E2AEA" />}
|
alignItems: "center",
|
||||||
|
width: isMobile ? "100%" : "auto",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
marginLeft: isMobile ? "auto" : "0px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
onClick={() =>
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
expanded: !isExpanded,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isExpanded ? (
|
||||||
|
<ExpandMoreIcon />
|
||||||
|
) : (
|
||||||
|
<ExpandLessIcon fill="#7E2AEA" />
|
||||||
|
)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
{isExpanded ? (
|
{isExpanded ? (
|
||||||
<></>
|
<></>
|
||||||
) : (
|
) : (
|
||||||
<Box sx={{ display: "flex", borderRight: "solid 1px white" }}>
|
<Box sx={{ display: "flex", borderRight: "solid 1px white" }}>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Checkbox icon={<HideIcon color={"#7E2AEA"} />} checkedIcon={<CrossedEyeIcon />} />}
|
control={
|
||||||
|
<Checkbox
|
||||||
|
icon={<HideIcon color={"#7E2AEA"} />}
|
||||||
|
checkedIcon={<CrossedEyeIcon />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
label={""}
|
label={""}
|
||||||
sx={{
|
sx={{
|
||||||
color: theme.palette.grey2.main,
|
color: theme.palette.grey2.main,
|
||||||
@ -164,7 +267,11 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
|||||||
<CopyIcon color={"white"} />
|
<CopyIcon color={"white"} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
sx={{ cursor: "pointer", borderRadius: "6px", padding: "2px" }}
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
borderRadius: "6px",
|
||||||
|
padding: "2px",
|
||||||
|
}}
|
||||||
onClick={() => removeQuestion(quizId, totalIndex)}
|
onClick={() => removeQuestion(quizId, totalIndex)}
|
||||||
>
|
>
|
||||||
<DeleteIcon color={"white"} />
|
<DeleteIcon color={"white"} />
|
||||||
@ -231,7 +338,8 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
|||||||
backgroundPosition: "bottom",
|
backgroundPosition: "bottom",
|
||||||
backgroundRepeat: "repeat-x",
|
backgroundRepeat: "repeat-x",
|
||||||
backgroundSize: "20px 1px",
|
backgroundSize: "20px 1px",
|
||||||
backgroundImage: "radial-gradient(circle, #7E2AEA 6px, #F2F3F7 1px)",
|
backgroundImage:
|
||||||
|
"radial-gradient(circle, #7E2AEA 6px, #F2F3F7 1px)",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
|
@ -2,6 +2,7 @@ import { useParams } from "react-router-dom";
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
@ -18,6 +19,16 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
const debounceAnswer = useDebouncedCallback((value) => {
|
||||||
|
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.default = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -30,8 +41,15 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
|
|||||||
flexDirection: isMobile ? "column" : null,
|
flexDirection: isMobile ? "column" : null,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ padding: isMobile ? "20px 20px 0px 20px" : "20px 20px 20px 20px", width: "100%" }}>
|
<Box
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Настройки ответов</Typography>
|
sx={{
|
||||||
|
padding: isMobile ? "20px 20px 0px 20px" : "20px 20px 20px 20px",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Настройки ответов
|
||||||
|
</Typography>
|
||||||
<CustomCheckbox
|
<CustomCheckbox
|
||||||
label={"Можно несколько"}
|
label={"Можно несколько"}
|
||||||
checked={listQuestions[quizId][totalIndex].content.multi}
|
checked={listQuestions[quizId][totalIndex].content.multi}
|
||||||
@ -45,21 +63,21 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ display: isMobile ? "none" : "block" }}>
|
<Box sx={{ display: isMobile ? "none" : "block" }}>
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Текст в выпадающем списке</Typography>
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Текст в выпадающем списке
|
||||||
|
</Typography>
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
sx={{ maxWidth: "360px" }}
|
sx={{ maxWidth: "360px" }}
|
||||||
placeholder={"Выберите вариант"}
|
placeholder={"Выберите вариант"}
|
||||||
text={listQuestions[quizId][totalIndex].content.default}
|
text={listQuestions[quizId][totalIndex].content.default}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounceAnswer(target.value)}
|
||||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.default = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ padding: "20px", width: "100%" }}>
|
<Box sx={{ padding: "20px", width: "100%" }}>
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Настройки вопросов</Typography>
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Настройки вопросов
|
||||||
|
</Typography>
|
||||||
<CustomCheckbox
|
<CustomCheckbox
|
||||||
label={"Необязательный вопрос"}
|
label={"Необязательный вопрос"}
|
||||||
checked={!listQuestions[quizId][totalIndex].required}
|
checked={!listQuestions[quizId][totalIndex].required}
|
||||||
@ -69,7 +87,9 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ position: "relative", display: "flex", alignItems: "center" }}>
|
<Box
|
||||||
|
sx={{ position: "relative", display: "flex", alignItems: "center" }}
|
||||||
|
>
|
||||||
<CustomCheckbox
|
<CustomCheckbox
|
||||||
label={"Внутреннее название вопроса"}
|
label={"Внутреннее название вопроса"}
|
||||||
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
||||||
@ -87,33 +107,34 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<InfoIcon
|
<InfoIcon
|
||||||
sx={{ position: isMobile ? "absolute" : null, display: "block", right: isMobile ? "30px" : null }}
|
sx={{
|
||||||
|
position: isMobile ? "absolute" : null,
|
||||||
|
display: "block",
|
||||||
|
right: isMobile ? "30px" : null,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ width: "85%", pt: "20px", display: isMobile ? "block" : "none" }}>
|
<Box
|
||||||
<Typography sx={{ marginBottom: "15px" }}>Текст в выпадающем списке</Typography>
|
sx={{
|
||||||
|
width: "85%",
|
||||||
|
pt: "20px",
|
||||||
|
display: isMobile ? "block" : "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography sx={{ marginBottom: "15px" }}>
|
||||||
|
Текст в выпадающем списке
|
||||||
|
</Typography>
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
sx={{}}
|
|
||||||
placeholder={"Выберите вариант"}
|
placeholder={"Выберите вариант"}
|
||||||
text={listQuestions[quizId][totalIndex].content.default}
|
text={listQuestions[quizId][totalIndex].content.default}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounceAnswer(target.value)}
|
||||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.default = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
{listQuestions[quizId][totalIndex].content.innerNameCheck && (
|
{listQuestions[quizId][totalIndex].content.innerNameCheck && (
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: clonContent,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
@ -21,6 +22,11 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
|
|||||||
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));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -98,11 +104,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
@ -24,6 +25,21 @@ export default function SettingOptionsAndPict({
|
|||||||
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(680));
|
const isMobile = useMediaQuery(theme.breakpoints.down(680));
|
||||||
|
const debounced = useDebouncedCallback((replText) => {
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: {
|
||||||
|
...listQuestions[quizId][totalIndex].content,
|
||||||
|
replText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
const debounceDescription = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: clonContent,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -60,14 +76,7 @@ export default function SettingOptionsAndPict({
|
|||||||
sx={{ maxWidth: "330px", width: "100%" }}
|
sx={{ maxWidth: "330px", width: "100%" }}
|
||||||
placeholder={"Пример текста"}
|
placeholder={"Пример текста"}
|
||||||
text={listQuestions[quizId][totalIndex].content.replText}
|
text={listQuestions[quizId][totalIndex].content.replText}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: {
|
|
||||||
...listQuestions[quizId][totalIndex].content,
|
|
||||||
replText: target.value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -123,13 +132,7 @@ export default function SettingOptionsAndPict({
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounceDescription(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: clonContent,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isWrappColumn && (
|
{isWrappColumn && (
|
||||||
@ -141,14 +144,7 @@ export default function SettingOptionsAndPict({
|
|||||||
sx={{ maxWidth: "330px", width: "100%" }}
|
sx={{ maxWidth: "330px", width: "100%" }}
|
||||||
placeholder={"Пример текста"}
|
placeholder={"Пример текста"}
|
||||||
text={listQuestions[quizId][totalIndex].content.replText}
|
text={listQuestions[quizId][totalIndex].content.replText}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: {
|
|
||||||
...listQuestions[quizId][totalIndex].content,
|
|
||||||
replText: target.value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
@ -85,6 +86,13 @@ export default function SettingOpytionsPict({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: clonContent,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!listQuestions[quizId][totalIndex].content.xy) {
|
if (!listQuestions[quizId][totalIndex].content.xy) {
|
||||||
@ -254,13 +262,7 @@ export default function SettingOpytionsPict({
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Внутреннее описание вопроса"}
|
placeholder={"Внутреннее описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: clonContent,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Box, Typography, Tooltip, useTheme } from "@mui/material";
|
import { Box, Typography, Tooltip, useTheme } from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
@ -10,8 +11,6 @@ import { questionStore, updateQuestionsList } from "@root/questions";
|
|||||||
|
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
|
|
||||||
import type { ChangeEvent } from "react";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
totalIndex: number;
|
totalIndex: number;
|
||||||
}
|
}
|
||||||
@ -20,6 +19,11 @@ export default function OwnTextField({ totalIndex }: Props) {
|
|||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.placeholder = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
@ -40,11 +44,7 @@ export default function OwnTextField({ totalIndex }: Props) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Пример ответа"}
|
placeholder={"Пример ответа"}
|
||||||
text={listQuestions[quizId][totalIndex].content.placeholder}
|
text={listQuestions[quizId][totalIndex].content.placeholder}
|
||||||
onChange={({ target }: ChangeEvent<HTMLInputElement>) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.placeholder = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: "12px" }}>
|
<Box sx={{ display: "flex", alignItems: "center", gap: "12px" }}>
|
||||||
<Typography
|
<Typography
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
|
||||||
@ -42,6 +43,11 @@ export default function SettingTextField({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isWrapperColumn = useMediaQuery(theme.breakpoints.down(980));
|
const isWrapperColumn = useMediaQuery(theme.breakpoints.down(980));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -138,11 +144,7 @@ export default function SettingTextField({
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import AddImage from "../../../assets/icons/questionsPage/addImage";
|
import AddImage from "../../../assets/icons/questionsPage/addImage";
|
||||||
@ -26,6 +27,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(980));
|
const isTablet = useMediaQuery(theme.breakpoints.down(980));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(780));
|
const isMobile = useMediaQuery(theme.breakpoints.down(780));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.text = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
@ -47,15 +53,16 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Можно добавить текст"}
|
placeholder={"Можно добавить текст"}
|
||||||
text={listQuestions[quizId][totalIndex].content.text}
|
text={listQuestions[quizId][totalIndex].content.text}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.text = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{ display: "flex", alignItems: "center", gap: "12px", justifyContent: isMobile ? "space-between" : null }}
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "12px",
|
||||||
|
justifyContent: isMobile ? "space-between" : null,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
onClick={() => setOpenImageModal(true)}
|
onClick={() => setOpenImageModal(true)}
|
||||||
@ -129,7 +136,11 @@ export default function PageOptions({ disableInput, totalIndex }: Props) {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
<ButtonsOptions
|
||||||
|
switchState={switchState}
|
||||||
|
SSHC={SSHC}
|
||||||
|
totalIndex={totalIndex}
|
||||||
|
/>
|
||||||
<SwitchPageOptions switchState={switchState} totalIndex={totalIndex} />
|
<SwitchPageOptions switchState={switchState} totalIndex={totalIndex} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import { useParams } from "react-router-dom";
|
|||||||
import { Box, Typography, Tooltip } from "@mui/material";
|
import { Box, Typography, Tooltip } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
@ -16,6 +17,13 @@ export default function SettingPageOptions({
|
|||||||
}: SettingPageOptionsProps) {
|
}: SettingPageOptionsProps) {
|
||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, {
|
||||||
|
content: clonContent,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexDirection: "column", padding: "20px" }}>
|
<Box sx={{ display: "flex", flexDirection: "column", padding: "20px" }}>
|
||||||
@ -47,13 +55,7 @@ export default function SettingPageOptions({
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Внутреннее описание вопроса"}
|
placeholder={"Внутреннее описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, {
|
|
||||||
content: clonContent,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
import { Box, Button, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
IconButton,
|
||||||
|
Typography,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
import AddPlus from "../../assets/icons/questionsPage/addPlus";
|
import AddPlus from "../../assets/icons/questionsPage/addPlus";
|
||||||
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
|
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
|
||||||
import { quizStore } from "@root/quizes";
|
import { quizStore } from "@root/quizes";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { questionStore, createQuestion, updateQuestionsList } from "@root/questions";
|
import {
|
||||||
|
questionStore,
|
||||||
|
createQuestion,
|
||||||
|
updateQuestionsList,
|
||||||
|
} from "@root/questions";
|
||||||
import { DraggableList } from "./DraggableList";
|
import { DraggableList } from "./DraggableList";
|
||||||
|
|
||||||
export default function QuestionsPage() {
|
export default function QuestionsPage() {
|
||||||
@ -72,7 +83,10 @@ export default function QuestionsPage() {
|
|||||||
<AddPlus />
|
<AddPlus />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Box sx={{ display: "flex", gap: "8px" }}>
|
<Box sx={{ display: "flex", gap: "8px" }}>
|
||||||
<Button variant="outlined" sx={{ padding: "10px 20px", borderRadius: "8px", height: "44px" }}>
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
sx={{ padding: "10px 20px", borderRadius: "8px", height: "44px" }}
|
||||||
|
>
|
||||||
<ArrowLeft />
|
<ArrowLeft />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
@ -34,6 +35,11 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
|||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
|
const isWrappColumn = useMediaQuery(theme.breakpoints.down(980));
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const buttonRatingForm: ButtonRatingFrom[] = [
|
const buttonRatingForm: ButtonRatingFrom[] = [
|
||||||
{ name: "star", icon: <StarIconMini color={theme.palette.grey3.main} /> },
|
{ name: "star", icon: <StarIconMini color={theme.palette.grey3.main} /> },
|
||||||
@ -160,11 +166,7 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
@ -21,6 +22,11 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
|||||||
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));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -81,11 +87,7 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -2,6 +2,7 @@ import { useParams } from "react-router-dom";
|
|||||||
import { Box, Typography, Tooltip } from "@mui/material";
|
import { Box, Typography, Tooltip } from "@mui/material";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
@ -14,6 +15,11 @@ type SettingsUploadProps = {
|
|||||||
export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
|
export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
|
||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", flexDirection: "column", padding: "20px" }}>
|
<Box sx={{ display: "flex", flexDirection: "column", padding: "20px" }}>
|
||||||
@ -64,11 +70,7 @@ export default function SettingsUpload({ totalIndex }: SettingsUploadProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||||
import InfoIcon from "../../../assets/icons/InfoIcon";
|
import InfoIcon from "../../../assets/icons/InfoIcon";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
@ -21,6 +22,11 @@ export default function ResponseSettings({ totalIndex }: Props) {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(900));
|
const isTablet = useMediaQuery(theme.breakpoints.down(900));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.innerName = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -107,11 +113,7 @@ export default function ResponseSettings({ totalIndex }: Props) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Развёрнутое описание вопроса"}
|
placeholder={"Развёрнутое описание вопроса"}
|
||||||
text={listQuestions[quizId][totalIndex].content.innerName}
|
text={listQuestions[quizId][totalIndex].content.innerName}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.innerName = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { Box, ButtonBase, Typography } from "@mui/material";
|
import { Box, ButtonBase, Typography } from "@mui/material";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import SelectableButton from "@ui_kit/SelectableButton";
|
import SelectableButton from "@ui_kit/SelectableButton";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import { useState } from "react";
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import UploadIcon from "../../assets/icons/UploadIcon";
|
import UploadIcon from "../../assets/icons/UploadIcon";
|
||||||
import UploadBox from "@ui_kit/UploadBox";
|
import UploadBox from "@ui_kit/UploadBox";
|
||||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
@ -19,6 +20,11 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
|
|||||||
const [backgroundType, setBackgroundType] = useState<BackgroundType>("text");
|
const [backgroundType, setBackgroundType] = useState<BackgroundType>("text");
|
||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const { listQuestions } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
|
const debounced = useDebouncedCallback((value) => {
|
||||||
|
let clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
|
clonContent.hint.text = value;
|
||||||
|
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const videoHC = (url: string) => {
|
const videoHC = (url: string) => {
|
||||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||||
@ -62,11 +68,7 @@ export default function HelpQuestions({ totalIndex }: HelpQuestionsProps) {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Текст консультанта"}
|
placeholder={"Текст консультанта"}
|
||||||
text={listQuestions[quizId][totalIndex].content.hint.text}
|
text={listQuestions[quizId][totalIndex].content.hint.text}
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => debounced(target.value)}
|
||||||
let clonContent = listQuestions[quizId][totalIndex].content;
|
|
||||||
clonContent.hint.text = target.value;
|
|
||||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -9186,6 +9186,11 @@ url-parse@^1.5.3:
|
|||||||
querystringify "^2.1.1"
|
querystringify "^2.1.1"
|
||||||
requires-port "^1.0.0"
|
requires-port "^1.0.0"
|
||||||
|
|
||||||
|
use-debounce@^9.0.4:
|
||||||
|
version "9.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-9.0.4.tgz#51d25d856fbdfeb537553972ce3943b897f1ac85"
|
||||||
|
integrity sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==
|
||||||
|
|
||||||
use-memo-one@^1.1.1:
|
use-memo-one@^1.1.1:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
|
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
|
||||||
|
Loading…
Reference in New Issue
Block a user