Files
oms-website-nextjs/components/HeaderClient.tsx
2025-05-18 09:07:14 +02:00

395 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// components/HeaderClient.tsx
"use client";
import React, { useState } from "react";
import Link from "next/link";
import Image from "next/image";
import {
FiChevronDown,
FiClipboard,
FiArrowRight,
FiMenu,
FiX,
FiUsers,
FiBriefcase,
FiCpu,
FiBox,
FiFileText,
FiUserCheck,
} from "react-icons/fi";
import ThemeToggle from "./ThemeToggle";
const omsLogoUrl = "/oms-logo.svg";
type DropdownLinkProps = {
href: string;
children: React.ReactNode;
onClick?: () => void;
};
const DropdownLink = ({ href, children, onClick }: DropdownLinkProps) => (
<Link
href={href}
onClick={onClick}
className="block w-full text-left px-4 py-2 text-sm text-card-foreground hover:bg-secondary hover:text-primary transition-colors duration-150"
>
{children}
</Link>
);
const HeaderClient = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const toggleMenu = () => setIsMenuOpen((open) => !open);
const handleMobileLinkClick = () => setIsMenuOpen(false);
const [servicesDropdownOpen, setServicesDropdownOpen] = useState(false);
const [productsDropdownOpen, setProductsDropdownOpen] = useState(false);
const [joinUsDropdownOpen, setJoinUsDropdownOpen] = useState(false);
const handleServicesMouseEnter = () => setServicesDropdownOpen(true);
const handleServicesMouseLeave = () => setServicesDropdownOpen(false);
const handleProductsMouseEnter = () => setProductsDropdownOpen(true);
const handleProductsMouseLeave = () => setProductsDropdownOpen(false);
const handleJoinUsMouseEnter = () => setJoinUsDropdownOpen(true);
const handleJoinUsMouseLeave = () => setJoinUsDropdownOpen(false);
const megaMenuTriggerClasses = `
relative inline-flex items-center text-sm font-medium text-primary-foreground
hover:opacity-90 transition-opacity duration-150 ease-in-out pb-1
after:content-[''] after:absolute after:left-0 after:bottom-0 after:h-[2px]
after:w-0 after:bg-primary-foreground/80 after:transition-all after:duration-300 after:ease-out
`;
const megaMenuItemClasses = `
flex items-center p-3 -m-3 rounded-lg
hover:bg-secondary transition-colors duration-150 ease-in-out
`;
const megaMenuIconClasses = `flex-shrink-0 h-6 w-6 text-primary mr-4`;
const megaMenuTextWrapperClasses = `text-sm`;
const megaMenuTitleClasses = `font-semibold text-card-foreground`;
return (
<header className="sticky top-0 z-50 shadow-md bg-background border-b border-border">
{/* Top Row */}
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<Link
href="/"
className="flex items-center space-x-2"
title="OMS Home"
>
<Image
src={omsLogoUrl}
alt="OMS Logo"
width={40}
height={40}
priority
/>
<span className="text-xl font-bold text-foreground hidden sm:inline">
Owethu Managed Services
</span>
</Link>
<nav className="hidden md:flex items-center space-x-6 lg:space-x-8">
<Link
href="/"
className="text-sm font-medium text-foreground/80 hover:text-primary transition"
>
Home
</Link>
<Link
href="/tech-talk"
className="text-sm font-medium text-foreground/80 hover:text-primary transition"
>
Tech Talk
</Link>
<Link
href="/about"
className="text-sm font-medium text-foreground/80 hover:text-primary transition"
>
About Us
</Link>
<Link
href="/contact"
className="text-sm font-medium text-foreground/80 hover:text-primary transition"
>
Contact Us
</Link>
</nav>
<div className="hidden md:flex items-center space-x-4">
<ThemeToggle />
<Link
href="/request-demo"
className="flex items-center text-sm font-medium bg-primary text-primary-foreground px-3 py-1.5 rounded-lg hover:bg-opacity-90 transition-colors"
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" />
Request OBSE Demo
</Link>
</div>
<div className="md:hidden flex items-center">
<ThemeToggle />
<button
onClick={toggleMenu}
className="text-foreground/60 hover:text-primary focus:outline-none ml-3"
aria-label="Toggle menu"
aria-expanded={isMenuOpen}
aria-controls="mobile-menu"
>
{isMenuOpen ? (
<FiX className="w-6 h-6" />
) : (
<FiMenu className="w-6 h-6" />
)}
</button>
</div>
</div>
</div>
{/* Secondary Row w/ Mega Menus */}
<div className="bg-primary relative">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="hidden md:flex justify-between items-center h-12">
<nav className="flex items-center space-x-8 lg:space-x-10">
{/* Services */}
<div
className="group"
onMouseEnter={handleServicesMouseEnter}
onMouseLeave={handleServicesMouseLeave}
>
<button className={megaMenuTriggerClasses}>
Services
<FiChevronDown className="w-4 h-4 ml-1.5 opacity-70 transition-transform duration-200" />
</button>
<div
className={`
absolute left-0 top-full w-full shadow-lg z-40
bg-card border-x border-b border-border rounded-b-lg
opacity-0 invisible translate-y-[-10px]
${
servicesDropdownOpen
? "opacity-100 visible translate-y-0"
: ""
}
transition-all duration-300 ease-out transform
`}
>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-5">
<div className="grid grid-cols-1 md:grid-cols-3 gap-x-8 gap-y-6">
<Link
href="/services/resource-augmentation"
className={megaMenuItemClasses}
>
<FiUsers className={megaMenuIconClasses} />
<div className={megaMenuTextWrapperClasses}>
<p className={megaMenuTitleClasses}>
Resource Augmentation
</p>
</div>
</Link>
<Link
href="/services/project-management"
className={megaMenuItemClasses}
>
<FiBriefcase className={megaMenuIconClasses} />
<div className={megaMenuTextWrapperClasses}>
<p className={megaMenuTitleClasses}>
Project Management
</p>
</div>
</Link>
<Link
href="/services/product-development"
className={megaMenuItemClasses}
>
<FiCpu className={megaMenuIconClasses} />
<div className={megaMenuTextWrapperClasses}>
<p className={megaMenuTitleClasses}>
Product Development
</p>
</div>
</Link>
</div>
<div className="mt-6 pt-4 border-t border-border flex justify-end">
<Link
href="/services"
className="flex items-center text-sm font-medium text-primary hover:underline"
>
Explore All Services
<FiArrowRight className="w-4 h-4 ml-1" />
</Link>
</div>
</div>
</div>
</div>
{/* Products */}
<div
className="group"
onMouseEnter={handleProductsMouseEnter}
onMouseLeave={handleProductsMouseLeave}
>
<button className={megaMenuTriggerClasses}>
Products
<FiChevronDown className="w-4 h-4 ml-1.5 opacity-70 transition-transform duration-200" />
</button>
<div
className={`
absolute left-0 top-full w-full shadow-lg z-1000
bg-card border-x border-b border-border rounded-b-lg
opacity-0 invisible translate-y-[-10px]
${
productsDropdownOpen
? "opacity-100 visible translate-y-0"
: ""
}
transition-all duration-300 ease-out transform
`}
>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-5">
<div className="max-w-md">
<Link href="/obse" className={megaMenuItemClasses}>
<FiBox className={megaMenuIconClasses} />
<div className={megaMenuTextWrapperClasses}>
<p className={megaMenuTitleClasses}>OBSE Platform</p>
</div>
</Link>
</div>
</div>
</div>
</div>
{/* Join Our Team */}
<div
className="group"
onMouseEnter={handleJoinUsMouseEnter}
onMouseLeave={handleJoinUsMouseLeave}
>
<button className={megaMenuTriggerClasses}>
Join Our Team
<FiChevronDown className="w-4 h-4 ml-1.5 opacity-70 transition-transform duration-200" />
</button>
<div
className={`
absolute left-0 top-full w-full shadow-lg z-1000
bg-card border-x border-b border-border rounded-b-lg
opacity-0 invisible translate-y-[-10px]
${
joinUsDropdownOpen
? "opacity-100 visible translate-y-0"
: ""
}
transition-all duration-300 ease-out transform
`}
>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-5">
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6 max-w-xl">
<Link href="/vacancies" className={megaMenuItemClasses}>
<FiFileText className={megaMenuIconClasses} />
<div className={megaMenuTextWrapperClasses}>
<p className={megaMenuTitleClasses}>
Current Vacancies
</p>
</div>
</Link>
<Link href="/portal" className={megaMenuItemClasses}>
<FiUserCheck className={megaMenuIconClasses} />
<div className={megaMenuTextWrapperClasses}>
<p className={megaMenuTitleClasses}>
Recruitment Portal
</p>
</div>
</Link>
</div>
</div>
</div>
</div>
</nav>
{/* ← Heres the Explore Our Offerings link, back in its original spot */}
<Link
href="/services"
className="flex items-center text-sm font-medium text-primary-foreground hover:opacity-80 transition-opacity group"
>
Explore Our Offerings
<FiArrowRight className="w-4 h-4 ml-1.5 transition-transform duration-200 group-hover:translate-x-1" />
</Link>
</div>
</div>
</div>
{/* Mobile Menu */}
<div
id="mobile-menu"
className={`md:hidden absolute top-full left-0 w-full shadow-lg transition-all duration-300 ease-in-out overflow-hidden bg-card border-t border-border ${
isMenuOpen
? "max-h-[calc(100vh-4rem)] py-4 overflow-y-auto"
: "max-h-0 py-0"
}`}
>
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-1 text-foreground">
<DropdownLink href="/" onClick={handleMobileLinkClick}>
Home
</DropdownLink>
<DropdownLink href="/about" onClick={handleMobileLinkClick}>
About Us
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Services
</span>
<DropdownLink
href="/services/resource-augmentation"
onClick={handleMobileLinkClick}
>
Resource Augmentation
</DropdownLink>
<DropdownLink
href="/services/project-management"
onClick={handleMobileLinkClick}
>
Project Management
</DropdownLink>
<DropdownLink
href="/services/product-development"
onClick={handleMobileLinkClick}
>
Product Development
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Products
</span>
<DropdownLink href="/obse" onClick={handleMobileLinkClick}>
OBSE
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Join Us
</span>
<DropdownLink href="/vacancies" onClick={handleMobileLinkClick}>
Vacancies
</DropdownLink>
<DropdownLink href="/portal" onClick={handleMobileLinkClick}>
Recruitment Portal
</DropdownLink>
<DropdownLink href="/contact" onClick={handleMobileLinkClick}>
Contact Us
</DropdownLink>
<div className="pt-4">
<Link
href="/request-demo"
onClick={handleMobileLinkClick}
className="flex w-full justify-center items-center text-sm font-medium bg-primary text-primary-foreground px-4 py-2 rounded-lg hover:bg-opacity-90 transition-colors"
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" /> Request OBSE Demo
</Link>
</div>
<div className="pt-4 border-t border-border mt-4"></div>
</nav>
</div>
</header>
);
};
export default HeaderClient;