frontAnswerer/lib/stores/quizView.ts
Nastya 38bd30ce35
Some checks failed
Deploy / CreateImage (push) Failing after 3m49s
Deploy / DeployService (push) Failing after 25s
держится контекст о выбранной картинке у Images
2025-06-20 20:07:46 +03:00

164 lines
5.1 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";
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,
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: [],
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);
},
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) => {
const index = state.ownVariants.findIndex((variant) => variant.id === id);
if (index < 0) {
state.ownVariants.push({
id,
variant: {
id: id,
answer,
extendedText: extendedText || "",
hints: "",
originalImageUrl: originalImageUrl || "",
localImageUrl: localImageUrl || "",
},
});
} else {
state.ownVariants[index].variant.answer = answer;
if (extendedText) {
state.ownVariants[index].variant.extendedText = extendedText;
}
if (originalImageUrl) {
state.ownVariants[index].variant.originalImageUrl = originalImageUrl;
}
if (localImageUrl) {
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,
}
)
)
);