morethanadiagnosis-hub/web/components/common/Header.tsx
admin 913c272fb3 fix: resolve all frontend build errors
- Fix Link onClick issue in Header.tsx: wrap Link in div with onClick handler (3 locations)
- Fix Checkbox label type error: change JSX Element to string label
- Fix useSearchParams Suspense issue: extract into separate component with Suspense boundary

All TypeScript errors resolved. Frontend ready to build.

Job ID: MTAD-IMPL-2025-11-18-CL
2025-11-18 06:55:42 +00:00

194 lines
6.8 KiB
TypeScript

'use client'
import React from 'react'
import { Link } from './Link'
import { Button } from './Button'
import { Avatar } from './Avatar'
export interface HeaderProps {
isAuthenticated?: boolean
userDisplayName?: string
onLogin?: () => void
onLogout?: () => void
}
export const Header = ({
isAuthenticated = false,
userDisplayName,
onLogin,
onLogout,
}: HeaderProps) => {
const [mobileMenuOpen, setMobileMenuOpen] = React.useState(false)
const navItems = [
{ label: 'Blog', href: '/blog' },
{ label: 'Forum', href: '/forum' },
{ label: 'Podcast', href: '/podcast' },
{ label: 'Resources', href: '/resources' },
{ label: 'Merch', href: '/merch' },
{ label: 'Tribute', href: '/tribute' },
]
return (
<header className="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
<nav className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" aria-label="Main navigation">
<div className="flex justify-between h-16">
{/* Logo */}
<div className="flex items-center">
<Link href="/" variant="neutral" className="no-underline">
<span className="text-xl font-bold text-primary-600 dark:text-primary-400">
MoreThanADiagnosis
</span>
</Link>
</div>
{/* Desktop Navigation */}
<div className="hidden md:flex md:items-center md:space-x-6">
{navItems.map((item) => (
<Link
key={item.href}
href={item.href}
variant="neutral"
className="text-gray-700 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white no-underline hover:underline"
>
{item.label}
</Link>
))}
</div>
{/* Auth Section */}
<div className="hidden md:flex md:items-center md:space-x-4">
{isAuthenticated ? (
<>
<Link href="/dashboard" variant="neutral" className="no-underline">
<div className="flex items-center space-x-2">
<Avatar
alt={userDisplayName || 'User'}
fallbackText={userDisplayName}
size="sm"
/>
<span className="text-gray-700 dark:text-gray-300">
{userDisplayName}
</span>
</div>
</Link>
<Button variant="ghost" size="sm" onClick={onLogout}>
Logout
</Button>
</>
) : (
<>
<Button variant="ghost" size="sm" onClick={onLogin}>
Login
</Button>
<Link href="/auth/signup">
<Button variant="primary" size="sm">
Sign Up
</Button>
</Link>
</>
)}
</div>
{/* Mobile menu button */}
<div className="flex items-center md:hidden">
<button
type="button"
className="text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white p-2"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
aria-expanded={mobileMenuOpen}
aria-label="Toggle mobile menu"
>
<svg
className="h-6 w-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
{mobileMenuOpen ? (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
)}
</svg>
</button>
</div>
</div>
{/* Mobile menu */}
{mobileMenuOpen && (
<div className="md:hidden py-4 border-t border-gray-200 dark:border-gray-700">
<div className="space-y-2">
{navItems.map((item) => (
<div key={item.href} onClick={() => setMobileMenuOpen(false)}>
<Link
href={item.href}
variant="neutral"
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 rounded-md no-underline"
>
{item.label}
</Link>
</div>
))}
<div className="border-t border-gray-200 dark:border-gray-700 pt-2 mt-2">
{isAuthenticated ? (
<>
<div onClick={() => setMobileMenuOpen(false)}>
<Link
href="/dashboard"
variant="neutral"
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 rounded-md no-underline"
>
Dashboard
</Link>
</div>
<button
className="w-full text-left px-4 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 rounded-md"
onClick={() => {
onLogout?.()
setMobileMenuOpen(false)
}}
>
Logout
</button>
</>
) : (
<>
<button
className="w-full text-left px-4 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 rounded-md"
onClick={() => {
onLogin?.()
setMobileMenuOpen(false)
}}
>
Login
</button>
<div onClick={() => setMobileMenuOpen(false)}>
<Link
href="/auth/signup"
variant="neutral"
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 rounded-md no-underline"
>
Sign Up
</Link>
</div>
</>
)}
</div>
</div>
</div>
)}
</nav>
</header>
)
}