feat: refactor class selection handling by introducing user store and updating related components
This commit is contained in:
parent
da74d1bf82
commit
1684ac2743
@ -1,5 +1,4 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useClassStore } from "@/app/stores/classStore";
|
|
||||||
import { User } from "@/app/types/next-auth";
|
import { User } from "@/app/types/next-auth";
|
||||||
import { getInitials } from "@/app/utils/initial";
|
import { getInitials } from "@/app/utils/initial";
|
||||||
import {
|
import {
|
||||||
@ -19,19 +18,28 @@ import {
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher";
|
import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher";
|
||||||
|
import { useUserStore } from "@/app/stores/userStore";
|
||||||
|
import { useClassStore } from "@/app/stores/classStore";
|
||||||
|
|
||||||
export const HeaderContent = ({ user }: { user?: User }) => {
|
export const HeaderContent = ({ user }: { user?: User }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { classes, selectedClass, setSelectedClass, fetchClass } =
|
|
||||||
useClassStore();
|
|
||||||
|
|
||||||
const initials = user?.name ? getInitials(user.name) : "";
|
const { classes, fetchClass } = useClassStore();
|
||||||
|
const {
|
||||||
|
currentClassId: selectedClassId,
|
||||||
|
setCurrentClassId: setSelectedClassId,
|
||||||
|
} = useUserStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchClass().then((classesFetched) => {
|
fetchClass();
|
||||||
setSelectedClass(classesFetched[0]);
|
}, [fetchClass]);
|
||||||
});
|
|
||||||
}, [fetchClass, setSelectedClass]);
|
const selectedClass = classes.find((Class) => Class.id === selectedClassId);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectedClass && classes.length > 0)
|
||||||
|
setSelectedClassId(classes[0].id);
|
||||||
|
}, [selectedClass, classes, setSelectedClassId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Navbar className="mb-2">
|
<Navbar className="mb-2">
|
||||||
@ -46,15 +54,15 @@ export const HeaderContent = ({ user }: { user?: User }) => {
|
|||||||
value={selectedClass?.name}
|
value={selectedClass?.name}
|
||||||
selectedKey={selectedClass?.id}
|
selectedKey={selectedClass?.id}
|
||||||
onSelectionChange={(selectedId) => {
|
onSelectionChange={(selectedId) => {
|
||||||
console.log(selectedId);
|
|
||||||
const inputSelectedClass = classes.find(
|
const inputSelectedClass = classes.find(
|
||||||
(Class) => Class.id === selectedId,
|
(Class) => Class.id === selectedId,
|
||||||
);
|
);
|
||||||
setSelectedClass(inputSelectedClass);
|
if (inputSelectedClass)
|
||||||
|
setSelectedClassId(inputSelectedClass.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{classes.map((Class) => (
|
{classes.map((Class) => (
|
||||||
<AutocompleteItem key={Class.id} isSelected>
|
<AutocompleteItem key={Class.id}>
|
||||||
{Class.name}
|
{Class.name}
|
||||||
</AutocompleteItem>
|
</AutocompleteItem>
|
||||||
))}
|
))}
|
||||||
@ -86,7 +94,7 @@ export const HeaderContent = ({ user }: { user?: User }) => {
|
|||||||
as="button"
|
as="button"
|
||||||
className="transition-transform"
|
className="transition-transform"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
name={initials}
|
name={user?.name ? getInitials(user.name) : ""}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
</DropdownTrigger>
|
</DropdownTrigger>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useRoomStore } from "@/app/stores/roomStore";
|
import { useRoomStore } from "@/app/stores/roomStore";
|
||||||
|
import { useUserStore } from "@/app/stores/userStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { RoomList } from "./List";
|
import { RoomList } from "./List";
|
||||||
import { useClassStore } from "@/app/stores/classStore";
|
|
||||||
|
|
||||||
export const RoomTable = () => {
|
export const RoomTable = () => {
|
||||||
const { fetchRooms, actual, future, past } = useRoomStore();
|
const { fetchRooms, actual, future, past } = useRoomStore();
|
||||||
const { selectedClass } = useClassStore();
|
const { currentClassId: selectedClassId } = useUserStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchRooms();
|
if (selectedClassId) fetchRooms();
|
||||||
}, [fetchRooms, selectedClass]);
|
}, [fetchRooms, selectedClassId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
|
@ -10,7 +10,7 @@ export const Sidebar = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="fixed top-0 left-0 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0">
|
<aside className="fixed top-0 left-0 w-64 h-screen">
|
||||||
<div className="flex flex-col gap-2 h-full px-3 py-4 overflow-y-auto bg-foreground-100">
|
<div className="flex flex-col gap-2 h-full px-3 py-4 overflow-y-auto bg-foreground-100">
|
||||||
<ul className="font-medium gap-2">
|
<ul className="font-medium gap-2">
|
||||||
<li>
|
<li>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { API_URLS } from "../constants/apiUrl.constant";
|
import { API_URLS } from "../constants/apiUrl.constant";
|
||||||
import { axiosInstance } from "../lib/axios";
|
import { axiosInstance } from "../lib/axios";
|
||||||
import { Class } from "../stores/classStore";
|
|
||||||
|
|
||||||
const getAll = () => axiosInstance.get<Class[]>(API_URLS.class.all);
|
const getAll = () => axiosInstance.get<Class[]>(API_URLS.class.all);
|
||||||
|
|
||||||
|
@ -1,24 +1,19 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { classService } from "../services/class.service";
|
import { classService } from "../services/class.service";
|
||||||
|
|
||||||
export type Class = { id: string; name: string; createdAt: string };
|
|
||||||
|
|
||||||
type ClassStoreState = {
|
type ClassStoreState = {
|
||||||
classes: Class[];
|
classes: Class[];
|
||||||
selectedClass: Class | undefined | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type ClassStoreActions = {
|
type ClassStoreActions = {
|
||||||
_setClass: (classes: Class[]) => void;
|
_setClass: (classes: Class[]) => void;
|
||||||
fetchClass: () => Promise<Class[]>;
|
fetchClass: () => Promise<Class[]>;
|
||||||
setSelectedClass: (selectedClass: Class | undefined | null) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type ClassStore = ClassStoreState & ClassStoreActions;
|
type ClassStore = ClassStoreState & ClassStoreActions;
|
||||||
|
|
||||||
const defaultState: ClassStoreState = {
|
const defaultState: ClassStoreState = {
|
||||||
classes: [],
|
classes: [],
|
||||||
selectedClass: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useClassStore = create<ClassStore>()((set) => ({
|
export const useClassStore = create<ClassStore>()((set) => ({
|
||||||
@ -28,11 +23,6 @@ export const useClassStore = create<ClassStore>()((set) => ({
|
|||||||
classes: classes,
|
classes: classes,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
setSelectedClass: (selectedClass: Class | undefined | null) => {
|
|
||||||
set(() => ({
|
|
||||||
selectedClass: selectedClass,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
fetchClass: async () => {
|
fetchClass: async () => {
|
||||||
const classResponse = await classService.getAll();
|
const classResponse = await classService.getAll();
|
||||||
useClassStore.getState()._setClass(classResponse.data);
|
useClassStore.getState()._setClass(classResponse.data);
|
||||||
|
@ -2,7 +2,7 @@ import moment from "moment";
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { Room } from "../components/Room/Room";
|
import { Room } from "../components/Room/Room";
|
||||||
import { axiosInstance } from "../lib/axios";
|
import { axiosInstance } from "../lib/axios";
|
||||||
import { useClassStore } from "./classStore";
|
import { useUserStore } from "./userStore";
|
||||||
|
|
||||||
type RoomStoreState = {
|
type RoomStoreState = {
|
||||||
future: Room[] | null;
|
future: Room[] | null;
|
||||||
@ -38,11 +38,11 @@ export const useRoomStore = create<RoomStore>()((set) => ({
|
|||||||
set({ future, actual, past });
|
set({ future, actual, past });
|
||||||
},
|
},
|
||||||
fetchRooms: () => {
|
fetchRooms: () => {
|
||||||
const classSelected = useClassStore.getState().selectedClass;
|
const selectedClassId = useUserStore.getState().currentClassId;
|
||||||
if (!classSelected) return;
|
if (!selectedClassId) return;
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get<Room[]>(`/@me/class/${classSelected.id}/rooms`)
|
.get<Room[]>(`/@me/class/${selectedClassId}/rooms`)
|
||||||
.then((classes) => {
|
.then((classes) => {
|
||||||
useRoomStore.getState()._setRooms(classes.data);
|
useRoomStore.getState()._setRooms(classes.data);
|
||||||
});
|
});
|
||||||
|
31
src/app/stores/userStore.ts
Normal file
31
src/app/stores/userStore.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
import { persist, createJSONStorage } from "zustand/middleware";
|
||||||
|
|
||||||
|
type UserStoreState = {
|
||||||
|
currentClassId: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserStoreActions = {
|
||||||
|
setCurrentClassId: (classId: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserStore = UserStoreState & UserStoreActions;
|
||||||
|
|
||||||
|
const defaultState: UserStoreState = {
|
||||||
|
currentClassId: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUserStore = create<UserStore>()(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
|
...defaultState,
|
||||||
|
setCurrentClassId: (classId: string) => {
|
||||||
|
set({ currentClassId: classId });
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "userStore",
|
||||||
|
storage: createJSONStorage(() => localStorage),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
5
src/app/types/class.d.ts
vendored
Normal file
5
src/app/types/class.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
interface Class {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user