feat(results): add resutls page

fix(leaderboard): fix leaderboard fetch logic

fix(test): fix navigation bug upon test quit
This commit is contained in:
shafin-r
2026-02-10 19:32:46 +06:00
parent 8cfcb11f0a
commit 7f82e640e0
17 changed files with 560 additions and 82 deletions

View File

@ -50,10 +50,7 @@ export const useExamConfigStore = create<ExamConfigState>()(
}),
setUserXp: (userXp) =>
set({
payload: {
...(get().payload ?? {}),
userXp,
} as StartExamPayload,
userXp: userXp,
}),
setDifficulty: (difficulty) =>

16
src/stores/useResults.ts Normal file
View File

@ -0,0 +1,16 @@
import { create } from "zustand";
import type { Results } from "../types/test";
interface ResultsState {
results: Results | null;
setResults: (results: Results) => void;
clearResults: () => void;
}
export const useResults = create<ResultsState>((set) => ({
results: null,
setResults: (results: Results) => set({ results }),
clearResults: () => set({ results: null }),
}));

View File

@ -2,33 +2,14 @@ import { create } from "zustand";
import { persist } from "zustand/middleware";
import { type ExamPhase } from "../types/sheet";
import type { SessionModuleQuestions } from "../types/session";
// interface SatExamState {
// modules: Module[];
// phase: ExamPhase;
// moduleIndex: number;
// questionIndex: number;
// endTime: number | null;
// startExam: () => void;
// setModuleQuestionss: (modules: Module[]) => void;
// nextQuestion: () => void;
// prevQuestion: () => void;
// nextModule: () => void;
// nextPhase: () => void;
// skipBreak: () => void;
// getRemainingTime: () => number;
// finishExam: () => void;
// resetExam: () => void;
// replaceModules: (modules: Module[]) => void;
// }
import type { Results } from "../types/test";
interface SatExamState {
currentModuleQuestions: SessionModuleQuestions | null;
phase: ExamPhase;
questionIndex: number;
endTime: number | null;
results: Results | null;
setModuleQuestions: (module: SessionModuleQuestions) => void;
startExam: () => void;
@ -36,10 +17,14 @@ interface SatExamState {
prevQuestion: () => void;
goToQuestion: (index: number) => void;
setPhase: (phase: ExamPhase) => void;
startBreak: () => void;
skipBreak: () => void;
finishExam: () => void;
quitExam: () => void;
resetExam: () => void;
setResults: (results: Results) => void;
getRemainingTime: () => number;
}
@ -52,6 +37,7 @@ export const useSatExam = create<SatExamState>()(
phase: "IDLE",
questionIndex: 0,
endTime: null,
results: null,
setModuleQuestions: (module: SessionModuleQuestions) => {
const endTime = Date.now() + module.time_limit_minutes * 1000;
@ -117,6 +103,13 @@ export const useSatExam = create<SatExamState>()(
},
finishExam: () => set({ phase: "FINISHED", endTime: null }),
quitExam: () => set({ phase: "QUIT", endTime: null }),
setPhase: (phase) => {
set({ phase: phase });
},
setResults: (results: Results) => set({ results }),
getRemainingTime: () => {
const { endTime } = get();
@ -130,8 +123,19 @@ export const useSatExam = create<SatExamState>()(
phase: "IDLE",
questionIndex: 0,
endTime: null,
results: null, // reset results too
}),
}),
{ name: "sat-exam-storage" },
{
name: "sat-exam-storage",
partialize: (state) => ({
// Only persist things you want to survive reloads
currentModuleQuestions: state.currentModuleQuestions,
phase: state.phase,
questionIndex: state.questionIndex,
endTime: state.endTime,
// Notice: results is NOT included
}),
},
),
);