diff --git a/src/components/header/user-menu.tsx b/src/components/header/user-menu.tsx new file mode 100644 index 000000000..7efc6434c --- /dev/null +++ b/src/components/header/user-menu.tsx @@ -0,0 +1,144 @@ +import { useClickOutside } from "@hooks"; +import clsx from "clsx"; +import Image from "next/image"; +import Link from "next/link"; +import { signOut, useSession } from "next-auth/react"; +import { useState } from "react"; + +type TProps = { + /** Tone of surrounding header — affects placeholder/avatar contrast on dark headers. */ + mode?: "light" | "dark"; + className?: string; +}; + +const UserMenu = ({ mode = "dark", className }: TProps) => { + const { data: session, status } = useSession(); + const [open, setOpen] = useState(false); + const ref = useClickOutside(() => setOpen(false)); + + const handleLogout = async () => { + setOpen(false); + try { + await signOut({ callbackUrl: "/login" }); + } catch (error) { + console.error("[UserMenu] signOut failed:", error); + window.alert( + "Logout failed. Please try again, or clear your browser cookies for this site." + ); + } + }; + + if (status === "loading") { + return ( +
- setOffcanvas(false)} menu={menu} /> + setOffcanvas(false)} + menu={filteredMenu} + /> ); }; diff --git a/src/layouts/headers/header-02.tsx b/src/layouts/headers/header-02.tsx index 1ac851178..65e935ff2 100644 --- a/src/layouts/headers/header-02.tsx +++ b/src/layouts/headers/header-02.tsx @@ -1,12 +1,13 @@ +import UserMenu from "@components/header/user-menu"; import Logo from "@components/logo"; import MainMenu from "@components/menu/main-menu"; import menu, { filterMenuByAuth } from "@data/menu"; import { useSticky } from "@hooks"; import BurgerButton from "@ui/burger-button"; import clsx from "clsx"; -import { useSession } from "next-auth/react"; import dynamic from "next/dynamic"; import { useRouter } from "next/router"; +import { useSession } from "next-auth/react"; import { useEffect, useMemo, useState } from "react"; const MobileMenu = dynamic(() => import("../../components/menu/mobile-menu"), { @@ -51,11 +52,16 @@ const Header = ({ shadow, fluid }: TProps) => { fluid && "tw-max-w-full tw-px-3.8 3xl:tw-px-37" )} > - + -
+
+ setOffcanvas(true)} label="Toggle Menu" @@ -65,7 +71,11 @@ const Header = ({ shadow, fluid }: TProps) => {
- setOffcanvas(false)} menu={filteredMenu} /> + setOffcanvas(false)} + menu={filteredMenu} + /> ); }; diff --git a/src/layouts/headers/header.tsx b/src/layouts/headers/header.tsx index 0c5645e6b..57d6222e7 100644 --- a/src/layouts/headers/header.tsx +++ b/src/layouts/headers/header.tsx @@ -1,3 +1,4 @@ +import UserMenu from "@components/header/user-menu"; import Logo from "@components/logo"; import MainMenu from "@components/menu/main-menu"; import Social01 from "@components/socials/social-01"; @@ -7,9 +8,9 @@ import BurgerButton from "@ui/burger-button"; import Button from "@ui/button"; import CountdownTimer from "@ui/countdown-timer/layout-03"; import clsx from "clsx"; -import { useSession } from "next-auth/react"; import dynamic from "next/dynamic"; import { useRouter } from "next/router"; +import { useSession } from "next-auth/react"; import { useEffect, useMemo, useState } from "react"; const MobileMenu = dynamic(() => import("../../components/menu/mobile-menu"), { @@ -91,14 +92,28 @@ const Header = ({ shadow, fluid }: TProps) => {
- + - + 2026 Cohort Active
+ {
- setOffcanvas(false)} menu={filteredMenu} /> + setOffcanvas(false)} + menu={filteredMenu} + /> ); };