From 5b6313f16f508882a0ea67716b7dbaa1c6967f04 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 30 Jun 2025 08:28:13 +0000
Subject: (대표님) 20250630 16시 - 유저 도메인별 라우터 분리와 보안성검토 대응
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/layout/Header.tsx | 117 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 92 insertions(+), 25 deletions(-)

(limited to 'components/layout/Header.tsx')

diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx
index 6d70e6b2..45768a57 100644
--- a/components/layout/Header.tsx
+++ b/components/layout/Header.tsx
@@ -26,17 +26,30 @@ import { SearchIcon, BellIcon, Menu } from "lucide-react";
 import { useParams, usePathname } from "next/navigation";
 import { cn } from "@/lib/utils";
 import Image from "next/image";
-import { mainNav, additionalNav, MenuSection, MenuItem, mainNavVendor, additionalNavVendor } from "@/config/menuConfig"; // 메뉴 구성 임포트
+import { 
+    mainNav, 
+    additionalNav, 
+    additional2Nav,
+    procurementNav,
+    salesNav,
+    engineeringNav,
+    MenuSection, 
+    MenuItem, 
+    mainNavVendor, 
+    additionalNavVendor 
+} from "@/config/menuConfig";
 import { MobileMenu } from "./MobileMenu";
 import { CommandMenu } from "./command-menu";
 import { useSession, signOut } from "next-auth/react";
 import GroupedMenuRenderer from "./GroupedMenuRender";
+import { useActiveMenus, filterActiveMenus, filterActiveAdditionalMenus } from "@/hooks/use-active-menus";
 
 export function Header() {
     const params = useParams();
     const lng = params?.lng as string;
     const pathname = usePathname();
     const { data: session } = useSession();
+    const { activeMenus, isLoading } = useActiveMenus();
 
     const userName = session?.user?.name || ""; 
     const domain = session?.user?.domain || ""; 
@@ -45,23 +58,72 @@ export function Header() {
         .map((word) => word[0]?.toUpperCase())
         .join("");
 
-
-    const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); // 모바일 메뉴 상태
+    const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
 
     const toggleMobileMenu = () => {
         setIsMobileMenuOpen(!isMobileMenuOpen);
     };
 
-    const isPartnerRoute = pathname?.includes("/partners");
+    // 도메인별 메뉴 및 브랜딩 정보 가져오기
+    const getDomainConfig = (pathname: string) => {
+        if (pathname?.includes("/partners")) {
+            return {
+                main: mainNavVendor,
+                additional: additionalNavVendor,
+                logoHref: `/${lng}/partners`,
+                brandName: "eVCP Partners",
+                basePath: `/${lng}/partners`
+            };
+        }
+        
+        if (pathname?.includes("/procurement")) {
+            return {
+                main: procurementNav,
+                additional: additional2Nav,
+                logoHref: `/${lng}/procurement`,
+                brandName: "eVCP 구매관리",
+                basePath: `/${lng}/procurement`
+            };
+        }
+        
+        if (pathname?.includes("/sales")) {
+            return {
+                main: salesNav,
+                additional: additional2Nav,
+                logoHref: `/${lng}/sales`,
+                brandName: "eVCP 기술영업",
+                basePath: `/${lng}/sales`
+            };
+        }
+        
+        if (pathname?.includes("/engineering")) {
+            return {
+                main: engineeringNav,
+                additional: additional2Nav,
+                logoHref: `/${lng}/engineering`,
+                brandName: "eVCP 설계관리",
+                basePath: `/${lng}/engineering`
+            };
+        }
+        
+        // 기본값: /evcp (전체 메뉴)
+        return {
+            main: mainNav,
+            additional: additionalNav,
+            logoHref: `/${lng}/evcp`,
+            brandName: "eVCP 삼성중공업",
+            basePath: `/${lng}/evcp`
+        };
+    };
 
-    const main = isPartnerRoute ? mainNavVendor : mainNav;
-    const additional = isPartnerRoute ? additionalNavVendor : additionalNav;
+    const { main: originalMain, additional: originalAdditional, logoHref, brandName, basePath } = getDomainConfig(pathname);
 
-    const basePath = `/${lng}${isPartnerRoute ? "/partners" : "/evcp"}`;
+    // 활성 메뉴만 필터링 (로딩 중이거나 에러 시에는 모든 메뉴 표시)
+    const main = isLoading ? originalMain : filterActiveMenus(originalMain, activeMenus);
+    const additional = isLoading ? originalAdditional : filterActiveAdditionalMenus(originalAdditional, activeMenus);
 
     return (
         <>
-            {/* <header className="border-grid sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60"> */}
             <header className="border-grid sticky top-0 z-40 w-full border-b bg-slate-100 backdrop-blur supports-[backdrop-filter]:bg-background/60">
                 <div className="container-wrapper">
                     <div className="container flex h-14 items-center">
@@ -88,9 +150,9 @@ export function Header() {
                             <span className="sr-only">Toggle Menu</span>
                         </Button>
 
-                        {/* 로고 영역 - 항상 표시 */}
+                        {/* 로고 영역 - 도메인별 브랜딩 */}
                         <div className="mr-4 flex-shrink-0 flex items-center gap-2 lg:mr-6">
-                            <Link href={`/${lng}/evcp`} className="flex items-center gap-2">
+                            <Link href={logoHref} className="flex items-center gap-2">
                                 <Image
                                     className="dark:invert"
                                     src="/images/vercel.svg"
@@ -99,20 +161,14 @@ export function Header() {
                                     height={20}
                                 />
                                 <span className="hidden font-bold lg:inline-block">
-                                    {isPartnerRoute 
-                                        ? "eVCP Partners" 
-                                        : pathname?.includes("/evcp") 
-                                            ? "eVCP 삼성중공업" 
-                                            : "eVCP"}
+                                    {brandName}
                                 </span>
                             </Link>
                         </div>
                             
-                        {/* 네비게이션 메뉴 - 내부 스크롤 적용, 드롭다운은 제약 없이 표시 */}
+                        {/* 네비게이션 메뉴 - 도메인별 활성화된 메뉴만 표시 */}
                         <div className="hidden md:block flex-1 min-w-0">
-                            {/* NavigationMenu는 z-index를 높게 설정하여 드롭다운이 제대로 표시되도록 함 */}
                             <NavigationMenu className="relative z-50">
-                                {/* 스크롤 가능한 메뉴 리스트 컨테이너 */}
                                 <div className="w-full overflow-x-auto pb-1">
                                     <NavigationMenuList className="flex-nowrap w-max">
                                         {main.map((section: MenuSection) => (
@@ -124,7 +180,11 @@ export function Header() {
                                                 {/* 그룹핑이 필요한 메뉴의 경우 GroupedMenuRenderer 사용 */}
                                                 {section.useGrouping ? (
                                                     <NavigationMenuContent>
-                                                        <GroupedMenuRenderer items={section.items} lng={lng} />
+                                                        <GroupedMenuRenderer 
+                                                            items={section.items} 
+                                                            lng={lng}
+                                                            activeMenus={activeMenus}
+                                                        />
                                                     </NavigationMenuContent>
                                                 ) : (
                                                     <NavigationMenuContent>
@@ -144,7 +204,7 @@ export function Header() {
                                             </NavigationMenuItem>
                                         ))}
 
-                                        {/* 추가 네비게이션 항목 */}
+                                        {/* 추가 네비게이션 항목 - 도메인별 활성화된 것만 */}
                                         {additional.map((item) => (
                                             <NavigationMenuItem key={item.title}>
                                                 <Link href={`/${lng}${item.href}`} legacyBehavior passHref>
@@ -164,7 +224,7 @@ export function Header() {
                             </NavigationMenu>
                         </div>
 
-                        {/* 우측 영역 - 고정 너비와 우선순위로 항상 표시되도록 함 */}
+                        {/* 우측 영역 */}
                         <div className="ml-auto flex flex-shrink-0 items-center space-x-2">
                             {/* 데스크탑에서는 CommandMenu, 모바일에서는 검색 아이콘만 */}
                             <div className="hidden md:block md:w-auto">
@@ -177,11 +237,10 @@ export function Header() {
                             {/* 알림 버튼 */}
                             <Button variant="ghost" size="icon" className="relative" aria-label="Notifications">
                                 <BellIcon className="h-5 w-5" />
-                                {/* 알림 뱃지 예시 */}
                                 <span className="absolute -top-1 -right-1 inline-flex h-2 w-2 rounded-full bg-red-500"></span>
                             </Button>
 
-                            {/* 사용자 메뉴 (DropdownMenu) */}
+                            {/* 사용자 메뉴 */}
                             <DropdownMenu>
                                 <DropdownMenuTrigger asChild>
                                     <Avatar className="cursor-pointer h-8 w-8">
@@ -207,8 +266,16 @@ export function Header() {
                     </div>
                 </div>
 
-                {/* 모바일 메뉴 */}
-                {isMobileMenuOpen && <MobileMenu lng={lng} onClose={toggleMobileMenu} />}
+                {/* 모바일 메뉴 - 도메인별 활성화된 메뉴만 전달 */}
+                {isMobileMenuOpen && (
+                    <MobileMenu 
+                        lng={lng} 
+                        onClose={toggleMobileMenu}
+                        activeMenus={activeMenus}
+                        domainMain={originalMain}
+                        domainAdditional={originalAdditional}
+                    />
+                )}
             </header>
         </>
     );
-- 
cgit v1.2.3

