diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-11 12:18:38 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-11 12:18:38 +0000 |
| commit | ff902243a658067fae858a615c0629aa2e0a4837 (patch) | |
| tree | 42d30e986d1cbfb282c644c01730cd053b816b7a /components/layout | |
| parent | 42e38f41cb4c0b4bf9c08b71ed087cd7f0c7fc18 (diff) | |
(대표님) 20250611 21시 15분 OCR 등
Diffstat (limited to 'components/layout')
| -rw-r--r-- | components/layout/HeaderSimple.tsx | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/components/layout/HeaderSimple.tsx b/components/layout/HeaderSimple.tsx new file mode 100644 index 00000000..f099d3ef --- /dev/null +++ b/components/layout/HeaderSimple.tsx @@ -0,0 +1,192 @@ +"use client"; + +import * as React from "react"; +import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +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, 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 { MobileMenu } from "./MobileMenu"; +import { CommandMenu } from "./command-menu"; +import { useSession, signOut } from "next-auth/react"; +import GroupedMenuRenderer from "./GroupedMenuRender"; + +export function HeaderSimple() { + const params = useParams(); + const lng = params?.lng as string; + const pathname = usePathname(); + const { data: session } = useSession(); + + const userName = session?.user?.name || ""; + const domain = session?.user?.domain || ""; + const initials = userName + .split(" ") + .map((word) => word[0]?.toUpperCase()) + .join(""); + + + const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); // 모바일 메뉴 상태 + + const toggleMobileMenu = () => { + setIsMobileMenuOpen(!isMobileMenuOpen); + }; + + const isPartnerRoute = pathname?.includes("/partners"); + + const main = isPartnerRoute ? mainNavVendor : mainNav; + const additional = isPartnerRoute ? additionalNavVendor : additionalNav; + + const basePath = `/${lng}${isPartnerRoute ? "/partners" : "/evcp"}`; + + 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"> + {/* 햄버거 메뉴 버튼 (모바일) */} + <Button + onClick={toggleMobileMenu} + variant="ghost" + className="-ml-2 mr-2 h-8 w-8 px-0 text-base hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden" + > + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + strokeWidth="1.5" + stroke="currentColor" + className="!size-6" + > + <path + strokeLinecap="round" + strokeLinejoin="round" + d="M3.75 9h16.5m-16.5 6.75h16.5" + /> + </svg> + <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={`/`} className="flex items-center gap-2"> + <Image + className="dark:invert" + src="/images/SHI_logo.svg" + alt="EVCP Logo" + width={140} + height={20} + /> + <span className="hidden font-bold lg:inline-block"> + {isPartnerRoute + ? "eVCP Partners" + : pathname?.includes("/evcp") + ? "eVCP 삼성중공업" + : "eVCP"} + </span> + </Link> + </div> + + {/* 네비게이션 메뉴 - 내부 스크롤 적용, 드롭다운은 제약 없이 표시 */} + <div className="hidden md:block flex-1 min-w-0"> + + </div> + + {/* 우측 영역 - 고정 너비와 우선순위로 항상 표시되도록 함 */} + <div className="ml-auto flex flex-shrink-0 items-center space-x-2"> + {/* 데스크탑에서는 CommandMenu, 모바일에서는 검색 아이콘만 */} + <div className="hidden md:block md:w-auto"> + <CommandMenu /> + </div> + {/* <Button variant="ghost" size="icon" className="md:hidden" aria-label="Search"> + <SearchIcon className="h-5 w-5" /> + </Button> */} + + {/* 알림 버튼 */} + {/* <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"> + <AvatarImage src={`/profiles/${session?.user?.image}`||"/user-avatar.jpg"} alt="User Avatar" /> + <AvatarFallback> + {initials || "?"} + </AvatarFallback> + </Avatar> + </DropdownMenuTrigger> + <DropdownMenuContent className="w-48" align="end"> + <DropdownMenuLabel>My Account</DropdownMenuLabel> + <DropdownMenuSeparator /> + <DropdownMenuItem asChild> + <Link href={`${basePath}/settings`}>Settings</Link> + </DropdownMenuItem> + <DropdownMenuSeparator /> + <DropdownMenuItem onSelect={() => signOut({ callbackUrl: `/${lng}/${domain}` })}> + Logout + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> + </div> + </div> + </div> + + {/* 모바일 메뉴 */} + {isMobileMenuOpen && <MobileMenu lng={lng} onClose={toggleMobileMenu} />} + </header> + </> + ); +} + +const ListItem = React.forwardRef< + React.ElementRef<"a">, + React.ComponentPropsWithoutRef<"a"> +>(({ className, title, children, ...props }, ref) => { + return ( + <li> + <NavigationMenuLink asChild> + <a + ref={ref} + className={cn( + "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", + className + )} + {...props} + > + <div className="text-sm font-medium leading-none">{title}</div> + {children && ( + <p className="line-clamp-2 text-sm leading-snug text-muted-foreground"> + {children} + </p> + )} + </a> + </NavigationMenuLink> + </li> + ); +}); +ListItem.displayName = "ListItem";
\ No newline at end of file |
