Files
frontend/apps/dm_new/components/TopNav.tsx
T
2026-02-18 22:11:12 +09:00

188 lines
6.2 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useId, useMemo, useState } from "react";
import LoginModal from "@/components/LoginModal";
import { fetchAnonymousMenu, isMenuActive, type MenuItem } from "@/app/store/common";
const REGISTER_HREF = "/reuse/apply/place";
const LS_TOKEN_KEY = "reuse_accessToken";
const LS_USER_KEY = "reuse_userName";
const DEFAULT_NAV_ITEMS: Pick<MenuItem, "menuCd" | "menuKornNm" | "urlPath" | "newWndwYn">[] = [
{ menuCd: 1, menuKornNm: "Intro", urlPath: "/reuse/intro/law", newWndwYn: "N" },
{ menuCd: 2, menuKornNm: "Status", urlPath: "/reuse/cases/rain", newWndwYn: "N" },
{ menuCd: 3, menuKornNm: "Business", urlPath: "/reuse/business/rain/suwon", newWndwYn: "N" },
{ menuCd: 4, menuKornNm: "Demand", urlPath: "/reuse/apply/place", newWndwYn: "N" },
];
export default function TopNav() {
const router = useRouter();
const pathname = usePathname();
const [loginOpen, setLoginOpen] = useState(false);
const [userName, setUserName] = useState<string | null>(null);
const [topMenus, setTopMenus] = useState<MenuItem[]>([]);
useEffect(() => {
const name = localStorage.getItem(LS_USER_KEY);
setUserName(name);
}, []);
useEffect(() => {
let isMounted = true;
(async () => {
try {
const loaded = await fetchAnonymousMenu();
if (!isMounted) return;
const level1 = loaded.filter((menu) => menu.levelNo === 1 || menu.parentId === null);
setTopMenus(level1);
} catch (error) {
console.error("Failed to load DN top menu", error);
if (!isMounted) return;
setTopMenus([]);
}
})();
return () => {
isMounted = false;
};
}, []);
const navItems = useMemo(() => {
if (topMenus.length > 0) return topMenus;
return DEFAULT_NAV_ITEMS.map((item) => ({
...item,
parentId: null,
sortSeq: 0,
children: [],
levelNo: 1,
useYn: "Y",
otptYn: "Y",
}));
}, [topMenus]);
const openLogin = () => setLoginOpen(true);
const logout = () => {
localStorage.removeItem(LS_TOKEN_KEY);
localStorage.removeItem(LS_USER_KEY);
setUserName(null);
router.refresh();
};
return (
<>
<header className="fixed left-0 right-0 top-0 z-50 border-b bg-white shadow-md backdrop-blur">
<div className="px-6">
<div className="relative flex h-[83px] items-center justify-between">
<div className="flex items-center gap-3">
<Link href="/main" className="flex items-center">
<img src="/images/landing/logo.png" alt="HASUON" className="h-9 w-auto" />
</Link>
</div>
<nav className="absolute left-1/2 flex -translate-x-1/2 items-center gap-[40px] text-sm font-medium">
{navItems.map((item) => {
const requiresLogin = (item.urlPath)? item.urlPath.startsWith("/reuse/apply") : false;
const active = isMenuActive(pathname, item);
const className = [
"relative px-3 py-2 text-lg font-bold",
active ? "text-sky-700" : "text-gray-800 hover:text-sky-700",
].join(" ");
if (requiresLogin && !userName) {
return (
<button
key={item.menuCd}
type="button"
onClick={openLogin}
className={className}
>
{item.menuKornNm}
</button>
);
}
if (item.newWndwYn === "Y") {
return (
<button
key={item.menuCd}
type="button"
onClick={() => window.open(item.urlPath, "_blank")}
className={className}
>
{item.menuKornNm}
</button>
);
}
return (
<Link key={item.menuCd} href={item.urlPath || "#"} className={className}>
{item.menuKornNm}
</Link>
);
})}
</nav>
<div className="flex items-center gap-3">
{!userName ? (
<button
type="button"
onClick={openLogin}
className="inline-flex items-center gap-2 rounded-md bg-sky-500 px-4 py-2 text-base text-white hover:bg-sky-600"
>
Login
<span aria-hidden>
<img
src="/images/landing/icon_login.png"
alt="login icon"
className="ml-1 h-6 w-6 object-contain"
/>
</span>
</button>
) : (
<>
<span className="text-base text-gray-700">
<strong className="text-xl text-emerald-600">{userName}</strong>
</span>
<button
type="button"
onClick={logout}
className="inline-flex items-center gap-2 rounded-md bg-red-500 px-4 py-2 text-base text-white hover:bg-red-600"
>
Logout
<span aria-hidden>
<img
src="/images/landing/icon_logout.png"
alt="logout icon"
className="h-6 w-6 object-contain"
/>
</span>
</button>
</>
)}
</div>
</div>
</div>
</header>
<LoginModal
open={loginOpen}
onClose={() => setLoginOpen(false)}
onSuccess={({ userName: nextUserName, accessToken }) => {
localStorage.setItem(LS_USER_KEY, nextUserName);
if (accessToken) localStorage.setItem(LS_TOKEN_KEY, accessToken);
setUserName(nextUserName);
setLoginOpen(false);
router.refresh();
}}
/>
</>
);
}