"use client"; import * as React from "react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, } from "@/components/ui/navigation-menu"; import { SearchIcon, Loader2 } from "lucide-react"; import { useParams, usePathname } from "next/navigation"; import { cn } from "@/lib/utils"; import Image from "next/image"; import { useSession } from "next-auth/react"; import { customSignOut } from "@/lib/auth/custom-signout"; import DynamicMenuRender from "./DynamicMenuRender"; import { MobileMenuV2 } from "./MobileMenuV2"; import { CommandMenu } from "./command-menu"; import { NotificationDropdown } from "./NotificationDropdown"; import { useVisibleMenuTree } from "@/hooks/use-visible-menu-tree"; import { useTranslation } from "@/i18n/client"; import type { MenuDomain, MenuTreeNode } from "@/lib/menu-v2/types"; // 도메인별 브랜드명 const domainBrandingKeys: Record = { evcp: "branding.evcp_main", partners: "branding.evcp_partners", }; export function HeaderV2() { const params = useParams(); const lng = (params?.lng as string) || "ko"; const pathname = usePathname(); const { data: session } = useSession(); const { t } = useTranslation(lng, "menu"); // 현재 도메인 결정 const domain: MenuDomain = pathname?.includes("/partners") ? "partners" : "evcp"; // 메뉴 데이터 로드 (tree에 드롭다운과 단일 링크가 모두 포함됨) const { tree, isLoading } = useVisibleMenuTree(domain); const userName = session?.user?.name || ""; const initials = userName .split(" ") .map((word) => word[0]?.toUpperCase()) .join(""); const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); const [openMenuKey, setOpenMenuKey] = React.useState(""); const toggleMobileMenu = () => { setIsMobileMenuOpen(!isMobileMenuOpen); }; const toggleMenu = React.useCallback((menuKey: string) => { setOpenMenuKey((prev) => (prev === menuKey ? "" : menuKey)); }, []); // 페이지 이동 시 메뉴 닫기 React.useEffect(() => { setOpenMenuKey(""); }, [pathname]); // 브랜딩 및 경로 설정 const brandNameKey = domainBrandingKeys[domain]; const logoHref = `/${lng}/${domain}`; const basePath = `/${lng}/${domain}`; // 다국어 텍스트 선택 const getTitle = (node: MenuTreeNode) => lng === "ko" ? node.titleKo : node.titleEn || node.titleKo; const getDescription = (node: MenuTreeNode) => lng === "ko" ? node.descriptionKo : node.descriptionEn || node.descriptionKo; // 메뉴 노드가 드롭다운(자식 있음)인지 단일 링크인지 판단 const isDropdownMenu = (node: MenuTreeNode) => node.nodeType === 'menu_group' && node.children && node.children.length > 0; return ( <>
{/* 햄버거 메뉴 버튼 (모바일) */} {/* 로고 영역 */}
EVCP Logo {t(brandNameKey)}
{/* 네비게이션 메뉴 */}
{isLoading ? (
) : (
{tree.map((node) => { // 드롭다운 메뉴 (menu_group with children) if (isDropdownMenu(node)) { return ( { e.preventDefault(); e.stopPropagation(); toggleMenu(String(node.id)); }} onPointerEnter={(e) => e.preventDefault()} onPointerMove={(e) => e.preventDefault()} onPointerLeave={(e) => e.preventDefault()} > {getTitle(node)} e.preventDefault()} onPointerLeave={(e) => e.preventDefault()} forceMount={ openMenuKey === String(node.id) ? true : undefined } > setOpenMenuKey("")} /> ); } // 단일 링크 메뉴 (최상위 menu) if (node.nodeType === 'menu' && node.menuPath) { return ( e.preventDefault()} onPointerLeave={(e) => e.preventDefault()} > {getTitle(node)} ); } return null; })}
)}
{/* 우측 영역 */}
{/* 데스크탑에서는 CommandMenu, 모바일에서는 검색 아이콘만 */}
{/* 알림 버튼 */} {/* 사용자 메뉴 */} {initials || "?"} {t("user.my_account")} {t("user.settings")} customSignOut({ callbackUrl: `${window.location.origin}${basePath}`, }) } > {t("user.logout")}
{/* 모바일 메뉴 */} {isMobileMenuOpen && ( )}
); }