import { create } from "zustand"; import { createJSONStorage, persist } from "zustand/middleware"; import { immer } from "zustand/middleware/immer"; import { ExamFunctions, ExamState, Navigation, StateFlags } from "./types"; import { rootReducer } from "./reducers"; import axios from "axios"; import { v4 } from "uuid"; import { Stat } from "@/interfaces/user"; import { Exam, Shuffles, UserSolution } from "@/interfaces/exam"; import { Module } from "@/interfaces"; export const initialState: ExamState = { exams: [], userSolutions: [], showSolutions: false, selectedModules: [], assignment: undefined, timeSpent: 0, timeSpentCurrentModule: 0, sessionId: "", exam: undefined, moduleIndex: 0, partIndex: 0, exerciseIndex: 0, questionIndex: 0, inactivity: 0, shuffles: [], bgColor: "bg-white", evaluated: [], user: undefined, navigation: { previousDisabled: false, nextDisabled: false, previousLoading: false, nextLoading: false, }, flags: { timeIsUp: false, reviewAll: false, finalizeModule: false, finalizeExam: false, pendingEvaluation: false, }, }; const useExamStore = create((set, get) => ({ ...initialState, setUser: (user: string) => set(() => ({ user })), setShowSolutions: (showSolutions: boolean) => set(() => ({ showSolutions })), setExams: (exams: Exam[]) => set(() => ({ exams })), setExam: (exam?: Exam) => set(() => ({ exam })), setModuleIndex: (moduleIndex: number) => set(() => ({ moduleIndex })), setSelectedModules: (modules: Module[]) => set(() => ({ selectedModules: modules })), setSessionId: (sessionId: string) => set(() => ({ sessionId })), setUserSolutions: (userSolutions: UserSolution[]) => set(() => ({ userSolutions })), setShuffles: (shuffles: Shuffles[]) => set(() => ({ shuffles })), setPartIndex: (partIndex: number) => set(() => ({ partIndex })), setExerciseIndex: (exerciseIndex: number) => set(() => ({ exerciseIndex })), setQuestionIndex: (questionIndex: number) => set(() => ({ questionIndex })), setBgColor: (bgColor: string) => set(() => ({ bgColor })), setEvaluated: (evaluated: UserSolution[]) => set(() => ({ evaluated })), setNavigation: (updates: Partial) => set((state) => ({ navigation: { ...state.navigation, ...updates } })), setFlags: (updates: Partial) => set((state) => ({ flags: { ...state.flags, ...updates } })), setTimeIsUp: (timeIsUp: boolean) => set((state) => ({ flags: { ...state.flags, timeIsUp } })), reset: () => set(() => initialState), saveSession: async () => { console.log("Saving your session..."); const state = get(); await axios.post("/api/sessions", { id: state.sessionId, sessionId: state.sessionId, date: new Date().toISOString(), userSolutions: state.userSolutions.filter((s) => s.type !== "speaking" && s.type !== "interactiveSpeaking"), moduleIndex: state.moduleIndex, selectedModules: state.selectedModules, assignment: state.assignment, timeSpent: state.timeSpent, timeSpentCurrentModule: state.timeSpentCurrentModule, inactivity: state.inactivity, exams: state.exams, exam: state.exam, partIndex: state.partIndex, exerciseIndex: state.exerciseIndex, questionIndex: state.questionIndex, user: state.user, }); }, saveStats: async () => { const state = get(); const newStats: Stat[] = state.userSolutions.map((solution) => ({ ...solution, id: solution.id || v4(), timeSpent: state.timeSpent, inactivity: state.inactivity, session: state.sessionId, exam: solution.exam!, module: solution.module!, user: state.user || "", date: new Date().getTime(), isDisabled: solution.isDisabled, shuffleMaps: solution.shuffleMaps, ...(state.assignment ? { assignment: state.assignment.id } : {}), isPractice: solution.isPractice })); await axios.post<{ ok: boolean }>("/api/stats", newStats); }, dispatch: (action) => set((state) => rootReducer(state, action)) })); export const usePersistentExamStore = create()( persist( immer((set) => ({ ...initialState, setUser: (user: string) => set(() => ({ user })), setShowSolutions: (showSolutions: boolean) => set(() => ({ showSolutions })), setExams: (exams: Exam[]) => set(() => ({ exams })), setExam: (exam?: Exam) => set(() => ({ exam })), setModuleIndex: (moduleIndex: number) => set(() => ({ moduleIndex })), setSelectedModules: (modules: Module[]) => set(() => ({ selectedModules: modules })), setSessionId: (sessionId: string) => set(() => ({ sessionId })), setUserSolutions: (userSolutions: UserSolution[]) => set(() => ({ userSolutions })), setShuffles: (shuffles: Shuffles[]) => set(() => ({ shuffles })), setPartIndex: (partIndex: number) => set(() => ({ partIndex })), setExerciseIndex: (exerciseIndex: number) => set(() => ({ exerciseIndex })), setQuestionIndex: (questionIndex: number) => set(() => ({ questionIndex })), setBgColor: (bgColor: string) => set(() => ({ bgColor })), setNavigation: (updates: Partial) => set((state) => ({ navigation: { ...state.navigation, ...updates } })), setFlags: (updates: Partial) => set((state) => ({ flags: { ...state.flags, ...updates } })), setTimeIsUp: (timeIsUp: boolean) => set((state) => ({ flags: { ...state.flags, timeIsUp } })), saveStats: async () => { }, saveSession: async () => { }, setEvaluated: (evaluated: UserSolution[]) => {}, reset: () => set(() => initialState), dispatch: (action) => set((state) => rootReducer(state, action)) })), { name: 'persistent-exam-store', storage: createJSONStorage(() => localStorage), partialize: (state) => ({ ...state }), } ) ); export default useExamStore;