mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-28 07:27:05 -05:00
Compare commits
2 Commits
9f5240ae95
...
ed9d17bf10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed9d17bf10 | ||
|
|
de9a48951f |
@@ -3413,6 +3413,47 @@ export type Database = {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
ride_model_submission_technical_specifications: {
|
||||||
|
Row: {
|
||||||
|
category: string | null
|
||||||
|
created_at: string | null
|
||||||
|
display_order: number | null
|
||||||
|
id: string
|
||||||
|
ride_model_submission_id: string
|
||||||
|
spec_name: string
|
||||||
|
spec_unit: string | null
|
||||||
|
spec_value: string
|
||||||
|
}
|
||||||
|
Insert: {
|
||||||
|
category?: string | null
|
||||||
|
created_at?: string | null
|
||||||
|
display_order?: number | null
|
||||||
|
id?: string
|
||||||
|
ride_model_submission_id: string
|
||||||
|
spec_name: string
|
||||||
|
spec_unit?: string | null
|
||||||
|
spec_value: string
|
||||||
|
}
|
||||||
|
Update: {
|
||||||
|
category?: string | null
|
||||||
|
created_at?: string | null
|
||||||
|
display_order?: number | null
|
||||||
|
id?: string
|
||||||
|
ride_model_submission_id?: string
|
||||||
|
spec_name?: string
|
||||||
|
spec_unit?: string | null
|
||||||
|
spec_value?: string
|
||||||
|
}
|
||||||
|
Relationships: [
|
||||||
|
{
|
||||||
|
foreignKeyName: "fk_ride_model_submission"
|
||||||
|
columns: ["ride_model_submission_id"]
|
||||||
|
isOneToOne: false
|
||||||
|
referencedRelation: "ride_model_submissions"
|
||||||
|
referencedColumns: ["id"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
ride_model_submissions: {
|
ride_model_submissions: {
|
||||||
Row: {
|
Row: {
|
||||||
banner_image_id: string | null
|
banner_image_id: string | null
|
||||||
@@ -3867,12 +3908,16 @@ export type Database = {
|
|||||||
ride_submissions: {
|
ride_submissions: {
|
||||||
Row: {
|
Row: {
|
||||||
age_requirement: number | null
|
age_requirement: number | null
|
||||||
|
animatronics_count: number | null
|
||||||
|
arm_length_meters: number | null
|
||||||
banner_image_id: string | null
|
banner_image_id: string | null
|
||||||
banner_image_url: string | null
|
banner_image_url: string | null
|
||||||
|
boat_capacity: number | null
|
||||||
capacity_per_hour: number | null
|
capacity_per_hour: number | null
|
||||||
card_image_id: string | null
|
card_image_id: string | null
|
||||||
card_image_url: string | null
|
card_image_url: string | null
|
||||||
category: string
|
category: string
|
||||||
|
character_theme: string | null
|
||||||
closing_date: string | null
|
closing_date: string | null
|
||||||
closing_date_precision: string | null
|
closing_date_precision: string | null
|
||||||
coaster_type: string | null
|
coaster_type: string | null
|
||||||
@@ -3881,6 +3926,8 @@ export type Database = {
|
|||||||
designer_id: string | null
|
designer_id: string | null
|
||||||
drop_height_meters: number | null
|
drop_height_meters: number | null
|
||||||
duration_seconds: number | null
|
duration_seconds: number | null
|
||||||
|
educational_theme: string | null
|
||||||
|
flume_type: string | null
|
||||||
height_requirement: number | null
|
height_requirement: number | null
|
||||||
id: string
|
id: string
|
||||||
image_url: string | null
|
image_url: string | null
|
||||||
@@ -3888,32 +3935,59 @@ export type Database = {
|
|||||||
inversions: number | null
|
inversions: number | null
|
||||||
length_meters: number | null
|
length_meters: number | null
|
||||||
manufacturer_id: string | null
|
manufacturer_id: string | null
|
||||||
|
max_age: number | null
|
||||||
max_g_force: number | null
|
max_g_force: number | null
|
||||||
max_height_meters: number | null
|
max_height_meters: number | null
|
||||||
|
max_height_reached_meters: number | null
|
||||||
max_speed_kmh: number | null
|
max_speed_kmh: number | null
|
||||||
|
min_age: number | null
|
||||||
|
motion_pattern: string | null
|
||||||
name: string
|
name: string
|
||||||
opening_date: string | null
|
opening_date: string | null
|
||||||
opening_date_precision: string | null
|
opening_date_precision: string | null
|
||||||
park_id: string | null
|
park_id: string | null
|
||||||
|
platform_count: number | null
|
||||||
|
projection_type: string | null
|
||||||
propulsion_method: string[] | null
|
propulsion_method: string[] | null
|
||||||
ride_model_id: string | null
|
ride_model_id: string | null
|
||||||
ride_sub_type: 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
|
seating_type: string | null
|
||||||
|
show_duration_seconds: number | null
|
||||||
slug: string
|
slug: string
|
||||||
|
splash_height_meters: number | null
|
||||||
|
stations_count: number | null
|
||||||
status: string
|
status: string
|
||||||
|
story_description: string | null
|
||||||
submission_id: string
|
submission_id: string
|
||||||
support_material: string[] | null
|
support_material: string[] | null
|
||||||
|
swing_angle_degrees: number | null
|
||||||
|
theme_name: string | null
|
||||||
track_material: string[] | null
|
track_material: string[] | null
|
||||||
|
transport_type: string | null
|
||||||
updated_at: string
|
updated_at: string
|
||||||
|
vehicle_capacity: number | null
|
||||||
|
vehicles_count: number | null
|
||||||
|
water_depth_cm: number | null
|
||||||
|
wetness_level: string | null
|
||||||
}
|
}
|
||||||
Insert: {
|
Insert: {
|
||||||
age_requirement?: number | null
|
age_requirement?: number | null
|
||||||
|
animatronics_count?: number | null
|
||||||
|
arm_length_meters?: number | null
|
||||||
banner_image_id?: string | null
|
banner_image_id?: string | null
|
||||||
banner_image_url?: string | null
|
banner_image_url?: string | null
|
||||||
|
boat_capacity?: number | null
|
||||||
capacity_per_hour?: number | null
|
capacity_per_hour?: number | null
|
||||||
card_image_id?: string | null
|
card_image_id?: string | null
|
||||||
card_image_url?: string | null
|
card_image_url?: string | null
|
||||||
category: string
|
category: string
|
||||||
|
character_theme?: string | null
|
||||||
closing_date?: string | null
|
closing_date?: string | null
|
||||||
closing_date_precision?: string | null
|
closing_date_precision?: string | null
|
||||||
coaster_type?: string | null
|
coaster_type?: string | null
|
||||||
@@ -3922,6 +3996,8 @@ export type Database = {
|
|||||||
designer_id?: string | null
|
designer_id?: string | null
|
||||||
drop_height_meters?: number | null
|
drop_height_meters?: number | null
|
||||||
duration_seconds?: number | null
|
duration_seconds?: number | null
|
||||||
|
educational_theme?: string | null
|
||||||
|
flume_type?: string | null
|
||||||
height_requirement?: number | null
|
height_requirement?: number | null
|
||||||
id?: string
|
id?: string
|
||||||
image_url?: string | null
|
image_url?: string | null
|
||||||
@@ -3929,32 +4005,59 @@ export type Database = {
|
|||||||
inversions?: number | null
|
inversions?: number | null
|
||||||
length_meters?: number | null
|
length_meters?: number | null
|
||||||
manufacturer_id?: string | null
|
manufacturer_id?: string | null
|
||||||
|
max_age?: number | null
|
||||||
max_g_force?: number | null
|
max_g_force?: number | null
|
||||||
max_height_meters?: number | null
|
max_height_meters?: number | null
|
||||||
|
max_height_reached_meters?: number | null
|
||||||
max_speed_kmh?: number | null
|
max_speed_kmh?: number | null
|
||||||
|
min_age?: number | null
|
||||||
|
motion_pattern?: string | null
|
||||||
name: string
|
name: string
|
||||||
opening_date?: string | null
|
opening_date?: string | null
|
||||||
opening_date_precision?: string | null
|
opening_date_precision?: string | null
|
||||||
park_id?: string | null
|
park_id?: string | null
|
||||||
|
platform_count?: number | null
|
||||||
|
projection_type?: string | null
|
||||||
propulsion_method?: string[] | null
|
propulsion_method?: string[] | null
|
||||||
ride_model_id?: string | null
|
ride_model_id?: string | null
|
||||||
ride_sub_type?: 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
|
seating_type?: string | null
|
||||||
|
show_duration_seconds?: number | null
|
||||||
slug: string
|
slug: string
|
||||||
|
splash_height_meters?: number | null
|
||||||
|
stations_count?: number | null
|
||||||
status?: string
|
status?: string
|
||||||
|
story_description?: string | null
|
||||||
submission_id: string
|
submission_id: string
|
||||||
support_material?: string[] | null
|
support_material?: string[] | null
|
||||||
|
swing_angle_degrees?: number | null
|
||||||
|
theme_name?: string | null
|
||||||
track_material?: string[] | null
|
track_material?: string[] | null
|
||||||
|
transport_type?: string | null
|
||||||
updated_at?: string
|
updated_at?: string
|
||||||
|
vehicle_capacity?: number | null
|
||||||
|
vehicles_count?: number | null
|
||||||
|
water_depth_cm?: number | null
|
||||||
|
wetness_level?: string | null
|
||||||
}
|
}
|
||||||
Update: {
|
Update: {
|
||||||
age_requirement?: number | null
|
age_requirement?: number | null
|
||||||
|
animatronics_count?: number | null
|
||||||
|
arm_length_meters?: number | null
|
||||||
banner_image_id?: string | null
|
banner_image_id?: string | null
|
||||||
banner_image_url?: string | null
|
banner_image_url?: string | null
|
||||||
|
boat_capacity?: number | null
|
||||||
capacity_per_hour?: number | null
|
capacity_per_hour?: number | null
|
||||||
card_image_id?: string | null
|
card_image_id?: string | null
|
||||||
card_image_url?: string | null
|
card_image_url?: string | null
|
||||||
category?: string
|
category?: string
|
||||||
|
character_theme?: string | null
|
||||||
closing_date?: string | null
|
closing_date?: string | null
|
||||||
closing_date_precision?: string | null
|
closing_date_precision?: string | null
|
||||||
coaster_type?: string | null
|
coaster_type?: string | null
|
||||||
@@ -3963,6 +4066,8 @@ export type Database = {
|
|||||||
designer_id?: string | null
|
designer_id?: string | null
|
||||||
drop_height_meters?: number | null
|
drop_height_meters?: number | null
|
||||||
duration_seconds?: number | null
|
duration_seconds?: number | null
|
||||||
|
educational_theme?: string | null
|
||||||
|
flume_type?: string | null
|
||||||
height_requirement?: number | null
|
height_requirement?: number | null
|
||||||
id?: string
|
id?: string
|
||||||
image_url?: string | null
|
image_url?: string | null
|
||||||
@@ -3970,23 +4075,46 @@ export type Database = {
|
|||||||
inversions?: number | null
|
inversions?: number | null
|
||||||
length_meters?: number | null
|
length_meters?: number | null
|
||||||
manufacturer_id?: string | null
|
manufacturer_id?: string | null
|
||||||
|
max_age?: number | null
|
||||||
max_g_force?: number | null
|
max_g_force?: number | null
|
||||||
max_height_meters?: number | null
|
max_height_meters?: number | null
|
||||||
|
max_height_reached_meters?: number | null
|
||||||
max_speed_kmh?: number | null
|
max_speed_kmh?: number | null
|
||||||
|
min_age?: number | null
|
||||||
|
motion_pattern?: string | null
|
||||||
name?: string
|
name?: string
|
||||||
opening_date?: string | null
|
opening_date?: string | null
|
||||||
opening_date_precision?: string | null
|
opening_date_precision?: string | null
|
||||||
park_id?: string | null
|
park_id?: string | null
|
||||||
|
platform_count?: number | null
|
||||||
|
projection_type?: string | null
|
||||||
propulsion_method?: string[] | null
|
propulsion_method?: string[] | null
|
||||||
ride_model_id?: string | null
|
ride_model_id?: string | null
|
||||||
ride_sub_type?: 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
|
seating_type?: string | null
|
||||||
|
show_duration_seconds?: number | null
|
||||||
slug?: string
|
slug?: string
|
||||||
|
splash_height_meters?: number | null
|
||||||
|
stations_count?: number | null
|
||||||
status?: string
|
status?: string
|
||||||
|
story_description?: string | null
|
||||||
submission_id?: string
|
submission_id?: string
|
||||||
support_material?: string[] | null
|
support_material?: string[] | null
|
||||||
|
swing_angle_degrees?: number | null
|
||||||
|
theme_name?: string | null
|
||||||
track_material?: string[] | null
|
track_material?: string[] | null
|
||||||
|
transport_type?: string | null
|
||||||
updated_at?: string
|
updated_at?: string
|
||||||
|
vehicle_capacity?: number | null
|
||||||
|
vehicles_count?: number | null
|
||||||
|
water_depth_cm?: number | null
|
||||||
|
wetness_level?: string | null
|
||||||
}
|
}
|
||||||
Relationships: [
|
Relationships: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,6 +170,15 @@ export interface CompanyFormData {
|
|||||||
card_image_id?: string;
|
card_image_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TechnicalSpecification {
|
||||||
|
spec_name: string;
|
||||||
|
spec_value: string;
|
||||||
|
spec_type?: 'string' | 'number' | 'boolean' | 'date';
|
||||||
|
category?: string;
|
||||||
|
unit?: string;
|
||||||
|
display_order?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface RideModelFormData {
|
export interface RideModelFormData {
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
@@ -182,6 +191,7 @@ export interface RideModelFormData {
|
|||||||
banner_image_id?: string;
|
banner_image_id?: string;
|
||||||
card_image_url?: string;
|
card_image_url?: string;
|
||||||
card_image_id?: string;
|
card_image_id?: string;
|
||||||
|
_technical_specifications?: TechnicalSpecification[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1177,13 +1187,109 @@ export async function submitRideCreation(
|
|||||||
banner_image_id: bannerImage?.cloudflare_id || data.banner_image_id || null,
|
banner_image_id: bannerImage?.cloudflare_id || data.banner_image_id || null,
|
||||||
card_image_url: cardImage?.url || data.card_image_url || null,
|
card_image_url: cardImage?.url || data.card_image_url || null,
|
||||||
card_image_id: cardImage?.cloudflare_id || data.card_image_id || 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)
|
} as any)
|
||||||
.select('id')
|
.select('id')
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (rideSubmissionError) throw rideSubmissionError;
|
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
|
// Create submission_items record linking to ride_submissions
|
||||||
const { error: itemError } = await supabase
|
const { error: itemError } = await supabase
|
||||||
.from('submission_items')
|
.from('submission_items')
|
||||||
@@ -1494,6 +1600,53 @@ export async function submitRideModelCreation(
|
|||||||
|
|
||||||
if (itemError) throw itemError;
|
if (itemError) throw itemError;
|
||||||
|
|
||||||
|
// Insert into ride_model_submissions table for relational integrity
|
||||||
|
const { data: rideModelSubmissionData, error: rideModelSubmissionError } = await supabase
|
||||||
|
.from('ride_model_submissions')
|
||||||
|
.insert({
|
||||||
|
submission_id: submissionData.id,
|
||||||
|
name: data.name,
|
||||||
|
slug: data.slug,
|
||||||
|
manufacturer_id: data.manufacturer_id,
|
||||||
|
category: data.category,
|
||||||
|
ride_type: data.ride_type || data.category,
|
||||||
|
description: data.description || null,
|
||||||
|
banner_image_url: data.banner_image_url || null,
|
||||||
|
banner_image_id: data.banner_image_id || null,
|
||||||
|
card_image_url: data.card_image_url || null,
|
||||||
|
card_image_id: data.card_image_id || null
|
||||||
|
})
|
||||||
|
.select()
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (rideModelSubmissionError) {
|
||||||
|
logger.error('Failed to insert ride model submission', { error: rideModelSubmissionError });
|
||||||
|
throw rideModelSubmissionError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert technical specifications into submission table
|
||||||
|
if ((data as any)._technical_specifications?.length > 0) {
|
||||||
|
const { error: techSpecError } = await supabase
|
||||||
|
.from('ride_model_submission_technical_specifications')
|
||||||
|
.insert(
|
||||||
|
(data as any)._technical_specifications.map((spec: any) => ({
|
||||||
|
ride_model_submission_id: rideModelSubmissionData.id,
|
||||||
|
spec_name: spec.spec_name,
|
||||||
|
spec_value: spec.spec_value,
|
||||||
|
spec_unit: spec.spec_unit || null,
|
||||||
|
category: spec.category || null,
|
||||||
|
display_order: spec.display_order || 0
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (techSpecError) {
|
||||||
|
logger.error('Failed to insert ride model technical specs', { error: techSpecError });
|
||||||
|
throw techSpecError;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log('✅ Ride model technical specifications inserted:', (data as any)._technical_specifications.length);
|
||||||
|
}
|
||||||
|
|
||||||
return { submitted: true, submissionId: submissionData.id };
|
return { submitted: true, submissionId: submissionData.id };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1568,6 +1721,53 @@ export async function submitRideModelUpdate(
|
|||||||
|
|
||||||
if (itemError) throw itemError;
|
if (itemError) throw itemError;
|
||||||
|
|
||||||
|
// Insert into ride_model_submissions table for relational integrity
|
||||||
|
const { data: rideModelSubmissionData, error: rideModelSubmissionError } = await supabase
|
||||||
|
.from('ride_model_submissions')
|
||||||
|
.insert({
|
||||||
|
submission_id: submissionData.id,
|
||||||
|
name: data.name,
|
||||||
|
slug: data.slug,
|
||||||
|
manufacturer_id: data.manufacturer_id,
|
||||||
|
category: data.category,
|
||||||
|
ride_type: data.ride_type || data.category,
|
||||||
|
description: data.description || null,
|
||||||
|
banner_image_url: data.banner_image_url || null,
|
||||||
|
banner_image_id: data.banner_image_id || null,
|
||||||
|
card_image_url: data.card_image_url || null,
|
||||||
|
card_image_id: data.card_image_id || null
|
||||||
|
})
|
||||||
|
.select()
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (rideModelSubmissionError) {
|
||||||
|
logger.error('Failed to insert ride model update submission', { error: rideModelSubmissionError });
|
||||||
|
throw rideModelSubmissionError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert technical specifications into submission table
|
||||||
|
if ((data as any)._technical_specifications?.length > 0) {
|
||||||
|
const { error: techSpecError } = await supabase
|
||||||
|
.from('ride_model_submission_technical_specifications')
|
||||||
|
.insert(
|
||||||
|
(data as any)._technical_specifications.map((spec: any) => ({
|
||||||
|
ride_model_submission_id: rideModelSubmissionData.id,
|
||||||
|
spec_name: spec.spec_name,
|
||||||
|
spec_value: spec.spec_value,
|
||||||
|
spec_unit: spec.spec_unit || null,
|
||||||
|
category: spec.category || null,
|
||||||
|
display_order: spec.display_order || 0
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (techSpecError) {
|
||||||
|
logger.error('Failed to insert ride model update technical specs', { error: techSpecError });
|
||||||
|
throw techSpecError;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log('✅ Ride model update technical specifications inserted:', (data as any)._technical_specifications.length);
|
||||||
|
}
|
||||||
|
|
||||||
return { submitted: true, submissionId: submissionData.id };
|
return { submitted: true, submissionId: submissionData.id };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const parkValidationSchema = z.object({
|
|||||||
location_id: z.string().uuid().optional().nullable(),
|
location_id: z.string().uuid().optional().nullable(),
|
||||||
location: z.object({
|
location: z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
|
street_address: z.string().optional().nullable(),
|
||||||
city: z.string().optional().nullable(),
|
city: z.string().optional().nullable(),
|
||||||
state_province: z.string().optional().nullable(),
|
state_province: z.string().optional().nullable(),
|
||||||
country: z.string(),
|
country: z.string(),
|
||||||
|
|||||||
@@ -864,7 +864,40 @@ serve(withRateLimit(async (req) => {
|
|||||||
case 'ride':
|
case 'ride':
|
||||||
itemData = {
|
itemData = {
|
||||||
...(item as any).ride_submission,
|
...(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;
|
break;
|
||||||
case 'manufacturer':
|
case 'manufacturer':
|
||||||
@@ -1921,7 +1954,30 @@ async function createRideModel(supabase: any, data: any): Promise<string> {
|
|||||||
let rideModelId: string;
|
let rideModelId: string;
|
||||||
|
|
||||||
// Extract relational data before transformation
|
// Extract relational data before transformation
|
||||||
const technicalSpecifications = data._technical_specifications || [];
|
let technicalSpecifications = data._technical_specifications || [];
|
||||||
|
|
||||||
|
// If no inline specs provided, fetch from submission table
|
||||||
|
if (technicalSpecifications.length === 0 && data.submission_id) {
|
||||||
|
const { data: submissionData } = await supabase
|
||||||
|
.from('ride_model_submissions')
|
||||||
|
.select('id')
|
||||||
|
.eq('submission_id', data.submission_id)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (submissionData) {
|
||||||
|
const { data: submissionSpecs } = await supabase
|
||||||
|
.from('ride_model_submission_technical_specifications')
|
||||||
|
.select('*')
|
||||||
|
.eq('ride_model_submission_id', submissionData.id);
|
||||||
|
|
||||||
|
if (submissionSpecs && submissionSpecs.length > 0) {
|
||||||
|
edgeLogger.info('Fetched technical specs from submission table', {
|
||||||
|
count: submissionSpecs.length
|
||||||
|
});
|
||||||
|
technicalSpecifications = submissionSpecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove internal fields
|
// Remove internal fields
|
||||||
delete data._technical_specifications;
|
delete data._technical_specifications;
|
||||||
|
|||||||
@@ -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';
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
-- Create submission table for ride model technical specifications
|
||||||
|
-- This ensures technical specs flow through the submission pipeline without data loss
|
||||||
|
|
||||||
|
CREATE TABLE ride_model_submission_technical_specifications (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
ride_model_submission_id UUID NOT NULL,
|
||||||
|
spec_name TEXT NOT NULL,
|
||||||
|
spec_value TEXT NOT NULL,
|
||||||
|
spec_unit TEXT,
|
||||||
|
category TEXT,
|
||||||
|
display_order INTEGER DEFAULT 0,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT now(),
|
||||||
|
|
||||||
|
CONSTRAINT fk_ride_model_submission
|
||||||
|
FOREIGN KEY (ride_model_submission_id)
|
||||||
|
REFERENCES ride_model_submissions(id)
|
||||||
|
ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT unique_ride_model_submission_spec
|
||||||
|
UNIQUE(ride_model_submission_id, spec_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_ride_model_submission_specs_submission
|
||||||
|
ON ride_model_submission_technical_specifications(ride_model_submission_id);
|
||||||
|
|
||||||
|
-- Enable RLS
|
||||||
|
ALTER TABLE ride_model_submission_technical_specifications ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
-- Moderators can view all submission specs
|
||||||
|
CREATE POLICY "Moderators can view all ride model submission specs"
|
||||||
|
ON ride_model_submission_technical_specifications
|
||||||
|
FOR SELECT
|
||||||
|
USING (
|
||||||
|
is_moderator(auth.uid()) AND
|
||||||
|
((NOT has_mfa_enabled(auth.uid())) OR has_aal2())
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Users can view their own submission specs
|
||||||
|
CREATE POLICY "Users can view their own ride model submission specs"
|
||||||
|
ON ride_model_submission_technical_specifications
|
||||||
|
FOR SELECT
|
||||||
|
USING (
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1 FROM ride_model_submissions rms
|
||||||
|
JOIN content_submissions cs ON cs.id = rms.submission_id
|
||||||
|
WHERE rms.id = ride_model_submission_technical_specifications.ride_model_submission_id
|
||||||
|
AND cs.user_id = auth.uid()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Users can insert their own submission specs
|
||||||
|
CREATE POLICY "Users can insert their own ride model submission specs"
|
||||||
|
ON ride_model_submission_technical_specifications
|
||||||
|
FOR INSERT
|
||||||
|
WITH CHECK (
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1 FROM ride_model_submissions rms
|
||||||
|
JOIN content_submissions cs ON cs.id = rms.submission_id
|
||||||
|
WHERE rms.id = ride_model_submission_technical_specifications.ride_model_submission_id
|
||||||
|
AND cs.user_id = auth.uid()
|
||||||
|
)
|
||||||
|
AND NOT is_user_banned(auth.uid())
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Moderators can update submission specs
|
||||||
|
CREATE POLICY "Moderators can update ride model submission specs"
|
||||||
|
ON ride_model_submission_technical_specifications
|
||||||
|
FOR UPDATE
|
||||||
|
USING (
|
||||||
|
is_moderator(auth.uid()) AND
|
||||||
|
((NOT has_mfa_enabled(auth.uid())) OR has_aal2())
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Moderators can delete submission specs
|
||||||
|
CREATE POLICY "Moderators can delete ride model submission specs"
|
||||||
|
ON ride_model_submission_technical_specifications
|
||||||
|
FOR DELETE
|
||||||
|
USING (
|
||||||
|
is_moderator(auth.uid()) AND
|
||||||
|
((NOT has_mfa_enabled(auth.uid())) OR has_aal2())
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON TABLE ride_model_submission_technical_specifications IS
|
||||||
|
'Stores technical specifications for ride models during moderation - prevents data loss in submission pipeline';
|
||||||
Reference in New Issue
Block a user