diff --git a/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx b/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx index d4f140f5..103aef35 100644 --- a/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx @@ -11,8 +11,23 @@ import OptionsPict from "@icons/questionsPage/options_pict"; import Page from "@icons/questionsPage/page"; import RatingIcon from "@icons/questionsPage/rating"; import Slider from "@icons/questionsPage/slider"; -import { Box, FormControlLabel, IconButton, InputAdornment, Paper, useMediaQuery, useTheme } from "@mui/material"; -import { toggleExpandQuestion, updateQuestion, updateUntypedQuestion } from "@root/questions/actions"; +import { + Box, Checkbox, + FormControl, + FormControlLabel, + IconButton, + InputAdornment, + Paper, TextField, + useMediaQuery, + useTheme +} from "@mui/material"; +import { + copyQuestion, + deleteQuestion, deleteQuestionWithTimeout, + toggleExpandQuestion, + updateQuestion, + updateUntypedQuestion +} from "@root/questions/actions"; import CustomTextField from "@ui_kit/CustomTextField"; import { useRef, useState } from "react"; import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd"; @@ -51,150 +66,247 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr }); }, 200); - return ( - <> - - - - setTitle(target.value)} - sx={{ width: "100%" }} - InputProps={{ - startAdornment: ( - - setOpen((isOpened) => !isOpened)} - > - {IconAndrom(question.type)} - - setOpen(false)} - anchorRef={anchorRef} - question={question} - questionType={question.type} - /> - - ), - }} - /> - + - - toggleExpandQuestion(question.id)} - > - {question.expanded ? ( - - ) : ( - - )} - - - {questionIndex + 1} + + + setTitle(target.value)} + sx={{ + width: "100%", + margin: isMobile ? "10px 0" : 0, + "& .MuiInputBase-root": { + color: "#000000", + backgroundColor: question.expanded + ? theme.palette.background.default + : "transparent", + height: "48px", + borderRadius: "10px", + ".MuiOutlinedInput-notchedOutline": { + borderWidth: "1px !important", + border: !question.expanded ? "none" : null, + }, + "& .MuiInputBase-input::placeholder": { + color: "#4D4D4D", + opacity: 0.8, + }, + }, + }} + InputProps={{ + startAdornment: ( + + setOpen((isOpened) => !isOpened)} + > + {IconAndrom(question.type)} + + setOpen(false)} + anchorRef={anchorRef} + question={question} + questionType={question.type} + /> + + ), + }} + /> + + + + toggleExpandQuestion(question.id)} + > + {question.expanded ? ( + + ) : ( + + )} + + + {question.expanded ? ( + <> + ) : ( + + + } + checkedIcon={} + /> + } + label={""} + sx={{ + color: theme.palette.grey2.main, + ml: "-9px", + mr: 0, + userSelect: "none", + }} + /> + copyQuestion(question.id, question.quizId)} + > + + + { + deleteQuestionWithTimeout(question.id, deleteQuestion(question.id)); + + }} + > + + + + )} + + + {questionIndex + 1} + + + + + + + + + {question.expanded && ( + <> + {question.type === null ? ( + + ) : ( + + )} + + )} - - - - - - - - - {question.type === null ? ( - - ) : ( - - )} - - - - ); + + + ); } const IconAndrom = (questionType: QuestionType | null) => { diff --git a/src/pages/Questions/SliderOptions/SliderOptions.tsx b/src/pages/Questions/SliderOptions/SliderOptions.tsx index bcc23b7d..4a7225fe 100644 --- a/src/pages/Questions/SliderOptions/SliderOptions.tsx +++ b/src/pages/Questions/SliderOptions/SliderOptions.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; import ButtonsOptions from "../ButtonsOptions"; import CustomNumberField from "@ui_kit/CustomNumberField"; @@ -16,6 +16,38 @@ export default function SliderOptions({ question }: Props) { const isMobile = useMediaQuery(theme.breakpoints.down(790)); const [switchState, setSwitchState] = useState("setting"); const [stepError, setStepError] = useState(""); + const [startError, setStartError] = useState(false); + const [minError, setMinError] = useState(false); + const [maxError, setMaxError] = useState(false); + + useEffect(() => { + const min = Number(question.content.range.split("—")[0]); + const max = Number(question.content.range.split("—")[1]); + const start = Number(question.content.start); + + if (start < min || start > max) { + setStartError(true); + } + + if (start >= min && start <= max) { + setStartError(false); + } + }, [question.content.range, question.content.start]); + + useEffect(() => { + const min = Number(question.content.range.split("—")[0]); + const max = Number(question.content.range.split("—")[1]); + const step = Number(question.content.step); + const range = max - min; + + if (range % step) { + setStepError( + `Шаг должен делить без остатка диапазон ${max} - ${min} = ${max - min}` + ); + } else { + setStepError(""); + } + }, [question]); const SSHC = (data: string) => { setSwitchState(data); @@ -44,42 +76,43 @@ export default function SliderOptions({ question }: Props) { marginRight: isMobile ? "10px" : "0px", }} > - + Выбор значения из диапазона - + { - updateQuestion(question.id, (question) => { - if (question.type !== "number") return; - - question.content.range = `${target.value}—${question.content.range.split("—")[1]}`; - }); - }} - onBlur={({ target }) => { - const start = question.content.start; const min = Number(target.value); const max = Number(question.content.range.split("—")[1]); + updateQuestion(question.id, (question) => { + if (question.type !== "number") return; + + question.content.range = `${target.value}—${ + question.content.range.split("—")[1] + }`; + }); + if (min >= max) { - updateQuestion(question.id, (question) => { - if (question.type !== "number") return; - - question.content.range = `${max - 1 >= 0 ? max - 1 : 0}—${question.content.range.split("—")[1]}`; - }); - } - - if (start < min) { - updateQuestion(question.id, (question) => { - if (question.type !== "number") return; - - question.content.start = min; - }); + setMinError(true); + } else { + setMinError(false); + setMaxError(false); } }} /> @@ -90,35 +123,30 @@ export default function SliderOptions({ question }: Props) { min={0} max={100000000000} value={question.content.range.split("—")[1]} + emptyError={maxError} onChange={({ target }) => { + const min = Number(question.content.range.split("—")[0]); + const max = Number(target.value); + updateQuestion(question.id, (question) => { if (question.type !== "number") return; - question.content.range = `${question.content.range.split("—")[0]}—${target.value}`; + question.content.range = `${ + question.content.range.split("—")[0] + }—${target.value}`; }); + + if (max <= min) { + setMaxError(true); + } else { + setMaxError(false); + setMinError(false); + } }} onBlur={({ target }) => { - const start = question.content.start; const step = question.content.step; const min = Number(question.content.range.split("—")[0]); const max = Number(target.value); - const range = max - min; - - if (max <= min) { - updateQuestion(question.id, (question) => { - if (question.type !== "number") return; - - question.content.range = `${min}—${min + 1 >= 100 ? 100 : min + 1}`; - }); - } - - if (start > max) { - updateQuestion(question.id, (question) => { - if (question.type !== "number") return; - - question.content.start = max; - }); - } if (step > max) { updateQuestion(question.id, (question) => { @@ -126,12 +154,6 @@ export default function SliderOptions({ question }: Props) { question.content.step = min; }); - - if (range % step) { - setStepError(`Шаг должен делить без остатка диапазон ${max} - ${min} = ${max - min}`); - } else { - setStepError(""); - } } }} /> @@ -147,15 +169,21 @@ export default function SliderOptions({ question }: Props) { }} > - + Начальное значение { updateQuestion(question.id, (question) => { if (question.type !== "number") return; @@ -178,8 +206,8 @@ export default function SliderOptions({ question }: Props) { { - const min = Number(question.content.range.split("—")[0]); const max = Number(question.content.range.split("—")[1]); - const range = max - min; const step = Number(target.value); if (step > max) { @@ -203,18 +229,16 @@ export default function SliderOptions({ question }: Props) { question.content.step = max; }); } - - if (range % step) { - setStepError(`Шаг должен делить без остатка диапазон ${max} - ${min} = ${max - min}`); - } else { - setStepError(""); - } }} /> - + ); diff --git a/src/pages/ViewPublicationPage/questions/Number.tsx b/src/pages/ViewPublicationPage/questions/Number.tsx index 28936e83..6056beab 100644 --- a/src/pages/ViewPublicationPage/questions/Number.tsx +++ b/src/pages/ViewPublicationPage/questions/Number.tsx @@ -18,21 +18,29 @@ export const Number = ({ currentQuestion }: NumberProps) => { const [maxRange, setMaxRange] = useState("100000000000"); const theme = useTheme(); const { answers } = useQuizViewStore(); - const updateMinRangeDebounced = useDebouncedCallback((value, crowded = false) => { - if (crowded) { - setMinRange(maxRange); - } + const updateMinRangeDebounced = useDebouncedCallback( + (value, crowded = false) => { + if (crowded) { + setMinRange(maxRange); + } - updateAnswer(currentQuestion.content.id, value); - }, 1000); - const updateMaxRangeDebounced = useDebouncedCallback((value, crowded = false) => { - if (crowded) { - setMaxRange(minRange); - } + updateAnswer(currentQuestion.content.id, value); + }, + 1000 + ); + const updateMaxRangeDebounced = useDebouncedCallback( + (value, crowded = false) => { + if (crowded) { + setMaxRange(minRange); + } - updateAnswer(currentQuestion.content.id, value); - }, 1000); - const answer = answers.find(({ questionId }) => questionId === currentQuestion.content.id)?.answer as string; + updateAnswer(currentQuestion.content.id, value); + }, + 1000 + ); + const answer = answers.find( + ({ questionId }) => questionId === currentQuestion.content.id + )?.answer as string; const min = window.Number(currentQuestion.content.range.split("—")[0]); const max = window.Number(currentQuestion.content.range.split("—")[1]); diff --git a/src/ui_kit/CustomNumberField.tsx b/src/ui_kit/CustomNumberField.tsx index 8797d74f..c74be2eb 100644 --- a/src/ui_kit/CustomNumberField.tsx +++ b/src/ui_kit/CustomNumberField.tsx @@ -9,6 +9,7 @@ interface CustomNumberFieldProps { onKeyDown?: (event: KeyboardEvent) => void; onBlur?: (event: FocusEvent) => void; error?: string; + emptyError?: boolean; value: string; sx?: SxProps; min?: number; @@ -20,6 +21,7 @@ export default function CustomNumberField({ value, sx, error, + emptyError, onChange, onKeyDown, onBlur, @@ -57,6 +59,7 @@ export default function CustomNumberField({ placeholder={placeholder} sx={sx} error={error} + emptyError={emptyError} onChange={onInputChange} onKeyDown={onKeyDown} onBlur={onInputBlur} diff --git a/src/ui_kit/CustomTextField.tsx b/src/ui_kit/CustomTextField.tsx index 34dc98b8..8ce1f705 100755 --- a/src/ui_kit/CustomTextField.tsx +++ b/src/ui_kit/CustomTextField.tsx @@ -7,6 +7,7 @@ interface CustomTextFieldProps { placeholder: string; value?: string; error?: string; + emptyError?: boolean; onChange?: (event: ChangeEvent) => void; onKeyDown?: (event: KeyboardEvent) => void; onBlur?: (event: FocusEvent) => void; @@ -25,6 +26,7 @@ export default function CustomTextField({ text, sx, error, + emptyError, InputProps, maxLength = 200, }: CustomTextFieldProps) { @@ -62,7 +64,7 @@ export default function CustomTextField({ value={inputValue} placeholder={placeholder} onChange={handleInputChange} - error={!!error} + error={!!error || emptyError} label={error} onFocus={handleInputFocus} onBlur={handleInputBlur}