137 lines
4.2 KiB
TypeScript
Executable File
137 lines
4.2 KiB
TypeScript
Executable File
"use client";
|
|
|
|
import React from "react";
|
|
import { usePathname, useRouter } from "next/navigation";
|
|
import { appConfig, isActiveFeature } from "@/shared/config/app-config";
|
|
import { useAuthSession } from "@/shared/hooks/use-session";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { handleLogout } from "@/shared/hooks/use-auth-api";
|
|
import { cn } from "@/shared/utils/utils";
|
|
import { Button } from "../button/button";
|
|
|
|
const navigation = [
|
|
{ name: "Katalog", href: "#catalog" },
|
|
{ name: "OPD", href: "#organization" },
|
|
// { name: "Statistik", href: "#statistic" },
|
|
isActiveFeature.news && { name: "Berita", href: "#news" },
|
|
];
|
|
|
|
export function MenuHeader() {
|
|
const [isScrolled, setIsScrolled] = React.useState(false);
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
const { session, isAuthenticated } = useAuthSession();
|
|
|
|
React.useEffect(() => {
|
|
const handleScroll = () => {
|
|
setIsScrolled(window.scrollY > 10);
|
|
};
|
|
|
|
window.addEventListener("scroll", handleScroll);
|
|
return () => window.removeEventListener("scroll", handleScroll);
|
|
}, []);
|
|
|
|
const handleNavigation = (
|
|
e: React.MouseEvent<HTMLAnchorElement>,
|
|
href: string,
|
|
) => {
|
|
e.preventDefault();
|
|
const fixedHeaderHeight = 85;
|
|
|
|
if (pathname === "/") {
|
|
const targetElement = document.querySelector(href);
|
|
if (targetElement) {
|
|
const elementTop =
|
|
targetElement.getBoundingClientRect().top + window.pageYOffset;
|
|
const offsetTop = elementTop - fixedHeaderHeight;
|
|
|
|
window.scrollTo({
|
|
top: offsetTop,
|
|
behavior: "smooth",
|
|
});
|
|
}
|
|
} else {
|
|
router.push(`/${href}`);
|
|
}
|
|
};
|
|
|
|
const handleLogin = () => {
|
|
router.push("/auth/admin/login?callbackUrl=/admin");
|
|
};
|
|
|
|
return (
|
|
<header
|
|
className={cn(
|
|
"font-onest fixed top-0 right-0 left-0 z-[1005] h-20 border-b border-zinc-200 bg-white text-white transition-all duration-300",
|
|
isScrolled ?? "shadow-sm",
|
|
)}
|
|
>
|
|
<div className="container h-full">
|
|
<div className="flex h-full items-center justify-between">
|
|
<div className="flex items-center">
|
|
<Link href="/" className="h-auto w-40">
|
|
<Image
|
|
src={appConfig.logo}
|
|
alt="Satu Peta"
|
|
width={120}
|
|
height={120}
|
|
className="w-auto"
|
|
/>
|
|
</Link>
|
|
</div>
|
|
|
|
{/* list menu */}
|
|
<nav className="hidden md:flex md:items-center md:gap-x-12">
|
|
{navigation.map(
|
|
(item) =>
|
|
item && (
|
|
<a
|
|
key={item.name}
|
|
href={item.href}
|
|
onClick={(e) => handleNavigation(e, item.href)}
|
|
className="hover:text-primary text-md text-biru-500 transition-colors"
|
|
>
|
|
{item.name}
|
|
</a>
|
|
),
|
|
)}
|
|
|
|
{isAuthenticated ? (
|
|
<div className="flex items-center gap-4">
|
|
<span className="text-dark-300 font-onest text-sm">
|
|
Hi, {session?.user?.name}
|
|
</span>
|
|
<Button variant="outlined" size="sm" onClick={handleLogout}>
|
|
Logout
|
|
</Button>
|
|
</div>
|
|
) : (
|
|
<Button variant="primary" onClick={handleLogin}>
|
|
MASUK
|
|
</Button>
|
|
)}
|
|
<Button variant="outlined" size="icon" className="ml-2 md:hidden">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
|
</svg>
|
|
</Button>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|