refactor store & hooks

This commit is contained in:
nflnkr 2023-11-14 16:10:41 +03:00
parent a3b2adf0c6
commit 213075706b
6 changed files with 33 additions and 13 deletions

@ -42,7 +42,7 @@ export default function StartPage() {
}, },
}); });
const theme = useTheme(); const theme = useTheme();
const quiz = useCurrentQuiz(); const { quiz } = useCurrentQuiz();
const currentStep = useQuizStore(state => state.currentStep); const currentStep = useQuizStore(state => state.currentStep);
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(660)); const isMobile = useMediaQuery(theme.breakpoints.down(660));

@ -9,10 +9,10 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
export default function StepOne() { export default function StepOne() {
const navigate = useNavigate(); const navigate = useNavigate();
const quiz = useCurrentQuiz(); const { quiz } = useCurrentQuiz();
const config = quiz?.config; const config = quiz?.config;
if (!config) return null; if (!config) return null; // TODO throw and catch with error boundary
return ( return (
<Box <Box
@ -51,7 +51,7 @@ export default function StepOne() {
<Button <Button
variant="text" variant="text"
onClick={() => { onClick={() => {
setQuizType(quiz.id,"form", navigate); setQuizType(quiz.id, "form", navigate);
}} }}
> >
<CreationCard <CreationCard

@ -18,11 +18,11 @@ export default function Steptwo() {
const navigate = useNavigate(); const navigate = useNavigate();
const theme = useTheme(); const theme = useTheme();
const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1300)); const isSmallMonitor = useMediaQuery(theme.breakpoints.down(1300));
const quiz = useCurrentQuiz(); const { quiz } = useCurrentQuiz();
const config = quiz?.config; const config = quiz?.config;
if (!config) return null; if (!config) return null; // TODO throw and catch with error boundary
return ( return (
<Box sx={{ mt: "60px" }}> <Box sx={{ mt: "60px" }}>

@ -42,7 +42,13 @@ export const setQuizField = <T extends keyof Quiz>(
const quiz = state.quizById[quizId]; const quiz = state.quizById[quizId];
if (!quiz) return; if (!quiz) return;
const oldId = quiz.id;
quiz[field] = value; quiz[field] = value;
if (field === "id") {
delete state.quizById[oldId];
state.quizById[value as number] = quiz;
}
}, { }, {
type: "setQuizField", type: "setQuizField",
quizId, quizId,
@ -68,12 +74,16 @@ export const incrementCurrentStep = () => setProducedState(state => {
state.currentStep = Math.min( state.currentStep = Math.min(
maxQuizSetupSteps, state.currentStep + 1 maxQuizSetupSteps, state.currentStep + 1
) as QuizSetupStep; ) as QuizSetupStep;
}, {
type: "incrementCurrentStep",
}); });
export const decrementCurrentStep = () => setProducedState(state => { export const decrementCurrentStep = () => setProducedState(state => {
state.currentStep = Math.max( state.currentStep = Math.max(
1, state.currentStep - 1 1, state.currentStep - 1
) as QuizSetupStep; ) as QuizSetupStep;
}, {
type: "decrementCurrentStep",
}); });
export const setCurrentStep = (step: number) => setProducedState(state => { export const setCurrentStep = (step: number) => setProducedState(state => {
@ -126,7 +136,7 @@ export const setQuizType = (
}; };
export const setQuizStartpageType = ( export const setQuizStartpageType = (
quizId: number, quizId: number | undefined,
startpageType: QuizConfig["startpageType"], startpageType: QuizConfig["startpageType"],
navigate: NavigateFunction, navigate: NavigateFunction,
) => { ) => {
@ -144,11 +154,13 @@ let savedOriginalQuiz: Quiz | null = null;
let controller: AbortController | null = null; let controller: AbortController | null = null;
export const updateQuizWithFnOptimistic = async ( export const updateQuizWithFnOptimistic = async (
quizId: number, quizId: number | undefined,
updateFn: (quiz: Quiz) => void, updateFn: (quiz: Quiz) => void,
navigate: NavigateFunction, navigate: NavigateFunction,
rollbackOnError = true, rollbackOnError = true,
) => { ) => {
if (!quizId) return;
const quiz = useQuizStore.getState().quizById[quizId] ?? null; const quiz = useQuizStore.getState().quizById[quizId] ?? null;
if (!quiz) return; if (!quiz) return;
@ -160,11 +172,11 @@ export const updateQuizWithFnOptimistic = async (
setQuiz(currentUpdatedQuiz); setQuiz(currentUpdatedQuiz);
try { try {
const { updated } = await quizApi.edit(quizToEditQuizRequest(currentUpdatedQuiz), controller.signal); const { updated: newId } = await quizApi.edit(quizToEditQuizRequest(currentUpdatedQuiz), controller.signal);
// await new Promise((resolve, reject) => setTimeout(reject, 2000, new Error("Api rejected"))); // await new Promise((resolve, reject) => setTimeout(reject, 2000, new Error("Api rejected")));
setQuizField(quiz.id, "version", updated); setQuizField(quiz.id, "id", newId);
navigate(`/setting/${quizId}`, { replace: true }); navigate(`/setting/${newId}`, { replace: true });
controller = null; controller = null;
savedOriginalQuiz = null; savedOriginalQuiz = null;

@ -1,6 +1,8 @@
import { Quiz } from "@model/quiz/quiz"; import { Quiz } from "@model/quiz/quiz";
import { useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useQuizStore } from "./store"; import { useQuizStore } from "./store";
import { useCallback } from "react";
import { updateQuizWithFnOptimistic } from "./actions";
export function useQuizArray(): Quiz[] { export function useQuizArray(): Quiz[] {
@ -10,8 +12,13 @@ export function useQuizArray(): Quiz[] {
} }
export function useCurrentQuiz() { export function useCurrentQuiz() {
const navigate = useNavigate();
const quizId = parseInt(useParams().quizId ?? ""); const quizId = parseInt(useParams().quizId ?? "");
const quiz = useQuizStore(state => state.quizById[quizId]); const quiz = useQuizStore(state => state.quizById[quizId]);
return quiz; const updateQuiz = useCallback((updateFn: (quiz: Quiz) => void) => {
updateQuizWithFnOptimistic(quizId, updateFn, navigate);
}, [navigate, quizId]);
return { quiz, updateQuiz };
} }

@ -20,6 +20,7 @@ export const useQuizStore = create<QuizStore>()(
{ {
name: "QuizStore", name: "QuizStore",
enabled: process.env.NODE_ENV === "development", enabled: process.env.NODE_ENV === "development",
trace: process.env.NODE_ENV === "development",
} }
) )
); );