| | "use client"; |
| |
|
| | import { ChevronRight, Home } from "lucide-react"; |
| | import Link from "next/link"; |
| | import { usePathname } from "next/navigation"; |
| | import React, { useEffect, useState } from "react"; |
| | |
| | |
| | |
| | interface BreadcrumbItem { |
| | label: string; |
| | href: string; |
| | } |
| |
|
| | const routeNameMap: Record<string, string> = { |
| | 'dashboard': 'Dashboard', |
| | 'candidate-explorer': 'Candidate Explorer', |
| | 'recruitment': 'Recruitment', |
| | 'upload': 'Upload', |
| | 'extract': 'Extract Profile', |
| | 'settings': 'Settings', |
| | 'profile': 'Profile', |
| | 'admin': 'Admin', |
| | 'users': 'Users', |
| | 'reports': 'Reports', |
| | }; |
| |
|
| | function Breadcrumb({ children }: { children: React.ReactNode }) { |
| | return ( |
| | <nav aria-label="breadcrumb" className="flex items-center space-x-2"> |
| | {children} |
| | </nav> |
| | ); |
| | } |
| |
|
| | function BreadcrumbList({ children }: { children: React.ReactNode }) { |
| | return ( |
| | <ol className="flex items-center space-x-2 text-sm"> |
| | {children} |
| | </ol> |
| | ); |
| | } |
| |
|
| | function BreadcrumbItem({ children }: { children: React.ReactNode }) { |
| | return ( |
| | <li className="flex items-center"> |
| | {children} |
| | </li> |
| | ); |
| | } |
| |
|
| | function BreadcrumbLink({ href, children }: { href?: string; children: React.ReactNode }) { |
| | if (!href) { |
| | return ( |
| | <span className="text-gray-500 hover:text-gray-700 transition-colors"> |
| | {children} |
| | </span> |
| | ); |
| | } |
| |
|
| | return ( |
| | <Link |
| | href={href} |
| | className="text-gray-500 hover:text-gray-700 transition-colors hover:underline" |
| | > |
| | {children} |
| | </Link> |
| | ); |
| | } |
| |
|
| | function BreadcrumbHome({ href = '/' }: { href?: string }) { |
| | return ( |
| | <BreadcrumbItem> |
| | <Link |
| | href={href} |
| | className="text-gray-500 hover:text-gray-700 transition-colors" |
| | aria-label="Home" |
| | > |
| | <Home className="w-4 h-4" /> |
| | </Link> |
| | </BreadcrumbItem> |
| | ); |
| | } |
| |
|
| | function BreadcrumbSeparator() { |
| | return ( |
| | <li aria-hidden="true" className="text-gray-400"> |
| | <ChevronRight className="w-4 h-4" /> |
| | </li> |
| | ); |
| | } |
| |
|
| | function BreadcrumbPage({ children }: { children: React.ReactNode }) { |
| | return ( |
| | <span className="text-gray-900 font-medium"> |
| | {children} |
| | </span> |
| | ); |
| | } |
| |
|
| | function DynamicBreadcrumb() { |
| | const pathname = usePathname(); |
| |
|
| | const generateBreadcrumbs = (): BreadcrumbItem[] => { |
| | const segments = pathname.split('/').filter(segment => segment !== ''); |
| | |
| | if (segments.length === 0) { |
| | return []; |
| | } |
| |
|
| | const breadcrumbs: BreadcrumbItem[] = []; |
| | let currentPath = ''; |
| |
|
| | segments.forEach((segment) => { |
| | currentPath += `/${segment}`; |
| | const label = routeNameMap[segment] || formatSegment(segment); |
| | |
| | breadcrumbs.push({ |
| | label, |
| | href: currentPath |
| | }); |
| | }); |
| |
|
| | return breadcrumbs; |
| | }; |
| |
|
| | const formatSegment = (segment: string): string => { |
| | return segment |
| | .split('-') |
| | .map(word => word.charAt(0).toUpperCase() + word.slice(1)) |
| | .join(' '); |
| | }; |
| |
|
| | const breadcrumbs = generateBreadcrumbs(); |
| |
|
| | if (breadcrumbs.length === 0) { |
| | return null; |
| | } |
| |
|
| | return ( |
| | <Breadcrumb> |
| | <BreadcrumbList> |
| | <BreadcrumbHome /> |
| | |
| | {breadcrumbs.map((crumb, index) => { |
| | const isLast = index === breadcrumbs.length - 1; |
| | |
| | return ( |
| | <React.Fragment key={crumb.href}> |
| | <BreadcrumbSeparator /> |
| | <BreadcrumbItem> |
| | {isLast ? ( |
| | <BreadcrumbPage>{crumb.label}</BreadcrumbPage> |
| | ) : ( |
| | <BreadcrumbLink href={crumb.href}> |
| | {crumb.label} |
| | </BreadcrumbLink> |
| | )} |
| | </BreadcrumbItem> |
| | </React.Fragment> |
| | ); |
| | })} |
| | </BreadcrumbList> |
| | </Breadcrumb> |
| | ); |
| | } |
| |
|
| |
|
| | export function HeaderMenu() { |
| | const [now, setNow] = useState<Date | null>(null) |
| |
|
| | useEffect(() => { |
| | setNow(new Date()) |
| | const interval = setInterval(() => setNow(new Date()), 1000) |
| | return () => clearInterval(interval) |
| | }, []) |
| |
|
| | const dateStr = now?.toLocaleDateString("en-US", { |
| | weekday: "long", day: "2-digit", month: "short", |
| | year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", |
| | }) ?? "" |
| |
|
| | return ( |
| | <> |
| | <header className="h-16 bg-white border-b border-gray-200 px-8 flex items-center justify-between"> |
| | {/* <Breadcrumb> |
| | <BreadcrumbList> |
| | <BreadcrumbHome /> |
| | <BreadcrumbSeparator /> |
| | <BreadcrumbItem> |
| | <BreadcrumbLink>Dashboard</BreadcrumbLink> |
| | </BreadcrumbItem> |
| | </BreadcrumbList> |
| | </Breadcrumb> */} |
| | <DynamicBreadcrumb /> |
| | <div className="text-sm text-gray-500">{dateStr}</div> |
| | </header> |
| | <header className="h-16 bg-white border-b border-gray-200 px-8 flex items-center justify-between bg-[url(/dashboard/background.png)] bg-cover"> |
| | <h1 className="text-base font-bold text-foreground relative z-10"> |
| | Recruitment AI Dashboard – MT Intake |
| | </h1> |
| | </header> |
| | </> |
| | ); |
| | } |