mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 09:51:12 -05:00
feat: Enhance ride detail page with new sections
This commit is contained in:
@@ -29,6 +29,12 @@ import {
|
||||
import { ReviewsSection } from '@/components/reviews/ReviewsSection';
|
||||
import { MeasurementDisplay } from '@/components/ui/measurement-display';
|
||||
import { RidePhotoGallery } from '@/components/rides/RidePhotoGallery';
|
||||
import { RatingDistribution } from '@/components/rides/RatingDistribution';
|
||||
import { RideHighlights } from '@/components/rides/RideHighlights';
|
||||
import { SimilarRides } from '@/components/rides/SimilarRides';
|
||||
import { FormerNames } from '@/components/rides/FormerNames';
|
||||
import { RecentPhotosPreview } from '@/components/rides/RecentPhotosPreview';
|
||||
import { ParkLocationMap } from '@/components/maps/ParkLocationMap';
|
||||
import { Ride } from '@/types/database';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
|
||||
@@ -37,6 +43,7 @@ export default function RideDetail() {
|
||||
const navigate = useNavigate();
|
||||
const [ride, setRide] = useState<Ride | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [activeTab, setActiveTab] = useState("overview");
|
||||
|
||||
useEffect(() => {
|
||||
if (parkSlug && rideSlug) {
|
||||
@@ -54,7 +61,7 @@ export default function RideDetail() {
|
||||
.maybeSingle();
|
||||
|
||||
if (parkData) {
|
||||
// Then get ride details
|
||||
// Then get ride details with park_id stored separately
|
||||
const { data: rideData } = await supabase
|
||||
.from('rides')
|
||||
.select(`
|
||||
@@ -67,6 +74,11 @@ export default function RideDetail() {
|
||||
.eq('slug', rideSlug)
|
||||
.maybeSingle();
|
||||
|
||||
if (rideData) {
|
||||
// Store park_id for easier access
|
||||
(rideData as any).currentParkId = parkData.id;
|
||||
}
|
||||
|
||||
setRide(rideData);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -193,14 +205,35 @@ export default function RideDetail() {
|
||||
</div>
|
||||
|
||||
{ride.average_rating > 0 && (
|
||||
<div className="bg-black/20 backdrop-blur-sm rounded-lg p-4 text-center">
|
||||
<div className="flex items-center gap-2 text-white mb-1">
|
||||
<Star className="w-5 h-5 fill-yellow-400 text-yellow-400" />
|
||||
<span className="text-2xl font-bold">{ride.average_rating.toFixed(1)}</span>
|
||||
<div className="bg-black/30 backdrop-blur-md rounded-lg p-6 text-center min-w-[160px]">
|
||||
<div className="flex items-center justify-center gap-2 text-white mb-2">
|
||||
<Star className="w-6 h-6 fill-yellow-400 text-yellow-400" />
|
||||
<span className="text-3xl font-bold">
|
||||
{ride.average_rating.toFixed(1)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-white/70 text-sm">
|
||||
{ride.review_count} reviews
|
||||
<div className="flex items-center justify-center gap-1 mb-3">
|
||||
{[1, 2, 3, 4, 5].map((star) => (
|
||||
<Star
|
||||
key={star}
|
||||
className={`w-4 h-4 ${
|
||||
star <= Math.round(ride.average_rating)
|
||||
? 'fill-yellow-400 text-yellow-400'
|
||||
: 'text-white/40'
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-white/90 text-sm mb-3">
|
||||
{ride.review_count} {ride.review_count === 1 ? "review" : "reviews"}
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
onClick={() => setActiveTab("reviews")}
|
||||
>
|
||||
Write Review
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -323,7 +356,7 @@ export default function RideDetail() {
|
||||
)}
|
||||
|
||||
{/* Main Content */}
|
||||
<Tabs defaultValue="overview" className="w-full">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-4">
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
<TabsTrigger value="specs">Specifications</TabsTrigger>
|
||||
@@ -347,9 +380,32 @@ export default function RideDetail() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<RideHighlights ride={ride} />
|
||||
|
||||
{ride.former_names && ride.former_names.length > 0 && (
|
||||
<FormerNames formerNames={ride.former_names} currentName={ride.name} />
|
||||
)}
|
||||
|
||||
<SimilarRides
|
||||
currentRideId={ride.id}
|
||||
parkId={(ride as any).currentParkId}
|
||||
parkSlug={parkSlug || ''}
|
||||
category={ride.category}
|
||||
/>
|
||||
|
||||
<RecentPhotosPreview
|
||||
rideId={ride.id}
|
||||
onViewAll={() => setActiveTab("photos")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<RatingDistribution
|
||||
rideId={ride.id}
|
||||
totalReviews={ride.review_count}
|
||||
averageRating={ride.average_rating}
|
||||
/>
|
||||
{/* Ride Information */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -457,6 +513,22 @@ export default function RideDetail() {
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{ride.park?.location?.latitude && ride.park?.location?.longitude && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Location</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ParkLocationMap
|
||||
latitude={ride.park.location.latitude}
|
||||
longitude={ride.park.location.longitude}
|
||||
parkName={ride.park.name}
|
||||
className="h-48"
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
Reference in New Issue
Block a user