103 lines
3.6 KiB
TypeScript
103 lines
3.6 KiB
TypeScript
import { QuestionVariant } from "@model/questionTypes/shared";
|
|
import { QuizStep } from "@model/settingsData";
|
|
import type { Moment } from "moment";
|
|
import { nanoid } from "nanoid";
|
|
import { createContext, useContext } from "react";
|
|
import { createStore, useStore } from "zustand";
|
|
import { immer } from "zustand/middleware/immer";
|
|
|
|
type QuestionAnswer = {
|
|
questionId: string;
|
|
answer: string | string[] | Moment;
|
|
};
|
|
|
|
type OwnVariant = {
|
|
id: string;
|
|
variant: QuestionVariant;
|
|
};
|
|
|
|
interface QuizViewStore {
|
|
answers: QuestionAnswer[];
|
|
ownVariants: OwnVariant[];
|
|
pointsSum: number;
|
|
points: Record<string, number>;
|
|
currentQuizStep: QuizStep;
|
|
}
|
|
|
|
interface QuizViewActions {
|
|
updateAnswer: (questionId: string, answer: string | string[] | Moment, points: number) => void;
|
|
deleteAnswer: (questionId: string) => void;
|
|
updateOwnVariant: (id: string, answer: string) => void;
|
|
deleteOwnVariant: (id: string) => void;
|
|
setCurrentQuizStep: (step: QuizStep) => void;
|
|
}
|
|
|
|
export const QuizViewContext = createContext<ReturnType<typeof createQuizViewStore> | null>(null);
|
|
|
|
export function useQuizViewStore<U>(selector: (state: QuizViewStore & QuizViewActions) => U): U {
|
|
const context = useContext(QuizViewContext);
|
|
if (!context) throw new Error("QuizViewStore context is null");
|
|
|
|
return useStore(context, selector);
|
|
}
|
|
|
|
export const createQuizViewStore = () => createStore<QuizViewStore & QuizViewActions>()(
|
|
immer(
|
|
(set, get) => ({
|
|
answers: [],
|
|
ownVariants: [],
|
|
points: {},
|
|
pointsSum: 0,
|
|
currentQuizStep: "startpage",
|
|
updateAnswer(questionId, answer, points) {
|
|
set(state => {
|
|
const index = state.answers.findIndex(answer => questionId === answer.questionId);
|
|
|
|
if (index < 0) {
|
|
state.answers.push({ questionId, answer });
|
|
} else {
|
|
state.answers[index] = { questionId, answer };
|
|
}
|
|
|
|
state.points = { ...state.points, ...{ [questionId]: points } };
|
|
|
|
state.pointsSum = Object.values(state.points).reduce((sum, value) => sum + value);
|
|
});
|
|
},
|
|
deleteAnswer(questionId) {
|
|
set(state => {
|
|
state.answers = state.answers.filter(answer => questionId !== answer.questionId);
|
|
});
|
|
},
|
|
updateOwnVariant(id, answer) {
|
|
set(state => {
|
|
const index = state.ownVariants.findIndex((variant) => variant.id === id);
|
|
|
|
if (index < 0) {
|
|
state.ownVariants.push({
|
|
id,
|
|
variant: {
|
|
id: nanoid(),
|
|
answer,
|
|
extendedText: "",
|
|
hints: "",
|
|
originalImageUrl: "",
|
|
},
|
|
});
|
|
} else {
|
|
state.ownVariants[index].variant.answer = answer;
|
|
}
|
|
});
|
|
},
|
|
deleteOwnVariant(id) {
|
|
set(state => {
|
|
state.ownVariants = state.ownVariants.filter((variant) => variant.id !== id);
|
|
});
|
|
},
|
|
setCurrentQuizStep(step) {
|
|
set({ currentQuizStep: step });
|
|
},
|
|
})
|
|
)
|
|
);
|