Files
thrilltrack-explorer/src-old/components/layout/Header.tsx

256 lines
12 KiB
TypeScript

import { useState } from 'react';
import { Search, Menu, Sparkles, MapPin, Star, ChevronDown, Building, Users, Crown, Palette, Shield, FerrisWheel, Factory } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import { Badge } from '@/components/ui/badge';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { Link, useNavigate } from 'react-router-dom';
import { SearchDropdown } from '@/components/search/SearchDropdown';
import { MobileSearch } from '@/components/search/MobileSearch';
import { AuthButtons } from '@/components/auth/AuthButtons';
import { ThemeToggle } from '@/components/theme/ThemeToggle';
import { NotificationCenter } from '@/components/notifications/NotificationCenter';
import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole';
import { useIsMobile } from '@/hooks/use-mobile';
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu";
export function Header() {
const navigate = useNavigate();
const [open, setOpen] = useState(false);
const [mobileSearchOpen, setMobileSearchOpen] = useState(false);
const { user } = useAuth();
const { isModerator, loading: rolesLoading } = useUserRole();
const isMobile = useIsMobile();
return (
<>
<header className="sticky top-0 z-40 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-14 md:h-16 items-center justify-between gap-2 md:gap-4 px-3 md:px-4">
{/* Mobile: Menu + Logo */}
<div className="flex items-center gap-2 md:gap-6 flex-1 md:flex-initial min-w-0">
{/* Mobile Menu */}
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="md:hidden h-9 w-9">
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="w-[280px] sm:w-[320px]">
<nav className="flex flex-col gap-1 mt-8">
<div className="mb-4">
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-2 px-3">
Explore
</h3>
</div>
<Link
to="/rides"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Rides
</Link>
<Link
to="/parks"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Parks
</Link>
<Link
to="/manufacturers"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Manufacturers
</Link>
<Link
to="/designers"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Designers
</Link>
<Link
to="/operators"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Operators
</Link>
<Link
to="/owners"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Property Owners
</Link>
{!rolesLoading && isModerator() && (
<>
<div className="my-2 border-t border-border" />
<Link
to="/admin"
className="px-3 py-2.5 text-base font-medium hover:bg-accent hover:text-accent-foreground rounded-md transition-colors"
onClick={() => setOpen(false)}
>
Admin
</Link>
</>
)}
<div className="my-2 border-t border-border" />
<div className="px-3 py-2.5 flex items-center justify-between">
<span className="text-base font-medium">Theme</span>
<ThemeToggle />
</div>
</nav>
</SheetContent>
</Sheet>
{/* Logo */}
<Link to="/" className="flex items-center hover:opacity-80 transition-opacity flex-shrink-0">
<span className="font-bold text-base sm:text-lg md:text-xl bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent whitespace-nowrap">
ThrillWiki
</span>
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-1">
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger className="h-9">Explore</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid min-w-[320px] max-w-[500px] w-fit gap-3 p-4">
<li>
<NavigationMenuLink asChild>
<Link
to="/rides"
className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent/20 focus:bg-accent/20"
>
<div className="text-sm font-medium leading-none">Rides</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
Discover exciting rides and attractions
</p>
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
to="/parks"
className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent/20 focus:bg-accent/20"
>
<div className="text-sm font-medium leading-none">Parks</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
Browse theme parks around the world
</p>
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
to="/manufacturers"
className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent/20 focus:bg-accent/20"
>
<div className="text-sm font-medium leading-none">Manufacturers</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
Explore ride manufacturers
</p>
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
to="/designers"
className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent/20 focus:bg-accent/20"
>
<div className="text-sm font-medium leading-none">Designers</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
View ride designers
</p>
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
to="/operators"
className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent/20 focus:bg-accent/20"
>
<div className="text-sm font-medium leading-none">Operators</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
Find park operators
</p>
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
to="/owners"
className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent/20 focus:bg-accent/20"
>
<div className="text-sm font-medium leading-none">Property Owners</div>
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
View property owners
</p>
</Link>
</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
{!rolesLoading && isModerator() && (
<Button variant="ghost" size="sm" className="h-9" asChild>
<Link to="/admin">Admin</Link>
</Button>
)}
</nav>
</div>
{/* Right side: Search, Theme, Auth */}
<div className="flex items-center gap-1.5 md:gap-2 flex-shrink-0">
{/* Desktop Search */}
<div className="hidden lg:block lg:w-64 xl:w-80 min-w-0">
<SearchDropdown />
</div>
{/* Mobile Search Button */}
<Button
variant="ghost"
size="icon"
className="lg:hidden h-9 w-9 min-w-[36px]"
onClick={() => setMobileSearchOpen(true)}
>
<Search className="h-5 w-5" />
<span className="sr-only">Search</span>
</Button>
<div className="hidden md:block">
<ThemeToggle />
</div>
{user && <NotificationCenter />}
<AuthButtons />
</div>
</div>
</header>
{/* Mobile Search Modal */}
<MobileSearch open={mobileSearchOpen} onOpenChange={setMobileSearchOpen} />
</>
);
}