feat: added zustand store to help keep track of lesson sessions
This commit is contained in:
38
package-lock.json
generated
38
package-lock.json
generated
@@ -24,7 +24,8 @@
|
|||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
"superjson": "^2.2.1",
|
"superjson": "^2.2.1",
|
||||||
"svix": "^1.15.0",
|
"svix": "^1.15.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4",
|
||||||
|
"zustand": "^4.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/eslint-plugin-next": "^14.0.3",
|
"@next/eslint-plugin-next": "^14.0.3",
|
||||||
@@ -1254,7 +1255,7 @@
|
|||||||
"version": "15.7.11",
|
"version": "15.7.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
|
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/qs": {
|
"node_modules/@types/qs": {
|
||||||
"version": "6.9.10",
|
"version": "6.9.10",
|
||||||
@@ -1270,7 +1271,7 @@
|
|||||||
"version": "18.2.41",
|
"version": "18.2.41",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.41.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.41.tgz",
|
||||||
"integrity": "sha512-CwOGr/PiLiNBxEBqpJ7fO3kocP/2SSuC9fpH5K7tusrg4xPSRT/193rzolYwQnTN02We/ATXKnb6GqA5w4fRxw==",
|
"integrity": "sha512-CwOGr/PiLiNBxEBqpJ7fO3kocP/2SSuC9fpH5K7tusrg4xPSRT/193rzolYwQnTN02We/ATXKnb6GqA5w4fRxw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"@types/scheduler": "*",
|
"@types/scheduler": "*",
|
||||||
@@ -1290,7 +1291,7 @@
|
|||||||
"version": "0.16.8",
|
"version": "0.16.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/semver": {
|
"node_modules/@types/semver": {
|
||||||
"version": "7.5.6",
|
"version": "7.5.6",
|
||||||
@@ -2006,7 +2007,7 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
|
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/d": {
|
"node_modules/d": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -5104,6 +5105,33 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zustand": {
|
||||||
|
"version": "4.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz",
|
||||||
|
"integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==",
|
||||||
|
"dependencies": {
|
||||||
|
"use-sync-external-store": "1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.7.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": ">=16.8",
|
||||||
|
"immer": ">=9.0",
|
||||||
|
"react": ">=16.8"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"immer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
"superjson": "^2.2.1",
|
"superjson": "^2.2.1",
|
||||||
"svix": "^1.15.0",
|
"svix": "^1.15.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4",
|
||||||
|
"zustand": "^4.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/eslint-plugin-next": "^14.0.3",
|
"@next/eslint-plugin-next": "^14.0.3",
|
||||||
|
|||||||
29
src/app/_hooks/useLessonStore.ts
Normal file
29
src/app/_hooks/useLessonStore.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
import type { SelectExercises } from "~/server/db/schema-types";
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
id: Id | undefined;
|
||||||
|
exercises: SelectExercises[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Actions {
|
||||||
|
setId: (id?: Id) => void;
|
||||||
|
reset: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Id {
|
||||||
|
courseId: number;
|
||||||
|
topicId: number;
|
||||||
|
lessonId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: State = {
|
||||||
|
id: undefined,
|
||||||
|
exercises: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useLessonStore = create<State & Actions>()((set) => ({
|
||||||
|
...initialState,
|
||||||
|
setId: (id) => set(() => ({ id })),
|
||||||
|
reset: () => set(initialState),
|
||||||
|
}));
|
||||||
20
src/app/_hooks/useResetLesson.ts
Normal file
20
src/app/_hooks/useResetLesson.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import { useLessonStore } from "~/app/_hooks/useLessonStore";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This resets the lesson store any time a user leaves
|
||||||
|
* the lessons page
|
||||||
|
*/
|
||||||
|
export default function useResetLesson() {
|
||||||
|
const lastRoute = useRef("/");
|
||||||
|
|
||||||
|
const id = useLessonStore((state) => state.id);
|
||||||
|
const reset = useLessonStore((state) => state.reset);
|
||||||
|
|
||||||
|
const pathname = usePathname();
|
||||||
|
useEffect(() => {
|
||||||
|
if (lastRoute.current === "/lesson" && id) reset();
|
||||||
|
lastRoute.current = pathname;
|
||||||
|
}, [pathname]);
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type { PropsWithChildren } from "react";
|
import type { PropsWithChildren } from "react";
|
||||||
|
import useResetLesson from "~/app/_hooks/useResetLesson";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client-side provider components that need to wrap
|
* Client-side provider components that need to wrap
|
||||||
* the entire app should be defined here to avoid
|
* the entire app should be defined here to avoid
|
||||||
* turning the entire app into a client component
|
* turning the entire app into a client component
|
||||||
*/
|
*/
|
||||||
export default function ClientProviders({ children }: PropsWithChildren) {
|
export default function ClientProviders({ children }: PropsWithChildren) {
|
||||||
|
useResetLesson();
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user