import { useState, useEffect } from "react"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; import { useDebouncedCallback } from "use-debounce"; import CustomTextField from "@ui_kit/CustomTextField"; import { CustomSlider } from "@ui_kit/CustomSlider"; import { useQuizViewStore, updateAnswer } from "@stores/quizView/store"; import type { QuizQuestionNumber } from "../../../model/questionTypes/number"; import { enqueueSnackbar } from "notistack"; import { sendAnswer } from "@api/quizRelase"; import { quizThemes } from "@utils/themes/Publication/themePublication"; import { useQuizData } from "@utils/hooks/useQuizData"; type NumberProps = { currentQuestion: QuizQuestionNumber; }; export const Number = ({ currentQuestion }: NumberProps) => { const { settings } = useQuizData(); const [inputValue, setInputValue] = useState("0"); const [minRange, setMinRange] = useState("0"); const [maxRange, setMaxRange] = useState("100000000000"); const theme = useTheme(); const { answers } = useQuizViewStore(); const isMobile = useMediaQuery(theme.breakpoints.down(650)); const min = window.Number(currentQuestion.content.range.split("—")[0]); const max = window.Number(currentQuestion.content.range.split("—")[1]); const sendAnswerToBackend = async (value: string) => { try { await sendAnswer({ questionId: currentQuestion.id, body: value, //@ts-ignore qid: settings.qid, }); updateAnswer(currentQuestion.id, value); } catch (e) { enqueueSnackbar("ответ не был засчитан"); } }; const updateValueDebounced = useDebouncedCallback(async (value: string) => { const newValue = window.Number(value) < window.Number(minRange) ? minRange : window.Number(value) > window.Number(maxRange) ? maxRange : value; setInputValue(newValue); await sendAnswerToBackend(newValue); }, 1000); const updateMinRangeDebounced = useDebouncedCallback( async (value: string, crowded = false) => { const newMinValue = crowded ? maxRange : window.Number(value.split("—")[0]) < min ? String(min) : value.split("—")[0]; setMinRange(newMinValue); await sendAnswerToBackend(`${newMinValue}—${value.split("—")[1]}`); }, 1000 ); const updateMaxRangeDebounced = useDebouncedCallback( async (value: string, crowded = false) => { const newMaxValue = crowded ? minRange : window.Number(value.split("—")[1]) > max ? String(max) : value.split("—")[1]; setMaxRange(newMaxValue); await sendAnswerToBackend(`${value.split("—")[0]}—${newMaxValue}`); }, 1000 ); const answer = answers.find( ({ questionId }) => questionId === currentQuestion.id )?.answer as string; const sliderValue = answer || currentQuestion.content.start + "—" + max; useEffect(() => { if (answer) { if (answer.includes("—")) { setMinRange(answer.split("—")[0]); setMaxRange(answer.split("—")[1]); } else { setInputValue(answer); } } if (!answer) { setMinRange(String(currentQuestion.content.start)); setMaxRange(String(max)); setInputValue(String(currentQuestion.content.start)); } }, []); return ( {currentQuestion.title} 1 ? sliderValue.split("—").map((item) => window.Number(item)) : [min, min + 1] : window.Number(sliderValue.split("—")[0]) } min={min} max={max} step={currentQuestion.content.step || 1} onChange={(_, value) => { const range = Array.isArray(value) ? `${value[0]}—${value[1]}` : String(value); updateAnswer(currentQuestion.id, range); }} onChangeCommitted={async (_, value) => { if (currentQuestion.content.chooseRange && Array.isArray(value)) { setMinRange(String(value[0])); setMaxRange(String(value[1])); await sendAnswerToBackend(`${value[0]}—${value[1]}`); return; } setInputValue(String(value)); await sendAnswerToBackend(String(value)); }} //@ts-ignore sx={{ color: theme.palette.primary.main, "& .MuiSlider-valueLabel": { background: theme.palette.primary.main, }, }} /> {!currentQuestion.content.chooseRange && ( { const value = target.value.replace(/\D/g, ""); setInputValue(value); updateValueDebounced(value); }} sx={{ maxWidth: "80px", borderColor: theme.palette.text.primary, "& .MuiInputBase-input": { textAlign: "center", backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default, }, }} /> )} {currentQuestion.content.chooseRange && ( { const newValue = target.value.replace(/\D/g, ""); setMinRange(newValue); if (window.Number(newValue) >= window.Number(maxRange)) { updateMinRangeDebounced(`${maxRange}—${maxRange}`, true); return; } updateMinRangeDebounced(`${newValue}—${maxRange}`); }} sx={{ maxWidth: "80px", borderColor: theme.palette.text.primary, "& .MuiInputBase-input": { textAlign: "center", backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default, }, }} /> до { const newValue = target.value.replace(/\D/g, ""); setMaxRange(newValue); if (window.Number(newValue) <= window.Number(minRange)) { updateMaxRangeDebounced(`${minRange}—${minRange}`, true); return; } updateMaxRangeDebounced(`${minRange}—${newValue}`); }} sx={{ maxWidth: "80px", borderColor: theme.palette.text.primary, "& .MuiInputBase-input": { textAlign: "center", backgroundColor: quizThemes[settings.cfg.theme].isLight ? "white" : theme.palette.background.default, }, }} /> )} ); };