marian/src/components/Header.tsx
2026-02-06 02:10:35 +01:00

225 lines
9.2 KiB
TypeScript

import { useState } from 'react';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Menu, X, Phone, Home, Shield, FileText, Truck, Users, Search, Accessibility } from 'lucide-react';
import { Button } from '@/components/ui/button';
import LanguageSwitcher from '@/components/LanguageSwitcher';
import AccessibilityBar from '@/components/AccessibilityBar';
const Header = () => {
const { t } = useTranslation('nav');
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isAccessibilityOpen, setIsAccessibilityOpen] = useState(false);
const location = useLocation();
const navigate = useNavigate();
const [searchQuery, setSearchQuery] = useState('');
const baseUrl = import.meta.env.BASE_URL;
const navigation = [
{ name: t('home'), href: '/', icon: Home },
{ name: t('privateCustomers'), href: '/privatkunden', icon: Users },
{ name: t('familiesAndChildren', 'Familien & Kinder'), href: '/familien-kinder', icon: Users },
{ name: t('seniors'), href: '/senioren', icon: Shield },
{ name: t('businessCustomers'), href: '/geschaeftskunden', icon: Truck },
];
const rightMenuItems = [
{ name: t('agency'), href: '/agentur', icon: Shield },
{ name: t('finances'), href: '/finanzen', icon: FileText },
{ name: t('contact'), href: '/contact#contact', icon: Phone },
];
const searchItems = [
...navigation,
...rightMenuItems,
{ name: t('accidentInsurance', 'Unfall'), href: '/unfall', icon: Shield },
{ name: t('carInsurance', 'KFZ'), href: '/kfz', icon: Truck },
{ name: t('services', 'Leistungen'), href: '/leistungen', icon: FileText },
{ name: 'Risikolebensversicherung', href: '/risikolebensversicherung', icon: Shield },
{ name: 'Krankheits-Schutzbrief', href: '/krankheitsschutzbrief', icon: Shield },
{ name: 'Vermögenssicherung', href: '/vermoegenssicherung', icon: Shield },
];
const normalizedQuery = searchQuery.trim().toLowerCase();
const filteredItems = normalizedQuery
? searchItems.filter((item) => item.name.toLowerCase().includes(normalizedQuery))
: [];
return (
<header className="bg-white shadow-sm border-b">
<div className="container mx-auto px-2 lg:px-4">
<div className="flex items-center justify-between h-16 min-w-0">
{/* Logo */}
<div className="flex items-center gap-3 shrink-0 min-w-0">
<Link to="/" className="flex items-center space-x-2 shrink-0 min-w-0">
<img
src={`${baseUrl}${encodeURI('Agentur Mizera & Partner logo_2016.png')}`}
alt="Agentur Mizera & Partner"
className="h-14 w-auto"
loading="eager"
/>
</Link>
</div>
{/* Right side items */}
<div className="flex items-center space-x-2 lg:space-x-4 shrink-0">
{/* Header Search (Desktop) */}
<div className="hidden md:block relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500" />
<input
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-44 lg:w-56 2xl:w-72 h-10 rounded-full border border-gray-200 bg-white pl-9 pr-4 text-sm shadow-sm"
placeholder={t('searchPlaceholder', 'Suche...')}
/>
{filteredItems.length > 0 && (
<div className="absolute right-0 mt-2 w-72 rounded-md border border-gray-200 bg-white shadow-sm overflow-hidden z-50">
{filteredItems.slice(0, 8).map((item) => (
<button
key={`${item.href}-${item.name}`}
type="button"
className="w-full text-left px-4 py-3 hover:bg-gray-50 transition-colors"
onClick={() => {
navigate(item.href);
setSearchQuery('');
}}
>
<div className="text-sm font-semibold text-gray-900">{item.name}</div>
<div className="text-xs text-gray-600 mt-0.5">{item.href}</div>
</button>
))}
</div>
)}
</div>
{/* Language Switcher (Desktop only) */}
<div className="hidden md:block">
<LanguageSwitcher />
</div>
{/* Mobile menu button */}
<Button
variant="ghost"
size="sm"
className="md:hidden"
onClick={() => setIsMenuOpen(!isMenuOpen)}
>
{isMenuOpen ? (
<X className="h-6 w-6" />
) : (
<Menu className="h-6 w-6" />
)}
</Button>
</div>
</div>
{/* Desktop Navigation (zweite Zeile) */}
<div className="hidden md:flex items-center justify-between gap-4 border-t py-3 min-w-0">
<nav className="flex flex-1 items-center min-w-0">
<div className="flex flex-wrap items-center gap-2 min-w-0">
{navigation.map((item) => {
const Icon = item.icon;
const isActive = location.pathname === item.href;
return (
<Link
key={item.name}
to={item.href}
className={`flex items-center space-x-1 px-3 py-2 rounded-md text-sm font-semibold transition-colors ${
isActive
? 'text-blue-600 bg-blue-50'
: 'text-gray-700 hover:text-blue-600 hover:bg-gray-50'
}`}
>
<Icon className="h-5 w-5" strokeWidth={1.25} />
<span className="whitespace-nowrap">{item.name}</span>
</Link>
);
})}
</div>
</nav>
<div className="flex flex-wrap items-center gap-2 shrink-0">
{rightMenuItems.map((item) => {
const Icon = item.icon;
const isActive = location.pathname === item.href;
return (
<Link
key={item.name}
to={item.href}
className={`flex items-center space-x-1 px-3 py-2 rounded-md text-sm font-semibold transition-colors ${
isActive
? 'text-blue-600 bg-blue-50'
: 'text-gray-700 hover:text-blue-600 hover:bg-gray-50'
}`}
>
<Icon className="h-5 w-5" strokeWidth={1.25} />
<span className="whitespace-nowrap">{item.name}</span>
</Link>
);
})}
</div>
</div>
{/* Mobile Navigation */}
{isMenuOpen && (
<div className="md:hidden border-t py-4">
<nav className="flex flex-col space-y-2">
{/* Language & Accessibility Section (Mobile) */}
<div className="px-3 py-2 border-b border-gray-200">
<div className="text-xs font-medium text-gray-500 mb-2">Sprache / Language</div>
<div className="flex items-center justify-between">
<LanguageSwitcher />
<button
onClick={() => setIsAccessibilityOpen(!isAccessibilityOpen)}
className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 border ${
isAccessibilityOpen
? 'text-blue-600 bg-blue-50 border-blue-200 shadow-sm'
: 'text-gray-700 bg-white border-gray-200 hover:text-blue-600 hover:bg-gray-50 hover:border-blue-200'
}`}
aria-label="Barrierefreiheit"
>
<Accessibility className="h-4 w-4" strokeWidth={1.5} />
</button>
</div>
</div>
{[...navigation, ...rightMenuItems].map((item) => {
const Icon = item.icon;
const isActive = location.pathname === item.href;
return (
<Link
key={item.name}
to={item.href}
onClick={() => setIsMenuOpen(false)}
className={`flex items-center space-x-3 px-3 py-2 rounded-md text-sm font-medium transition-colors ${
isActive
? 'text-blue-600 bg-blue-50'
: 'text-gray-700 hover:text-blue-600 hover:bg-gray-50'
}`}
>
<Icon className="h-5 w-5" strokeWidth={1.25} />
<span>{item.name}</span>
</Link>
);
})}
</nav>
{/* Mobile Accessibility Bar */}
{isAccessibilityOpen && (
<div className="mt-4 pt-4 border-t border-gray-200">
<AccessibilityBar />
</div>
)}
</div>
)}
</div>
</header>
);
};
export default Header;