Home page completed

This commit is contained in:
libertyoms
2025-04-20 18:19:43 +02:00
parent 211cb3fc6f
commit 5eb60015cc
24 changed files with 1412 additions and 428 deletions

View File

@ -4,7 +4,8 @@
import React, { useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { usePathname } from "next/navigation";
// Use usePathname only if needed for active state logic not shown here
// import { usePathname } from "next/navigation";
import {
FiChevronDown,
FiClipboard,
@ -12,11 +13,12 @@ import {
FiMenu,
FiX,
} from "react-icons/fi";
import ThemeToggle from "./ThemeToggle";
import ThemeToggle from "./ThemeToggle"; // Assuming ThemeToggle component exists
const omsLogoUrl = "/oms-logo.svg";
const omsLogoUrl = "/oms-logo.svg"; // Ensure this is in your /public folder
// --- Basic Dropdown Placeholder ---
// --- Basic Dropdown Component ---
// Using semantic variables for background, text, and borders
type DropdownMenuProps = {
trigger: React.ReactNode;
children: React.ReactNode;
@ -27,16 +29,17 @@ const DropdownMenu = ({
children,
menuClasses = "w-48",
}: DropdownMenuProps) => (
// Using group-focus-within for better keyboard/touch accessibility
<div className="relative group">
<button className="flex items-center space-x-1 text-sm font-medium focus:outline-none inherit-color group">
{trigger}
<FiChevronDown className="w-4 h-4 transition-transform duration-200 group-hover:rotate-180" />
<FiChevronDown className="w-4 h-4 transition-transform duration-200 group-hover:rotate-180 group-focus-within:rotate-180" />
</button>
<div
className={`
absolute left-0 mt-2 ${menuClasses} origin-top-left rounded-md shadow-lg z-50
bg-light border border-gray-200 dark:bg-[var(--color-dark-bg-secondary)] dark:border-[var(--color-dark-border)]
opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200
bg-card border border-border {/* USE SEMANTIC VARS */}
opacity-0 invisible group-hover:opacity-100 group-hover:visible group-focus-within:opacity-100 group-focus-within:visible transition-all duration-200
`}
>
<div className="py-1">{children}</div>
@ -44,34 +47,40 @@ const DropdownMenu = ({
</div>
);
// Dropdown Link component using semantic variables
type DropdownLinkProps = {
href: string;
children: React.ReactNode;
onClick?: () => void; // Added onClick for mobile menu closure
};
const DropdownLink = ({ href, children }: DropdownLinkProps) => (
const DropdownLink = ({ href, children, onClick }: DropdownLinkProps) => (
<Link
href={href}
className="block px-4 py-2 text-sm text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:bg-gray-100 hover:text-primary dark:hover:bg-gray-700 dark:hover:text-primary"
onClick={onClick} // Call onClick if provided
className="block w-full text-left px-4 py-2 text-sm text-card-foreground hover:bg-secondary hover:text-primary" // USE SEMANTIC VARS
>
{children}
</Link>
);
// --- End Dropdown Placeholder ---
// --- End Dropdown Component ---
const Header = () => {
const pathname = usePathname() || "/";
const isActive = (path: string) => pathname === path;
// If you need pathname for active states later:
// const pathname = usePathname() || "/";
// const isActive = (path: string) => pathname === path;
// const isActive = (path: string) => false; // Simple placeholder
const [isMenuOpen, setIsMenuOpen] = useState(false);
const toggleMenu = () => setIsMenuOpen((open) => !open);
// Close menu when a link is clicked
const handleMobileLinkClick = () => setIsMenuOpen(false);
// Optionally switch logo based on a global CSS class or via next-themes
const currentLogo = omsLogoUrl;
return (
<header className="sticky top-0 z-50 shadow-md bg-light dark:bg-dark-bg dark:border-b dark:border-dark-border">
// Use semantic variables for header background and border
<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">
@ -88,40 +97,36 @@ const Header = () => {
height={40}
priority
/>
<span className="text-xl font-bold text-dark dark:text-light hidden sm:inline">
{/* Use semantic variable for text color */}
<span className="text-xl font-bold text-foreground hidden sm:inline">
Owethu Managed Services
</span>
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6 lg:space-x-8">
{/* Use semantic variables for text, hover uses primary */}
<Link
href="/"
className={`text-sm font-medium ${
isActive("/")
? "text-primary font-semibold"
: "text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:text-primary"
}`}
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
/* Active state example (requires usePathname) */
/* ${isActive("/") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
>
Home
</Link>
<Link
href="/about"
className={`text-sm font-medium ${
pathname.startsWith("/about")
? "text-primary font-semibold"
: "text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:text-primary"
}`}
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
/* Active state example */
/* ${pathname.startsWith("/about") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
>
About Us
</Link>
<Link
href="/contact"
className={`text-sm font-medium ${
isActive("/contact")
? "text-primary font-semibold"
: "text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:text-primary"
}`}
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
/* Active state example */
/* ${isActive("/contact") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
>
Contact Us
</Link>
@ -131,9 +136,10 @@ const Header = () => {
<div className="hidden md:flex items-center space-x-4">
<ThemeToggle />
{/* Use semantic variables for button */}
<Link
href="/request-demo"
className="flex items-center text-sm font-medium bg-primary text-dark px-3 py-1.5 rounded-md hover:bg-opacity-90 transition-colors"
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" // Use rounded-lg from radius
title="Request a Demo"
>
<FiClipboard className="w-4 h-4 mr-1.5" />
@ -143,12 +149,13 @@ const Header = () => {
{/* Mobile Buttons */}
<div className="md:hidden flex items-center">
<ThemeToggle />
<ThemeToggle /> {/* Theme toggle appears first */}
<button
onClick={toggleMenu}
className="text-gray-600 dark:text-gray-400 hover:text-primary dark:hover:text-primary focus:outline-none ml-3"
className="text-foreground/60 hover:text-primary focus:outline-none ml-3" // Use semantic muted color, hover primary
aria-label="Toggle menu"
aria-expanded={isMenuOpen}
aria-controls="mobile-menu"
>
{isMenuOpen ? (
<FiX className="w-6 h-6" />
@ -161,34 +168,48 @@ const Header = () => {
</div>
{/* Secondary Row */}
<div className="bg-primary dark:bg-primary">
<div className="bg-primary">
{" "}
{/* Keep gold background */}
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{/* Hide on mobile */}
<div className="hidden md:flex justify-between items-center h-12">
<nav className="flex items-center space-x-6 lg:space-x-8 text-dark">
<DropdownMenu trigger={<span>Services</span>}>
<DropdownLink href="/services/resource-augmentation">
Resource Augmentation
</DropdownLink>
<DropdownLink href="/services/project-management">
Project Management
</DropdownLink>
<DropdownLink href="/services/product-development">
Product Development
</DropdownLink>
</DropdownMenu>
<DropdownMenu trigger={<span>Products</span>}>
<DropdownLink href="/products/obse">OBSE</DropdownLink>
</DropdownMenu>
<DropdownMenu trigger={<span>Join Our Team</span>}>
<DropdownLink href="/join-us/vacancies">Vacancies</DropdownLink>
<DropdownLink href="/join-us/portal">
Recruitment Portal
</DropdownLink>
</DropdownMenu>
{/* Use primary-foreground for text color */}
<nav className="flex items-center space-x-6 lg:space-x-8 text-primary-foreground">
{/* Wrap dropdown triggers for consistent hover */}
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Services</span>}>
<DropdownLink href="/services/resource-augmentation">
Resource Augmentation
</DropdownLink>
<DropdownLink href="/services/project-management">
Project Management
</DropdownLink>
<DropdownLink href="/services/product-development">
Product Development
</DropdownLink>
</DropdownMenu>
</div>
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Products</span>}>
<DropdownLink href="/products/obse">OBSE</DropdownLink>
</DropdownMenu>
</div>
<div className="hover:text-opacity-80 transition-opacity">
<DropdownMenu trigger={<span>Join Our Team</span>}>
<DropdownLink href="/join-us/vacancies">
Vacancies
</DropdownLink>
<DropdownLink href="/join-us/portal">
Recruitment Portal
</DropdownLink>
</DropdownMenu>
</div>
</nav>
{/* Use primary-foreground for link */}
<Link
href="/services"
className="flex items-center text-sm font-medium text-dark hover:text-opacity-80 transition-opacity group"
className="flex items-center text-sm font-medium text-primary-foreground hover:text-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" />
@ -200,105 +221,74 @@ const Header = () => {
{/* Mobile Menu Panel */}
<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-light dark:bg-[var(--color-dark-bg-secondary)] border-t border-gray-200 dark:border-[var(--color-dark-border)] ${
isMenuOpen ? "max-h-screen py-4" : "max-h-0 py-0"
// Use semantic variables for background and border
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" // Animate height, allow scroll
}`}
>
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-3">
<Link
href="/"
onClick={handleMobileLinkClick}
className={`block py-2 text-base font-medium ${
isActive("/")
? "text-primary font-semibold"
: "text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
}`}
>
{/* Use semantic variable for text color */}
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-1 text-foreground">
{" "}
{/* Reduced space-y */}
{/* Simplified mobile links, using DropdownLink component for consistency */}
<DropdownLink href="/" onClick={handleMobileLinkClick}>
Home
</Link>
<Link
href="/about"
onClick={handleMobileLinkClick}
className={`block py-2 text-base font-medium ${
pathname.startsWith("/about")
? "text-primary font-semibold"
: "text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
}`}
>
</DropdownLink>
<DropdownLink href="/about" onClick={handleMobileLinkClick}>
About Us
</Link>
<span className="pt-2 text-xs uppercase text-gray-500 dark:text-gray-400">
</DropdownLink>
{/* Maybe use collapsible sections here in a real app, but simple list for now */}
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Services
</span>
<Link
<DropdownLink
href="/services/resource-augmentation"
onClick={handleMobileLinkClick}
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
>
Resource Augmentation
</Link>
<Link
</DropdownLink>
<DropdownLink
href="/services/project-management"
onClick={handleMobileLinkClick}
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
>
Project Management
</Link>
<Link
</DropdownLink>
<DropdownLink
href="/services/product-development"
onClick={handleMobileLinkClick}
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
>
Product Development
</Link>
<span className="pt-2 text-xs uppercase text-gray-500 dark:text-gray-400">
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Products
</span>
<Link
href="/products/obse"
onClick={handleMobileLinkClick}
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
>
<DropdownLink href="/products/obse" onClick={handleMobileLinkClick}>
OBSE
</Link>
<span className="pt-2 text-xs uppercase text-gray-500 dark:text-gray-400">
</DropdownLink>
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
Join Us
</span>
<Link
<DropdownLink
href="/join-us/vacancies"
onClick={handleMobileLinkClick}
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
>
Vacancies
</Link>
<Link
href="/join-us/portal"
onClick={handleMobileLinkClick}
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
>
</DropdownLink>
<DropdownLink href="/join-us/portal" onClick={handleMobileLinkClick}>
Recruitment Portal
</Link>
<Link
href="/contact"
onClick={handleMobileLinkClick}
className={`block py-2 text-base font-medium ${
isActive("/contact")
? "text-primary font-semibold"
: "text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
}`}
>
</DropdownLink>
<DropdownLink href="/contact" onClick={handleMobileLinkClick}>
Contact Us
</Link>
</DropdownLink>
{/* Demo button at the bottom */}
<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-dark px-4 py-2 rounded-md hover:bg-opacity-90 transition-colors"
// Use semantic variables for button style
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" />