diff --git a/package.json b/package.json index a70ffd6..93d62dd 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@nextui-org/system": "^2.4.5", "@nextui-org/theme": "^2.4.4", "axios": "^1.7.9", + "axios-hooks": "^5.1.0", "framer-motion": "^11.15.0", "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", diff --git a/src/app/components/Header/contents.tsx b/src/app/components/Header/contents.tsx new file mode 100644 index 0000000..5894e81 --- /dev/null +++ b/src/app/components/Header/contents.tsx @@ -0,0 +1,111 @@ +"use client"; +import { useClassStore } from "@/app/stores/classStore"; +import { User } from "@/app/types/next-auth"; +import { getInitials } from "@/app/utils/initial"; +import { + Autocomplete, + AutocompleteItem, + Avatar, + Button, + Dropdown, + DropdownItem, + DropdownMenu, + DropdownTrigger, + Navbar, + NavbarBrand, + NavbarContent, + NavbarItem, +} from "@nextui-org/react"; +import { useRouter } from "next/navigation"; +import { useEffect } from "react"; +import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher"; + +export const HeaderContent = ({ user }: { user?: User }) => { + const router = useRouter(); + const { classes, selectedClass, setSelectedClass, fetchClass } = + useClassStore(); + + const initials = user?.name ? getInitials(user.name) : ""; + + useEffect(() => { + fetchClass().then((classesFetched) => { + setSelectedClass(classesFetched[0]); + }); + }, [fetchClass, setSelectedClass]); + + return ( + + +

Toogether

+
+ + + { + console.log(selectedId); + const inputSelectedClass = classes.find( + (Class) => Class.id === selectedId, + ); + setSelectedClass(inputSelectedClass); + }} + > + {classes.map((Class) => ( + + {Class.name} + + ))} + + + + + {user?.roles.includes("admin") ? ( + + + + ) : null} + + + + + + + + + + + +

Signed in as

+

{user?.name}

+
+ Settings + + Logout + +
+
+
+
+ ); +}; diff --git a/src/app/components/Header/index.tsx b/src/app/components/Header/index.tsx index 0c925a2..af626ac 100644 --- a/src/app/components/Header/index.tsx +++ b/src/app/components/Header/index.tsx @@ -1,124 +1,9 @@ -"use client"; -import { useClassStore } from "@/app/stores/classStore"; -import { User } from "@/app/types/next-auth"; -import { - Autocomplete, - AutocompleteItem, - Avatar, - Button, - Dropdown, - DropdownItem, - DropdownMenu, - DropdownTrigger, - Navbar, - NavbarBrand, - NavbarContent, - NavbarItem, -} from "@nextui-org/react"; -import { useRouter } from "next/navigation"; -import { useEffect } from "react"; -import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher"; +import { getServerSession } from "next-auth"; +import { authOptions } from "@/authOptions"; +import { HeaderContent } from "./contents"; -const getInitials = (name: string) => { - if (!name) return ""; +export const Header = async () => { + const session = await getServerSession(authOptions); - const nameParts = name.split(" "); - if (nameParts.length === 1) { - return name; - } - - const firstInitial = nameParts[0]?.[0] || ""; - const secondInitial = nameParts[1]?.[0] || nameParts[0]?.[1] || ""; - - return firstInitial + secondInitial; -}; - -export const Header = ({ user }: { user?: User }) => { - const router = useRouter(); - const { classes, selectedClass, setSelectedClass, fetchClass } = - useClassStore(); - - const initials = user?.name ? getInitials(user.name) : ""; - - useEffect(() => { - fetchClass().then((classesFetched) => { - setSelectedClass(classesFetched[0]); - }); - }, [fetchClass, setSelectedClass]); - - return ( - - -

Toogether

-
- - - { - console.log(selectedId); - const inputSelectedClass = classes.find( - (Class) => Class.id === selectedId, - ); - setSelectedClass(inputSelectedClass); - }} - > - {classes.map((Class) => ( - - {Class.name} - - ))} - - - - - {user?.roles.includes("admin") ? ( - - - - ) : null} - - - - - - - - - - - -

Signed in as

-

{user?.name}

-
- Settings - - Logout - -
-
-
-
- ); + return ; }; diff --git a/src/app/constants/apiUrl.constant.ts b/src/app/constants/apiUrl.constant.ts new file mode 100644 index 0000000..276433a --- /dev/null +++ b/src/app/constants/apiUrl.constant.ts @@ -0,0 +1,7 @@ +const NEXT_PUBLIC_API_URL = process.env.NEXT_PUBLIC_API_URL; + +export const API_URLS = { + class: { + all: `${NEXT_PUBLIC_API_URL}/class`, + }, +}; diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx index a574612..b0b4a70 100644 --- a/src/app/dashboard/layout.tsx +++ b/src/app/dashboard/layout.tsx @@ -1,6 +1,6 @@ import { authOptions } from "@/authOptions"; import { getServerSession } from "next-auth"; -import { Header } from "../components/Header"; +import { HeaderContent } from "../components/Header/contents"; export default async function Layout({ children, @@ -11,7 +11,7 @@ export default async function Layout({ return (
-
+
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx index b7f4a44..f38f607 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,4 @@ -import { authOptions } from "@/authOptions"; import { Metadata } from "next"; -import { getServerSession } from "next-auth"; import { Header } from "./components/Header"; import { RoomTable } from "./components/Room/Table"; @@ -11,11 +9,9 @@ export const metadata: Metadata = { }; export default async function HomePage() { - const session = await getServerSession(authOptions); - return ( <> -
+
diff --git a/src/app/services/class.service.ts b/src/app/services/class.service.ts new file mode 100644 index 0000000..86762ae --- /dev/null +++ b/src/app/services/class.service.ts @@ -0,0 +1,7 @@ +import { API_URLS } from "../constants/apiUrl.constant"; +import { axiosInstance } from "../lib/axios"; +import { Class } from "../stores/classStore"; + +const getAll = () => axiosInstance.get(API_URLS.class.all); + +export const classService = { getAll }; diff --git a/src/app/stores/classStore.tsx b/src/app/stores/classStore.tsx index 66bf38d..9fa2ae5 100644 --- a/src/app/stores/classStore.tsx +++ b/src/app/stores/classStore.tsx @@ -1,7 +1,7 @@ import { create } from "zustand"; -import { axiosInstance } from "../lib/axios"; +import { classService } from "../services/class.service"; -type Class = { id: string; name: string; createdAt: string }; +export type Class = { id: string; name: string; createdAt: string }; type ClassStoreState = { classes: Class[]; @@ -34,7 +34,7 @@ export const useClassStore = create()((set) => ({ })); }, fetchClass: async () => { - const classResponse = await axiosInstance.get("/@me/class"); + const classResponse = await classService.getAll(); useClassStore.getState()._setClass(classResponse.data); return classResponse.data; }, diff --git a/src/app/utils/initial.ts b/src/app/utils/initial.ts new file mode 100644 index 0000000..a786a32 --- /dev/null +++ b/src/app/utils/initial.ts @@ -0,0 +1,13 @@ +export const getInitials = (name: string) => { + if (!name) return ""; + + const nameParts = name.split(" "); + if (nameParts.length === 1) { + return name; + } + + const firstInitial = nameParts[0]?.[0] || ""; + const secondInitial = nameParts[1]?.[0] || nameParts[0]?.[1] || ""; + + return firstInitial + secondInitial; +}; diff --git a/yarn.lock b/yarn.lock index d876ea6..dd97126 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== -"@babel/runtime@^7.20.13": +"@babel/runtime@7.26.0", "@babel/runtime@^7.20.13": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== @@ -2598,6 +2598,15 @@ axe-core@^4.10.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== +axios-hooks@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/axios-hooks/-/axios-hooks-5.1.0.tgz#f9c9e2b9c1418e66a8986624aafb5dbf90d17aff" + integrity sha512-tRTll4vPMJ30pLY2uivHJuBXM0nXFKzLWgnSaLzJEHduCdf6d9B/IHENybYcXJ8AngPUYEpkgWNGLKGuWzN+Jw== + dependencies: + "@babel/runtime" "7.26.0" + dequal "2.0.3" + lru-cache "^11.0.0" + axios@^1.7.9: version "1.7.9" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" @@ -2883,7 +2892,7 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -dequal@^2.0.3: +dequal@2.0.3, dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -4043,6 +4052,11 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^11.0.0: + version "11.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39" + integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"