diff --git a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx index 35ea548c..57d1beb2 100644 --- a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx +++ b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx @@ -12,7 +12,7 @@ import { } from "@mui/material"; import { addQuestionVariant, deleteQuestionVariant, setQuestionVariantField, updateQuestion } from "@root/questions/actions"; import { enqueueSnackbar } from "notistack"; -import { memo, type ChangeEvent, type FC, type KeyboardEvent, type ReactNode } from "react"; +import { memo, useCallback, type ChangeEvent, type FC, type KeyboardEvent, type ReactNode } from "react"; import { Draggable } from "react-beautiful-dnd"; import type { QuestionVariant, QuizQuestionVariant } from "@frontend/squzanswerer"; @@ -28,10 +28,13 @@ type AnswerItemProps = { additionalMobile?: ReactNode; isOwn: boolean; ownPlaceholder: string; + shouldAutoFocus?: boolean; + onFocusHandled?: () => void; + onEnterKeyPress?: () => void; }; const AnswerItem = memo( - ({ index, variant, questionId, largeCheck = false, additionalContent, additionalMobile, disableKeyDown, isOwn, ownPlaceholder }) => { + ({ index, variant, questionId, largeCheck = false, additionalContent, additionalMobile, disableKeyDown, isOwn, ownPlaceholder, shouldAutoFocus, onFocusHandled, onEnterKeyPress }) => { const theme = useTheme(); const isTablet = useMediaQuery(theme.breakpoints.down(790)); @@ -41,6 +44,26 @@ const AnswerItem = memo( }); }; + const inputRefCallback = useCallback((element: HTMLInputElement | null) => { + if (element && shouldAutoFocus) { + element.focus(); + onFocusHandled?.(); + } + }, [shouldAutoFocus, onFocusHandled]); + + const handleKeyDown = (event: KeyboardEvent) => { + if (disableKeyDown) { + enqueueSnackbar("100 максимальное количество"); + } else if (event.code === "Enter" && !largeCheck) { + if (onEnterKeyPress) { + onEnterKeyPress(); + } else { + // Fallback если onEnterKeyPress не передан + addQuestionVariant(questionId); + } + } + }; + return ( ( }} > ) => { if (target.value.length <= 1000) { @@ -79,13 +103,7 @@ const AnswerItem = memo( enqueueSnackbar("Превышена длина вводимого текста") } }} - onKeyDown={(event: KeyboardEvent) => { - if (disableKeyDown) { - enqueueSnackbar("100 максимальное количество"); - } else if (event.code === "Enter" && !largeCheck) { - addQuestionVariant(questionId); - } - }} + onKeyDown={handleKeyDown} InputProps={{ startAdornment: ( <> diff --git a/src/pages/Questions/AnswerDraggableList/ImageEditAnswerItem.tsx b/src/pages/Questions/AnswerDraggableList/ImageEditAnswerItem.tsx index d019b07e..1a5ed5bd 100644 --- a/src/pages/Questions/AnswerDraggableList/ImageEditAnswerItem.tsx +++ b/src/pages/Questions/AnswerDraggableList/ImageEditAnswerItem.tsx @@ -16,6 +16,9 @@ type Props = Omit< openImageUploadModal: () => void; isOwn: boolean; ownPlaceholder: string; + shouldAutoFocus?: boolean; + onFocusHandled?: () => void; + onEnterKeyPress?: () => void; }; export default function ImageEditAnswerItem({ @@ -31,6 +34,9 @@ export default function ImageEditAnswerItem({ openImageUploadModal, isOwn, ownPlaceholder, + shouldAutoFocus, + onFocusHandled, + onEnterKeyPress, }: Props) { const addOrEditImageButton = useMemo(() => { return ( @@ -111,6 +117,9 @@ export default function ImageEditAnswerItem({ additionalMobile={addOrEditImageButtonMobile} isOwn={isOwn} ownPlaceholder={ownPlaceholder} + shouldAutoFocus={shouldAutoFocus} + onFocusHandled={onFocusHandled} + onEnterKeyPress={onEnterKeyPress} /> ); } diff --git a/src/pages/Questions/DropDown/DropDown.tsx b/src/pages/Questions/DropDown/DropDown.tsx index 74969434..d1b313b4 100644 --- a/src/pages/Questions/DropDown/DropDown.tsx +++ b/src/pages/Questions/DropDown/DropDown.tsx @@ -1,7 +1,7 @@ import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material"; import { useCallback, useState } from "react"; import { EnterIcon } from "@/assets/icons/questionsPage/enterIcon"; -import { useAddAnswer } from "../../../utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "../../../utils/questionVariants"; import { AnswerDraggableList } from "../AnswerDraggableList"; import ButtonsOptions from "../QuestionOptions/ButtonsLayout/ButtonsOptions"; import SwitchDropDown from "./switchDropDown"; @@ -16,7 +16,7 @@ interface Props { } export default function DropDown({ question, openBranchingPage, setOpenBranchingPage }: Props) { - const {onClickAddAnAnswer} = useAddAnswer(); + const {addVariantWithFocus, addVariantOnEnter, focusedVariantId, clearFocusedVariant} = useQuestionVariantsWithFocus(); const [switchState, setSwitchState] = useState("setting"); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(790)); @@ -50,6 +50,11 @@ export default function DropDown({ question, openBranchingPage, setOpenBranching disableKeyDown={question.content.variants.length >= 100} questionId={question.id} variant={variant} + isOwn={Boolean(variant?.isOwn)} + ownPlaceholder={question.content.ownPlaceholder || ""} + shouldAutoFocus={focusedVariantId === variant.id} + onFocusHandled={clearFocusedVariant} + onEnterKeyPress={() => addVariantOnEnter(question.id)} /> ))} /> @@ -71,7 +76,7 @@ export default function DropDown({ question, openBranchingPage, setOpenBranching mr: "4px", height: "19px", }} - onClick={() => onClickAddAnAnswer(question)} + onClick={() => addVariantWithFocus(question)} > Добавьте ответ diff --git a/src/pages/Questions/Emoji/Emoji.tsx b/src/pages/Questions/Emoji/Emoji.tsx index e7c0df86..6354aa84 100644 --- a/src/pages/Questions/Emoji/Emoji.tsx +++ b/src/pages/Questions/Emoji/Emoji.tsx @@ -4,7 +4,7 @@ import { EmojiPicker } from "@ui_kit/EmojiPicker"; import { useState } from "react"; import { EnterIcon } from "@/assets/icons/questionsPage/enterIcon"; import type { QuizQuestionEmoji } from "@frontend/squzanswerer"; -import { useAddAnswer } from "../../../utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "../../../utils/questionVariants"; import { AnswerDraggableList } from "../AnswerDraggableList"; import ButtonsOptions from "../QuestionOptions/ButtonsLayout/ButtonsOptions"; import EmojiAnswerItem from "./EmojiAnswerItem/EmojiAnswerItem"; @@ -19,7 +19,7 @@ interface Props { export default function Emoji({ question, openBranchingPage, setOpenBranchingPage }: Props) { const [switchState, setSwitchState] = useState("setting"); - const {onClickAddAnAnswer} = useAddAnswer(); + const {addVariantWithFocus, addVariantOnEnter, focusedVariantId, clearFocusedVariant} = useQuestionVariantsWithFocus(); const [open, setOpen] = useState(false); const [anchorElement, setAnchorElement] = useState(null); const [selectedVariant, setSelectedVariant] = useState(null); @@ -48,6 +48,9 @@ export default function Emoji({ question, openBranchingPage, setOpenBranchingPag setSelectedVariant={setSelectedVariant} isOwn={Boolean(variant?.isOwn)} ownPlaceholder={question.content.ownPlaceholder} + shouldAutoFocus={focusedVariantId === variant.id} + onFocusHandled={clearFocusedVariant} + onEnterKeyPress={() => addVariantOnEnter(question.id)} /> ))} /> @@ -93,7 +96,7 @@ export default function Emoji({ question, openBranchingPage, setOpenBranchingPag component="button" variant="body2" sx={{ color: theme.palette.brightPurple.main }} - onClick={() => onClickAddAnAnswer(question)} + onClick={() => addVariantWithFocus(question)} > Добавьте ответ diff --git a/src/pages/Questions/Emoji/EmojiAnswerItem/EmojiAnswerItem.tsx b/src/pages/Questions/Emoji/EmojiAnswerItem/EmojiAnswerItem.tsx index 2dc6e7cb..483d6854 100644 --- a/src/pages/Questions/Emoji/EmojiAnswerItem/EmojiAnswerItem.tsx +++ b/src/pages/Questions/Emoji/EmojiAnswerItem/EmojiAnswerItem.tsx @@ -14,6 +14,9 @@ type Props = Omit< setOpen: React.Dispatch>; isOwn: boolean; ownPlaceholder: string; + shouldAutoFocus?: boolean; + onFocusHandled?: () => void; + onEnterKeyPress?: () => void; }; export default function EmojiAnswerItem({ @@ -28,6 +31,9 @@ export default function EmojiAnswerItem({ setOpen, isOwn, ownPlaceholder, + shouldAutoFocus, + onFocusHandled, + onEnterKeyPress, }: Props) { @@ -99,6 +105,9 @@ export default function EmojiAnswerItem({ additionalMobile={addOrEditImageButtonMobile} isOwn={isOwn} ownPlaceholder={ownPlaceholder} + shouldAutoFocus={shouldAutoFocus} + onFocusHandled={onFocusHandled} + onEnterKeyPress={onEnterKeyPress} /> ); } diff --git a/src/pages/Questions/Emoji/settingEmoji.tsx b/src/pages/Questions/Emoji/settingEmoji.tsx index 1cff9275..84371e2d 100644 --- a/src/pages/Questions/Emoji/settingEmoji.tsx +++ b/src/pages/Questions/Emoji/settingEmoji.tsx @@ -4,7 +4,7 @@ import { updateQuestion } from "@root/questions/actions"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; import { memo } from "react"; import CustomTextField from "@ui_kit/CustomTextField"; -import { useAddAnswer } from "@/utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; type SettingEmojiProps = { question: QuizQuestionEmoji; @@ -17,7 +17,7 @@ type SettingEmojiProps = { const SettingEmoji = memo(function ({ question, questionId, isRequired, isLargeCheck, isMulti, isOwn }) { const theme = useTheme(); - const {switchOwn} = useAddAnswer(); + const {switchOwnVariant} = useQuestionVariantsWithFocus(); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); @@ -92,7 +92,7 @@ const SettingEmoji = memo(function ({ question, questionId, i label={'Вариант "свой ответ"'} checked={isOwn} handleChange={({ target }) => { - switchOwn({question, checked:target.checked}) + switchOwnVariant({question, checked:target.checked}) }} /> {/* diff --git a/src/pages/Questions/QuestionOptions/OptionsAndPicture/OptionsAndPicture.tsx b/src/pages/Questions/QuestionOptions/OptionsAndPicture/OptionsAndPicture.tsx index 6dfc6dc8..aee0fc07 100644 --- a/src/pages/Questions/QuestionOptions/OptionsAndPicture/OptionsAndPicture.tsx +++ b/src/pages/Questions/QuestionOptions/OptionsAndPicture/OptionsAndPicture.tsx @@ -1,9 +1,9 @@ import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material"; import { - addQuestionVariant, clearQuestionImages, uploadQuestionImage, } from "@root/questions/actions"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; import { useCurrentQuiz } from "@root/quizes/hooks"; import { useEffect, useMemo, useState } from "react"; import { EnterIcon } from "@/assets/icons/questionsPage/enterIcon"; @@ -31,6 +31,7 @@ export default function OptionsAndPicture({ const [switchState, setSwitchState] = useState("setting"); const [pictureUploding, setPictureUploading] = useState(false); const [openCropModal, setOpenCropModal] = useState(false); + const {addVariantWithFocus, addVariantOnEnter, focusedVariantId, clearFocusedVariant} = useQuestionVariantsWithFocus(); const [selectedVariantId, setSelectedVariantId] = useState( null, @@ -111,6 +112,9 @@ export default function OptionsAndPicture({ setSelectedVariantId={setSelectedVariantId} isOwn={Boolean(variant?.isOwn)} ownPlaceholder={question.content.ownPlaceholder} + shouldAutoFocus={focusedVariantId === variant.id} + onFocusHandled={clearFocusedVariant} + onEnterKeyPress={() => addVariantOnEnter(question.id)} /> ))} /> @@ -148,7 +152,7 @@ export default function OptionsAndPicture({ height: "19px", }} onClick={() => { - addQuestionVariant(question.id); + addVariantWithFocus(question); }} > Добавьте ответ diff --git a/src/pages/Questions/QuestionOptions/OptionsAndPicture/SettingOptionsAndPict.tsx b/src/pages/Questions/QuestionOptions/OptionsAndPicture/SettingOptionsAndPict.tsx index 7cb9f70f..c38ee7ed 100644 --- a/src/pages/Questions/QuestionOptions/OptionsAndPicture/SettingOptionsAndPict.tsx +++ b/src/pages/Questions/QuestionOptions/OptionsAndPicture/SettingOptionsAndPict.tsx @@ -1,4 +1,4 @@ -import { useAddAnswer } from "@/utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; import type { QuizQuestionVarImg, QuizQuestionVariant } from "@frontend/squzanswerer"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; import { updateQuestion } from "@root/questions/actions"; @@ -19,7 +19,7 @@ type SettingOptionsAndPictProps = { const SettingOptionsAndPict = memo(function ({ question, questionId, ownPlaceholder, isMulti, isLargeCheck, replText, isRequired, isOwn }) { const theme = useTheme(); - const { switchOwn } = useAddAnswer(); + const { switchOwnVariant } = useQuestionVariantsWithFocus(); const isWrappColumn = useMediaQuery(theme.breakpoints.down(980)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); @@ -73,7 +73,7 @@ const SettingOptionsAndPict = memo(function ({ quest label={'Вариант "свой ответ"'} checked={isOwn} handleChange={({ target }) => { - switchOwn({ question, checked: target.checked }) + switchOwnVariant({ question, checked: target.checked }) }} /> (false); const [openCropModal, setOpenCropModal] = useState(false); @@ -93,6 +93,9 @@ export default function OptionsPicture({ setSelectedVariantId={setSelectedVariantId} isOwn={Boolean(variant?.isOwn)} ownPlaceholder={question.content.ownPlaceholder} + shouldAutoFocus={focusedVariantId === variant.id} + onFocusHandled={clearFocusedVariant} + onEnterKeyPress={() => addVariantOnEnter(question.id)} /> ))} /> @@ -117,7 +120,7 @@ export default function OptionsPicture({ component="button" variant="body2" sx={{ color: theme.palette.brightPurple.main }} - onClick={() => onClickAddAnAnswer(question)} + onClick={() => addVariantWithFocus(question)} > Добавьте ответ diff --git a/src/pages/Questions/QuestionOptions/OptionsPicture/settingOptionsPict.tsx b/src/pages/Questions/QuestionOptions/OptionsPicture/settingOptionsPict.tsx index 26cfd18a..07a36db6 100644 --- a/src/pages/Questions/QuestionOptions/OptionsPicture/settingOptionsPict.tsx +++ b/src/pages/Questions/QuestionOptions/OptionsPicture/settingOptionsPict.tsx @@ -9,7 +9,7 @@ import ProportionsIcon11 from "@/assets/icons/questionsPage/ProportionsIcon11"; import ProportionsIcon12 from "@/assets/icons/questionsPage/ProportionsIcon12"; import ProportionsIcon21 from "@/assets/icons/questionsPage/ProportionsIcon21"; import CustomTextField from "@ui_kit/CustomTextField"; -import { useAddAnswer } from "@/utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; type Proportion = "1:1" | "1:2" | "2:1"; @@ -69,7 +69,7 @@ const SettingOptionsPict = memo(function ({ question.content.ownPlaceholder = replText; }); }; - const {switchOwn} = useAddAnswer(); + const {switchOwnVariant} = useQuestionVariantsWithFocus(); return ( (function ({ label={'Вариант "свой ответ"'} checked={isOwn} handleChange={({ target }) => { - switchOwn({question, checked:target.checked}) + switchOwnVariant({question, checked:target.checked}) }} /> {/* diff --git a/src/pages/Questions/QuestionOptions/OptionsPicture/settingOpytionsPict.tsx b/src/pages/Questions/QuestionOptions/OptionsPicture/settingOpytionsPict.tsx index 26cfd18a..07a36db6 100644 --- a/src/pages/Questions/QuestionOptions/OptionsPicture/settingOpytionsPict.tsx +++ b/src/pages/Questions/QuestionOptions/OptionsPicture/settingOpytionsPict.tsx @@ -9,7 +9,7 @@ import ProportionsIcon11 from "@/assets/icons/questionsPage/ProportionsIcon11"; import ProportionsIcon12 from "@/assets/icons/questionsPage/ProportionsIcon12"; import ProportionsIcon21 from "@/assets/icons/questionsPage/ProportionsIcon21"; import CustomTextField from "@ui_kit/CustomTextField"; -import { useAddAnswer } from "@/utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; type Proportion = "1:1" | "1:2" | "2:1"; @@ -69,7 +69,7 @@ const SettingOptionsPict = memo(function ({ question.content.ownPlaceholder = replText; }); }; - const {switchOwn} = useAddAnswer(); + const {switchOwnVariant} = useQuestionVariantsWithFocus(); return ( (function ({ label={'Вариант "свой ответ"'} checked={isOwn} handleChange={({ target }) => { - switchOwn({question, checked:target.checked}) + switchOwnVariant({question, checked:target.checked}) }} /> {/* diff --git a/src/pages/Questions/QuestionOptions/answerOptions/AnswerOptions.tsx b/src/pages/Questions/QuestionOptions/answerOptions/AnswerOptions.tsx index 5f55e6c5..3c2556df 100755 --- a/src/pages/Questions/QuestionOptions/answerOptions/AnswerOptions.tsx +++ b/src/pages/Questions/QuestionOptions/answerOptions/AnswerOptions.tsx @@ -2,7 +2,7 @@ import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material"; import { useEffect, useState } from "react"; import { EnterIcon } from "@/assets/icons/questionsPage/enterIcon"; import type { QuizQuestionVariant } from "@frontend/squzanswerer"; -import { useAddAnswer } from "@/utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; import { AnswerDraggableList } from "../../AnswerDraggableList"; import AnswerItem from "../../AnswerDraggableList/AnswerItem"; import ButtonsOptions from "../ButtonsLayout/ButtonsOptions"; @@ -15,7 +15,7 @@ interface Props { } export default function AnswerOptions({ question, openBranchingPage, setOpenBranchingPage }: Props) { - const {onClickAddAnAnswer} = useAddAnswer(); + const {addVariantWithFocus, addVariantOnEnter, focusedVariantId, clearFocusedVariant} = useQuestionVariantsWithFocus(); const [switchState, setSwitchState] = useState("setting"); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(790)); @@ -55,6 +55,9 @@ export default function AnswerOptions({ question, openBranchingPage, setOpenBran variant={variant} isOwn={Boolean(variant.isOwn)} ownPlaceholder={question.content.ownPlaceholder} + shouldAutoFocus={focusedVariantId === variant.id} + onFocusHandled={clearFocusedVariant} + onEnterKeyPress={() => addVariantOnEnter(question.id)} /> ))} /> @@ -77,7 +80,7 @@ export default function AnswerOptions({ question, openBranchingPage, setOpenBran mr: "4px", height: "19px", }} - onClick={() => onClickAddAnAnswer(question)} + onClick={() => addVariantWithFocus(question)} > Добавьте ответ diff --git a/src/pages/Questions/QuestionOptions/answerOptions/responseSettings.tsx b/src/pages/Questions/QuestionOptions/answerOptions/responseSettings.tsx index 655024ef..548fe64f 100644 --- a/src/pages/Questions/QuestionOptions/answerOptions/responseSettings.tsx +++ b/src/pages/Questions/QuestionOptions/answerOptions/responseSettings.tsx @@ -4,7 +4,7 @@ import CustomCheckbox from "@ui_kit/CustomCheckbox"; import type { QuizQuestionVariant } from "@frontend/squzanswerer"; import { memo } from "react"; import CustomTextField from "@ui_kit/CustomTextField"; -import { useAddAnswer } from "@/utils/hooks/useAddAnswer"; +import { useQuestionVariantsWithFocus } from "@/utils/questionVariants"; interface Props { question: QuizQuestionVariant; @@ -21,7 +21,7 @@ const ResponseSettings = memo(function ({question, questionId, ownPlaceho const isTablet = useMediaQuery(theme.breakpoints.down(900)); const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990)); const isMobile = useMediaQuery(theme.breakpoints.down(790)); - const {switchOwn} = useAddAnswer(); + const {switchOwnVariant} = useQuestionVariantsWithFocus(); return ( (function ({question, questionId, ownPlaceho label={'Вариант "свой ответ"'} checked={isOwn} handleChange={({ target }) => { - switchOwn({question, checked:target.checked}) + switchOwnVariant({question, checked:target.checked}) }} /> diff --git a/src/stores/questions/actions.ts b/src/stores/questions/actions.ts index 5a479490..59cf214d 100644 --- a/src/stores/questions/actions.ts +++ b/src/stores/questions/actions.ts @@ -327,7 +327,8 @@ export const updateQuestion = async ( requestQueue.enqueue(`updateQuestion-${questionId}`, request); }; -export const addQuestionVariant = (questionId: string) => { +export const addQuestionVariant = (questionId: string): string => { + const newVariant = createQuestionVariant(); updateQuestion(questionId, (question) => { switch (question.type) { case "variant": @@ -335,12 +336,13 @@ export const addQuestionVariant = (questionId: string) => { case "select": case "images": case "varimg": - question.content.variants.push(createQuestionVariant()); + question.content.variants.push(newVariant); break; default: throw new Error(`Cannot add variant to question of type "${question.type}"`); } }); + return newVariant.id; }; export const addQuestionOwnVariant = (questionId: string) => { updateQuestion(questionId, (question) => { diff --git a/src/utils/hooks/useAddAnswer.ts b/src/utils/hooks/useAddAnswer.ts deleted file mode 100644 index 0c8ee048..00000000 --- a/src/utils/hooks/useAddAnswer.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { QuizQuestionsWithVariants } from "@frontend/squzanswerer"; -import { addQuestionOwnVariant, addQuestionVariant, updateQuestion } from "@root/questions/actions"; - -export const useAddAnswer = () => { - const onClickAddAnAnswer = (question: QuizQuestionsWithVariants) => { - addQuestionVariant(question.id); - }; - interface SwitchOwnProps { - question: QuizQuestionsWithVariants; - checked: boolean - } - const switchOwn = ({ question, checked }: SwitchOwnProps) => { - if (!question.content.variants.some(v => v.isOwn) && checked) { - addQuestionOwnVariant(question.id) - } - - updateQuestion(question.id, (question) => { - question.content.own = checked; - }); - } - - return { - onClickAddAnAnswer, - switchOwn - }; -}; diff --git a/src/utils/questionVariants.ts b/src/utils/questionVariants.ts new file mode 100644 index 00000000..398d0892 --- /dev/null +++ b/src/utils/questionVariants.ts @@ -0,0 +1,47 @@ +import { QuizQuestionsWithVariants, QuizQuestionVariant } from "@frontend/squzanswerer"; +import { addQuestionOwnVariant, addQuestionVariant, updateQuestion } from "@root/questions/actions"; +import { useState } from "react"; + +/** + * Утилита для управления вариантами ответов с автофокусом + */ +export const useQuestionVariantsWithFocus = () => { + const [focusedVariantId, setFocusedVariantId] = useState(null); + + const addVariantWithFocus = (question: QuizQuestionsWithVariants) => { + const newVariantId = addQuestionVariant(question.id); + setFocusedVariantId(newVariantId); + }; + + const addVariantOnEnter = (questionId: string) => { + const newVariantId = addQuestionVariant(questionId); + setFocusedVariantId(newVariantId); + }; + + const clearFocusedVariant = () => { + setFocusedVariantId(null); + }; + + interface SwitchOwnProps { + question: QuizQuestionsWithVariants; + checked: boolean + } + + const switchOwnVariant = ({ question, checked }: SwitchOwnProps) => { + if (!question.content.variants.some(v => v.isOwn) && checked) { + addQuestionOwnVariant(question.id) + } + + updateQuestion(question.id, (question) => { + question.content.own = checked; + }); + } + + return { + addVariantWithFocus, + addVariantOnEnter, + switchOwnVariant, + focusedVariantId, + clearFocusedVariant + }; +};