diff --git a/src/App.tsx b/src/App.tsx
index 05077585..2549212d 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -11,6 +11,7 @@ import { Footer } from "@/components/layout/Footer";
import Index from "./pages/Index";
import Parks from "./pages/Parks";
import ParkDetail from "./pages/ParkDetail";
+import ParkRides from "./pages/ParkRides";
import RideDetail from "./pages/RideDetail";
import Rides from "./pages/Rides";
import Manufacturers from "./pages/Manufacturers";
@@ -72,9 +73,10 @@ function AppContent() {
} />
- } />
- } />
- } />
+ } />
+ } />
+ } />
+ } />
} />
} />
} />
diff --git a/src/pages/ParkRides.tsx b/src/pages/ParkRides.tsx
new file mode 100644
index 00000000..2588eaff
--- /dev/null
+++ b/src/pages/ParkRides.tsx
@@ -0,0 +1,343 @@
+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 { supabase } from '@/integrations/supabase/client';
+import { useAuth } from '@/hooks/useAuth';
+import { toast } from '@/hooks/use-toast';
+
+export default function ParkRides() {
+ const { parkSlug } = useParams<{ parkSlug: string }>();
+ const navigate = useNavigate();
+ const { user } = useAuth();
+ 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');
+ 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('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;
+
+ setRides(ridesData || []);
+ } catch (error) {
+ console.error('Error fetching park and rides:', error);
+ toast({
+ title: "Error",
+ description: "Failed to load park rides.",
+ variant: "destructive"
+ });
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleCreateSubmit = async (data: any) => {
+ try {
+ if (!user) {
+ navigate('/auth');
+ return;
+ }
+
+ // Pre-fill park_id in the submission
+ const submissionData = {
+ ...data,
+ park_id: park?.id,
+ };
+
+ const { submitRideCreation } = await import('@/lib/entitySubmissionHelpers');
+ await submitRideCreation(submissionData, user.id);
+
+ toast({
+ title: "Ride Submitted",
+ description: "Your ride submission has been sent for moderation review.",
+ });
+
+ setIsCreateModalOpen(false);
+ } catch (error: any) {
+ toast({
+ title: "Submission Failed",
+ description: error.message || "Failed to submit ride.",
+ variant: "destructive"
+ });
+ }
+ };
+
+ const filteredRides = rides.filter(ride =>
+ ride.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ ride.manufacturer?.name?.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+
+ 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 */}
+
+
navigate(`/parks/${park.slug}`)}
+ className="mb-4 -ml-2 gap-2"
+ >
+
+ Back to {park.name}
+
+
+
+
+
{park.name}
+
+
+ Rides & Attractions
+
+
+
+
+
+ {filteredRides.length} rides
+
+
+ {rides.filter(r => r.category === 'roller_coaster').length} coasters
+
+
+
+
+
{
+ if (!user) {
+ navigate('/auth');
+ } else {
+ setIsCreateModalOpen(true);
+ }
+ }}
+ className="gap-2"
+ >
+
+ Add Ride
+
+
+
+
+
+ {/* Search and Filters */}
+
+
+
+
setSearchQuery(query)}
+ showRecentSearches={false}
+ />
+
+
+
+
+
+
+
+
+ Name A-Z
+ Highest Rated
+ Fastest
+ Tallest
+ Most Reviews
+
+
+
+
+
+
+
+
+
+ {categories.map(category => (
+
+ {category.label}
+
+ ))}
+
+
+
+
+
+
+
+
+ {statusOptions.map(status => (
+
+ {status.label}
+
+ ))}
+
+
+
+
+
+
+ {/* 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 && (
+
setIsCreateModalOpen(true)} className="gap-2">
+
+ Add First Ride
+
+ )}
+
+ )}
+
+ {/* Create Modal */}
+
+
+ setIsCreateModalOpen(false)}
+ isEditing={false}
+ initialData={{ park_id: park.id }}
+ />
+
+
+
+
+ );
+}