import { useState, useEffect, useCallback, lazy, Suspense } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { Header } from '@/components/layout/Header'; import { getBannerUrls } from '@/lib/cloudflareImageUtils'; import { trackPageView } from '@/lib/viewTracking'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Separator } from '@/components/ui/separator'; import { MapPin, Star, Clock, Phone, Globe, Calendar, ArrowLeft, Users, Zap, Camera, Castle, FerrisWheel, Waves, Tent, Plus } from 'lucide-react'; import { useAuth } from '@/hooks/useAuth'; import { ReviewsSection } from '@/components/reviews/ReviewsSection'; import { RideCard } from '@/components/rides/RideCard'; import { Park, Ride } from '@/types/database'; import { ParkLocationMap } from '@/components/maps/ParkLocationMap'; import { EntityPhotoGallery } from '@/components/upload/EntityPhotoGallery'; import { supabase } from '@/integrations/supabase/client'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { AdminFormSkeleton } from '@/components/loading/PageSkeletons'; import { toast } from '@/hooks/use-toast'; // Lazy load admin forms const RideForm = lazy(() => import('@/components/admin/RideForm').then(m => ({ default: m.RideForm }))); const ParkForm = lazy(() => import('@/components/admin/ParkForm').then(m => ({ default: m.ParkForm }))); import { getErrorMessage } from '@/lib/errorHandler'; import { useUserRole } from '@/hooks/useUserRole'; import { Edit } from 'lucide-react'; import { VersionIndicator } from '@/components/versioning/VersionIndicator'; import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs'; import { useAuthModal } from '@/hooks/useAuthModal'; import { useDocumentTitle } from '@/hooks/useDocumentTitle'; import { useOpenGraph } from '@/hooks/useOpenGraph'; export default function ParkDetail() { const { slug } = useParams<{ slug: 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 [isAddRideModalOpen, setIsAddRideModalOpen] = useState(false); const [isEditParkModalOpen, setIsEditParkModalOpen] = useState(false); const [photoCount, setPhotoCount] = useState(0); const [statsLoading, setStatsLoading] = useState(true); const { isModerator } = useUserRole(); // Update document title when park changes useDocumentTitle(park?.name || 'Park Details'); // Update Open Graph meta tags useOpenGraph({ title: park?.name || '', description: park?.description || (park ? `${park.name} - A theme park${park.location ? ` in ${park.location.city}, ${park.location.country}` : ''}` : ''), imageUrl: park?.banner_image_url, imageId: park?.banner_image_id, type: 'website', enabled: !!park }); const fetchPhotoCount = useCallback(async (parkId: string) => { try { const { count, error } = await supabase .from('photos') .select('id', { count: 'exact', head: true }) .eq('entity_type', 'park') .eq('entity_id', parkId); if (error) throw error; setPhotoCount(count || 0); } catch (error) { console.error('Error fetching photo count:', error); setPhotoCount(0); } finally { setStatsLoading(false); } }, []); const fetchParkData = useCallback(async () => { try { // Fetch park details const { data: parkData } = await supabase.from('parks').select(` *, location:locations(*), operator:companies!parks_operator_id_fkey(*), property_owner:companies!parks_property_owner_id_fkey(*) `).eq('slug', slug).maybeSingle(); if (parkData) { setPark(parkData); fetchPhotoCount(parkData.id); // Fetch park rides const { data: ridesData } = await supabase.from('rides').select(`*`).eq('park_id', parkData.id).order('name'); setRides(ridesData || []); } } catch (error) { console.error('Error fetching park data:', error); } finally { setLoading(false); } }, [slug, fetchPhotoCount]); useEffect(() => { if (slug) { fetchParkData(); } }, [slug, fetchParkData]); // Track page view when park is loaded useEffect(() => { if (park?.id) { trackPageView('park', park.id); } }, [park?.id]); const getStatusColor = (status: string) => { switch (status) { case 'operating': return 'bg-green-500/20 text-green-400 border-green-500/30'; case 'seasonal': return 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30'; case 'under_construction': return 'bg-blue-500/20 text-blue-400 border-blue-500/30'; default: return 'bg-red-500/20 text-red-400 border-red-500/30'; } }; const getParkTypeIcon = (type: string) => { switch (type) { case 'theme_park': return ; case 'amusement_park': return ; case 'water_park': return ; case 'family_entertainment': return ; default: return ; } }; const formatParkType = (type: string) => { return type.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); }; const handleRideSubmit = async (rideData: any) => { try { const { submitRideCreation } = await import('@/lib/entitySubmissionHelpers'); await submitRideCreation( { ...rideData, park_id: park?.id }, user.id ); toast({ title: "Submission Sent", description: "Your ride submission has been sent for moderation review.", }); setIsAddRideModalOpen(false); } catch (error) { const errorMsg = getErrorMessage(error); toast({ title: "Submission Failed", description: errorMsg, variant: "destructive" }); } }; const handleEditParkSubmit = async (parkData: any) => { if (!user || !park) return; try { // Everyone goes through submission queue const { submitParkUpdate } = await import('@/lib/entitySubmissionHelpers'); await submitParkUpdate(park.id, parkData, user.id); toast({ title: "Edit Submitted", description: isModerator() ? "Your edit has been submitted. You can approve it in the moderation queue." : "Your park edit has been submitted for review.", }); setIsEditParkModalOpen(false); } catch (error) { const errorMsg = getErrorMessage(error); toast({ title: "Error", description: errorMsg, variant: "destructive" }); } }; if (loading) { return
; } if (!park) { return

Park Not Found

The park you're looking for doesn't exist or has been removed.

; } return
{/* Back Button and Edit Button */}
{/* Hero Section */}
{(park.banner_image_url || park.banner_image_id) ? ( {park.name} ) : (
{getParkTypeIcon(park.park_type)}
)}
{/* Park Title Overlay */}
{park.status.replace('_', ' ').toUpperCase()} {formatParkType(park.park_type)}

{park.name}

{park.location &&
{park.location.city && `${park.location.city}, `}{park.location.country}
}
{park.average_rating > 0 &&
{park.average_rating.toFixed(1)}
{park.review_count} reviews
}
{/* Quick Stats */}
{/* Background decorative elements */}
{/* Total Rides */}
{park.ride_count}
Total Rides
{/* Roller Coasters */}
{park.coaster_count}
Roller Coasters
{/* Reviews */}
{park.review_count}
Reviews
{park.average_rating > 0 &&
{park.average_rating.toFixed(1)}
}
{/* Operating Status */}
{park.opening_date ? : }
{park.opening_date ? `Opened ${park.opening_date.split('-')[0]}` : 'Opening Soon'}
{/* Main Content */} Overview Rides {rides.length > 0 && `(${rides.length})`} Reviews {park.review_count > 0 && `(${park.review_count})`} Photos {!statsLoading && photoCount > 0 && `(${photoCount})`} History
{/* Description */} {park.description && About {park.name}

{park.description}

} {/* Featured Rides */} {rides.length > 0 && ( Featured Rides
{rides.slice(0, 4).map(ride => ( ))}
{rides.length > 4 && (
)}
)}
{/* Park Information */} Park Information {park.opening_date &&
Opened
{new Date(park.opening_date).getFullYear()}
} {park.operator &&
Operator
{park.operator.name}
} {park.website_url && } {park.phone &&
Phone
{park.phone}
}
Location
{park.location && (
{/* Full Address Display */}
Address:
{park.location.name &&
{park.location.name}
} {park.location.city &&
{park.location.city}
} {park.location.state_province &&
{park.location.state_province}
} {park.location.postal_code &&
{park.location.postal_code}
}
{park.location.country}
{/* Map Links */} {park.location?.latitude && park.location?.longitude && ( )}
)} {park.location?.latitude && park.location?.longitude && (
)}
{/* Header with Add Ride button */}

Rides at {park.name}

{/* Conditional rendering */} {rides.length === 0 ? (

No rides yet

Be the first to add a ride to this park

) : ( <>
{rides.map(ride => ( ))}
)}
{/* Add Ride Modal */} Add New Ride to {park.name} Submit a new ride for moderation. All submissions are reviewed before being published. }> setIsAddRideModalOpen(false)} /> {/* Edit Park Modal */} Edit Park Make changes to the park information. {isModerator() ? 'Changes will be applied immediately.' : 'Your changes will be submitted for review.'} }> setIsEditParkModalOpen(false)} initialData={{ id: park?.id, name: park?.name, slug: park?.slug, description: park?.description, park_type: park?.park_type, status: park?.status, opening_date: park?.opening_date, closing_date: park?.closing_date, website_url: park?.website_url, phone: park?.phone, email: park?.email, operator_id: park?.operator?.id, property_owner_id: park?.property_owner?.id, banner_image_url: park?.banner_image_url, card_image_url: park?.card_image_url }} isEditing={true} />
; }