frontAnswerer/lib/stores/quizView.ts

166 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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";
import { devtools } from "zustand/middleware";
export type Answer = string | string[] | Moment;
export type QuestionAnswer = {
questionId: string;
answer: Answer;
};
export 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 | null, //
extendedText?: string, //
originalImageUrl?: string, //
localImageUrl?: 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 store = useContext(QuizViewContext);
if (!store) throw new Error("QuizViewStore context is null");
return useStore(store, selector);
}
export const createQuizViewStore = () =>
createStore<QuizViewStore & QuizViewActions>()(
immer(
devtools(
(set, get) => ({
answers: [], //Массив вообще всех ответов. Объекты хранят инфо о id вопроса и списке выбранных ответов
ownVariants: [], //Подробное описание ответов для особенных. Здесь подробно расписана вся кастомизация ответов в own вариантах
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);
},
false,
{
type: "updateAnswer",
questionId,
answer,
points,
}
);
},
deleteAnswer(questionId) {
set(
(state) => {
state.answers = state.answers.filter((answer) => questionId !== answer.questionId);
},
false,
{
type: "deleteAnswer",
questionId,
}
);
},
updateOwnVariant(id, answer, extendedText, originalImageUrl, localImageUrl) {
set(
(state) => {
console.log("!!! STORE !!! ___ Случился вызов варианта свой ответ. Вот что я получил:");
console.log(id, answer, extendedText, originalImageUrl, localImageUrl);
const index = state.ownVariants.findIndex((variant) => variant.id === id);
if (index < 0) {
state.ownVariants.push({
id,
variant: {
id: id,
answer: answer === null ? state.ownVariants[index].variant.answer : answer,
extendedText: extendedText || "",
hints: "",
originalImageUrl: originalImageUrl || "",
localImageUrl: localImageUrl || "",
},
});
} else {
if (answer !== null) state.ownVariants[index].variant.answer = answer;
if (extendedText !== undefined) {
state.ownVariants[index].variant.extendedText = extendedText;
}
if (originalImageUrl !== undefined) {
state.ownVariants[index].variant.originalImageUrl = originalImageUrl;
}
if (localImageUrl !== undefined) {
state.ownVariants[index].variant.localImageUrl = localImageUrl;
}
}
},
false,
{
type: "updateOwnVariant",
id,
answer,
}
);
},
deleteOwnVariant(id) {
set(
(state) => {
state.ownVariants = state.ownVariants.filter((variant) => variant.id !== id);
},
false,
{
type: "deleteOwnVariant",
id,
}
);
},
setCurrentQuizStep(step) {
set({ currentQuizStep: step }, false, {
type: "setCurrentQuizStep",
step,
});
},
}),
{
name: "QuizViewStore-" + nanoid(4),
enabled: import.meta.env.DEV,
trace: import.meta.env.DEV,
}
)
)
);