generated from muhtadeetaron/nextjs-template
feat(zustand): add zustand stores for exam, timer and auth
This commit is contained in:
90
stores/examStore.ts
Normal file
90
stores/examStore.ts
Normal file
@ -0,0 +1,90 @@
|
||||
"use client";
|
||||
|
||||
import { create } from "zustand";
|
||||
import { Test, Answer } from "@/types/exam";
|
||||
import { API_URL, getToken } from "@/lib/auth";
|
||||
|
||||
interface ExamState {
|
||||
test: Test | null;
|
||||
answers: Answer[];
|
||||
|
||||
startExam: (testType: string, testId: string) => Promise<void>;
|
||||
setAnswer: (questionIndex: number, answer: Answer) => void;
|
||||
submitExam: (testType: string) => Promise<void>;
|
||||
cancelExam: () => void;
|
||||
}
|
||||
|
||||
export const useExamStore = create<ExamState>((set, get) => ({
|
||||
test: null,
|
||||
answers: [],
|
||||
|
||||
// start exam
|
||||
startExam: async (testType: string, testId: string) => {
|
||||
try {
|
||||
const token = await getToken();
|
||||
const res = await fetch(`${API_URL}/tests/${testType}/${testId}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error(`Failed to fetch test: ${res.status}`);
|
||||
const data: Test = await res.json();
|
||||
|
||||
set({
|
||||
test: data,
|
||||
answers: Array(data.questions.length).fill(null),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("startExam error:", err);
|
||||
}
|
||||
},
|
||||
|
||||
// set an answer
|
||||
setAnswer: (questionIndex: number, answer: Answer) => {
|
||||
set((state) => {
|
||||
const updated = [...state.answers];
|
||||
updated[questionIndex] = answer;
|
||||
return { answers: updated };
|
||||
});
|
||||
},
|
||||
|
||||
// submit exam
|
||||
submitExam: async (testType: string) => {
|
||||
const { test, answers } = get();
|
||||
if (!test) return;
|
||||
|
||||
const token = await getToken();
|
||||
|
||||
try {
|
||||
const { test_id, attempt_id } = test.metadata;
|
||||
console.log(answers);
|
||||
const res = await fetch(
|
||||
`${API_URL}/tests/${testType}/${test_id}/${attempt_id}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({ answers }),
|
||||
}
|
||||
);
|
||||
|
||||
console.log(res);
|
||||
|
||||
if (!res.ok) throw new Error("Failed to submit exam");
|
||||
|
||||
// reset store
|
||||
set({ test: null, answers: [] });
|
||||
} catch (err) {
|
||||
console.error("Failed to submit exam. Reason:", err);
|
||||
}
|
||||
},
|
||||
|
||||
// cancel exam
|
||||
cancelExam: () => {
|
||||
set({ test: null, answers: [] });
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user