frontPanel/src/pages/Questions/QuestionOptions/SliderOptions/SliderOptions.tsx

226 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from "react";
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { useDebouncedCallback } from "use-debounce";
import CustomNumberField from "@ui_kit/CustomNumberField";
import ButtonsOptions from "../ButtonsLayout/ButtonsOptions";
import SwitchSlider from "./switchSlider";
import { updateQuestion } from "@root/questions/actions";
import type { QuizQuestionNumber } from "@frontend/squzanswerer";
interface Props {
question: QuizQuestionNumber;
openBranchingPage: boolean;
setOpenBranchingPage: (a: boolean) => void;
}
export default function SliderOptions({ question, openBranchingPage, setOpenBranchingPage }: Props) {
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down(980));
const isMobile = useMediaQuery(theme.breakpoints.down(790));
const [switchState, setSwitchState] = useState("setting");
const [startError, setStartError] = useState("");
const [stepError, setStepError] = useState("");
const updateStartDebounced = useDebouncedCallback((value: number) => {
setStartError("");
updateQuestion<QuizQuestionNumber>(question.id, (question) => {
question.content.start = value;
});
}, 5000);
const updateStepDebounced = useDebouncedCallback((value: number) => {
setStepError("");
updateQuestion<QuizQuestionNumber>(question.id, (question) => {
question.content.step = value;
});
}, 5000);
const calculateValues = () => {
const { step, start } = question.content;
const [min, max] = question.content.range.split("—").map(Number);
const minBorder = min <= max ? min : max;
const maxBorder = max >= min ? max : min;
const range = maxBorder - minBorder;
const reversed = min > max;
if (start < minBorder) {
setStartError("Стартовое значени должно быть внутри диапазона");
updateStartDebounced(reversed ? max : min);
}
if (start > maxBorder) {
setStartError("Стартовое значени должно быть внутри диапазона");
updateStartDebounced(reversed ? min : max);
}
if (!step) {
setStepError("Стартовое значение должно быть больше 0");
updateStepDebounced(1);
}
if (step > maxBorder) {
setStepError("Шаг не может выходить за пределы диапазона");
updateStepDebounced(1);
}
if (range % step) {
setStepError(`Шаг должен делить без остатка диапазон ${maxBorder} - ${minBorder} = ${maxBorder - minBorder}`);
updateStepDebounced(1);
}
};
return (
<>
<Box
sx={{
width: isTablet ? "auto" : "100%",
maxWidth: "720.8px",
display: "flex",
pl: "20px",
pr: isMobile ? "13px" : "20px",
pb: isMobile ? "30px" : "20px",
flexDirection: "column",
gap: isMobile ? "25px" : "20px",
}}
>
<Box
sx={{
gap: isMobile ? "10px" : "14px",
mt: isMobile ? "25px" : "0px",
display: "flex",
flexDirection: "column",
marginRight: isMobile ? "10px" : "0px",
}}
>
<Typography sx={{ fontWeight: "500", fontSize: "18px", color: "#4D4D4D" }}>
Выбор значения из диапазона
</Typography>
<Box
sx={{
width: "100%",
display: "flex",
alignItems: "center",
gap: isMobile ? "9px" : "20px",
}}
>
<CustomNumberField
sx={{ maxWidth: "310px", width: "100%" }}
placeholder={"0"}
min={0}
max={99999999999}
value={question.content.range.split("—")[0]}
onChange={({ target }) => {
updateQuestion<QuizQuestionNumber>(question.id, (question) => {
question.content.range = `${target.value}${question.content.range.split("—")[1]}`;
});
}}
onBlur={calculateValues}
/>
<Typography></Typography>
<CustomNumberField
sx={{ maxWidth: "310px", width: "100%" }}
placeholder={"100"}
min={0}
max={100000000000}
value={question.content.range.split("—")[1]}
onChange={({ target }) => {
updateQuestion<QuizQuestionNumber>(question.id, (question) => {
question.content.range = `${question.content.range.split("—")[0]}${target.value}`;
});
}}
onBlur={calculateValues}
/>
</Box>
</Box>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
flexDirection: isMobile ? "column-reverse" : "",
gap: isMobile ? "15px" : "50px",
}}
>
<Box sx={{ width: "100%" }}>
<Typography
sx={{
fontWeight: "500",
fontSize: "18px",
color: "#4D4D4D",
mb: isMobile ? "10px" : "14px",
}}
>
Начальное значение
</Typography>
<CustomNumberField
sx={{ maxWidth: "310px", width: "100%" }}
placeholder={"50"}
value={String(question.content.start)}
error={startError}
onChange={({ target }) => {
const newValue = Number(target.value);
updateQuestion<QuizQuestionNumber>(question.id, (question) => {
question.content.start = newValue;
});
updateStartDebounced(newValue);
}}
onBlur={calculateValues}
/>
</Box>
<Box sx={{ width: "100%" }}>
<Typography
sx={{
fontWeight: "500",
fontSize: "18px",
color: "#4D4D4D",
mb: "10px",
}}
>
Шаг
</Typography>
<CustomNumberField
sx={{ maxWidth: "310px", width: "100%" }}
min={Number(question.content.range.split("—")[0])}
max={Number(question.content.range.split("—")[1])}
placeholder={"1"}
error={stepError}
value={String(question.content.step)}
onChange={({ target, type }) => {
if (type === "blur") {
return;
}
const newValue = Number(target.value);
updateQuestion<QuizQuestionNumber>(question.id, (question) => {
question.content.step = newValue;
});
updateStepDebounced(newValue);
}}
onBlur={calculateValues}
/>
</Box>
</Box>
</Box>
<ButtonsOptions
switchState={switchState}
setSwitchState={setSwitchState}
questionId={question.id}
questionContentId={question.content.id}
questionType={question.type}
questionHasParent={question.content.rule.parentId?.length !== 0}
setOpenBranchingPage={setOpenBranchingPage}
/>
<SwitchSlider
switchState={switchState}
question={question}
/>
</>
);
}