import { useState, useEffect } from 'react'; import { useDebouncedValue } from '@/hooks/useDebouncedValue'; import { useGlobalSearch } from '@/hooks/search/useGlobalSearch'; import { formatLocationShort } from '@/lib/locationFormatter'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { MapPin, Star, Search as SearchIcon, Castle, FerrisWheel, Waves, Theater, Factory } from 'lucide-react'; import { Park, Ride, Company } from '@/types/database'; import { supabase } from '@/lib/supabaseClient'; import { useNavigate } from 'react-router-dom'; import { getErrorMessage } from '@/lib/errorHandler'; import { logger } from '@/lib/logger'; interface SearchResultsProps { query: string; onClose: () => void; } type SearchResult = { type: 'park' | 'ride' | 'company'; data: Park | Ride | Company; }; export function SearchResults({ query, onClose }: SearchResultsProps) { const navigate = useNavigate(); // Debounce search query const debouncedQuery = useDebouncedValue(query, 300); // Use global search hook with caching const { data, isLoading: loading } = useGlobalSearch(debouncedQuery); // Flatten results const results: SearchResult[] = [ ...(data?.parks || []).map(park => ({ type: 'park' as const, data: park })), ...(data?.rides || []).map(ride => ({ type: 'ride' as const, data: ride })), ...(data?.companies || []).map(company => ({ type: 'company' as const, data: company })), ]; const handleResultClick = (result: SearchResult) => { onClose(); switch (result.type) { case 'park': navigate(`/parks/${(result.data as Park).slug}`); break; case 'ride': const ride = result.data as Ride; if (ride.park && typeof ride.park === 'object' && 'slug' in ride.park) { navigate(`/parks/${ride.park.slug}/rides/${ride.slug}`); } break; case 'company': // Navigate to manufacturer page when implemented break; } }; const getResultIcon = (result: SearchResult) => { switch (result.type) { case 'park': const park = result.data as Park; switch (park.park_type) { case 'theme_park': return ; case 'amusement_park': return ; case 'water_park': return ; default: return ; } case 'ride': const ride = result.data as Ride; switch (ride.category) { case 'roller_coaster': return ; case 'water_ride': return ; case 'dark_ride': return ; default: return ; } case 'company': return ; } }; const getResultTitle = (result: SearchResult) => { return result.data.name; }; const getResultSubtitle = (result: SearchResult) => { switch (result.type) { case 'park': const park = result.data as Park; return park.location ? formatLocationShort(park.location) : 'Theme Park'; case 'ride': const ride = result.data as Ride; return ride.park && typeof ride.park === 'object' && 'name' in ride.park ? `at ${ride.park.name}` : 'Ride'; case 'company': const company = result.data as Company; return company.company_type.replace('_', ' '); } }; const getResultRating = (result: SearchResult) => { if (result.type === 'park' || result.type === 'ride') { const data = result.data as Park | Ride; return (data.average_rating != null && data.average_rating > 0) ? data.average_rating : null; } return null; }; if (query.length < 2) { return (

Start typing to search parks, rides, and manufacturers...

); } if (loading) { return (
{[...Array(5)].map((_, i) => (
))}
); } if (results.length === 0) { return (

No results found for "{query}"

Try searching for park names, ride names, or locations

); } return (
{results.map((result, index) => ( handleResultClick(result)} >
{getResultIcon(result)}

{getResultTitle(result)}

{result.type}

{getResultSubtitle(result)}

{getResultRating(result) && (
{getResultRating(result)?.toFixed(1)}
)}
))}
{results.length > 0 && (
)}
); }