diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index 2ddad322..817f8611 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -3867,12 +3867,16 @@ export type Database = { ride_submissions: { Row: { age_requirement: number | null + animatronics_count: number | null + arm_length_meters: number | null banner_image_id: string | null banner_image_url: string | null + boat_capacity: number | null capacity_per_hour: number | null card_image_id: string | null card_image_url: string | null category: string + character_theme: string | null closing_date: string | null closing_date_precision: string | null coaster_type: string | null @@ -3881,6 +3885,8 @@ export type Database = { designer_id: string | null drop_height_meters: number | null duration_seconds: number | null + educational_theme: string | null + flume_type: string | null height_requirement: number | null id: string image_url: string | null @@ -3888,32 +3894,59 @@ export type Database = { inversions: number | null length_meters: number | null manufacturer_id: string | null + max_age: number | null max_g_force: number | null max_height_meters: number | null + max_height_reached_meters: number | null max_speed_kmh: number | null + min_age: number | null + motion_pattern: string | null name: string opening_date: string | null opening_date_precision: string | null park_id: string | null + platform_count: number | null + projection_type: string | null propulsion_method: string[] | null ride_model_id: string | null ride_sub_type: string | null + ride_system: string | null + rotation_speed_rpm: number | null + rotation_type: string | null + round_trip_duration_seconds: number | null + route_length_meters: number | null + scenes_count: number | null seating_type: string | null + show_duration_seconds: number | null slug: string + splash_height_meters: number | null + stations_count: number | null status: string + story_description: string | null submission_id: string support_material: string[] | null + swing_angle_degrees: number | null + theme_name: string | null track_material: string[] | null + transport_type: string | null updated_at: string + vehicle_capacity: number | null + vehicles_count: number | null + water_depth_cm: number | null + wetness_level: string | null } Insert: { age_requirement?: number | null + animatronics_count?: number | null + arm_length_meters?: number | null banner_image_id?: string | null banner_image_url?: string | null + boat_capacity?: number | null capacity_per_hour?: number | null card_image_id?: string | null card_image_url?: string | null category: string + character_theme?: string | null closing_date?: string | null closing_date_precision?: string | null coaster_type?: string | null @@ -3922,6 +3955,8 @@ export type Database = { designer_id?: string | null drop_height_meters?: number | null duration_seconds?: number | null + educational_theme?: string | null + flume_type?: string | null height_requirement?: number | null id?: string image_url?: string | null @@ -3929,32 +3964,59 @@ export type Database = { inversions?: number | null length_meters?: number | null manufacturer_id?: string | null + max_age?: number | null max_g_force?: number | null max_height_meters?: number | null + max_height_reached_meters?: number | null max_speed_kmh?: number | null + min_age?: number | null + motion_pattern?: string | null name: string opening_date?: string | null opening_date_precision?: string | null park_id?: string | null + platform_count?: number | null + projection_type?: string | null propulsion_method?: string[] | null ride_model_id?: string | null ride_sub_type?: string | null + ride_system?: string | null + rotation_speed_rpm?: number | null + rotation_type?: string | null + round_trip_duration_seconds?: number | null + route_length_meters?: number | null + scenes_count?: number | null seating_type?: string | null + show_duration_seconds?: number | null slug: string + splash_height_meters?: number | null + stations_count?: number | null status?: string + story_description?: string | null submission_id: string support_material?: string[] | null + swing_angle_degrees?: number | null + theme_name?: string | null track_material?: string[] | null + transport_type?: string | null updated_at?: string + vehicle_capacity?: number | null + vehicles_count?: number | null + water_depth_cm?: number | null + wetness_level?: string | null } Update: { age_requirement?: number | null + animatronics_count?: number | null + arm_length_meters?: number | null banner_image_id?: string | null banner_image_url?: string | null + boat_capacity?: number | null capacity_per_hour?: number | null card_image_id?: string | null card_image_url?: string | null category?: string + character_theme?: string | null closing_date?: string | null closing_date_precision?: string | null coaster_type?: string | null @@ -3963,6 +4025,8 @@ export type Database = { designer_id?: string | null drop_height_meters?: number | null duration_seconds?: number | null + educational_theme?: string | null + flume_type?: string | null height_requirement?: number | null id?: string image_url?: string | null @@ -3970,23 +4034,46 @@ export type Database = { inversions?: number | null length_meters?: number | null manufacturer_id?: string | null + max_age?: number | null max_g_force?: number | null max_height_meters?: number | null + max_height_reached_meters?: number | null max_speed_kmh?: number | null + min_age?: number | null + motion_pattern?: string | null name?: string opening_date?: string | null opening_date_precision?: string | null park_id?: string | null + platform_count?: number | null + projection_type?: string | null propulsion_method?: string[] | null ride_model_id?: string | null ride_sub_type?: string | null + ride_system?: string | null + rotation_speed_rpm?: number | null + rotation_type?: string | null + round_trip_duration_seconds?: number | null + route_length_meters?: number | null + scenes_count?: number | null seating_type?: string | null + show_duration_seconds?: number | null slug?: string + splash_height_meters?: number | null + stations_count?: number | null status?: string + story_description?: string | null submission_id?: string support_material?: string[] | null + swing_angle_degrees?: number | null + theme_name?: string | null track_material?: string[] | null + transport_type?: string | null updated_at?: string + vehicle_capacity?: number | null + vehicles_count?: number | null + water_depth_cm?: number | null + wetness_level?: string | null } Relationships: [ { diff --git a/src/lib/entitySubmissionHelpers.ts b/src/lib/entitySubmissionHelpers.ts index c815903c..abda6458 100644 --- a/src/lib/entitySubmissionHelpers.ts +++ b/src/lib/entitySubmissionHelpers.ts @@ -1177,13 +1177,109 @@ export async function submitRideCreation( banner_image_id: bannerImage?.cloudflare_id || data.banner_image_id || null, card_image_url: cardImage?.url || data.card_image_url || null, card_image_id: cardImage?.cloudflare_id || data.card_image_id || null, - image_url: null + image_url: null, + // Category-specific fields + track_material: (data as any).track_material || null, + support_material: (data as any).support_material || null, + propulsion_method: (data as any).propulsion_method || null, + water_depth_cm: (data as any).water_depth_cm || null, + splash_height_meters: (data as any).splash_height_meters || null, + wetness_level: (data as any).wetness_level || null, + flume_type: (data as any).flume_type || null, + boat_capacity: (data as any).boat_capacity || null, + theme_name: (data as any).theme_name || null, + story_description: (data as any).story_description || null, + show_duration_seconds: (data as any).show_duration_seconds || null, + animatronics_count: (data as any).animatronics_count || null, + projection_type: (data as any).projection_type || null, + ride_system: (data as any).ride_system || null, + scenes_count: (data as any).scenes_count || null, + rotation_type: (data as any).rotation_type || null, + motion_pattern: (data as any).motion_pattern || null, + platform_count: (data as any).platform_count || null, + swing_angle_degrees: (data as any).swing_angle_degrees || null, + rotation_speed_rpm: (data as any).rotation_speed_rpm || null, + arm_length_meters: (data as any).arm_length_meters || null, + max_height_reached_meters: (data as any).max_height_reached_meters || null, + min_age: (data as any).min_age || null, + max_age: (data as any).max_age || null, + educational_theme: (data as any).educational_theme || null, + character_theme: (data as any).character_theme || null, + transport_type: (data as any).transport_type || null, + route_length_meters: (data as any).route_length_meters || null, + stations_count: (data as any).stations_count || null, + vehicle_capacity: (data as any).vehicle_capacity || null, + vehicles_count: (data as any).vehicles_count || null, + round_trip_duration_seconds: (data as any).round_trip_duration_seconds || null } as any) .select('id') .single(); if (rideSubmissionError) throw rideSubmissionError; + // Insert technical specifications if present + if ((data as any)._technical_specifications?.length > 0) { + const { error: techSpecError } = await supabase + .from('ride_technical_specs' as any) + .insert( + (data as any)._technical_specifications.map((spec: any) => ({ + ride_submission_id: (rideSubmission as any).id, + spec_name: spec.spec_name, + spec_value: spec.spec_value, + spec_type: spec.spec_type, + category: spec.category || null, + unit: spec.unit || null + })) + ); + + if (techSpecError) { + logger.error('Failed to insert technical specs', { error: techSpecError }); + throw techSpecError; + } + } + + // Insert coaster statistics if present + if ((data as any)._coaster_statistics?.length > 0) { + const { error: statsError } = await supabase + .from('ride_coaster_stats' as any) + .insert( + (data as any)._coaster_statistics.map((stat: any) => ({ + ride_submission_id: (rideSubmission as any).id, + stat_name: stat.stat_name, + stat_value: stat.stat_value, + unit: stat.unit || null, + category: stat.category || null + })) + ); + + if (statsError) { + logger.error('Failed to insert coaster stats', { error: statsError }); + throw statsError; + } + } + + // Insert name history if present + if ((data as any)._name_history?.length > 0) { + const { error: historyError } = await supabase + .from('ride_name_history_submissions' as any) + .insert( + (data as any)._name_history.map((name: any) => ({ + ride_submission_id: (rideSubmission as any).id, + former_name: name.former_name, + date_changed: name.date_changed ? new Date(name.date_changed).toISOString().split('T')[0] : null, + reason: name.reason || null, + from_year: name.from_year || null, + to_year: name.to_year || null, + order_index: name.order_index || 0 + })) + ); + + if (historyError) { + logger.error('Failed to insert name history', { error: historyError }); + throw historyError; + } + } + // Create submission_items record linking to ride_submissions const { error: itemError } = await supabase .from('submission_items') diff --git a/src/lib/entityValidationSchemas.ts b/src/lib/entityValidationSchemas.ts index 5b04a079..b3588c29 100644 --- a/src/lib/entityValidationSchemas.ts +++ b/src/lib/entityValidationSchemas.ts @@ -41,6 +41,7 @@ export const parkValidationSchema = z.object({ location_id: z.string().uuid().optional().nullable(), location: z.object({ name: z.string(), + street_address: z.string().optional().nullable(), city: z.string().optional().nullable(), state_province: z.string().optional().nullable(), country: z.string(), diff --git a/supabase/functions/process-selective-approval/index.ts b/supabase/functions/process-selective-approval/index.ts index 4fe1a7a9..ceff9dba 100644 --- a/supabase/functions/process-selective-approval/index.ts +++ b/supabase/functions/process-selective-approval/index.ts @@ -864,7 +864,40 @@ serve(withRateLimit(async (req) => { case 'ride': itemData = { ...(item as any).ride_submission, - ...(tempRefsByItemId.get(item.id) || {}) + ...(tempRefsByItemId.get(item.id) || {}), + // Ensure all category-specific fields are included + track_material: (item as any).ride_submission?.track_material, + support_material: (item as any).ride_submission?.support_material, + propulsion_method: (item as any).ride_submission?.propulsion_method, + water_depth_cm: (item as any).ride_submission?.water_depth_cm, + splash_height_meters: (item as any).ride_submission?.splash_height_meters, + wetness_level: (item as any).ride_submission?.wetness_level, + flume_type: (item as any).ride_submission?.flume_type, + boat_capacity: (item as any).ride_submission?.boat_capacity, + theme_name: (item as any).ride_submission?.theme_name, + story_description: (item as any).ride_submission?.story_description, + show_duration_seconds: (item as any).ride_submission?.show_duration_seconds, + animatronics_count: (item as any).ride_submission?.animatronics_count, + projection_type: (item as any).ride_submission?.projection_type, + ride_system: (item as any).ride_submission?.ride_system, + scenes_count: (item as any).ride_submission?.scenes_count, + rotation_type: (item as any).ride_submission?.rotation_type, + motion_pattern: (item as any).ride_submission?.motion_pattern, + platform_count: (item as any).ride_submission?.platform_count, + swing_angle_degrees: (item as any).ride_submission?.swing_angle_degrees, + rotation_speed_rpm: (item as any).ride_submission?.rotation_speed_rpm, + arm_length_meters: (item as any).ride_submission?.arm_length_meters, + max_height_reached_meters: (item as any).ride_submission?.max_height_reached_meters, + min_age: (item as any).ride_submission?.min_age, + max_age: (item as any).ride_submission?.max_age, + educational_theme: (item as any).ride_submission?.educational_theme, + character_theme: (item as any).ride_submission?.character_theme, + transport_type: (item as any).ride_submission?.transport_type, + route_length_meters: (item as any).ride_submission?.route_length_meters, + stations_count: (item as any).ride_submission?.stations_count, + vehicle_capacity: (item as any).ride_submission?.vehicle_capacity, + vehicles_count: (item as any).ride_submission?.vehicles_count, + round_trip_duration_seconds: (item as any).ride_submission?.round_trip_duration_seconds }; break; case 'manufacturer': diff --git a/supabase/migrations/20251106145008_76057598-b289-44bb-b90e-35e96598dfe0.sql b/supabase/migrations/20251106145008_76057598-b289-44bb-b90e-35e96598dfe0.sql new file mode 100644 index 00000000..824ab484 --- /dev/null +++ b/supabase/migrations/20251106145008_76057598-b289-44bb-b90e-35e96598dfe0.sql @@ -0,0 +1,43 @@ +-- Add missing category-specific fields to ride_submissions table +-- This ensures all ride category data can flow through the submission pipeline + +ALTER TABLE ride_submissions +ADD COLUMN IF NOT EXISTS track_material TEXT[], +ADD COLUMN IF NOT EXISTS support_material TEXT[], +ADD COLUMN IF NOT EXISTS propulsion_method TEXT[], +-- Water ride fields +ADD COLUMN IF NOT EXISTS water_depth_cm INTEGER, +ADD COLUMN IF NOT EXISTS splash_height_meters NUMERIC, +ADD COLUMN IF NOT EXISTS wetness_level TEXT, +ADD COLUMN IF NOT EXISTS flume_type TEXT, +ADD COLUMN IF NOT EXISTS boat_capacity INTEGER, +-- Dark ride fields +ADD COLUMN IF NOT EXISTS theme_name TEXT, +ADD COLUMN IF NOT EXISTS story_description TEXT, +ADD COLUMN IF NOT EXISTS show_duration_seconds INTEGER, +ADD COLUMN IF NOT EXISTS animatronics_count INTEGER, +ADD COLUMN IF NOT EXISTS projection_type TEXT, +ADD COLUMN IF NOT EXISTS ride_system TEXT, +ADD COLUMN IF NOT EXISTS scenes_count INTEGER, +-- Flat ride fields +ADD COLUMN IF NOT EXISTS rotation_type TEXT, +ADD COLUMN IF NOT EXISTS motion_pattern TEXT, +ADD COLUMN IF NOT EXISTS platform_count INTEGER, +ADD COLUMN IF NOT EXISTS swing_angle_degrees NUMERIC, +ADD COLUMN IF NOT EXISTS rotation_speed_rpm NUMERIC, +ADD COLUMN IF NOT EXISTS arm_length_meters NUMERIC, +ADD COLUMN IF NOT EXISTS max_height_reached_meters NUMERIC, +-- Kiddie ride fields +ADD COLUMN IF NOT EXISTS min_age INTEGER, +ADD COLUMN IF NOT EXISTS max_age INTEGER, +ADD COLUMN IF NOT EXISTS educational_theme TEXT, +ADD COLUMN IF NOT EXISTS character_theme TEXT, +-- Transportation ride fields +ADD COLUMN IF NOT EXISTS transport_type TEXT, +ADD COLUMN IF NOT EXISTS route_length_meters NUMERIC, +ADD COLUMN IF NOT EXISTS stations_count INTEGER, +ADD COLUMN IF NOT EXISTS vehicle_capacity INTEGER, +ADD COLUMN IF NOT EXISTS vehicles_count INTEGER, +ADD COLUMN IF NOT EXISTS round_trip_duration_seconds INTEGER; + +COMMENT ON TABLE ride_submissions IS 'Submission data for rides - includes all category-specific fields to prevent data loss during moderation';