import { useState, useEffect, useMemo } 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 { Card, CardContent } from '@/components/ui/card'; import { ArrowLeft, MapPin, Filter, FerrisWheel } from 'lucide-react'; import { Park, Company } from '@/types/database'; import { supabase } from '@/lib/supabaseClient'; import { ParkGridView } from '@/components/parks/ParkGridView'; import { ParkListView } from '@/components/parks/ParkListView'; import { ParkSearch } from '@/components/parks/ParkSearch'; import { ParkSortOptions } from '@/components/parks/ParkSortOptions'; import { ParkFilters } from '@/components/parks/ParkFilters'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Grid3X3, List } from 'lucide-react'; import { FilterState, SortState } from './Parks'; import { useDocumentTitle } from '@/hooks/useDocumentTitle'; import { useOpenGraph } from '@/hooks/useOpenGraph'; import { handleNonCriticalError } from '@/lib/errorHandler'; const initialFilters: FilterState = { search: '', parkType: [], status: [], country: [], minRating: 0, maxRating: 5, minRides: 0, maxRides: 1000, openingYearStart: null, openingYearEnd: null, }; const initialSort: SortState = { field: 'name', direction: 'asc' }; export default function OwnerParks() { const { ownerSlug } = useParams<{ ownerSlug: string }>(); const navigate = useNavigate(); const [owner, setOwner] = useState(null); const [parks, setParks] = useState([]); const [loading, setLoading] = useState(true); const [filters, setFilters] = useState(initialFilters); const [sort, setSort] = useState(initialSort); const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid'); const [showFilters, setShowFilters] = useState(false); // Update document title when owner changes useDocumentTitle(owner ? `${owner.name} - Parks` : 'Owner Parks'); useEffect(() => { if (ownerSlug) { fetchData(); } }, [ownerSlug]); const fetchData = async () => { try { // Fetch owner const { data: ownerData, error: ownerError} = await supabase .from('companies') .select('*') .eq('slug', ownerSlug || '') .eq('company_type', 'property_owner') .maybeSingle(); if (ownerError) throw ownerError; setOwner(ownerData); if (ownerData) { // Fetch parks owned by this property owner const { data: parksData, error: parksError } = await supabase .from('parks') .select(` *, location:locations(*), operator:companies!parks_operator_id_fkey(*), property_owner:companies!parks_property_owner_id_fkey(*) `) .eq('property_owner_id', ownerData.id) .order('name'); if (parksError) throw parksError; setParks(parksData || []); } } catch (error) { handleNonCriticalError(error, { action: 'Fetch Owner Parks Data', metadata: { ownerSlug } }); } finally { setLoading(false); } }; const filteredAndSortedParks = useMemo(() => { let filtered = parks.filter(park => { if (filters.search) { const searchTerm = filters.search.toLowerCase(); const matchesSearch = park.name.toLowerCase().includes(searchTerm) || park.description?.toLowerCase().includes(searchTerm) || park.location?.city?.toLowerCase().includes(searchTerm) || park.location?.country?.toLowerCase().includes(searchTerm); if (!matchesSearch) return false; } if (filters.parkType.length > 0 && !filters.parkType.includes(park.park_type)) return false; if (filters.status.length > 0 && !filters.status.includes(park.status)) return false; if (filters.country.length > 0 && !filters.country.includes(park.location?.country || '')) return false; const rating = park.average_rating || 0; if (rating < filters.minRating || rating > filters.maxRating) return false; const rideCount = park.ride_count || 0; if (rideCount < filters.minRides || rideCount > filters.maxRides) return false; return true; }); filtered.sort((a, b) => { let aValue: any, bValue: any; switch (sort.field) { case 'name': aValue = a.name; bValue = b.name; break; case 'rating': aValue = a.average_rating || 0; bValue = b.average_rating || 0; break; case 'rides': aValue = a.ride_count || 0; bValue = b.ride_count || 0; break; default: aValue = a.name; bValue = b.name; } if (typeof aValue === 'string' && typeof bValue === 'string') { return sort.direction === 'asc' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); } return sort.direction === 'asc' ? aValue - bValue : bValue - aValue; }); return filtered; }, [parks, filters, sort]); useOpenGraph({ title: owner ? `Parks by ${owner.name} - ThrillWiki` : 'Owner Parks', description: owner ? `Explore ${filteredAndSortedParks.length} theme parks owned by ${owner.name}` : undefined, imageUrl: owner?.banner_image_url ?? filteredAndSortedParks[0]?.banner_image_url ?? undefined, imageId: owner?.banner_image_id ?? filteredAndSortedParks[0]?.banner_image_id ?? undefined, type: 'website', enabled: !!owner && !loading }); if (loading) { return (
{[...Array(8)].map((_, i) => (
))}
); } if (!owner) { return (

Property Owner Not Found

); } return (

Parks Owned by {owner.name}

Explore all theme parks owned by {owner.name}

{filteredAndSortedParks.length} parks
setFilters(prev => ({ ...prev, search }))} />
setViewMode(v as 'grid' | 'list')} className="hidden md:inline-flex">
{showFilters && ( )}
{filteredAndSortedParks.length > 0 ? ( viewMode === 'grid' ? ( ) : ( navigate(`/parks/${park.slug}`)} /> ) ) : (

No parks found

{owner.name} doesn't own any parks matching your criteria

)}
); }