satupeta-main/shared/components/layout/header.tsx
2026-01-27 09:31:12 +07:00

137 lines
4.3 KiB
TypeScript

"use client";
import React from "react";
import { usePathname, useRouter } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import { cn } from "@/shared/utils/utils";
import { appConfig, isActiveFeature } from "@/shared/config/app-config";
import { useAuthSession } from "@/shared/hooks/use-session";
import { handleLogout } from "@/shared/hooks/use-auth-api";
import { Button } from "../button/button";
const navigation = [
{ name: "Katalog Mapset", href: "#catalog" },
{ name: "Daftar OPD", href: "#organization" },
{ name: "Statistik Konten", href: "#statistic" },
isActiveFeature.news && { name: "Berita dan Pengumuman", href: "#news" },
];
export function Header() {
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 = 64;
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-inter fixed top-0 right-0 left-0 z-[403] h-[64px] border-b border-zinc-200 bg-zinc-50 text-slate-800 transition-all duration-300",
isScrolled ?? "shadow-sm",
)}
>
<div className="container mx-auto h-full max-w-7xl">
<div className="lg:px-8nter flex h-full items-center justify-between px-4 sm:px-6">
<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 className="mx-4 h-8 w-px bg-zinc-200" />
<nav className="hidden md:ml-10 md:flex md:space-x-8">
{navigation.map(
(item) =>
item && (
<a
key={item.name}
href={item.href}
onClick={(e) => handleNavigation(e, item.href)}
className="hover:text-primary text-sm font-medium text-gray-700 transition-colors"
>
{item.name}
</a>
),
)}
</nav>
</div>
<div className="flex items-center">
{isAuthenticated ? (
<div className="flex items-center gap-4">
<span className="text-sm font-medium">
Hi, {session?.user?.name}
</span>
<Button variant="outlined" onClick={handleLogout}>
Logout
</Button>
</div>
) : (
<Button variant="primary" onClick={handleLogin}>
Login
</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>
</div>
</div>
</div>
</header>
);
}