profit-planet-frontend/src/app/components/nav/Header.tsx
2025-10-02 15:09:03 +02:00

338 lines
13 KiB
TypeScript

'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation';
import Image from 'next/image';
import {
Dialog,
DialogPanel,
Disclosure,
DisclosureButton,
DisclosurePanel,
Popover,
PopoverButton,
PopoverGroup,
PopoverPanel,
} from '@headlessui/react'
import {
Bars3Icon,
ShoppingBagIcon,
UsersIcon,
HomeIcon,
UserCircleIcon,
XMarkIcon,
ArrowRightOnRectangleIcon
} from '@heroicons/react/24/outline'
import { ChevronDownIcon } from '@heroicons/react/20/solid'
import useAuthStore from '../../store/authStore';
import { Avatar } from '../avatar';
import LanguageSwitcher from '../LanguageSwitcher';
const products = [
{
name: 'Shop',
description: 'Browse our exclusive product catalog',
href: '/shop',
icon: ShoppingBagIcon,
},
{
name: 'Community',
description: 'Connect with other members',
href: '/community',
icon: UsersIcon,
},
{
name: 'Dashboard',
description: 'Manage your account and activities',
href: '/dashboard',
icon: HomeIcon
},
]
export default function Header() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const user = useAuthStore((s) => s.user);
const logout = useAuthStore((s) => s.logout);
const router = useRouter();
const handleLogout = async () => {
try {
await logout();
router.push('/login');
} catch (err) {
console.error('Logout failed:', err);
}
};
// Helper to get user initials for profile icon
const getUserInitials = () => {
if (!user) return 'U';
if (user.firstName || user.lastName) {
return (
(user.firstName?.[0] || '') +
(user.lastName?.[0] || '')
).toUpperCase();
}
if (user.email) {
return user.email[0].toUpperCase();
}
return 'U';
};
return (
<header className="relative isolate z-10 bg-gray-900">
<nav aria-label="Global" className="mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8">
<div className="flex lg:flex-1">
<button
onClick={() => router.push('/')}
className="-m-1.5 p-1.5"
>
<span className="sr-only">ProfitPlanet</span>
<Image
src="/images/logos/pp_logo_gold_transparent.png"
alt="ProfitPlanet Logo"
width={180}
height={48}
className="h-12 w-auto"
/>
</button>
</div>
<div className="flex lg:hidden">
<button
type="button"
onClick={() => setMobileMenuOpen(true)}
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-400"
>
<span className="sr-only">Open main menu</span>
<Bars3Icon aria-hidden="true" className="size-6" />
</button>
</div>
<PopoverGroup className="hidden lg:flex lg:gap-x-12">
<Popover>
<PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-white">
Product
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-gray-500" />
</PopoverButton>
<PopoverPanel
transition
className="absolute inset-x-0 top-16 bg-gray-900 transition data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in"
>
<div aria-hidden="true" className="absolute inset-0 top-1/2 bg-gray-900 ring-1 ring-white/15" />
<div className="relative bg-gray-900">
<div className="mx-auto grid max-w-7xl grid-cols-3 gap-x-4 px-6 py-10 lg:px-8 xl:gap-x-8">
{products.map((item) => (
<div key={item.name} className="group relative rounded-lg p-6 text-sm/6 hover:bg-white/5">
<div className="flex size-11 items-center justify-center rounded-lg bg-gray-700/50 group-hover:bg-gray-700">
<item.icon aria-hidden="true" className="size-6 text-gray-400 group-hover:text-white" />
</div>
<button
onClick={() => router.push(item.href)}
className="mt-6 block font-semibold text-white"
>
{item.name}
<span className="absolute inset-0" />
</button>
<p className="mt-1 text-gray-400">{item.description}</p>
</div>
))}
</div>
</div>
</PopoverPanel>
</Popover>
<button
onClick={() => router.push('/features')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors"
>
Features
</button>
<button
onClick={() => router.push('/marketplace')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors"
>
Marketplace
</button>
<button
onClick={() => router.push('/company')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors"
>
Company
</button>
{/* Profile Dropdown - nur wenn eingeloggt */}
{user && (
<Popover>
<PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-white">
<Avatar
src=""
initials={getUserInitials()}
className="size-8 bg-gradient-to-br from-indigo-500/40 to-indigo-600/60 text-white"
/>
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-gray-500" />
</PopoverButton>
<PopoverPanel
transition
className="absolute right-0 top-16 w-64 bg-gray-900 ring-1 ring-white/15 transition data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in"
>
<div className="p-4">
<div className="flex flex-col border-b border-white/10 pb-4 mb-4">
<div className="font-medium text-white">
{user?.firstName && user?.lastName
? `${user.firstName} ${user.lastName}`
: user?.email || 'User'
}
</div>
<div className="text-sm text-gray-400">
{user?.email || 'user@example.com'}
</div>
</div>
<button
onClick={() => router.push('/profile')}
className="flex items-center gap-x-2 w-full text-left p-2 text-sm text-white hover:bg-white/5 rounded-md"
>
<UserCircleIcon className="size-5 text-gray-400" />
Profile
</button>
<button
onClick={handleLogout}
className="flex items-center gap-x-2 w-full text-left p-2 text-sm text-white hover:bg-white/5 rounded-md"
>
<ArrowRightOnRectangleIcon className="size-5 text-gray-400" />
Logout
</button>
</div>
</PopoverPanel>
</Popover>
)}
</PopoverGroup>
<div className="hidden lg:flex lg:flex-1 lg:justify-end lg:items-center lg:gap-x-4">
{/* Language Switcher */}
<LanguageSwitcher variant="dark" />
{!user && (
<button
onClick={() => router.push('/login')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors"
>
Log in <span aria-hidden="true">&rarr;</span>
</button>
)}
</div>
</nav>
<Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden">
<div className="fixed inset-0 z-50" />
<DialogPanel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-gray-900 p-6 sm:max-w-sm sm:ring-1 sm:ring-gray-100/10">
<div className="flex items-center justify-between">
<button
onClick={() => router.push('/')}
className="-m-1.5 p-1.5"
>
<span className="sr-only">ProfitPlanet</span>
<Image
src="/images/logos/pp_logo_gold_transparent.png"
alt="ProfitPlanet Logo"
width={150}
height={40}
className="h-10 w-auto"
/>
</button>
<button
type="button"
onClick={() => setMobileMenuOpen(false)}
className="-m-2.5 rounded-md p-2.5 text-gray-400"
>
<span className="sr-only">Close menu</span>
<XMarkIcon aria-hidden="true" className="size-6" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-white/10">
{user ? (
<>
<div className="space-y-2 py-6">
<Disclosure as="div" className="-mx-3">
<DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 pr-3.5 pl-3 text-base/7 font-semibold text-white hover:bg-white/5">
Navigation
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-2">
{products.map((item) => (
<DisclosureButton
key={item.name}
as="button"
onClick={() => {
router.push(item.href);
setMobileMenuOpen(false);
}}
className="block rounded-lg py-2 pr-3 pl-6 text-sm/7 font-semibold text-white hover:bg-white/5 w-full text-left"
>
{item.name}
</DisclosureButton>
))}
</DisclosurePanel>
</Disclosure>
</div>
<div className="py-6 space-y-2">
<div className="flex flex-col border-b border-white/10 pb-4 mb-4 px-3">
<div className="font-medium text-white">
{user?.firstName && user?.lastName
? `${user.firstName} ${user.lastName}`
: user?.email || 'User'
}
</div>
<div className="text-sm text-gray-400">
{user?.email || 'user@example.com'}
</div>
<div className="mt-4">
<div className="text-sm font-medium text-gray-400 mb-2">Language</div>
<LanguageSwitcher variant="dark" />
</div>
</div>
<button
onClick={() => {
router.push('/profile');
setMobileMenuOpen(false);
}}
className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-white hover:bg-white/5 w-full text-left"
>
Profile
</button>
<button
onClick={() => {
handleLogout();
setMobileMenuOpen(false);
}}
className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-white hover:bg-white/5 w-full text-left"
>
Logout
</button>
</div>
</>
) : (
<div className="py-6 space-y-4">
<div className="-mx-3 px-3">
<div className="text-sm font-medium text-gray-400 mb-2">Language</div>
<LanguageSwitcher variant="dark" />
</div>
<button
onClick={() => {
router.push('/login');
setMobileMenuOpen(false);
}}
className="-mx-3 block rounded-lg px-3 py-2.5 text-base/7 font-semibold text-white hover:bg-white/5 w-full text-left"
>
Log in
</button>
</div>
)}
</div>
</div>
</DialogPanel>
</Dialog>
</header>
)
}