diff --git a/src/pages/Questions/DraggableList/QuestionPageCard.tsx b/src/pages/Questions/DraggableList/QuestionPageCard.tsx index 1a64c47b..4d167b4f 100644 --- a/src/pages/Questions/DraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/DraggableList/QuestionPageCard.tsx @@ -39,7 +39,7 @@ import SwitchQuestionsPage from "../SwitchQuestionsPage"; import { ChooseAnswerModal } from "./ChooseAnswerModal"; import TypeQuestions from "../TypeQuestions"; import { QuestionType } from "@model/question/question"; -import { useCurrentQuiz } from "@root/quizes/hooks" +import { useCurrentQuiz } from "@root/quizes/hooks"; interface Props { question: AnyTypedQuizQuestion | UntypedQuizQuestion; @@ -98,7 +98,7 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging setTitle(target.value)} + onChange={({ target }: { target: HTMLInputElement; }) => setTitle(target.value)} InputProps={{ startAdornment: ( @@ -238,7 +238,7 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging margin: "0 5px 0 10px", }} onClick={() => { // TODO - const removedId = question.id; + const removedId = question.id; // if (question.deleteTimeoutId) { // clearTimeout(question.deleteTimeoutId); // } @@ -264,26 +264,28 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging )} - - {index + 1} - + {question.type !== null && + + {question.page + 1} + + } setProdu backendId, }); +const updateQuestionOrders = () => { + const questions = useQuestionsStore.getState().questions.filter( + (question): question is AnyTypedQuizQuestion => question.type !== null + ); + + questions.forEach((question, index) => { + updateQuestion(question.id, question => { + question.page = index; + }, true); + }); +}; + export const reorderQuestions = ( sourceIndex: number, destinationIndex: number, @@ -99,6 +110,8 @@ export const reorderQuestions = ( sourceIndex, destinationIndex, }); + + updateQuestionOrders(); }; export const toggleExpandQuestion = (questionId: string) => setProducedState(state => { @@ -123,6 +136,7 @@ let requestTimeoutId: ReturnType; export const updateQuestion = ( questionId: string, updateFn: (question: AnyTypedQuizQuestion) => void, + skipQueue = false, ) => { setProducedState(state => { const question = state.questions.find(q => q.id === questionId) || state.questions.find(q => q.type !== null && q.content.id === questionId); @@ -137,21 +151,31 @@ export const updateQuestion = ( }); // clearTimeout(requestTimeoutId); - // requestTimeoutId = setTimeout(() => { - requestQueue.enqueue(async () => { + + const request = async () => { const q = useQuestionsStore.getState().questions.find(q => q.id === questionId) || useQuestionsStore.getState().questions.find(q => q.type !== null && q.content.id === questionId); if (!q) return; if (q.type === null) throw new Error("Cannot send update request for untyped question"); - const response = await questionApi.edit(questionToEditQuestionRequest(q)); + try { + const response = await questionApi.edit(questionToEditQuestionRequest(q)); - setQuestionBackendId(questionId, response.updated); - }).catch(error => { - if (isAxiosCanceledError(error)) return; + setQuestionBackendId(questionId, response.updated); + } catch (error) { + if (isAxiosCanceledError(error)) return; - devlog("Error editing question", { error, questionId }); - enqueueSnackbar("Не удалось сохранить вопрос"); - }); + devlog("Error editing question", { error, questionId }); + enqueueSnackbar("Не удалось сохранить вопрос"); + } + }; + + if (skipQueue) { + request(); + return; + } + + // requestTimeoutId = setTimeout(() => { + requestQueue.enqueue(request); // }, REQUEST_DEBOUNCE); }; @@ -261,13 +285,13 @@ export const changeQuestionType = ( type: QuestionType, ) => { updateQuestion(questionId, question => { - const oldId = question.content.id - const oldRule = question.content.rule - oldRule.main = [] + const oldId = question.content.id; + const oldRule = question.content.rule; + oldRule.main = []; question.type = type; question.content = defaultQuestionByType[type].content; - question.content.id = oldId - question.content.rule = oldRule + question.content.id = oldId; + question.content.rule = oldRule; }); }; @@ -275,7 +299,8 @@ export const createTypedQuestion = async ( questionId: string, type: QuestionType, ) => requestQueue.enqueue(async () => { - const question = useQuestionsStore.getState().questions.find(q => q.id === questionId); + const questions = useQuestionsStore.getState().questions; + const question = questions.find(q => q.id === questionId); if (!question) return; if (question.type !== null) throw new Error("Cannot upgrade already typed question"); @@ -285,7 +310,7 @@ export const createTypedQuestion = async ( type, title: question.title, description: question.description, - page: 0, + page: questions.length, required: true, content: JSON.stringify(defaultQuestionByType[type].content), }); @@ -320,8 +345,8 @@ export const deleteQuestion = async (questionId: string, quizId: string) => requ try { await questionApi.delete(question.backendId); if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quizId, "") - clearRoleForAll() + updateRootContentId(quizId, ""); + clearRoleForAll(); } removeQuestion(questionId); @@ -338,8 +363,7 @@ export const copyQuestion = async (questionId: string, quizId: number) => reques const frontId = nanoid(); if (question.type === null) { const copiedQuestion = structuredClone(question); - copiedQuestion.id = frontId - copiedQuestion.content.id = frontId + copiedQuestion.id = frontId; setProducedState(state => { state.questions.push(copiedQuestion); @@ -357,9 +381,9 @@ export const copyQuestion = async (questionId: string, quizId: number) => reques const copiedQuestion = structuredClone(question); copiedQuestion.backendId = newQuestionId; - copiedQuestion.id = frontId - copiedQuestion.content.id = frontId - copiedQuestion.content.rule = { main: [], parentId: "", default: "" } + copiedQuestion.id = frontId; + copiedQuestion.content.id = frontId; + copiedQuestion.content.rule = { main: [], parentId: "", default: "" }; setProducedState(state => { state.questions.push(copiedQuestion); @@ -368,6 +392,8 @@ export const copyQuestion = async (questionId: string, quizId: number) => reques questionId, quizId, }); + + updateQuestionOrders(); } catch (error) { devlog("Error copying question", error); enqueueSnackbar("Не удалось скопировать вопрос"); @@ -394,7 +420,7 @@ export const getQuestionByContentId = (questionContentId: string | null) => { if (questionContentId === null) return null; return useQuestionsStore.getState().questions.find(q => { if (q.type === null) return false; - + return (q.content.id === questionContentId); }) || null; }; @@ -402,19 +428,19 @@ export const getQuestionByContentId = (questionContentId: string | null) => { export const updateOpenedModalSettingsId = (id?: string) => useQuestionsStore.setState({ openedModalSettingsId: id ? id : null }); export const updateDragQuestionContentId = (contentId?: string) => { useQuestionsStore.setState({ dragQuestionContentId: contentId ? contentId : null }); -} +}; export const clearRoleForAll = () => { - const { questions } = useQuestionsStore.getState() + const { questions } = useQuestionsStore.getState(); questions.forEach(question => { if (question.type !== null && (question.content.rule.main.length > 0 || question.content.rule.default.length > 0 || question.content.rule.parentId.length > 0)) { updateQuestion(question.content.id, question => { - question.content.rule.parentId = "" - question.content.rule.main = [] - question.content.rule.default = "" - }) + question.content.rule.parentId = ""; + question.content.rule.main = []; + question.content.rule.default = ""; + }); } }); -} +}; -export const updateOpenBranchingPanel = (value: boolean) => useQuestionsStore.setState({openBranchingPanel: !value}); +export const updateOpenBranchingPanel = (value: boolean) => useQuestionsStore.setState({ openBranchingPanel: !value });