diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index a7959131..14d724df 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Search, Menu, Zap, MapPin, Star, ChevronDown, Building, Users, Crown, Palette, Shield, FerrisWheel, Factory } from 'lucide-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'; @@ -7,137 +7,240 @@ 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 { 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 { isModerator } = useUserRole(); - return
-
- {/* Logo and Brand */} -
- -

- ThrillWiki -

- - - {/* Desktop Navigation */} - -
+ const isMobile = useIsMobile(); - {/* Search Bar */} -
- -
- - {/* User Actions */} -
- {isModerator() && ( - - )} - - - - {/* Mobile Menu */} - - - - - -
-
Explore
- - - - - - -
- -
-
-
- + + +
-
- - + setOpen(false)} + > + Parks + + setOpen(false)} + > + Rides + + setOpen(false)} + > + Manufacturers + + setOpen(false)} + > + Designers + + setOpen(false)} + > + Operators + + setOpen(false)} + > + Property Owners + + {isModerator() && ( + <> +
+ setOpen(false)} + > + Admin + + + )} + + + + + {/* Logo */} + + + + ThrillWiki + + + + {/* Desktop Navigation */} + +
+ + {/* Right side: Search, Theme, Auth */} +
+ {/* Desktop Search */} +
+ +
+ + {/* Mobile Search Button */} + + + + +
-
-
; + + + {/* Mobile Search Modal */} + + + ); } \ No newline at end of file diff --git a/src/components/manufacturers/ManufacturerCard.tsx b/src/components/manufacturers/ManufacturerCard.tsx index 40981972..5e5d41ed 100644 --- a/src/components/manufacturers/ManufacturerCard.tsx +++ b/src/components/manufacturers/ManufacturerCard.tsx @@ -35,7 +35,7 @@ export function ManufacturerCard({ company }: ManufacturerCardProps) { return ( {/* Logo/Image Section */} @@ -43,8 +43,8 @@ export function ManufacturerCard({ company }: ManufacturerCardProps) {
{/* Company Type Badge */} -
- +
+ {formatCompanyType(company.company_type)}
@@ -52,7 +52,7 @@ export function ManufacturerCard({ company }: ManufacturerCardProps) { {/* Logo Display */}
{company.logo_url ? ( -
+
{`${company.name}
) : ( -
+
{getCompanyIcon(company.company_type)}
)}
- + {/* Company Name */} -

+

{company.name}

{/* Description */} {company.description && ( -

+

{company.description}

)} {/* Company Info */} -
+
{company.founded_year && (
Founded: @@ -90,8 +90,8 @@ export function ManufacturerCard({ company }: ManufacturerCardProps) { )} {company.headquarters_location && ( -
- +
+ {company.headquarters_location} @@ -102,16 +102,16 @@ export function ManufacturerCard({ company }: ManufacturerCardProps) { {/* Rating */} {company.average_rating > 0 && (
- - {company.average_rating.toFixed(1)} + + {company.average_rating.toFixed(1)} {company.review_count > 0 && ( - ({company.review_count} reviews) + ({company.review_count}) )}
)} {/* Stats Display */} -
+
{(company as any).ride_count > 0 && (
diff --git a/src/components/search/MobileSearch.tsx b/src/components/search/MobileSearch.tsx new file mode 100644 index 00000000..d549a7d7 --- /dev/null +++ b/src/components/search/MobileSearch.tsx @@ -0,0 +1,69 @@ +import { useState } from 'react'; +import { Search, X } from 'lucide-react'; +import { Dialog, DialogContent } from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { SearchResults } from './SearchResults'; + +interface MobileSearchProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function MobileSearch({ open, onOpenChange }: MobileSearchProps) { + const [query, setQuery] = useState(''); + + const handleClose = () => { + setQuery(''); + onOpenChange(false); + }; + + return ( + + +
+ {/* Search Header */} +
+
+ +
+ + setQuery(e.target.value)} + className="pl-10 h-11 text-base" + /> +
+
+
+ + {/* Search Results */} +
+ {query.length >= 1 ? ( + + ) : ( +
+
+ +

Start searching

+

+ Find parks, rides, and manufacturers +

+
+
+ )} +
+
+
+
+ ); +} diff --git a/src/components/ui/bottom-sheet.tsx b/src/components/ui/bottom-sheet.tsx new file mode 100644 index 00000000..d1de14ee --- /dev/null +++ b/src/components/ui/bottom-sheet.tsx @@ -0,0 +1,115 @@ +import * as React from "react" +import { Drawer as DrawerPrimitive } from "vaul" +import { cn } from "@/lib/utils" + +const BottomSheet = ({ + shouldScaleBackground = true, + ...props +}: React.ComponentProps) => ( + +) +BottomSheet.displayName = "BottomSheet" + +const BottomSheetTrigger = DrawerPrimitive.Trigger + +const BottomSheetPortal = DrawerPrimitive.Portal + +const BottomSheetClose = DrawerPrimitive.Close + +const BottomSheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +BottomSheetOverlay.displayName = DrawerPrimitive.Overlay.displayName + +const BottomSheetContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + +
+ {children} + + +)) +BottomSheetContent.displayName = "BottomSheetContent" + +const BottomSheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +BottomSheetHeader.displayName = "BottomSheetHeader" + +const BottomSheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +BottomSheetFooter.displayName = "BottomSheetFooter" + +const BottomSheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +BottomSheetTitle.displayName = DrawerPrimitive.Title.displayName + +const BottomSheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +BottomSheetDescription.displayName = DrawerPrimitive.Description.displayName + +export { + BottomSheet, + BottomSheetPortal, + BottomSheetOverlay, + BottomSheetTrigger, + BottomSheetClose, + BottomSheetContent, + BottomSheetHeader, + BottomSheetFooter, + BottomSheetTitle, + BottomSheetDescription, +} diff --git a/src/pages/Designers.tsx b/src/pages/Designers.tsx index 5bf76fb8..a98ad19e 100644 --- a/src/pages/Designers.tsx +++ b/src/pages/Designers.tsx @@ -126,35 +126,32 @@ export default function Designers() {
{/* Search and Filters */} -
-
-
- - setSearchQuery(e.target.value)} - className="pl-10" - /> -
-
- -
+
+
+ + setSearchQuery(e.target.value)} + className="pl-10 h-11" + />
+ +
{/* Companies Grid */} {filteredCompanies.length > 0 ? ( -
+
{filteredCompanies.map((company) => ( ))} diff --git a/src/pages/Manufacturers.tsx b/src/pages/Manufacturers.tsx index 1e462b0e..9678ae73 100644 --- a/src/pages/Manufacturers.tsx +++ b/src/pages/Manufacturers.tsx @@ -146,36 +146,32 @@ export default function Manufacturers() {
{/* Search and Filters */} -
-
-
- - setSearchQuery(e.target.value)} - className="pl-10" - /> -
-
- - -
+
+
+ + setSearchQuery(e.target.value)} + className="pl-10 h-11" + />
+ +
{/* Companies Grid */} {filteredCompanies.length > 0 ? ( -
+
{filteredCompanies.map((company) => ( ))} diff --git a/src/pages/Operators.tsx b/src/pages/Operators.tsx index e47a698d..2fc0fe98 100644 --- a/src/pages/Operators.tsx +++ b/src/pages/Operators.tsx @@ -97,40 +97,42 @@ const Operators = () => {
{/* Search and Filters */} -
-
+
+
setSearchTerm(e.target.value)} - className="pl-10" + className="pl-10 h-11" />
- +
+ - + +
{/* Results Count */} @@ -157,7 +159,7 @@ const Operators = () => { {/* Operators Grid */} {!isLoading && filteredAndSortedOperators && ( -
+
{filteredAndSortedOperators.map((operator) => ( ))} diff --git a/src/pages/ParkOwners.tsx b/src/pages/ParkOwners.tsx index 7ddc7041..a7f5cec7 100644 --- a/src/pages/ParkOwners.tsx +++ b/src/pages/ParkOwners.tsx @@ -97,40 +97,42 @@ const ParkOwners = () => {
{/* Search and Filters */} -
-
+
+
setSearchTerm(e.target.value)} - className="pl-10" + className="pl-10 h-11" />
- +
+ - + +
{/* Results Count */} @@ -157,7 +159,7 @@ const ParkOwners = () => { {/* Property Owners Grid */} {!isLoading && filteredAndSortedOwners && ( -
+
{filteredAndSortedOwners.map((owner) => ( ))}