diff --git a/src/pages/ParkOwners.tsx b/src/pages/ParkOwners.tsx index e62d6e0f..8e4a2b63 100644 --- a/src/pages/ParkOwners.tsx +++ b/src/pages/ParkOwners.tsx @@ -47,7 +47,7 @@ const ParkOwners = () => { .from('parks') .select('property_owner_id') .not('property_owner_id', 'is', null) - .then(({ data }) => data?.map(park => park.property_owner_id) || []) + .then(({ data }) => data?.map(park => park.property_owner_id).filter((id): id is string => id !== null) || []) ) .order('name'); @@ -68,7 +68,7 @@ const ParkOwners = () => { await submitCompanyCreation( data, 'property_owner', - user.id + user!.id ); toast({ @@ -95,7 +95,7 @@ const ParkOwners = () => { (owner.description && owner.description.toLowerCase().includes(searchTerm.toLowerCase())); if (filterBy === 'all') return matchesSearch; - if (filterBy === 'with-rating') return matchesSearch && owner.average_rating > 0; + if (filterBy === 'with-rating') return matchesSearch && (owner.average_rating ?? 0) > 0; if (filterBy === 'established') return matchesSearch && owner.founded_year; return matchesSearch; @@ -123,8 +123,8 @@ const ParkOwners = () => { useOpenGraph({ title: 'Property Owners - ThrillWiki', description: `Browse ${filteredAndSortedOwners.length} theme park property owners worldwide`, - imageUrl: filteredAndSortedOwners[0]?.banner_image_url, - imageId: filteredAndSortedOwners[0]?.banner_image_id, + imageUrl: filteredAndSortedOwners[0]?.banner_image_url ?? undefined, + imageId: filteredAndSortedOwners[0]?.banner_image_id ?? undefined, type: 'website', enabled: !isLoading }); diff --git a/src/pages/ParkRides.tsx b/src/pages/ParkRides.tsx index 792d559a..f64002d5 100644 --- a/src/pages/ParkRides.tsx +++ b/src/pages/ParkRides.tsx @@ -50,7 +50,7 @@ export default function ParkRides() { const { data: parkData, error: parkError } = await supabase .from('parks') .select('*') - .eq('slug', parkSlug) + .eq('slug', parkSlug || '') .maybeSingle(); if (parkError) throw parkError; @@ -121,14 +121,24 @@ export default function ParkRides() { const handleCreateSubmit = async (data: Omit & { park_id?: string }) => { try { - // Pre-fill park_id in the submission + 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, - park_id: park.id, - }; + ...data, + description: data.description ?? undefined, + park_id: park.id, + }; const { submitRideCreation } = await import('@/lib/entitySubmissionHelpers'); - await submitRideCreation(submissionData, user.id); + await submitRideCreation(submissionData as any, user!.id); toast({ title: "Ride Submitted", @@ -156,8 +166,8 @@ export default function ParkRides() { description: park ? `Explore ${filteredRides.length} rides and attractions at ${park.name}` : undefined, - imageUrl: park?.banner_image_url || filteredRides[0]?.banner_image_url, - imageId: park?.banner_image_id || filteredRides[0]?.banner_image_id, + 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 }); @@ -340,7 +350,7 @@ export default function ParkRides() { setIsCreateModalOpen(false)} isEditing={false} initialData={{ park_id: park.id }} diff --git a/src/pages/Parks.tsx b/src/pages/Parks.tsx index 8c3c9484..99e8fedc 100644 --- a/src/pages/Parks.tsx +++ b/src/pages/Parks.tsx @@ -276,10 +276,10 @@ export default function Parks() { const generateDescription = () => { if (!parks.length) return "Browse theme parks worldwide on ThrillWiki"; - const activeFilters = []; - if (filters.country.length === 1) activeFilters.push(`in ${filters.country[0]}`); - if (filters.parkType.length > 0) activeFilters.push(filters.parkType.join(", ")); - if (filters.status.length > 0) activeFilters.push(filters.status.join(", ")); + const activeFilters: string[] = []; + if (filters.country.length === 1) activeFilters.push(`in ${filters.country[0]!}`); + if (filters.parkType.length > 0) activeFilters.push(...filters.parkType); + if (filters.status.length > 0) activeFilters.push(...filters.status); if (activeFilters.length > 0) { return `Browse ${filteredAndSortedParks.length} ${activeFilters.join(" ")} theme parks`; @@ -291,8 +291,8 @@ export default function Parks() { useOpenGraph({ title: "Theme Parks - ThrillWiki", description: generateDescription(), - imageUrl: filteredAndSortedParks[0]?.banner_image_url, - imageId: filteredAndSortedParks[0]?.banner_image_id, + imageUrl: filteredAndSortedParks[0]?.banner_image_url ?? undefined, + imageId: filteredAndSortedParks[0]?.banner_image_id ?? undefined, type: "website", }); @@ -335,7 +335,7 @@ export default function Parks() { const handleParkSubmit = async (parkData: any) => { try { const { submitParkCreation } = await import("@/lib/entitySubmissionHelpers"); - await submitParkCreation(parkData, user.id); + await submitParkCreation(parkData, user!.id); toast({ title: "Park Submitted", diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index 118d7495..e13e1b70 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -411,7 +411,7 @@ export default function Profile() { if (data) { // Fetch location separately if location_id is visible - let locationData = null; + let locationData: any = null; if (data.location_id) { const { data: location } = await supabase .from('locations') @@ -426,7 +426,7 @@ export default function Profile() { location: locationData }; - setProfile(profileWithLocation as ProfileType); + setProfile(profileWithLocation as unknown as ProfileType); setEditForm({ username: data.username || '', display_name: data.display_name || '', @@ -436,8 +436,8 @@ export default function Profile() { setAvatarImageId(data.avatar_image_id || ''); // Fetch calculated stats and recent activity for this user - await fetchCalculatedStats(data.user_id); - await fetchRecentActivity(data.user_id); + await fetchCalculatedStats(data.user_id || ''); + await fetchRecentActivity(data.user_id || ''); } } catch (error) { console.error('Error fetching profile:', error); @@ -772,7 +772,10 @@ export default function Profile() { {/* Show location (privacy already enforced by get_filtered_profile) */} } diff --git a/src/pages/PropertyOwnerDetail.tsx b/src/pages/PropertyOwnerDetail.tsx index e5994716..1a191e46 100644 --- a/src/pages/PropertyOwnerDetail.tsx +++ b/src/pages/PropertyOwnerDetail.tsx @@ -51,8 +51,8 @@ export default function PropertyOwnerDetail() { useOpenGraph({ title: owner?.name || '', description: owner?.description || (owner ? `${owner.name} - Property Owner${owner.headquarters_location ? ` based in ${owner.headquarters_location}` : ''}` : ''), - imageUrl: owner?.banner_image_url, - imageId: owner?.banner_image_id, + imageUrl: owner?.banner_image_url ?? undefined, + imageId: owner?.banner_image_id ?? undefined, type: 'profile', enabled: !!owner }); @@ -75,7 +75,7 @@ export default function PropertyOwnerDetail() { const { data, error } = await supabase .from('companies') .select('*') - .eq('slug', slug) + .eq('slug', slug || '') .eq('company_type', 'property_owner') .maybeSingle(); @@ -242,10 +242,10 @@ export default function PropertyOwnerDetail() { {owner.name} - {owner.average_rating > 0 && ( + {(owner.average_rating ?? 0) > 0 && (
- - {owner.average_rating.toFixed(1)} - + + {(owner.average_rating ?? 0).toFixed(1)} +
{owner.review_count} {owner.review_count === 1 ? "review" : "reviews"} @@ -447,14 +447,14 @@ export default function PropertyOwnerDetail() { id: owner.id, name: owner.name, slug: owner.slug, - description: owner.description, + description: owner.description ?? undefined, company_type: 'property_owner', person_type: (owner.person_type || 'company') as 'company' | 'individual' | 'firm' | 'organization', - website_url: owner.website_url, - founded_year: owner.founded_year, - headquarters_location: owner.headquarters_location, - banner_image_url: owner.banner_image_url, - card_image_url: owner.card_image_url + website_url: owner.website_url ?? undefined, + founded_year: owner.founded_year ?? undefined, + headquarters_location: owner.headquarters_location ?? undefined, + banner_image_url: owner.banner_image_url ?? undefined, + card_image_url: owner.card_image_url ?? undefined }} onSubmit={handleEditSubmit} onCancel={() => setIsEditModalOpen(false)} diff --git a/src/pages/RideDetail.tsx b/src/pages/RideDetail.tsx index 9bf601d9..08c58751 100644 --- a/src/pages/RideDetail.tsx +++ b/src/pages/RideDetail.tsx @@ -90,8 +90,8 @@ export default function RideDetail() { useOpenGraph({ title: ride?.name ? `${ride.name}${ride.park?.name ? ` at ${ride.park.name}` : ''}` : '', description: ride?.description || (ride ? `${ride.name} - A thrilling ride${ride.park?.name ? ` at ${ride.park.name}` : ''}` : ''), - imageUrl: ride?.banner_image_url, - imageId: ride?.banner_image_id, + imageUrl: ride?.banner_image_url ?? undefined, + imageId: ride?.banner_image_id ?? undefined, type: 'website', enabled: !!ride }); @@ -140,7 +140,7 @@ export default function RideDetail() { toast({ title: "Edit Submitted", - description: isModerator + description: isModerator() ? "Your edit has been submitted. You can approve it in the moderation queue." : "Your ride edit has been submitted for review." }); @@ -222,10 +222,10 @@ export default function RideDetail() { {ride.name}
- {ride.average_rating > 0 && ( + {(ride.average_rating ?? 0) > 0 && (
- {ride.average_rating.toFixed(1)} + {(ride.average_rating ?? 0).toFixed(1)}
@@ -393,7 +393,7 @@ export default function RideDetail() { Overview Specifications - Reviews {ride.review_count > 0 && `(${ride.review_count})`} + Reviews {(ride.review_count ?? 0) > 0 && `(${ride.review_count})`} Photos {!statsLoading && photoCount > 0 && `(${photoCount})`} @@ -424,7 +424,7 @@ export default function RideDetail() { @@ -438,8 +438,8 @@ export default function RideDetail() {
{/* Ride Information */} @@ -650,9 +650,9 @@ export default function RideDetail() { {/* Coaster Materials & Propulsion */} {ride.category === 'roller_coaster' && ( - ride.track_material?.length > 0 || - ride.support_material?.length > 0 || - ride.propulsion_method?.length > 0 + (ride.track_material?.length ?? 0) > 0 || + (ride.support_material?.length ?? 0) > 0 || + (ride.propulsion_method?.length ?? 0) > 0 ) && ( @@ -994,8 +994,8 @@ export default function RideDetail() { entityType="ride" entityId={ride.id} entityName={ride.name} - averageRating={ride.average_rating} - reviewCount={ride.review_count} + averageRating={ride.average_rating ?? 0} + reviewCount={ride.review_count ?? 0} /> @@ -1025,7 +1025,7 @@ export default function RideDetail() { Edit Ride - {isModerator + {isModerator() ? "Make changes to this ride. Changes will be applied immediately." : "Submit changes to this ride for review. A moderator will review your submission."} @@ -1037,68 +1037,68 @@ export default function RideDetail() { id: ride.id, name: ride.name, slug: ride.slug, - description: ride.description, + description: ride.description ?? undefined, category: ride.category, - ride_sub_type: ride.ride_sub_type, + ride_sub_type: ride.ride_sub_type ?? undefined, status: ride.status as "operating" | "closed_permanently" | "closed_temporarily" | "under_construction" | "relocated" | "stored" | "demolished", - opening_date: ride.opening_date, - closing_date: ride.closing_date, - height_requirement: ride.height_requirement, - age_requirement: ride.age_requirement, - capacity_per_hour: ride.capacity_per_hour, - duration_seconds: ride.duration_seconds, - max_speed_kmh: ride.max_speed_kmh, - max_height_meters: ride.max_height_meters, - length_meters: ride.length_meters, - inversions: ride.inversions, + opening_date: ride.opening_date ?? undefined, + closing_date: ride.closing_date ?? undefined, + height_requirement: ride.height_requirement ?? undefined, + age_requirement: ride.age_requirement ?? undefined, + capacity_per_hour: ride.capacity_per_hour ?? undefined, + duration_seconds: ride.duration_seconds ?? undefined, + max_speed_kmh: ride.max_speed_kmh ?? undefined, + max_height_meters: ride.max_height_meters ?? undefined, + length_meters: ride.length_meters ?? undefined, + inversions: ride.inversions ?? undefined, // Coaster fields - coaster_type: ride.coaster_type, - seating_type: ride.seating_type, - intensity_level: ride.intensity_level, + coaster_type: ride.coaster_type ?? undefined, + seating_type: ride.seating_type ?? undefined, + intensity_level: ride.intensity_level ?? undefined, track_material: ride.track_material, support_material: ride.support_material, propulsion_method: ride.propulsion_method, - drop_height_meters: ride.drop_height_meters, - max_g_force: ride.max_g_force, + drop_height_meters: ride.drop_height_meters ?? undefined, + max_g_force: ride.max_g_force ?? undefined, // Water ride fields - water_depth_cm: ride.water_depth_cm, - splash_height_meters: ride.splash_height_meters, + water_depth_cm: ride.water_depth_cm ?? undefined, + splash_height_meters: ride.splash_height_meters ?? undefined, wetness_level: ride.wetness_level as any, - flume_type: ride.flume_type, - boat_capacity: ride.boat_capacity, + flume_type: ride.flume_type ?? undefined, + boat_capacity: ride.boat_capacity ?? undefined, // Dark ride fields - theme_name: ride.theme_name, - story_description: ride.story_description, - show_duration_seconds: ride.show_duration_seconds, - animatronics_count: ride.animatronics_count, - projection_type: ride.projection_type, - ride_system: ride.ride_system, - scenes_count: ride.scenes_count, + theme_name: ride.theme_name ?? undefined, + story_description: ride.story_description ?? undefined, + show_duration_seconds: ride.show_duration_seconds ?? undefined, + animatronics_count: ride.animatronics_count ?? undefined, + projection_type: ride.projection_type ?? undefined, + ride_system: ride.ride_system ?? undefined, + scenes_count: ride.scenes_count ?? undefined, // Flat ride fields rotation_type: ride.rotation_type as any, - motion_pattern: ride.motion_pattern, - platform_count: ride.platform_count, - swing_angle_degrees: ride.swing_angle_degrees, - rotation_speed_rpm: ride.rotation_speed_rpm, - arm_length_meters: ride.arm_length_meters, - max_height_reached_meters: ride.max_height_reached_meters, + motion_pattern: ride.motion_pattern ?? undefined, + platform_count: ride.platform_count ?? undefined, + swing_angle_degrees: ride.swing_angle_degrees ?? undefined, + rotation_speed_rpm: ride.rotation_speed_rpm ?? undefined, + arm_length_meters: ride.arm_length_meters ?? undefined, + max_height_reached_meters: ride.max_height_reached_meters ?? undefined, // Kiddie ride fields - min_age: ride.min_age, - max_age: ride.max_age, - educational_theme: ride.educational_theme, - character_theme: ride.character_theme, + min_age: ride.min_age ?? undefined, + max_age: ride.max_age ?? undefined, + educational_theme: ride.educational_theme ?? undefined, + character_theme: ride.character_theme ?? undefined, // Transportation fields transport_type: ride.transport_type as any, - route_length_meters: ride.route_length_meters, - stations_count: ride.stations_count, - vehicle_capacity: ride.vehicle_capacity, - vehicles_count: ride.vehicles_count, - round_trip_duration_seconds: ride.round_trip_duration_seconds, + route_length_meters: ride.route_length_meters ?? undefined, + stations_count: ride.stations_count ?? undefined, + vehicle_capacity: ride.vehicle_capacity ?? undefined, + vehicles_count: ride.vehicles_count ?? undefined, + round_trip_duration_seconds: ride.round_trip_duration_seconds ?? undefined, // Common fields manufacturer_id: ride.manufacturer?.id, ride_model_id: ride.ride_model?.id, - banner_image_url: ride.banner_image_url, - card_image_url: ride.card_image_url + banner_image_url: ride.banner_image_url ?? undefined, + card_image_url: ride.card_image_url ?? undefined }} onSubmit={handleEditSubmit} onCancel={() => setIsEditModalOpen(false)} diff --git a/src/pages/RideModelDetail.tsx b/src/pages/RideModelDetail.tsx index fb685389..bb99c549 100644 --- a/src/pages/RideModelDetail.tsx +++ b/src/pages/RideModelDetail.tsx @@ -59,7 +59,7 @@ export default function RideModelDetail() { const { data: manufacturerData, error: manufacturerError } = await supabase .from('companies') .select('*') - .eq('slug', manufacturerSlug) + .eq('slug', manufacturerSlug || '') .eq('company_type', 'manufacturer') .maybeSingle(); @@ -71,7 +71,7 @@ export default function RideModelDetail() { const { data: modelData, error: modelError } = await supabase .from('ride_models') .select('*') - .eq('slug', modelSlug) + .eq('slug', modelSlug || '') .eq('manufacturer_id', manufacturerData.id) .maybeSingle(); diff --git a/src/pages/RideModelRides.tsx b/src/pages/RideModelRides.tsx index eea2c954..19f36d23 100644 --- a/src/pages/RideModelRides.tsx +++ b/src/pages/RideModelRides.tsx @@ -44,7 +44,7 @@ export default function RideModelRides() { const { data: manufacturerData, error: mfgError } = await supabase .from("companies") .select("*") - .eq("slug", manufacturerSlug) + .eq("slug", manufacturerSlug || '') .eq("company_type", "manufacturer") .maybeSingle(); @@ -58,7 +58,7 @@ export default function RideModelRides() { const { data: modelData, error: modelError } = await supabase .from("ride_models") .select("*") - .eq("slug", modelSlug) + .eq("slug", modelSlug || '') .eq("manufacturer_id", manufacturerData.id) .maybeSingle(); diff --git a/src/pages/Rides.tsx b/src/pages/Rides.tsx index f77c8928..5027a81a 100644 --- a/src/pages/Rides.tsx +++ b/src/pages/Rides.tsx @@ -66,7 +66,7 @@ export default function Rides() { const handleCreateSubmit = async (data: any) => { try { const { submitRideCreation } = await import('@/lib/entitySubmissionHelpers'); - await submitRideCreation(data, user.id); + await submitRideCreation(data, user!.id); toast({ title: "Ride Submitted", @@ -294,8 +294,8 @@ export default function Rides() { const generateDescription = () => { if (!filteredAndSortedRides.length) return 'Discover thrilling rides and roller coasters worldwide'; - const activeFilters = []; - if (filters.categories.length > 0) activeFilters.push(filters.categories.join(', ')); + const activeFilters: string[] = []; + if (filters.categories.length > 0) activeFilters.push(...filters.categories); if (filters.status !== 'all') activeFilters.push(filters.status); if (activeFilters.length > 0) { @@ -308,8 +308,8 @@ export default function Rides() { useOpenGraph({ title: 'Rides & Attractions - ThrillWiki', description: generateDescription(), - imageUrl: filteredAndSortedRides[0]?.banner_image_url, - imageId: filteredAndSortedRides[0]?.banner_image_id, + imageUrl: filteredAndSortedRides[0]?.banner_image_url ?? undefined, + imageId: filteredAndSortedRides[0]?.banner_image_id ?? undefined, type: 'website', enabled: !loading }); @@ -458,7 +458,7 @@ export default function Rides() { - + @@ -485,7 +485,7 @@ export default function Rides() { - +
@@ -499,11 +499,11 @@ export default function Rides() { {viewMode === 'grid' ? (
{paginatedRides.map((ride) => ( - + ))}
) : ( - navigate(`/parks/${ride.park?.slug}/rides/${ride.slug}`)} /> + navigate(`/parks/${ride.park?.slug}/rides/${ride.slug}`)} /> )}