import { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { Header } from '@/components/layout/Header'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Filter, SlidersHorizontal, FerrisWheel, Plus, ArrowLeft } from 'lucide-react'; import { AutocompleteSearch } from '@/components/search/AutocompleteSearch'; import { RideCard } from '@/components/rides/RideCard'; import { RideForm } from '@/components/admin/RideForm'; import { Ride, Park } from '@/types/database'; import { RideSubmissionData } from '@/types/submission-data'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/hooks/useAuth'; import { toast } from '@/hooks/use-toast'; import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler'; import { useAuthModal } from '@/hooks/useAuthModal'; import { useDocumentTitle } from '@/hooks/useDocumentTitle'; import { useOpenGraph } from '@/hooks/useOpenGraph'; import { SubmissionErrorBoundary } from '@/components/error/SubmissionErrorBoundary'; export default function ParkRides() { const { parkSlug } = useParams<{ parkSlug: string }>(); const navigate = useNavigate(); const { user } = useAuth(); const { requireAuth } = useAuthModal(); const [park, setPark] = useState(null); const [rides, setRides] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [sortBy, setSortBy] = useState('name'); const [filterCategory, setFilterCategory] = useState('all'); // Update document title when park changes useDocumentTitle(park ? `${park.name} - Rides` : 'Park Rides'); const [filterStatus, setFilterStatus] = useState('all'); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); useEffect(() => { if (parkSlug) { fetchParkAndRides(); } }, [parkSlug, sortBy, filterCategory, filterStatus]); const fetchParkAndRides = async () => { try { setLoading(true); // Fetch park details first const { data: parkData, error: parkError } = await supabase .from('parks') .select('*') .eq('slug', parkSlug || '') .maybeSingle(); if (parkError) throw parkError; if (!parkData) { toast({ title: "Park Not Found", description: "The park you're looking for doesn't exist.", variant: "destructive" }); navigate('/parks'); return; } setPark(parkData); // Fetch rides for this park let query = supabase .from('rides') .select(` *, manufacturer:companies!rides_manufacturer_id_fkey(*) `) .eq('park_id', parkData.id); // Apply filters if (filterCategory !== 'all') { query = query.eq('category', filterCategory); } if (filterStatus !== 'all') { query = query.eq('status', filterStatus); } // Apply sorting switch (sortBy) { case 'rating': query = query.order('average_rating', { ascending: false }); break; case 'speed': query = query.order('max_speed_kmh', { ascending: false, nullsFirst: false }); break; case 'height': query = query.order('max_height_meters', { ascending: false, nullsFirst: false }); break; case 'reviews': query = query.order('review_count', { ascending: false }); break; default: query = query.order('name'); } const { data: ridesData, error: ridesError } = await query; if (ridesError) throw ridesError; // Supabase returns nullable types, but our Ride type uses undefined // eslint-disable-next-line @typescript-eslint/no-explicit-any setRides((ridesData || []) as any); } catch (error) { handleNonCriticalError(error, { action: 'Fetch Park Rides', metadata: { parkSlug } }); toast({ title: "Error", description: "Failed to load park rides.", variant: "destructive" }); } finally { setLoading(false); } }; const handleCreateSubmit = async (data: Omit & { park_id?: string }) => { try { if (!park) { toast({ title: "Error", description: "Park information not loaded", variant: "destructive" }); return; } // Pre-fill park_id in the submission and convert nulls to undefined const submissionData = { ...data, description: data.description ?? undefined, park_id: park.id, }; const { submitRideCreation } = await import('@/lib/entitySubmissionHelpers'); // Type assertion needed: Form data structure doesn't perfectly match submission helper expectations // eslint-disable-next-line @typescript-eslint/no-explicit-any await submitRideCreation(submissionData as any, user!.id); toast({ title: "Ride Submitted", description: "Your ride submission has been sent for moderation review.", }); setIsCreateModalOpen(false); } catch (error) { const errorMsg = getErrorMessage(error); toast({ title: "Submission Failed", description: errorMsg, variant: "destructive" }); } }; const filteredRides = rides.filter(ride => ride.name.toLowerCase().includes(searchQuery.toLowerCase()) || ride.manufacturer?.name?.toLowerCase().includes(searchQuery.toLowerCase()) ); useOpenGraph({ title: park ? `${park.name} - Rides & Attractions` : 'Park Rides', description: park ? `Explore ${filteredRides.length} rides and attractions at ${park.name}` : undefined, imageUrl: park?.banner_image_url ?? filteredRides[0]?.banner_image_url ?? undefined, imageId: park?.banner_image_id ?? filteredRides[0]?.banner_image_id ?? undefined, type: 'website', enabled: !!park && !loading }); const categories = [ { value: 'all', label: 'All Categories' }, { value: 'roller_coaster', label: 'Roller Coasters' }, { value: 'flat_ride', label: 'Flat Rides' }, { value: 'water_ride', label: 'Water Rides' }, { value: 'dark_ride', label: 'Dark Rides' }, { value: 'kiddie_ride', label: 'Kiddie Rides' }, { value: 'transportation', label: 'Transportation' } ]; const statusOptions = [ { value: 'all', label: 'All Status' }, { value: 'operating', label: 'Operating' }, { value: 'seasonal', label: 'Seasonal' }, { value: 'under_construction', label: 'Under Construction' }, { value: 'closed', label: 'Closed' } ]; if (loading) { return (
{[...Array(8)].map((_, i) => (
))}
); } if (!park) { return null; } return (
{/* Back Button & Page Header */}

{park.name}

Rides & Attractions

{filteredRides.length} rides {rides.filter(r => r.category === 'roller_coaster').length} coasters
{/* Search and Filters */}
setSearchQuery(query)} showRecentSearches={false} />
{/* Rides Grid */} {filteredRides.length > 0 ? (
{filteredRides.map((ride) => ( ))}
) : (

No rides found

{rides.length === 0 ? `${park.name} doesn't have any rides yet.` : 'Try adjusting your search criteria or filters' }

{rides.length === 0 && user && ( )}
)} {/* Create Modal */} setIsCreateModalOpen(false)} isEditing={false} initialData={{ park_id: park.id }} />
); }