Files
thrilltrack-explorer/src/components/rides/RideModelCard.tsx
pac7 21bd962767 Improve ride model card to show unknown for missing category or type
Update RideModelCardProps to accept null or undefined for category and type, returning 'Unknown' if they are not provided.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 567218be-0199-4aaa-af7e-8307f67d4453
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
2025-10-08 18:32:24 +00:00

96 lines
3.2 KiB
TypeScript

import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { FerrisWheel } from 'lucide-react';
import { RideModel } from '@/types/database';
import { useNavigate } from 'react-router-dom';
interface RideModelCardProps {
model: RideModel;
manufacturerSlug: string;
}
export function RideModelCard({ model, manufacturerSlug }: RideModelCardProps) {
const navigate = useNavigate();
const formatCategory = (category: string | null | undefined) => {
if (!category) return 'Unknown';
return category.split('_').map(word =>
word.charAt(0).toUpperCase() + word.slice(1)
).join(' ');
};
const formatRideType = (type: string | null | undefined) => {
if (!type) return 'Unknown';
return type.split('_').map(word =>
word.charAt(0).toUpperCase() + word.slice(1)
).join(' ');
};
// Safely extract ride count and image data
const extendedModel = model as RideModel & {
ride_count?: number;
card_image_url?: string;
card_image_id?: string;
};
const rideCount = extendedModel.ride_count || 0;
const cardImageUrl = extendedModel.card_image_url;
const cardImageId = extendedModel.card_image_id;
return (
<Card className="overflow-hidden hover:shadow-lg transition-shadow cursor-pointer group">
<div
className="aspect-video bg-gradient-to-br from-primary/10 via-secondary/10 to-accent/10 relative overflow-hidden"
>
{(cardImageUrl || cardImageId) ? (
<img
src={cardImageUrl || `https://imagedelivery.net/${import.meta.env.VITE_CLOUDFLARE_ACCOUNT_HASH}/${cardImageId}/public`}
alt={model.name}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
) : (
<div className="flex items-center justify-center h-full">
<FerrisWheel className="w-16 h-16 text-muted-foreground/30" />
</div>
)}
</div>
<CardContent className="p-4 space-y-3">
<div>
<h3 className="font-semibold text-lg line-clamp-1 group-hover:text-primary transition-colors">
{model.name}
</h3>
{model.description && (
<p className="text-sm text-muted-foreground line-clamp-2 mt-1">
{model.description}
</p>
)}
</div>
<div className="flex flex-wrap gap-2">
<Badge variant="secondary" className="text-xs">
{formatCategory(model.category)}
</Badge>
<Badge variant="outline" className="text-xs">
{formatRideType(model.ride_type)}
</Badge>
</div>
<div className="pt-2 flex items-center justify-between">
<span className="text-sm text-muted-foreground">
{rideCount} {rideCount === 1 ? 'ride' : 'rides'}
</span>
<Button
variant="ghost"
size="sm"
onClick={() => navigate(`/manufacturers/${manufacturerSlug}/rides?model=${model.slug}`)}
>
View Rides
</Button>
</div>
</CardContent>
</Card>
);
}