import { create } from "zustand"; import { persist } from "zustand/middleware"; import { QuizQuestionEmoji } from "../model/questionTypes/emoji"; import { QuizQuestionImages } from "../model/questionTypes/images"; import { QuizQuestionVariant } from "../model/questionTypes/variant"; import { QuizQuestionVarImg } from "../model/questionTypes/varimg"; import type { AnyQuizQuestion, QuizQuestionType, QuestionVariant, } from "../model/questionTypes/shared"; import { QUIZ_QUESTION_BASE } from "../constants/base"; import { QUIZ_QUESTION_DATE } from "../constants/date"; import { QUIZ_QUESTION_EMOJI } from "../constants/emoji"; import { QUIZ_QUESTION_FILE } from "../constants/file"; import { QUIZ_QUESTION_IMAGES } from "../constants/images"; import { QUIZ_QUESTION_NUMBER } from "../constants/number"; import { QUIZ_QUESTION_PAGE } from "../constants/page"; import { QUIZ_QUESTION_RATING } from "../constants/rating"; import { QUIZ_QUESTION_SELECT } from "../constants/select"; import { QUIZ_QUESTION_TEXT } from "../constants/text"; import { QUIZ_QUESTION_VARIANT } from "../constants/variant"; import { QUIZ_QUESTION_VARIMG } from "../constants/varimg"; import { setAutoFreeze } from "immer"; setAutoFreeze(false); interface QuestionStore { listQuestions: Record; openedModalSettings: string; } let isFirstPartialize = true; export const questionStore = create()( persist( () => ({ listQuestions: {}, openedModalSettings: "", }), { name: "question", partialize: (state: QuestionStore) => { if (isFirstPartialize) { isFirstPartialize = false; Object.keys(state.listQuestions).forEach((quizId) => { [...state.listQuestions[quizId]].forEach(({ id, deleted }) => { if (deleted) { const removedItemIndex = state.listQuestions[quizId].findIndex( (item) => item.id === id ); state.listQuestions[quizId].splice(removedItemIndex, 1); } }); }); } return state; }, merge: (persistedState, currentState) => { const state = persistedState as QuestionStore; // replace blob urls with "" Object.values(state.listQuestions).forEach(questions => { questions.forEach(question => { if (question.type === "page" && question.content.picture.startsWith("blob:")) { question.content.picture = ""; } if (question.type === "images") { question.content.variants.forEach(variant => { if (variant.extendedText.startsWith("blob:")) { variant.extendedText = ""; } }); } if (question.type === "varimg") { question.content.variants.forEach(variant => { if (variant.extendedText.startsWith("blob:")) { variant.extendedText = ""; } }); } }); }); return { ...currentState, ...state, }; }, } ) ); export const updateQuestionsList = ( quizId: number, index: number, data: Partial ) => { const questionListClone = { ...questionStore.getState()["listQuestions"] }; questionListClone[quizId][index] = { ...questionListClone[quizId][index], ...data, }; questionStore.setState({ listQuestions: questionListClone }); }; export const updateQuestionsListDragAndDrop = ( quizId: number, updatedQuestions: AnyQuizQuestion[] ) => { const questionListClone = { ...questionStore.getState()["listQuestions"] }; questionStore.setState({ listQuestions: { ...questionListClone, [quizId]: updatedQuestions }, }); }; export const updateVariants = ( quizId: number, index: number, variants: QuestionVariant[] ) => { const listQuestions = { ...questionStore.getState()["listQuestions"] }; switch (listQuestions[quizId][index].type) { case "emoji": const emojiState = listQuestions[quizId][index] as QuizQuestionEmoji; emojiState.content.variants = variants; return questionStore.setState({ listQuestions }); case "images": const imagesState = listQuestions[quizId][index] as QuizQuestionImages; imagesState.content.variants = variants; return questionStore.setState({ listQuestions }); case "variant": const variantState = listQuestions[quizId][index] as QuizQuestionVariant; variantState.content.variants = variants; return questionStore.setState({ listQuestions }); case "varimg": const varImgState = listQuestions[quizId][index] as QuizQuestionVarImg; varImgState.content.variants = variants; return questionStore.setState({ listQuestions }); } }; export const createQuestion = ( quizId: number, questionType: QuizQuestionType = "nonselected", placeIndex = -1 ) => { const id = getRandom(); const newData = { ...questionStore.getState()["listQuestions"] }; if (!newData[quizId]) { newData[quizId] = []; } const defaultObject = [ QUIZ_QUESTION_BASE, QUIZ_QUESTION_DATE, QUIZ_QUESTION_EMOJI, QUIZ_QUESTION_FILE, QUIZ_QUESTION_IMAGES, QUIZ_QUESTION_NUMBER, QUIZ_QUESTION_PAGE, QUIZ_QUESTION_RATING, QUIZ_QUESTION_SELECT, QUIZ_QUESTION_TEXT, QUIZ_QUESTION_VARIANT, QUIZ_QUESTION_VARIMG, ].find((defaultObjectItem) => defaultObjectItem.type === questionType); if (defaultObject) { newData[quizId].splice( placeIndex < 0 ? newData[quizId].length : placeIndex, 0, { ...defaultObject, id } ); questionStore.setState({ listQuestions: newData }); } }; export const copyQuestion = (quizId: number, copiedQuestionIndex: number) => { const listQuestions = { ...questionStore.getState()["listQuestions"] }; const copiedQuiz = listQuestions[quizId][copiedQuestionIndex] copiedQuiz.id = getRandom() listQuestions[quizId].splice( copiedQuestionIndex, 0, copiedQuiz ); questionStore.setState({ listQuestions }); }; export const removeQuestionForce = (quizId: number, removedId: number) => { const questionListClone = { ...questionStore.getState()["listQuestions"] }; const removedItemIndex = questionListClone[quizId].findIndex( ({ id }) => id === removedId ); questionListClone[quizId].splice(removedItemIndex, 1); questionStore.setState({ listQuestions: questionListClone }); }; export const removeQuestion = (quizId: number, index: number) => { const questionListClone = { ...questionStore.getState()["listQuestions"] }; questionListClone[quizId][index].deleted = true; questionStore.setState({ listQuestions: questionListClone }); }; export const resetSomeField = (data: Record) => { questionStore.setState(data); }; export const findQuestionById = (quizId: number) => { let found = null; questionStore .getState() ["listQuestions"][quizId].some((quiz: AnyQuizQuestion, index: number) => { if (quiz.id === quizId) { found = { quiz, index }; return true; } }); return found; }; function getRandom() { const min = Math.ceil(1000000); const max = Math.floor(10000000); return Math.floor(Math.random() * (max - min)) + min; }