import { useState, lazy, Suspense, useEffect } from 'react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'; import { CompanyPreviewCard } from '@/components/preview/CompanyPreviewCard'; 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 { formatLocationShort } from '@/lib/locationFormatter'; 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 { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { AdminFormSkeleton } from '@/components/loading/PageSkeletons'; import { toast } from '@/hooks/use-toast'; import { useParkDetail } from '@/hooks/parks/useParkDetail'; import { useParkRides } from '@/hooks/parks/useParkRides'; import { usePhotoCount } from '@/hooks/photos/usePhotoCount'; // 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 { SubmissionErrorBoundary } from '@/components/error/SubmissionErrorBoundary'; 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 [isAddRideModalOpen, setIsAddRideModalOpen] = useState(false); const [isEditParkModalOpen, setIsEditParkModalOpen] = useState(false); const { isModerator } = useUserRole(); // Fetch park data with caching const { data: park, isLoading: loading, error } = useParkDetail(slug); // Fetch rides with caching const { data: rides = [] } = useParkRides(park?.id, !!park?.id); // Fetch photo count with caching const { data: photoCount = 0, isLoading: statsLoading } = usePhotoCount('park', park?.id, !!park?.id); // 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}` : ''}` : undefined), imageUrl: park?.banner_image_url ?? undefined, imageId: park?.banner_image_id ?? undefined, type: 'website', enabled: !!park }); // 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 &&
{formatLocationShort(park.location)}
}
{(park.average_rating ?? 0) > 0 &&
{(park.average_rating ?? 0).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) > 0 &&
{(park.average_rating ?? 0).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) > 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:
{/* Street Address on its own line if it exists */} {park.location.street_address && (
{park.location.street_address}
)} {/* City, State Postal on same line */} {(park.location.city || park.location.state_province || park.location.postal_code) && (
{park.location.city} {park.location.city && park.location.state_province && ', '} {park.location.state_province} {park.location.postal_code && ` ${park.location.postal_code}`}
)} {/* Country on its own line */} {park.location.country && (
{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)} initialData={{ park_id: park.id }} /> {/* 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 ?? undefined, park_type: park?.park_type, status: park?.status, opening_date: park?.opening_date ?? undefined, opening_date_precision: (park?.opening_date_precision as 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate') ?? undefined, closing_date: park?.closing_date ?? undefined, closing_date_precision: (park?.closing_date_precision as 'exact' | 'month' | 'year' | 'decade' | 'century' | 'approximate') ?? undefined, location_id: park?.location?.id, location: park?.location ? { name: park.location.name || '', city: park.location.city || '', state_province: park.location.state_province || '', country: park.location.country || '', postal_code: park.location.postal_code || '', latitude: park.location.latitude || 0, longitude: park.location.longitude || 0, timezone: park.location.timezone || '', display_name: park.location.name || '', } : undefined, website_url: park?.website_url ?? undefined, phone: park?.phone ?? undefined, email: park?.email ?? undefined, operator_id: park?.operator?.id, property_owner_id: park?.property_owner?.id, banner_image_url: park?.banner_image_url ?? undefined, card_image_url: park?.card_image_url ?? undefined }} isEditing={true} />
; }