189 lines
6.8 KiB
TypeScript
189 lines
6.8 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState, useRef, useEffect } from 'react'
|
|
import { ArrowRight, Globe, ChevronDown } from 'lucide-react'
|
|
import { usePathname } from 'next/navigation'
|
|
|
|
export interface NavItem {
|
|
id?: string
|
|
label: string
|
|
href: string
|
|
}
|
|
|
|
interface HeaderProps {
|
|
companyName?: string | null
|
|
tagline?: string | null
|
|
items?: NavItem[]
|
|
phone?: string | null
|
|
homeHref?: string
|
|
currentLocale?: string
|
|
contactHref?: string | null
|
|
contactLabel?: string | null
|
|
phoneLabel?: string | null
|
|
}
|
|
|
|
export function Header({
|
|
companyName,
|
|
tagline,
|
|
items,
|
|
phone,
|
|
homeHref = '/',
|
|
currentLocale = 'pl',
|
|
contactHref,
|
|
contactLabel,
|
|
phoneLabel,
|
|
}: HeaderProps) {
|
|
const pathname = usePathname() || ''
|
|
const [langDropdownOpen, setLangDropdownOpen] = useState(false)
|
|
const dropdownRef = useRef<HTMLDivElement>(null)
|
|
|
|
// Close dropdown on outside click
|
|
useEffect(() => {
|
|
function handleClickOutside(event: MouseEvent) {
|
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
|
setLangDropdownOpen(false)
|
|
}
|
|
}
|
|
document.addEventListener('mousedown', handleClickOutside)
|
|
return () => document.removeEventListener('mousedown', handleClickOutside)
|
|
}, [])
|
|
|
|
// Function to switch locale in URL
|
|
const getSwitchedLocalePath = (targetLocale: string) => {
|
|
if (currentLocale === targetLocale) return pathname
|
|
if (pathname.startsWith(`/${currentLocale}`)) {
|
|
return pathname.replace(`/${currentLocale}`, `/${targetLocale}`)
|
|
}
|
|
return `/${targetLocale}${pathname}`
|
|
}
|
|
|
|
// Filter out duplicated "Kontakt" from menu items since it has a dedicated right CTA button
|
|
const filteredNavItems = items?.filter(
|
|
(item) => !item.label.toLowerCase().includes('kontakt')
|
|
)
|
|
|
|
const languages = [
|
|
{ code: 'pl', label: 'PL' },
|
|
{ code: 'en', label: 'UK' },
|
|
]
|
|
|
|
const activeLang = languages.find((l) => l.code === currentLocale) || languages[0]
|
|
|
|
return (
|
|
<header className="sticky top-0 z-50 w-full bg-white border-b-2 border-[#1f1f1f] shadow-xs">
|
|
{/* Top Black Utility Bar */}
|
|
{(tagline || phone) && (
|
|
<div className="bg-[#1f1f1f] text-white text-xs py-2 hidden md:block">
|
|
<div className="container mx-auto px-4 sm:px-6 lg:px-12 max-w-7xl flex items-center justify-between">
|
|
{tagline && (
|
|
<div className="flex items-center gap-2">
|
|
<span className="inline-block w-2.5 h-2.5 bg-[#FFED00]" />
|
|
<span className="font-bold uppercase tracking-wider text-[11px] text-[#e0e0e0]">
|
|
{tagline}
|
|
</span>
|
|
</div>
|
|
)}
|
|
{phone && (
|
|
<div className="flex items-center gap-2 ml-auto">
|
|
{phoneLabel && (
|
|
<span className="font-bold uppercase tracking-wider text-[11px] text-[#e0e0e0]">
|
|
{phoneLabel}
|
|
</span>
|
|
)}
|
|
<a
|
|
href={`tel:${phone.replace(/\s+/g, '')}`}
|
|
className="font-black uppercase tracking-wider text-[11px] text-[#FFED00] hover:underline font-mono"
|
|
>
|
|
{phone}
|
|
</a>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Main Navigation Bar */}
|
|
<div className="container mx-auto flex h-20 items-center justify-between px-4 sm:px-6 lg:px-12 max-w-7xl">
|
|
<a href={homeHref} className="flex items-center gap-3.5">
|
|
<div className="flex h-11 w-11 items-center justify-center bg-[#FFED00] text-[#1f1f1f] font-black text-xl border-2 border-[#1f1f1f] shadow-xs">
|
|
POI
|
|
</div>
|
|
<div>
|
|
{companyName && (
|
|
<span className="text-xl font-black uppercase tracking-tight text-[#1f1f1f] block leading-none">
|
|
{companyName}
|
|
</span>
|
|
)}
|
|
{tagline && (
|
|
<span className="text-[10px] uppercase tracking-widest text-[#666666] font-bold block mt-1">
|
|
{tagline}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</a>
|
|
|
|
{/* Navigation Items */}
|
|
{filteredNavItems && filteredNavItems.length > 0 && (
|
|
<nav className="hidden lg:flex items-center gap-8 text-xs font-black uppercase tracking-wider text-[#1f1f1f]">
|
|
{filteredNavItems.map((item, idx) => (
|
|
<a
|
|
key={item.id || idx}
|
|
href={item.href}
|
|
className="hover:text-[#1f1f1f] hover:border-b-2 hover:border-[#FFED00] transition-all py-2"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
))}
|
|
</nav>
|
|
)}
|
|
|
|
<div className="flex items-center gap-4">
|
|
{/* Wysuwany przełącznik języków */}
|
|
<div className="relative" ref={dropdownRef}>
|
|
<button
|
|
type="button"
|
|
onClick={() => setLangDropdownOpen(!langDropdownOpen)}
|
|
className="flex items-center gap-2 border-2 border-[#1f1f1f] bg-white px-3 py-2 text-xs font-black text-[#1f1f1f] hover:bg-[#f4f4f4] transition-colors cursor-pointer"
|
|
>
|
|
<Globe className="h-3.5 w-3.5 text-[#1f1f1f]" />
|
|
<span className="uppercase">{activeLang.code.toUpperCase()}</span>
|
|
<ChevronDown className={`h-3.5 w-3.5 transition-transform duration-200 ${langDropdownOpen ? 'rotate-180' : ''}`} />
|
|
</button>
|
|
|
|
{langDropdownOpen && (
|
|
<div className="absolute right-0 mt-1 w-28 bg-white border-2 border-[#1f1f1f] shadow-xl z-50 py-1">
|
|
{languages.map((lang) => (
|
|
<a
|
|
key={lang.code}
|
|
href={getSwitchedLocalePath(lang.code)}
|
|
onClick={() => setLangDropdownOpen(false)}
|
|
className={`flex items-center justify-between px-3 py-2 text-xs font-bold transition-colors ${
|
|
currentLocale === lang.code
|
|
? 'bg-[#1f1f1f] text-[#FFED00]'
|
|
: 'text-[#1f1f1f] hover:bg-[#FFED00]/20'
|
|
}`}
|
|
>
|
|
<span>{lang.label}</span>
|
|
{currentLocale === lang.code && <span className="w-1.5 h-1.5 bg-[#FFED00]" />}
|
|
</a>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Right CTA Button */}
|
|
{contactHref && contactLabel && (
|
|
<a
|
|
href={contactHref}
|
|
className="inline-flex items-center gap-2 bg-[#FFED00] hover:bg-[#fae100] text-[#1f1f1f] border-2 border-[#1f1f1f] px-6 py-3 text-xs font-black uppercase tracking-widest transition-colors shadow-xs"
|
|
>
|
|
<span>{contactLabel}</span>
|
|
<ArrowRight className="h-4 w-4" />
|
|
</a>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|