feat: Implement bot detection plan

This commit is contained in:
gpt-engineer-app[bot]
2025-10-30 13:05:32 +00:00
parent 8fd8d2e843
commit 8540d227b2
2 changed files with 418 additions and 2 deletions

View File

@@ -29,7 +29,11 @@ import {
Waves,
Theater,
Train,
Edit
Edit,
Wrench,
Sparkles,
Repeat,
Baby
} from 'lucide-react';
import { ReviewsSection } from '@/components/reviews/ReviewsSection';
import { MeasurementDisplay } from '@/components/ui/measurement-display';
@@ -703,6 +707,345 @@ export default function RideDetail() {
</div>
</CardContent>
</Card>
{/* Coaster Materials & Propulsion */}
{ride.category === 'roller_coaster' && (
ride.track_material?.length > 0 ||
ride.support_material?.length > 0 ||
ride.propulsion_method?.length > 0
) && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Wrench className="w-5 h-5" />
Coaster Construction
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{ride.track_material && ride.track_material.length > 0 && (
<div>
<div className="text-sm font-medium mb-2">Track Material</div>
<div className="flex flex-wrap gap-2">
{ride.track_material.map(material => (
<Badge key={material} variant="outline">
{material.replace('_', ' ').toUpperCase()}
</Badge>
))}
</div>
</div>
)}
{ride.support_material && ride.support_material.length > 0 && (
<div>
<div className="text-sm font-medium mb-2">Support Material</div>
<div className="flex flex-wrap gap-2">
{ride.support_material.map(material => (
<Badge key={material} variant="outline">
{material.replace('_', ' ').toUpperCase()}
</Badge>
))}
</div>
</div>
)}
{ride.propulsion_method && ride.propulsion_method.length > 0 && (
<div>
<div className="text-sm font-medium mb-2">Propulsion Method</div>
<div className="flex flex-wrap gap-2">
{ride.propulsion_method.map(method => (
<Badge key={method} variant="outline">
{method.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</Badge>
))}
</div>
</div>
)}
</CardContent>
</Card>
)}
{/* Water Ride Details */}
{ride.category === 'water_ride' && (
ride.water_depth_cm || ride.splash_height_meters || ride.wetness_level ||
ride.flume_type || ride.boat_capacity
) && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Waves className="w-5 h-5" />
Water Ride Details
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{ride.water_depth_cm && (
<div className="flex justify-between">
<span>Water Depth</span>
<span className="font-medium">
<MeasurementDisplay value={ride.water_depth_cm} type="height" />
</span>
</div>
)}
{ride.splash_height_meters && (
<div className="flex justify-between">
<span>Splash Height</span>
<span className="font-medium">
<MeasurementDisplay value={ride.splash_height_meters} type="distance" />
</span>
</div>
)}
{ride.wetness_level && (
<div className="flex justify-between">
<span>Wetness Level</span>
<Badge variant="outline">
{ride.wetness_level.charAt(0).toUpperCase() + ride.wetness_level.slice(1)}
</Badge>
</div>
)}
{ride.flume_type && (
<div className="flex justify-between">
<span>Flume Type</span>
<span className="font-medium">
{ride.flume_type.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</span>
</div>
)}
{ride.boat_capacity && (
<div className="flex justify-between">
<span>Boat Capacity</span>
<span className="font-medium">{ride.boat_capacity} riders</span>
</div>
)}
</CardContent>
</Card>
)}
{/* Dark Ride Details */}
{ride.category === 'dark_ride' && (
ride.theme_name || ride.story_description || ride.show_duration_seconds ||
ride.animatronics_count || ride.projection_type || ride.ride_system || ride.scenes_count
) && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Sparkles className="w-5 h-5" />
Dark Ride Details
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{ride.theme_name && (
<div className="flex justify-between">
<span>Theme</span>
<span className="font-medium">{ride.theme_name}</span>
</div>
)}
{ride.story_description && (
<div>
<div className="text-sm font-medium mb-1">Story</div>
<p className="text-sm text-muted-foreground">{ride.story_description}</p>
</div>
)}
{ride.show_duration_seconds && (
<div className="flex justify-between">
<span>Show Duration</span>
<span className="font-medium">
{Math.floor(ride.show_duration_seconds / 60)}:{(ride.show_duration_seconds % 60).toString().padStart(2, '0')}
</span>
</div>
)}
{ride.animatronics_count && (
<div className="flex justify-between">
<span>Animatronics</span>
<span className="font-medium">{ride.animatronics_count}</span>
</div>
)}
{ride.scenes_count && (
<div className="flex justify-between">
<span>Scenes</span>
<span className="font-medium">{ride.scenes_count}</span>
</div>
)}
{ride.projection_type && (
<div className="flex justify-between">
<span>Projection Type</span>
<span className="font-medium">
{ride.projection_type.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</span>
</div>
)}
{ride.ride_system && (
<div className="flex justify-between">
<span>Ride System</span>
<span className="font-medium">
{ride.ride_system.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</span>
</div>
)}
</CardContent>
</Card>
)}
{/* Flat Ride Details */}
{ride.category === 'flat_ride' && (
ride.rotation_type || ride.motion_pattern || ride.platform_count ||
ride.swing_angle_degrees || ride.rotation_speed_rpm || ride.arm_length_meters ||
ride.max_height_reached_meters
) && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Repeat className="w-5 h-5" />
Flat Ride Details
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{ride.rotation_type && (
<div className="flex justify-between">
<span>Rotation Type</span>
<span className="font-medium">
{ride.rotation_type.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</span>
</div>
)}
{ride.motion_pattern && (
<div className="flex justify-between">
<span>Motion Pattern</span>
<span className="font-medium">
{ride.motion_pattern.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</span>
</div>
)}
{ride.platform_count && (
<div className="flex justify-between">
<span>Platforms</span>
<span className="font-medium">{ride.platform_count}</span>
</div>
)}
{ride.swing_angle_degrees && (
<div className="flex justify-between">
<span>Swing Angle</span>
<span className="font-medium">{ride.swing_angle_degrees}°</span>
</div>
)}
{ride.rotation_speed_rpm && (
<div className="flex justify-between">
<span>Rotation Speed</span>
<span className="font-medium">{ride.rotation_speed_rpm} RPM</span>
</div>
)}
{ride.arm_length_meters && (
<div className="flex justify-between">
<span>Arm Length</span>
<span className="font-medium">
<MeasurementDisplay value={ride.arm_length_meters} type="distance" />
</span>
</div>
)}
{ride.max_height_reached_meters && (
<div className="flex justify-between">
<span>Max Height Reached</span>
<span className="font-medium">
<MeasurementDisplay value={ride.max_height_reached_meters} type="distance" />
</span>
</div>
)}
</CardContent>
</Card>
)}
{/* Kiddie Ride Details */}
{ride.category === 'kiddie_ride' && (
ride.min_age || ride.max_age || ride.educational_theme || ride.character_theme
) && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Baby className="w-5 h-5" />
Kiddie Ride Details
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{(ride.min_age || ride.max_age) && (
<div className="flex justify-between">
<span>Age Range</span>
<span className="font-medium">
{ride.min_age && ride.max_age ? `${ride.min_age}-${ride.max_age} years` :
ride.min_age ? `${ride.min_age}+ years` :
ride.max_age ? `Up to ${ride.max_age} years` : 'N/A'}
</span>
</div>
)}
{ride.educational_theme && (
<div className="flex justify-between">
<span>Educational Theme</span>
<span className="font-medium">{ride.educational_theme}</span>
</div>
)}
{ride.character_theme && (
<div className="flex justify-between">
<span>Character Theme</span>
<span className="font-medium">{ride.character_theme}</span>
</div>
)}
</CardContent>
</Card>
)}
{/* Transportation Details */}
{ride.category === 'transportation' && (
ride.transport_type || ride.route_length_meters || ride.stations_count ||
ride.vehicle_capacity || ride.vehicles_count || ride.round_trip_duration_seconds
) && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Train className="w-5 h-5" />
Transportation Details
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{ride.transport_type && (
<div className="flex justify-between">
<span>Transport Type</span>
<span className="font-medium">
{ride.transport_type.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())}
</span>
</div>
)}
{ride.route_length_meters && (
<div className="flex justify-between">
<span>Route Length</span>
<span className="font-medium">
<MeasurementDisplay value={ride.route_length_meters} type="distance" />
</span>
</div>
)}
{ride.stations_count && (
<div className="flex justify-between">
<span>Stations</span>
<span className="font-medium">{ride.stations_count}</span>
</div>
)}
{ride.vehicle_capacity && (
<div className="flex justify-between">
<span>Vehicle Capacity</span>
<span className="font-medium">{ride.vehicle_capacity} passengers</span>
</div>
)}
{ride.vehicles_count && (
<div className="flex justify-between">
<span>Number of Vehicles</span>
<span className="font-medium">{ride.vehicles_count}</span>
</div>
)}
{ride.round_trip_duration_seconds && (
<div className="flex justify-between">
<span>Round Trip Duration</span>
<span className="font-medium">
{Math.floor(ride.round_trip_duration_seconds / 60)}:{(ride.round_trip_duration_seconds % 60).toString().padStart(2, '0')}
</span>
</div>
)}
</CardContent>
</Card>
)}
</div>
</TabsContent>
@@ -768,11 +1111,50 @@ export default function RideDetail() {
max_height_meters: ride.max_height_meters,
length_meters: ride.length_meters,
inversions: ride.inversions,
// Coaster fields
coaster_type: ride.coaster_type,
seating_type: ride.seating_type,
intensity_level: ride.intensity_level,
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,
// Water ride fields
water_depth_cm: ride.water_depth_cm,
splash_height_meters: ride.splash_height_meters,
wetness_level: ride.wetness_level,
flume_type: ride.flume_type,
boat_capacity: ride.boat_capacity,
// 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,
// Flat ride fields
rotation_type: ride.rotation_type,
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,
// Kiddie ride fields
min_age: ride.min_age,
max_age: ride.max_age,
educational_theme: ride.educational_theme,
character_theme: ride.character_theme,
// Transportation fields
transport_type: ride.transport_type,
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,
// Common fields
manufacturer_id: ride.manufacturer?.id,
ride_model_id: ride.ride_model?.id,
banner_image_url: ride.banner_image_url,

View File

@@ -162,7 +162,7 @@ export interface Ride {
banner_image_id?: string;
card_image_url?: string;
card_image_id?: string;
// New roller coaster specific fields
// Roller coaster specific fields
coaster_type?: string;
seating_type?: string;
intensity_level?: string;
@@ -171,6 +171,40 @@ export interface Ride {
propulsion_method?: string[];
drop_height_meters?: number;
max_g_force?: number;
// Water ride specific fields
water_depth_cm?: number;
splash_height_meters?: number;
wetness_level?: 'dry' | 'light' | 'moderate' | 'soaked';
flume_type?: string;
boat_capacity?: number;
// Dark ride specific fields
theme_name?: string;
story_description?: string;
show_duration_seconds?: number;
animatronics_count?: number;
projection_type?: string;
ride_system?: string;
scenes_count?: number;
// Flat ride specific fields
rotation_type?: 'horizontal' | 'vertical' | 'multi_axis' | 'pendulum' | 'none';
motion_pattern?: string;
platform_count?: number;
swing_angle_degrees?: number;
rotation_speed_rpm?: number;
arm_length_meters?: number;
max_height_reached_meters?: number;
// Kiddie ride specific fields
min_age?: number;
max_age?: number;
educational_theme?: string;
character_theme?: string;
// Transportation specific fields
transport_type?: 'monorail' | 'train' | 'skylift' | 'ferry' | 'cable_car' | 'peoplemover';
route_length_meters?: number;
stations_count?: number;
vehicle_capacity?: number;
vehicles_count?: number;
round_trip_duration_seconds?: number;
}
export interface Profile {