mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 13:51:14 -05:00
feat: Enhance ride detail page with new sections
This commit is contained in:
102
src/components/rides/SimilarRides.tsx
Normal file
102
src/components/rides/SimilarRides.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
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 { Star } from 'lucide-react';
|
||||
|
||||
interface SimilarRidesProps {
|
||||
currentRideId: string;
|
||||
parkId: string;
|
||||
parkSlug: string;
|
||||
category: string;
|
||||
}
|
||||
|
||||
interface SimilarRide {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
image_url: string | null;
|
||||
average_rating: number;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export function SimilarRides({ currentRideId, parkId, parkSlug, category }: SimilarRidesProps) {
|
||||
const [rides, setRides] = useState<SimilarRide[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchSimilarRides() {
|
||||
const { data, error } = await supabase
|
||||
.from('rides')
|
||||
.select('id, name, slug, image_url, average_rating, status')
|
||||
.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) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Similar Rides You Might Enjoy</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{rides.map((ride) => (
|
||||
<Link
|
||||
key={ride.id}
|
||||
to={`/parks/${parkSlug}/rides/${ride.slug}`}
|
||||
className="group block"
|
||||
>
|
||||
<div className="border border-border rounded-lg overflow-hidden hover:shadow-lg transition-shadow">
|
||||
{ride.image_url ? (
|
||||
<div className="aspect-video overflow-hidden">
|
||||
<img
|
||||
src={ride.image_url}
|
||||
alt={ride.name}
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="aspect-video bg-accent flex items-center justify-center">
|
||||
<span className="text-muted-foreground">No image</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="p-3">
|
||||
<h4 className="font-medium mb-1 group-hover:text-primary transition-colors">
|
||||
{ride.name}
|
||||
</h4>
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<Star className="w-3 h-3 fill-yellow-400 text-yellow-400" />
|
||||
<span>{ride.average_rating.toFixed(1)}</span>
|
||||
<span className="text-muted-foreground">•</span>
|
||||
<span className="text-muted-foreground capitalize">{ride.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 text-center">
|
||||
<Button variant="outline" asChild>
|
||||
<Link to={`/parks/${parkSlug}/rides`}>View All Rides</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user