From 9073b239bae7fbe249a6351c44906fee1e84f9ac Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 23:06:08 +0000 Subject: [PATCH] feat: Implement Phase 3 plan --- src/components/homepage/FeaturedParks.tsx | 48 +-------------- src/components/lists/ListDisplay.tsx | 74 ++--------------------- src/components/rides/SimilarRides.tsx | 42 +------------ 3 files changed, 12 insertions(+), 152 deletions(-) diff --git a/src/components/homepage/FeaturedParks.tsx b/src/components/homepage/FeaturedParks.tsx index 750a729b..ca49cc8c 100644 --- a/src/components/homepage/FeaturedParks.tsx +++ b/src/components/homepage/FeaturedParks.tsx @@ -1,54 +1,12 @@ -import { useState, useEffect } from 'react'; import { Star, TrendingUp, Award, Castle, FerrisWheel, Waves, Tent } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Park } from '@/types/database'; -import { supabase } from '@/integrations/supabase/client'; -import { getErrorMessage } from '@/lib/errorHandler'; -import { logger } from '@/lib/logger'; +import { useFeaturedParks } from '@/hooks/homepage/useFeaturedParks'; export function FeaturedParks() { - const [topRatedParks, setTopRatedParks] = useState([]); - const [mostRidesParks, setMostRidesParks] = useState([]); - const [loading, setLoading] = useState(true); - - useEffect(() => { - fetchFeaturedParks(); - }, []); - - const fetchFeaturedParks = async () => { - try { - // Fetch top rated parks - const { data: topRated } = await supabase - .from('parks') - .select(` - *, - location:locations(*), - operator:companies!parks_operator_id_fkey(*) - `) - .order('average_rating', { ascending: false }) - .limit(3); - - // Fetch parks with most rides - const { data: mostRides } = await supabase - .from('parks') - .select(` - *, - location:locations(*), - operator:companies!parks_operator_id_fkey(*) - `) - .order('ride_count', { ascending: false }) - .limit(3); - - setTopRatedParks(topRated || []); - setMostRidesParks(mostRides || []); - } catch (error: unknown) { - logger.error('Failed to fetch featured parks', { error: getErrorMessage(error) }); - } finally { - setLoading(false); - } - }; + const { topRated, mostRides } = useFeaturedParks(); const FeaturedParkCard = ({ park, icon: Icon, label }: { park: Park; icon: any; label: string }) => ( @@ -105,7 +63,7 @@ export function FeaturedParks() { ); - if (loading) { + if (topRated.isLoading || mostRides.isLoading) { return (
diff --git a/src/components/lists/ListDisplay.tsx b/src/components/lists/ListDisplay.tsx index c77555a6..a0461189 100644 --- a/src/components/lists/ListDisplay.tsx +++ b/src/components/lists/ListDisplay.tsx @@ -1,78 +1,16 @@ -import { useState, useEffect } from "react"; -import { UserTopList, UserTopListItem, Park, Ride, Company } from "@/types/database"; -import { supabase } from "@/integrations/supabase/client"; +import { UserTopList, Park, Ride, Company } from "@/types/database"; import { Link } from "react-router-dom"; import { Badge } from "@/components/ui/badge"; +import { useListItems } from "@/hooks/lists/useListItems"; interface ListDisplayProps { list: UserTopList; } -interface EnrichedListItem extends UserTopListItem { - entity?: Park | Ride | Company; -} - export function ListDisplay({ list }: ListDisplayProps) { - const [items, setItems] = useState([]); - const [loading, setLoading] = useState(true); + const { data: items, isLoading } = useListItems(list.id); - useEffect(() => { - fetchItemsWithEntities(); - }, [list.id]); - - const fetchItemsWithEntities = async () => { - setLoading(true); - - // First, get the list items - const { data: itemsData, error: itemsError } = await supabase - .from("user_top_list_items") - .select("*") - .eq("list_id", list.id) - .order("position", { ascending: true }); - - if (itemsError) { - console.error("Error fetching items:", itemsError); - setLoading(false); - return; - } - - // Then, fetch the entities for each item - const enrichedItems = await Promise.all( - (itemsData as UserTopListItem[]).map(async (item) => { - let entity = null; - - if (item.entity_type === "park") { - const { data } = await supabase - .from("parks") - .select("id, name, slug, park_type, location_id") - .eq("id", item.entity_id) - .single(); - entity = data; - } else if (item.entity_type === "ride") { - const { data } = await supabase - .from("rides") - .select("id, name, slug, category, park_id") - .eq("id", item.entity_id) - .single(); - entity = data; - } else if (item.entity_type === "company") { - const { data } = await supabase - .from("companies") - .select("id, name, slug, company_type") - .eq("id", item.entity_id) - .single(); - entity = data; - } - - return { ...item, entity }; - }) - ); - - setItems(enrichedItems); - setLoading(false); - }; - - const getEntityUrl = (item: EnrichedListItem) => { + const getEntityUrl = (item: NonNullable[0]) => { if (!item.entity) return "#"; const entity = item.entity as { slug?: string }; @@ -89,11 +27,11 @@ export function ListDisplay({ list }: ListDisplayProps) { return "#"; }; - if (loading) { + if (isLoading) { return
Loading...
; } - if (items.length === 0) { + if (!items || items.length === 0) { return (
This list is empty. Click "Edit" to add items. diff --git a/src/components/rides/SimilarRides.tsx b/src/components/rides/SimilarRides.tsx index c5a92bf2..8be8c695 100644 --- a/src/components/rides/SimilarRides.tsx +++ b/src/components/rides/SimilarRides.tsx @@ -1,9 +1,8 @@ -import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; -import { supabase } from '@/integrations/supabase/client'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { RideCard } from '@/components/rides/RideCard'; +import { useSimilarRides } from '@/hooks/rides/useSimilarRides'; interface SimilarRidesProps { currentRideId: string; @@ -32,44 +31,9 @@ interface SimilarRide { } export function SimilarRides({ currentRideId, parkId, parkSlug, category }: SimilarRidesProps) { - const [rides, setRides] = useState([]); - const [loading, setLoading] = useState(true); + const { data: rides, isLoading } = useSimilarRides(currentRideId, parkId, category); - useEffect(() => { - async function fetchSimilarRides() { - const { data, error } = await supabase - .from('rides') - .select(` - id, - name, - slug, - image_url, - average_rating, - status, - category, - description, - max_speed_kmh, - max_height_meters, - duration_seconds, - review_count, - park:parks!inner(name, slug) - `) - .eq('park_id', parkId) - .eq('category', category) - .neq('id', currentRideId) - .order('average_rating', { ascending: false }) - .limit(4); - - if (!error && data) { - setRides(data); - } - setLoading(false); - } - - fetchSimilarRides(); - }, [currentRideId, parkId, category]); - - if (loading || rides.length === 0) { + if (isLoading || !rides || rides.length === 0) { return null; }