diff --git a/src/lib/submissionItemsService.ts b/src/lib/submissionItemsService.ts index 8e88f7e2..eb0e489a 100644 --- a/src/lib/submissionItemsService.ts +++ b/src/lib/submissionItemsService.ts @@ -251,6 +251,35 @@ function topologicalSort(items: SubmissionItemWithDeps[]): SubmissionItemWithDep return sorted; } +/** + * Extract image URLs from ImageAssignments structure + */ +function extractImageAssignments(images: any) { + if (!images || !images.uploaded || !Array.isArray(images.uploaded)) { + return { + banner_image_url: null, + banner_image_id: null, + card_image_url: null, + card_image_id: null, + }; + } + + const bannerImage = images.banner_assignment !== null && images.banner_assignment !== undefined + ? images.uploaded[images.banner_assignment] + : null; + + const cardImage = images.card_assignment !== null && images.card_assignment !== undefined + ? images.uploaded[images.card_assignment] + : null; + + return { + banner_image_url: bannerImage?.url || null, + banner_image_id: bannerImage?.cloudflare_id || null, + card_image_url: cardImage?.url || null, + card_image_id: cardImage?.cloudflare_id || null, + }; +} + /** * Helper functions to create entities with dependency resolution */ @@ -258,18 +287,61 @@ async function createPark(data: any, dependencyMap: Map): Promis const { transformParkData, validateSubmissionData } = await import('./entityTransformers'); const { ensureUniqueSlug } = await import('./slugUtils'); - // Validate input data - validateSubmissionData(data, 'Park'); + // Check if this is an edit (has park_id) + const isEdit = !!data.park_id; - // Resolve dependencies + if (isEdit) { + // Handle park edit + const resolvedData = resolveDependencies(data, dependencyMap); + + // Extract image assignments from ImageAssignments structure + const imageData = extractImageAssignments(resolvedData.images); + + // Update the park + const updateData: any = { + name: resolvedData.name, + slug: resolvedData.slug, + description: resolvedData.description || null, + park_type: resolvedData.park_type, + status: resolvedData.status, + opening_date: resolvedData.opening_date || null, + closing_date: resolvedData.closing_date || null, + website_url: resolvedData.website_url || null, + phone: resolvedData.phone || null, + email: resolvedData.email || null, + operator_id: resolvedData.operator_id || null, + property_owner_id: resolvedData.property_owner_id || null, + location_id: resolvedData.location_id || null, + ...imageData, + updated_at: new Date().toISOString() + }; + + const { error } = await supabase + .from('parks') + .update(updateData) + .eq('id', data.park_id); + + if (error) { + console.error('Error updating park:', error); + throw new Error(`Database error: ${error.message}`); + } + + return data.park_id; + } + + // Handle park creation + validateSubmissionData(data, 'Park'); const resolvedData = resolveDependencies(data, dependencyMap); // Ensure unique slug const uniqueSlug = await ensureUniqueSlug(resolvedData.slug, 'parks'); resolvedData.slug = uniqueSlug; + // Extract image assignments + const imageData = extractImageAssignments(resolvedData.images); + // Transform to database format - const parkData = transformParkData(resolvedData); + const parkData = { ...transformParkData(resolvedData), ...imageData }; // Insert into database const { data: park, error } = await supabase @@ -290,25 +362,75 @@ async function createRide(data: any, dependencyMap: Map): Promis const { transformRideData, validateSubmissionData } = await import('./entityTransformers'); const { ensureUniqueSlug } = await import('./slugUtils'); - // Validate input data - validateSubmissionData(data, 'Ride'); + // Check if this is an edit (has ride_id) + const isEdit = !!data.ride_id; - // Resolve dependencies + if (isEdit) { + // Handle ride edit + const resolvedData = resolveDependencies(data, dependencyMap); + + // Extract image assignments from ImageAssignments structure + const imageData = extractImageAssignments(resolvedData.images); + + // Update the ride + const updateData: any = { + name: resolvedData.name, + slug: resolvedData.slug, + description: resolvedData.description, + category: resolvedData.category, + ride_sub_type: resolvedData.ride_sub_type, + status: resolvedData.status, + opening_date: resolvedData.opening_date, + closing_date: resolvedData.closing_date, + height_requirement: resolvedData.height_requirement, + age_requirement: resolvedData.age_requirement, + capacity_per_hour: resolvedData.capacity_per_hour, + duration_seconds: resolvedData.duration_seconds, + max_speed_kmh: resolvedData.max_speed_kmh, + max_height_meters: resolvedData.max_height_meters, + length_meters: resolvedData.length_meters, + inversions: resolvedData.inversions, + coaster_type: resolvedData.coaster_type, + seating_type: resolvedData.seating_type, + intensity_level: resolvedData.intensity_level, + drop_height_meters: resolvedData.drop_height_meters, + max_g_force: resolvedData.max_g_force, + manufacturer_id: resolvedData.manufacturer_id, + ride_model_id: resolvedData.ride_model_id, + ...imageData, + updated_at: new Date().toISOString() + }; + + const { error } = await supabase + .from('rides') + .update(updateData) + .eq('id', data.ride_id); + + if (error) { + console.error('Error updating ride:', error); + throw new Error(`Database error: ${error.message}`); + } + + return data.ride_id; + } + + // Handle ride creation + validateSubmissionData(data, 'Ride'); const resolvedData = resolveDependencies(data, dependencyMap); - // Validate park_id is present (required for rides) if (!resolvedData.park_id) { throw new Error('Ride must be associated with a park'); } - // Ensure unique slug const uniqueSlug = await ensureUniqueSlug(resolvedData.slug, 'rides'); resolvedData.slug = uniqueSlug; - // Transform to database format - const rideData = transformRideData(resolvedData); + // Extract image assignments + const imageData = extractImageAssignments(resolvedData.images); + + // Transform to database format + const rideData = { ...transformRideData(resolvedData), ...imageData }; - // Insert into database const { data: ride, error } = await supabase .from('rides') .insert(rideData) @@ -331,20 +453,54 @@ async function createCompany( const { transformCompanyData, validateSubmissionData } = await import('./entityTransformers'); const { ensureUniqueSlug } = await import('./slugUtils'); - // Validate input data - validateSubmissionData(data, 'Company'); + // Check if this is an edit (has company_id) + const isEdit = !!data.id; - // Resolve dependencies + if (isEdit) { + // Handle company edit + const resolvedData = resolveDependencies(data, dependencyMap); + + // Extract image assignments from ImageAssignments structure + const imageData = extractImageAssignments(resolvedData.images); + + // Update the company + const updateData: any = { + name: resolvedData.name, + slug: resolvedData.slug, + description: resolvedData.description || null, + website_url: resolvedData.website_url || null, + founded_year: resolvedData.founded_year || null, + headquarters_location: resolvedData.headquarters_location || null, + ...imageData, + updated_at: new Date().toISOString() + }; + + const { error } = await supabase + .from('companies') + .update(updateData) + .eq('id', data.id); + + if (error) { + console.error('Error updating company:', error); + throw new Error(`Database error: ${error.message}`); + } + + return data.id; + } + + // Handle company creation + validateSubmissionData(data, 'Company'); const resolvedData = resolveDependencies(data, dependencyMap); - // Ensure unique slug const uniqueSlug = await ensureUniqueSlug(resolvedData.slug, 'companies'); resolvedData.slug = uniqueSlug; - // Transform to database format - const companyData = transformCompanyData(resolvedData, companyType as any); + // Extract image assignments + const imageData = extractImageAssignments(resolvedData.images); + + // Transform to database format + const companyData = { ...transformCompanyData(resolvedData, companyType as any), ...imageData }; - // Insert into database const { data: company, error } = await supabase .from('companies') .insert(companyData) diff --git a/src/pages/ParkDetail.tsx b/src/pages/ParkDetail.tsx index 3e5e8a5f..6a4e4a0e 100644 --- a/src/pages/ParkDetail.tsx +++ b/src/pages/ParkDetail.tsx @@ -175,60 +175,22 @@ export default function ParkDetail() { if (!user || !park) return; try { - if (isModerator()) { - // Moderators can update directly - const updateData: any = { - name: parkData.name, - slug: parkData.slug, - description: parkData.description || null, - park_type: parkData.park_type, - status: parkData.status, - opening_date: parkData.opening_date || null, - closing_date: parkData.closing_date || null, - website_url: parkData.website_url || null, - phone: parkData.phone || null, - email: parkData.email || null, - banner_image_url: parkData.banner_image_url || null, - banner_image_id: parkData.banner_image_id || null, - card_image_url: parkData.card_image_url || null, - card_image_id: parkData.card_image_id || null, - operator_id: parkData.operator_id || null, - property_owner_id: parkData.property_owner_id || null - }; + // Everyone goes through submission queue + const { submitParkUpdate } = await import('@/lib/entitySubmissionHelpers'); + await submitParkUpdate(park.id, parkData, user.id); - const { error } = await supabase - .from('parks') - .update({ - ...updateData, - updated_at: new Date().toISOString() - }) - .eq('id', park.id); + toast({ + title: "Edit Submitted", + description: isModerator() + ? "Your edit has been submitted. You can approve it in the moderation queue." + : "Your park edit has been submitted for review.", + }); - if (error) throw error; - - toast({ - title: "Park Updated", - description: "The park has been updated successfully.", - }); - - setIsEditParkModalOpen(false); - fetchParkData(); - } else { - // Regular users submit for moderation - const { submitParkUpdate } = await import('@/lib/entitySubmissionHelpers'); - await submitParkUpdate(park.id, parkData, user.id); - - toast({ - title: "Edit Submitted", - description: "Your park edit has been submitted for review.", - }); - - setIsEditParkModalOpen(false); - } + setIsEditParkModalOpen(false); } catch (error: any) { toast({ title: "Error", - description: error.message || "Failed to update park.", + description: error.message || "Failed to submit park edit.", variant: "destructive" }); } diff --git a/src/pages/RideDetail.tsx b/src/pages/RideDetail.tsx index dfd988fc..62341c56 100644 --- a/src/pages/RideDetail.tsx +++ b/src/pages/RideDetail.tsx @@ -125,75 +125,21 @@ export default function RideDetail() { }; const handleEditSubmit = async (data: any) => { + if (!user || !ride) return; + try { - if (isModerator) { - // Moderators can edit directly - const { error } = await supabase - .from('rides') - .update({ - name: data.name, - slug: data.slug, - description: data.description, - category: data.category, - ride_sub_type: data.ride_sub_type, - status: data.status, - opening_date: data.opening_date, - closing_date: data.closing_date, - height_requirement: data.height_requirement, - age_requirement: data.age_requirement, - capacity_per_hour: data.capacity_per_hour, - duration_seconds: data.duration_seconds, - max_speed_kmh: data.max_speed_kmh, - max_height_meters: data.max_height_meters, - length_meters: data.length_meters, - inversions: data.inversions, - coaster_type: data.coaster_type, - seating_type: data.seating_type, - intensity_level: data.intensity_level, - drop_height_meters: data.drop_height_meters, - max_g_force: data.max_g_force, - banner_image_url: data.banner_image_url, - banner_image_id: data.banner_image_id, - card_image_url: data.card_image_url, - card_image_id: data.card_image_id, - manufacturer_id: data.manufacturer_id, - ride_model_id: data.ride_model_id, - updated_at: new Date().toISOString() - }) - .eq('id', ride?.id); + // Everyone goes through submission queue + const { submitRideUpdate } = await import('@/lib/entitySubmissionHelpers'); + await submitRideUpdate(ride.id, data, user.id); - if (error) throw error; + toast({ + title: "Edit Submitted", + description: isModerator + ? "Your edit has been submitted. You can approve it in the moderation queue." + : "Your ride edit has been submitted for review." + }); - toast({ - title: "Ride Updated", - description: "The ride has been updated successfully." - }); - - setIsEditModalOpen(false); - fetchRideData(); // Refresh the ride data - } else { - // Regular users submit for moderation - const { error } = await supabase - .from('content_submissions') - .insert({ - user_id: user?.id, - submission_type: 'ride_edit', - content: { - ride_id: ride?.id, - ...data - }, - status: 'pending' - }); - - if (error) throw error; - - toast({ - title: "Edit Submitted", - description: "Your edit has been submitted for review." - }); - - setIsEditModalOpen(false); - } + setIsEditModalOpen(false); } catch (error: any) { toast({ title: "Error",