"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 } from "lucide-react"; import { useParams, usePathname, useSearchParams } from "next/navigation"; import { cn } from "@/lib/utils"; import Image from "next/image"; import { mainNav, additionalNav, additional2Nav, procurementNav, salesNav, engineeringNav, MenuSection, MenuItem, mainNavVendor, additionalNavVendor, domainBrandingKeys } from "@/config/menuConfig"; import { MobileMenu } from "./MobileMenu"; import { CommandMenu } from "./command-menu"; import { useSession } from "next-auth/react"; import { customSignOut } from "@/lib/auth/custom-signout"; import GroupedMenuRenderer from "./GroupedMenuRender"; import { useActiveMenus, filterActiveMenus, filterActiveAdditionalMenus } from "@/hooks/use-active-menus"; import { NotificationDropdown } from "./NotificationDropdown"; import { useTranslation } from '@/i18n/client' // 환경변수에 따라 숨길 메뉴 키 목록 (수정 및 제거가 용이하도록 상수로 분리) const HIDDEN_MENU_SECTION_KEYS = [ "menu.vendor.sales.title", "menu.vendor.procurement.title", ]; const HIDDEN_ADDITIONAL_MENU_KEYS = [ "menu.additional.system_settings", ]; /** * 환경변수에 따라 메뉴 섹션을 필터링하는 함수 */ const filterMenusByEnvironment = (sections: MenuSection[]): MenuSection[] => { const shouldHideMenus = process.env.NEXT_PUBLIC_HIDE_PARTNERS_MENU_BEFORE_OPEN === 'true'; if (!shouldHideMenus) { return sections; } return sections.filter(section => !HIDDEN_MENU_SECTION_KEYS.includes(section.titleKey)); }; /** * 환경변수에 따라 추가 메뉴 항목을 필터링하는 함수 */ const filterAdditionalMenusByEnvironment = (items: MenuItem[]): MenuItem[] => { const shouldHideMenus = process.env.NEXT_PUBLIC_HIDE_PARTNERS_MENU_BEFORE_OPEN === 'true'; if (!shouldHideMenus) { return items; } return items.filter(item => !HIDDEN_ADDITIONAL_MENU_KEYS.includes(item.titleKey)); }; export function Header() { const params = useParams(); const lng = params?.lng as string; const pathname = usePathname(); const { data: session } = useSession(); const { activeMenus, isLoading } = useActiveMenus(); const { t } = useTranslation(lng, 'menu'); 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 getDomainConfig = (pathname: string | null) => { if (pathname?.includes("/partners")) { return { main: mainNavVendor, additional: additionalNavVendor, logoHref: `/${lng}/partners`, brandNameKey: domainBrandingKeys.partners, basePath: `/${lng}/partners` }; } if (pathname?.includes("/procurement")) { return { main: procurementNav, additional: additional2Nav, logoHref: `/${lng}/procurement`, brandNameKey: domainBrandingKeys.procurement, basePath: `/${lng}/procurement` }; } if (pathname?.includes("/sales")) { return { main: salesNav, additional: additional2Nav, logoHref: `/${lng}/sales`, brandNameKey: domainBrandingKeys.sales, basePath: `/${lng}/sales` }; } if (pathname?.includes("/engineering")) { return { main: engineeringNav, additional: additional2Nav, logoHref: `/${lng}/engineering`, brandNameKey: domainBrandingKeys.engineering, basePath: `/${lng}/engineering` }; } // 기본값: /evcp (전체 메뉴) return { main: mainNav, additional: additionalNav, logoHref: `/${lng}/evcp`, brandNameKey: domainBrandingKeys.evcp, basePath: `/${lng}/evcp` }; }; const { main: originalMain, additional: originalAdditional, logoHref, brandNameKey, basePath } = getDomainConfig(pathname); // 1단계: 환경변수에 따른 메뉴 필터링 const envFilteredMain = filterMenusByEnvironment(originalMain); const envFilteredAdditional = filterAdditionalMenusByEnvironment(originalAdditional); // 2단계: 활성 메뉴만 필터링 (로딩 중이거나 에러 시에는 환경변수 필터링만 적용) const main = isLoading ? envFilteredMain : filterActiveMenus(envFilteredMain, activeMenus); const additional = isLoading ? envFilteredAdditional : filterActiveAdditionalMenus(envFilteredAdditional, activeMenus); return ( <>
{/* 햄버거 메뉴 버튼 (모바일) */} {/* 로고 영역 - 도메인별 브랜딩 (번역된) */}
EVCP Logo {t(brandNameKey)}
{/* 네비게이션 메뉴 - 도메인별 활성화된 메뉴만 표시 (번역된) */}
{main.map((section: MenuSection) => ( { e.preventDefault(); e.stopPropagation(); toggleMenu(section.titleKey); }} onPointerEnter={(e) => e.preventDefault()} onPointerMove={(e) => e.preventDefault()} > {t(section.titleKey)} {/* 그룹핑이 필요한 메뉴의 경우 GroupedMenuRenderer 사용 */} {section.useGrouping ? ( e.preventDefault()} onPointerLeave={(e) => e.preventDefault()} forceMount={openMenuKey === section.titleKey ? true : undefined} > ) : ( e.preventDefault()} onPointerLeave={(e) => e.preventDefault()} forceMount={openMenuKey === section.titleKey ? true : undefined} >
    {section.items.map((item) => ( {item.descriptionKey && t(item.descriptionKey)} ))}
)}
))} {/* 추가 네비게이션 항목 - 도메인별 활성화된 것만 (번역된) */} {additional.map((item) => ( {t(item.titleKey)} ))}
{/* 우측 영역 */}
{/* 데스크탑에서는 CommandMenu, 모바일에서는 검색 아이콘만 */}
{/* 알림 버튼 */} {/* 사용자 메뉴 (번역된) */} {initials || "?"} {t('user.my_account')} {t('user.settings')} customSignOut({ callbackUrl: `${window.location.origin}${basePath}` })}> {t('user.logout')}
{/* 모바일 메뉴 - 도메인별 활성화된 메뉴만 전달 (환경변수 필터링 적용) */} {isMobileMenuOpen && ( )}
); } const ListItem = React.forwardRef< React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a"> >(({ className, title, children, ...props }, ref) => { return (
  • {title}
    {children && (

    {children}

    )}
  • ); }); ListItem.displayName = "ListItem"; export function RouteLogger() { const path = usePathname(); const qs = useSearchParams()?.toString(); React.useEffect(() => { console.log("[URL]", path + (qs ? "?" + qs : "")); }, [path, qs]); return null; }