profit-planet-frontend/src/app/components/nav/Header.tsx

744 lines
35 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

'use client'
import { useState, useEffect, useCallback, useRef } from 'react'
import { useRouter } from 'next/navigation';
import Image from 'next/image';
import {
Dialog,
DialogPanel,
Disclosure,
DisclosureButton,
DisclosurePanel,
Popover,
PopoverButton,
PopoverGroup,
PopoverPanel,
Transition
} from '@headlessui/react'
import {
Bars3Icon,
UserCircleIcon,
XMarkIcon,
ArrowRightOnRectangleIcon,
MoonIcon,
SunIcon
} from '@heroicons/react/24/outline'
import { ChevronDownIcon } from '@heroicons/react/20/solid'
import useAuthStore from '../../store/authStore';
import { Avatar } from '../avatar';
const informationItems = [
{ name: 'Affiliate-Links', href: '/affiliate-links', description: 'Browse our partner links' },
{ name: 'Memberships', href: '/memberships', description: 'Explore membership options' },
{ name: 'About us', href: '/about-us', description: 'Learn more about us' },
];
const navLinks = [
{ name: 'Shop', href: '/shop' },
{ name: 'News', href: '/news' },
];
export default function Header() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [isDark, setIsDark] = useState(false)
const [mounted, setMounted] = useState(false) // added
const user = useAuthStore((s) => s.user);
const logout = useAuthStore((s) => s.logout);
const accessToken = useAuthStore((s) => s.accessToken);
const refreshAuthToken = useAuthStore((s) => s.refreshAuthToken);
const router = useRouter();
// NEW: permission flag
const [hasReferralPerm, setHasReferralPerm] = useState(false)
// NEW: admin management dropdown state
const [adminMgmtOpen, setAdminMgmtOpen] = useState(false)
const managementRef = useRef<HTMLDivElement | null>(null)
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';
};
// Theme initialization & persistence
useEffect(() => {
const stored = localStorage.getItem('theme')
if (stored === 'dark' || (!stored && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
setIsDark(true)
} else {
document.documentElement.classList.remove('dark')
setIsDark(false)
}
setMounted(true) // hydration complete
}, [])
const toggleTheme = useCallback(() => {
setIsDark(prev => {
const next = !prev
if (next) {
document.documentElement.classList.add('dark')
localStorage.setItem('theme', 'dark')
} else {
document.documentElement.classList.remove('dark')
localStorage.setItem('theme', 'light')
}
return next
})
}, [])
// Fetch user permissions and set hasReferralPerm
useEffect(() => {
let cancelled = false
const fetchPermissions = async () => {
if (!mounted) {
console.log('⏸️ Header: not mounted yet, skipping permissions fetch')
return
}
if (!user) {
console.log(' Header: no user, clearing permission flag')
if (!cancelled) setHasReferralPerm(false)
return
}
const uid = (user as any)?.id ?? (user as any)?._id ?? (user as any)?.userId
if (!uid) {
console.warn('⚠️ Header: user id missing, cannot fetch permissions', user)
if (!cancelled) setHasReferralPerm(false)
return
}
const base = process.env.NEXT_PUBLIC_API_BASE_URL || ''
const url = `${base}/api/users/${uid}/permissions`
console.log('🌐 Header: fetching permissions:', { url, uid })
// Ensure we have a token (try refresh if needed)
let tokenToUse = accessToken
try {
if (!tokenToUse && refreshAuthToken) {
const ok = await refreshAuthToken()
if (ok) tokenToUse = useAuthStore.getState().accessToken
}
} catch (e) {
console.error('❌ Header: refreshAuthToken error:', e)
}
try {
const res = await fetch(url, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
...(tokenToUse ? { Authorization: `Bearer ${tokenToUse}` } : {})
}
})
console.log('📡 Header: permissions status:', res.status)
const body = await res.json().catch(() => null)
console.log('📦 Header: permissions body:', body)
// Try common shapes
const permsSrc =
body?.data?.permissions ??
body?.permissions ??
body
let can = false
if (Array.isArray(permsSrc)) {
// Could be array of strings or objects
can =
permsSrc.includes?.('can_create_referrals') ||
permsSrc.some?.((p: any) => p?.name === 'can_create_referrals' || p?.key === 'can_create_referrals')
} else if (permsSrc && typeof permsSrc === 'object') {
can = !!permsSrc.can_create_referrals
}
console.log('✅ Header: can_create_referrals =', can)
if (!cancelled) setHasReferralPerm(!!can)
} catch (e) {
console.error('❌ Header: fetch permissions error:', e)
if (!cancelled) setHasReferralPerm(false)
}
}
fetchPermissions()
return () => { cancelled = true }
}, [mounted, user, accessToken, refreshAuthToken])
const isLoggedIn = !!user
const userPresent = mounted && isLoggedIn
// NEW: detect admin role across common shapes
const isAdmin =
!!user &&
(
(user as any)?.role === 'admin' ||
(user as any)?.userType === 'admin' ||
(user as any)?.isAdmin === true ||
((user as any)?.roles?.includes?.('admin'))
)
// Fix: Only render header after hydration to avoid SSR/CSR mismatch
if (!mounted) {
// Optionally, render a skeleton or nothing
return <div style={{ minHeight: 80 }} />;
}
return (
<header
// Remove bottom border when admin subheader is present to avoid a blue line under the gold bar
className={`relative isolate z-10 shadow-lg shadow-black/30 after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:bg-[radial-gradient(circle_at_20%_20%,rgba(56,124,255,0.18),transparent_55%),radial-gradient(circle_at_80%_35%,rgba(139,92,246,0.16),transparent_60%)] ${isAdmin ? '' : 'border-b border-white/10'}`}
style={{
background: 'linear-gradient(135deg, #0F1D37 0%, #0A162A 50%, #081224 100%)',
}}
>
<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="p-2 flex items-center gap-3 max-w-full lg:-m-1.5 lg:gap-0"
>
<span className="sr-only">ProfitPlanet</span>
<Image
src="/images/logos/pp_logo_gold_transparent.png"
alt="ProfitPlanet Logo"
width={280}
height={84}
className="h-14 w-auto flex-shrink-0 sm:h-16 lg:h-[4.5rem]"
/>
{/* Removed flickering mobile heading (now only shown inside the sliding panel) */}
</button>
</div>
<div className="flex lg:hidden">
<button
type="button"
onClick={() => setMobileMenuOpen(true)}
aria-expanded={mobileMenuOpen}
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-400 transition-transform duration-300 ease-out data-[open=true]:rotate-90"
data-open={mobileMenuOpen ? 'true' : 'false'}
>
<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">
{/* Navigation Links */}
{navLinks.map((link) => (
<button
key={link.href}
onClick={() => router.push(link.href)}
className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
>
{link.name}
</button>
))}
{/* Conditional user-specific links */}
{userPresent && hasReferralPerm && (
<>
<button
onClick={() => { console.log('🧭 Header: navigate to /referral-management'); router.push('/referral-management') }}
className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
>
Referral Management
</button>
<button
onClick={() => router.push('/personal-matrix')}
className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
>
Personal Matrix
</button>
<button
onClick={() => router.push('/coffee-abonnements')}
className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
>
Coffee Abonnements
</button>
</>
)}
{/* Information dropdown - moved to far right */}
<Popover>
<PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-gray-900 dark:text-white">
Information
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-gray-500" />
</PopoverButton>
<PopoverPanel
transition
className="absolute left-0 right-0 top-full z-50 rounded-b-2xl shadow-xl shadow-black/40 ring-1 ring-white/10 dark:ring-white/15 overflow-hidden 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"
style={{
background: 'linear-gradient(150deg, rgba(26,46,84,0.95) 0%, rgba(18,37,70,0.92) 45%, rgba(30,56,104,0.88) 100%)',
backdropFilter: 'blur(26px) saturate(175%)',
WebkitBackdropFilter: 'blur(26px) saturate(175%)'
}}
>
<div className="relative before:absolute before:inset-0 before:pointer-events-none before:bg-[radial-gradient(circle_at_18%_30%,rgba(56,124,255,0.30),transparent_62%),radial-gradient(circle_at_82%_40%,rgba(139,92,246,0.22),transparent_65%)]">
<div className="mx-auto grid max-w-7xl grid-cols-1 md:grid-cols-3 gap-x-4 px-6 py-10 lg:px-8 xl:gap-x-8">
{informationItems.map(item => (
<div
key={item.name}
className="group relative rounded-lg p-6 text-sm/6 hover:bg-white/5 transition-colors"
>
<button
onClick={() => router.push(item.href)}
className="block font-semibold text-white"
>
{item.name}
<span className="absolute inset-0" />
</button>
<p className="mt-1 text-gray-300">{item.description}</p>
</div>
))}
</div>
</div>
</PopoverPanel>
</Popover>
</PopoverGroup>
<div className="hidden lg:flex lg:flex-1 lg:justify-end lg:items-center lg:gap-x-4">
{/* Stable auth slot to avoid SSR/CSR structural drift */}
<div className="flex items-center">
{userPresent ? (
<Popover className="relative">
<PopoverButton className="flex items-center gap-x-1 text-sm font-semibold text-gray-900 dark:text-white">
<Avatar
src=""
initials={(() => {
if (!user) return 'U'
if (user.firstName || user.lastName) {
return ((user.firstName?.[0] || '') + (user.lastName?.[0] || '')).toUpperCase()
}
return user.email ? user.email[0].toUpperCase() : 'U'
})()}
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 left-0 top-full mt-2 w-64 rounded-md bg-white dark:bg-gray-900 ring-1 ring-black/10 dark:ring-white/10 shadow-lg data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-leave:duration-150"
>
<div className="p-4">
<div className="flex flex-col border-b border-gray-200 dark:border-white/10 pb-4 mb-4">
<div className="font-medium text-gray-900 dark:text-white">
{user?.firstName && user?.lastName ? `${user.firstName} ${user.lastName}` : (user?.email || 'User')}
</div>
<div className="text-sm text-gray-500 dark:text-gray-400">
{user?.email || 'user@example.com'}
</div>
</div>
<button
onClick={() => router.push('/dashboard')}
className="flex items-center gap-x-2 w-full text-left p-2 text-sm text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-white/5 rounded-md"
>
<Bars3Icon className="size-5 text-gray-400" />
Dashboard
</button>
<button
onClick={() => router.push('/profile')}
className="flex items-center gap-x-2 w-full text-left p-2 text-sm text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark: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-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-white/5 rounded-md"
>
<ArrowRightOnRectangleIcon className="size-5 text-gray-400" />
Logout
</button>
</div>
</PopoverPanel>
</Popover>
) : mounted ? (
<button
onClick={() => router.push('/login')}
className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
>
Log in <span aria-hidden="true">&rarr;</span>
</button>
) : (
<div aria-hidden="true" className="w-20 h-8 rounded-md bg-gray-200 dark:bg-gray-700/70 animate-pulse" />
)}
</div>
{/* Replace LanguageSwitcher with English-only dropdown + note */}
<Popover className="relative">
<PopoverButton className="p-2 rounded-md border border-gray-300 dark:border-white/10 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-200 text-sm font-semibold">
English
<ChevronDownIcon aria-hidden="true" className="ml-1 inline h-4 w-4 text-gray-500" />
</PopoverButton>
<PopoverPanel
transition
className="absolute right-0 top-full mt-2 w-72 rounded-md bg-white dark:bg-gray-900 ring-1 ring-black/10 dark:ring-white/10 shadow-lg p-3 text-sm text-gray-800 dark:text-gray-200 data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-leave:duration-150"
>
We are currently working on implementing other languages.
</PopoverPanel>
</Popover>
<button
onClick={toggleTheme}
aria-label="Toggle theme"
className="p-2 rounded-md border border-gray-300 dark:border-white/10 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-200 transition-colors"
>
{isDark ? <SunIcon className="h-5 w-5" /> : <MoonIcon className="h-5 w-5" />}
</button>
</div>
</nav>
{/* Admin subheader (gold) - centered */}
{userPresent && isAdmin && (
<div
className="w-full border-t border-amber-700/40"
style={{ background: 'linear-gradient(90deg, #D4AF37 0%, #C99A2E 100%)' }}
>
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="flex flex-wrap items-center justify-center gap-5 py-2">
<span className="text-xs font-semibold uppercase tracking-wide text-[#3B2C04]/80">
Admin Navigation
</span>
<button
onClick={() => { router.push('/admin') }}
className="text-sm font-semibold text-[#0F1D37] hover:text-[#7A5E1A]"
>
Dashboard
</button>
<button
onClick={() => { router.push('/admin/user-verify') }}
className="text-sm font-semibold text-[#0F1D37] hover:text-[#7A5E1A]"
>
User Verify
</button>
{/* Updated Management dropdown */}
<div
ref={managementRef}
className="relative"
>
<button
onClick={() => setAdminMgmtOpen(o => !o)}
aria-haspopup="true"
aria-expanded={adminMgmtOpen}
className="text-sm font-semibold text-[#0F1D37] hover:text-[#7A5E1A] flex items-center gap-1"
>
Management
<ChevronDownIcon
className={`h-4 w-4 transition-transform ${adminMgmtOpen ? 'rotate-180' : ''}`}
/>
</button>
{adminMgmtOpen && (
<div
className="absolute left-1/2 -translate-x-1/2 mt-2 min-w-[15rem] rounded-md bg-white shadow-lg ring-1 ring-black/10 z-50"
role="menu"
>
<div className="py-2">
<button
onClick={() => { router.push('/admin/user-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
User Management
</button>
<button
onClick={() => { router.push('/admin/matrix-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
Matrix Management
</button>
<button
onClick={() => { router.push('/admin/contract-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
Contract Management
</button>
<button
onClick={() => { router.push('/admin/subscriptions'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
Coffee Management
</button>
<button
onClick={() => { router.push('/admin/finance-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
Finance Management
</button>
<button
onClick={() => { router.push('/admin/pool-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
Pool Management
</button>
<button
onClick={() => { router.push('/admin/affiliate-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
Affiliate Management
</button>
<button
onClick={() => { router.push('/admin/news-management'); setAdminMgmtOpen(false); }}
className="w-full text-left px-4 py-2 text-sm text-[#0F1D37] hover:bg-[#F5F3EE]"
role="menuitem"
>
News Management
</button>
</div>
</div>
)}
</div>
</div>
</div>
</div>
)}
{/* Mobile dialog and rest of header */}
<Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden">
<Transition
appear
show={mobileMenuOpen}
>
<Transition.Child
enter="transition-opacity duration-300 ease-out"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-200 ease-in"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 z-40 bg-black/40 backdrop-blur-sm" />
</Transition.Child>
{/* Sliding panel */}
<Transition.Child
enter="transform transition-transform duration-300 ease-out"
enterFrom="translate-x-full"
enterTo="translate-x-0"
leave="transform transition-transform duration-250 ease-in"
leaveFrom="translate-x-0"
leaveTo="translate-x-full"
>
<DialogPanel className="fixed inset-y-0 right-0 z-50 w-full sm:max-w-sm h-full overflow-y-auto overflow-x-hidden bg-white dark:bg-gray-900 p-5 sm:ring-1 sm:ring-black/10 dark:sm:ring-gray-100/10">
<div className="flex items-center justify-between">
<button
onClick={() => router.push('/')}
className="p-1.5 flex items-center gap-3"
>
<span className="sr-only">ProfitPlanet</span>
<Image
src="/images/logos/pp_logo_gold_transparent.png"
alt="ProfitPlanet Logo"
width={190}
height={60}
className="h-12 w-auto flex-shrink-0"
/>
<span className="text-xl font-bold tracking-tight text-[#D4AF37]">
Profit Planet
</span>
</button>
<button
type="button"
onClick={() => setMobileMenuOpen(false)}
className="rounded-md p-2.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-transform duration-300 hover:scale-110"
>
<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-gray-200 dark:divide-white/10">
{!mounted ? (
<div className="py-6 px-3">
<div className="h-28 w-full rounded-lg bg-gray-200 dark:bg-gray-700 animate-pulse" />
</div>
) : user ? (
<>
{/* User info now FIRST under logo */}
<div className="pt-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>
<button
onClick={() => { router.push('/dashboard'); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Dashboard
</button>
<button
onClick={() => { router.push('/profile'); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Profile
</button>
<button
onClick={() => { handleLogout(); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Logout
</button>
</div>
{/* Theme + Language now AFTER user info */}
<div className="py-6">
<button
onClick={toggleTheme}
className="flex items-center gap-x-2 rounded-lg px-3 py-2.5 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-white/5 w-full"
>
{isDark ? <SunIcon className="h-5 w-5" /> : <MoonIcon className="h-5 w-5" />}
{isDark ? 'Light Mode' : 'Dark Mode'}
</button>
{/* Replace LanguageSwitcher with English-only dropdown + note for mobile */}
<Disclosure as="div" className="mt-4 px-1">
<DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 px-3 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5">
Language: English
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-1 px-3 text-sm text-gray-700 dark:text-gray-300">
We are currently working on implementing other languages.
</DisclosurePanel>
</Disclosure>
</div>
{/* Navigation after that */}
<div className="space-y-2 py-6">
{/* Information disclosure */}
<Disclosure as="div">
<DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 px-3 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5">
Information
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-1">
{informationItems.map(item => (
<DisclosureButton
key={item.name}
as="button"
onClick={() => { router.push(item.href); setMobileMenuOpen(false); }}
className="block rounded-lg py-2 pl-6 pr-3 text-sm/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
{item.name}
</DisclosureButton>
))}
</DisclosurePanel>
</Disclosure>
{/* Navigation Links */}
{navLinks.map((link) => (
<button
key={link.href}
onClick={() => { router.push(link.href); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
{link.name}
</button>
))}
{/* Conditional user-specific links */}
{hasReferralPerm && (
<>
<button
onClick={() => { console.log('🧭 Header Mobile: navigate to /referral-management'); router.push('/referral-management'); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Referral Management
</button>
<button
onClick={() => { router.push('/personal-matrix'); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Personal Matrix
</button>
<button
onClick={() => { router.push('/coffee-abonnements'); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Coffee Abonnements
</button>
</>
)}
</div>
</>
) : (
<div className="py-6 space-y-4">
{/* Information disclosure */}
<Disclosure as="div">
<DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 px-3 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5">
Information
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-1">
{informationItems.map(item => (
<DisclosureButton
key={item.name}
as="button"
onClick={() => { router.push(item.href); setMobileMenuOpen(false); }}
className="block rounded-lg py-2 pl-6 pr-3 text-sm/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
{item.name}
</DisclosureButton>
))}
</DisclosurePanel>
</Disclosure>
{/* Navigation Links */}
{navLinks.map((link) => (
<button
key={link.href}
onClick={() => { router.push(link.href); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
{link.name}
</button>
))}
{/* Language (English-only) in logged-out mobile */}
<div className="px-3">
<Disclosure as="div">
<DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 px-3 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5">
Language: English
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-1 px-3 text-sm text-gray-700 dark:text-gray-300">
We are currently working on implementing other languages.
</DisclosurePanel>
</Disclosure>
</div>
<div className="px-3">
<button
onClick={() => { router.push('/login'); setMobileMenuOpen(false); }}
className="block rounded-lg px-3 py-2.5 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
>
Log in
</button>
</div>
</div>
)}
</div>
</div>
</DialogPanel>
</Transition.Child>
</Transition>
</Dialog>
</header>
)
}