frontPanel/src/stores/questions.ts

241 lines
7.4 KiB
TypeScript

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<string, AnyQuizQuestion[]>;
openedModalSettings: string;
}
let isFirstPartialize = true;
export const questionStore = create<QuestionStore>()(
persist<QuestionStore>(
() => ({
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 = <T = AnyQuizQuestion>(
quizId: number,
index: number,
data: Partial<T>
) => {
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<string, string>) => {
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;
}