mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 11:31:11 -05:00
Fix submission flow issues
This commit is contained in:
@@ -223,10 +223,23 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
|
||||
submissionContent.park.property_owner_id = null;
|
||||
}
|
||||
|
||||
const finalOperatorId = tempNewOperator ? undefined : (selectedOperatorId || undefined);
|
||||
const finalPropertyOwnerId = operatorIsOwner
|
||||
? finalOperatorId
|
||||
: (tempNewPropertyOwner ? undefined : (selectedPropertyOwnerId || undefined));
|
||||
// Determine final IDs to pass
|
||||
// When creating new entities via composite submission, IDs should be undefined
|
||||
// When using existing entities, pass their IDs directly
|
||||
let finalOperatorId: string | undefined;
|
||||
let finalPropertyOwnerId: string | undefined;
|
||||
|
||||
if (tempNewOperator) {
|
||||
// New operator being created via composite submission
|
||||
finalOperatorId = undefined;
|
||||
finalPropertyOwnerId = operatorIsOwner ? undefined :
|
||||
(tempNewPropertyOwner ? undefined : selectedPropertyOwnerId);
|
||||
} else {
|
||||
// Using existing operator
|
||||
finalOperatorId = selectedOperatorId || undefined;
|
||||
finalPropertyOwnerId = operatorIsOwner ? finalOperatorId :
|
||||
(tempNewPropertyOwner ? undefined : selectedPropertyOwnerId);
|
||||
}
|
||||
|
||||
await onSubmit({
|
||||
...data,
|
||||
|
||||
@@ -185,24 +185,25 @@ export async function approveSubmissionItems(
|
||||
);
|
||||
|
||||
// Create the entity based on type with dependency resolution
|
||||
// PASS sortedItems to enable correct index-based resolution
|
||||
switch (item.item_type) {
|
||||
case 'park':
|
||||
entityId = await createPark(item.item_data, dependencyMap);
|
||||
entityId = await createPark(item.item_data, dependencyMap, sortedItems);
|
||||
break;
|
||||
case 'ride':
|
||||
entityId = await createRide(item.item_data, dependencyMap);
|
||||
entityId = await createRide(item.item_data, dependencyMap, sortedItems);
|
||||
break;
|
||||
case 'manufacturer':
|
||||
case 'operator':
|
||||
case 'property_owner':
|
||||
case 'designer':
|
||||
entityId = await createCompany(item.item_data, item.item_type, dependencyMap);
|
||||
entityId = await createCompany(item.item_data, item.item_type, dependencyMap, sortedItems);
|
||||
break;
|
||||
case 'ride_model':
|
||||
entityId = await createRideModel(item.item_data, dependencyMap);
|
||||
entityId = await createRideModel(item.item_data, dependencyMap, sortedItems);
|
||||
break;
|
||||
case 'photo':
|
||||
entityId = await approvePhotos(item.item_data, dependencyMap, userId, item.submission_id);
|
||||
entityId = await approvePhotos(item.item_data, dependencyMap, userId, item.submission_id, sortedItems);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -343,7 +344,7 @@ function extractImageAssignments(images: any) {
|
||||
/**
|
||||
* Helper functions to create entities with dependency resolution
|
||||
*/
|
||||
async function createPark(data: any, dependencyMap: Map<string, string>): Promise<string> {
|
||||
async function createPark(data: any, dependencyMap: Map<string, string>, sortedItems: SubmissionItemWithDeps[]): Promise<string> {
|
||||
const { transformParkData, validateSubmissionData } = await import('./entityTransformers');
|
||||
const { ensureUniqueSlug } = await import('./slugUtils');
|
||||
|
||||
@@ -352,7 +353,7 @@ async function createPark(data: any, dependencyMap: Map<string, string>): Promis
|
||||
|
||||
if (isEdit) {
|
||||
// Handle park edit
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
// Resolve location_id if location data is provided
|
||||
let locationId = resolvedData.location_id;
|
||||
@@ -401,7 +402,7 @@ async function createPark(data: any, dependencyMap: Map<string, string>): Promis
|
||||
|
||||
// Handle park creation
|
||||
validateSubmissionData(data, 'Park');
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
// Resolve location_id if location data is provided
|
||||
let locationId = resolvedData.location_id;
|
||||
@@ -498,7 +499,7 @@ async function resolveLocationId(locationData: any): Promise<string | null> {
|
||||
return newLocation.id;
|
||||
}
|
||||
|
||||
async function createRide(data: any, dependencyMap: Map<string, string>): Promise<string> {
|
||||
async function createRide(data: any, dependencyMap: Map<string, string>, sortedItems: SubmissionItemWithDeps[]): Promise<string> {
|
||||
const { transformRideData, validateSubmissionData } = await import('./entityTransformers');
|
||||
const { ensureUniqueSlug } = await import('./slugUtils');
|
||||
|
||||
@@ -507,7 +508,7 @@ async function createRide(data: any, dependencyMap: Map<string, string>): Promis
|
||||
|
||||
if (isEdit) {
|
||||
// Handle ride edit
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
// Extract image assignments from ImageAssignments structure
|
||||
const imageData = extractImageAssignments(resolvedData.images);
|
||||
@@ -556,7 +557,7 @@ async function createRide(data: any, dependencyMap: Map<string, string>): Promis
|
||||
|
||||
// Handle ride creation
|
||||
validateSubmissionData(data, 'Ride');
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
if (!resolvedData.park_id) {
|
||||
throw new Error('Ride must be associated with a park');
|
||||
@@ -588,7 +589,8 @@ async function createRide(data: any, dependencyMap: Map<string, string>): Promis
|
||||
async function createCompany(
|
||||
data: any,
|
||||
companyType: string,
|
||||
dependencyMap: Map<string, string>
|
||||
dependencyMap: Map<string, string>,
|
||||
sortedItems: SubmissionItemWithDeps[]
|
||||
): Promise<string> {
|
||||
const { transformCompanyData, validateSubmissionData } = await import('./entityTransformers');
|
||||
const { ensureUniqueSlug } = await import('./slugUtils');
|
||||
@@ -598,7 +600,7 @@ async function createCompany(
|
||||
|
||||
if (isEdit) {
|
||||
// Handle company edit
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
// Extract image assignments from ImageAssignments structure
|
||||
const imageData = extractImageAssignments(resolvedData.images);
|
||||
@@ -630,7 +632,7 @@ async function createCompany(
|
||||
|
||||
// Handle company creation
|
||||
validateSubmissionData(data, 'Company');
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
const uniqueSlug = await ensureUniqueSlug(resolvedData.slug, 'companies');
|
||||
resolvedData.slug = uniqueSlug;
|
||||
@@ -663,7 +665,7 @@ async function createCompany(
|
||||
return company.id;
|
||||
}
|
||||
|
||||
async function createRideModel(data: any, dependencyMap: Map<string, string>): Promise<string> {
|
||||
async function createRideModel(data: any, dependencyMap: Map<string, string>, sortedItems: SubmissionItemWithDeps[]): Promise<string> {
|
||||
const { transformRideModelData, validateSubmissionData } = await import('./entityTransformers');
|
||||
const { ensureUniqueSlug } = await import('./slugUtils');
|
||||
|
||||
@@ -672,7 +674,7 @@ async function createRideModel(data: any, dependencyMap: Map<string, string>): P
|
||||
|
||||
if (isEdit) {
|
||||
// Handle ride model edit
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
// Extract image assignments from ImageAssignments structure
|
||||
const imageData = extractImageAssignments(resolvedData.images);
|
||||
@@ -704,7 +706,7 @@ async function createRideModel(data: any, dependencyMap: Map<string, string>): P
|
||||
|
||||
// Handle ride model creation
|
||||
validateSubmissionData(data, 'Ride Model');
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
// Validate manufacturer_id is present (required for ride models)
|
||||
if (!resolvedData.manufacturer_id) {
|
||||
@@ -739,10 +741,10 @@ async function createRideModel(data: any, dependencyMap: Map<string, string>): P
|
||||
return model.id;
|
||||
}
|
||||
|
||||
async function approvePhotos(data: any, dependencyMap: Map<string, string>, userId: string, submissionId: string): Promise<string> {
|
||||
async function approvePhotos(data: any, dependencyMap: Map<string, string>, userId: string, submissionId: string, sortedItems: SubmissionItemWithDeps[]): Promise<string> {
|
||||
// Photos are already uploaded to Cloudflare
|
||||
// Resolve dependencies for entity associations
|
||||
const resolvedData = resolveDependencies(data, dependencyMap);
|
||||
const resolvedData = resolveDependencies(data, dependencyMap, sortedItems);
|
||||
|
||||
if (!resolvedData.photos || !Array.isArray(resolvedData.photos) || resolvedData.photos.length === 0) {
|
||||
throw new Error('No photos found in submission');
|
||||
@@ -900,8 +902,11 @@ async function updateEntityFeaturedImage(
|
||||
/**
|
||||
* Resolve dependency references in item_data by looking up approved entity IDs
|
||||
* Replaces temporary references (_temp_*_ref) with actual database entity IDs
|
||||
*
|
||||
* FIXED: Now uses sortedItems array for stable index-based resolution
|
||||
* instead of unreliable Array.from(dependencyMap.keys())[refIndex]
|
||||
*/
|
||||
function resolveDependencies(data: any, dependencyMap: Map<string, string>): any {
|
||||
function resolveDependencies(data: any, dependencyMap: Map<string, string>, sortedItems: SubmissionItemWithDeps[]): any {
|
||||
const resolved = { ...data };
|
||||
|
||||
// List of foreign key fields that may need resolution
|
||||
@@ -915,43 +920,62 @@ function resolveDependencies(data: any, dependencyMap: Map<string, string>): any
|
||||
'location_id',
|
||||
];
|
||||
|
||||
// Resolve temporary references first
|
||||
// Resolve temporary references using sortedItems array (FIXED)
|
||||
if (resolved._temp_manufacturer_ref !== undefined) {
|
||||
const refIndex = resolved._temp_manufacturer_ref;
|
||||
const refItemId = Array.from(dependencyMap.keys())[refIndex];
|
||||
if (refItemId && dependencyMap.has(refItemId)) {
|
||||
if (refIndex >= 0 && refIndex < sortedItems.length) {
|
||||
const refItemId = sortedItems[refIndex].id;
|
||||
if (dependencyMap.has(refItemId)) {
|
||||
resolved.manufacturer_id = dependencyMap.get(refItemId);
|
||||
}
|
||||
}
|
||||
delete resolved._temp_manufacturer_ref;
|
||||
}
|
||||
|
||||
if (resolved._temp_operator_ref !== undefined) {
|
||||
const refIndex = resolved._temp_operator_ref;
|
||||
const refItemId = Array.from(dependencyMap.keys())[refIndex];
|
||||
if (refItemId && dependencyMap.has(refItemId)) {
|
||||
if (refIndex >= 0 && refIndex < sortedItems.length) {
|
||||
const refItemId = sortedItems[refIndex].id;
|
||||
if (dependencyMap.has(refItemId)) {
|
||||
resolved.operator_id = dependencyMap.get(refItemId);
|
||||
}
|
||||
}
|
||||
delete resolved._temp_operator_ref;
|
||||
}
|
||||
|
||||
if (resolved._temp_property_owner_ref !== undefined) {
|
||||
const refIndex = resolved._temp_property_owner_ref;
|
||||
const refItemId = Array.from(dependencyMap.keys())[refIndex];
|
||||
if (refItemId && dependencyMap.has(refItemId)) {
|
||||
if (refIndex >= 0 && refIndex < sortedItems.length) {
|
||||
const refItemId = sortedItems[refIndex].id;
|
||||
if (dependencyMap.has(refItemId)) {
|
||||
resolved.property_owner_id = dependencyMap.get(refItemId);
|
||||
}
|
||||
}
|
||||
delete resolved._temp_property_owner_ref;
|
||||
}
|
||||
|
||||
if (resolved._temp_ride_model_ref !== undefined) {
|
||||
const refIndex = resolved._temp_ride_model_ref;
|
||||
const refItemId = Array.from(dependencyMap.keys())[refIndex];
|
||||
if (refItemId && dependencyMap.has(refItemId)) {
|
||||
if (refIndex >= 0 && refIndex < sortedItems.length) {
|
||||
const refItemId = sortedItems[refIndex].id;
|
||||
if (dependencyMap.has(refItemId)) {
|
||||
resolved.ride_model_id = dependencyMap.get(refItemId);
|
||||
}
|
||||
}
|
||||
delete resolved._temp_ride_model_ref;
|
||||
}
|
||||
|
||||
if (resolved._temp_designer_ref !== undefined) {
|
||||
const refIndex = resolved._temp_designer_ref;
|
||||
if (refIndex >= 0 && refIndex < sortedItems.length) {
|
||||
const refItemId = sortedItems[refIndex].id;
|
||||
if (dependencyMap.has(refItemId)) {
|
||||
resolved.designer_id = dependencyMap.get(refItemId);
|
||||
}
|
||||
}
|
||||
delete resolved._temp_designer_ref;
|
||||
}
|
||||
|
||||
// Resolve each foreign key if it's a submission item ID
|
||||
for (const key of foreignKeys) {
|
||||
if (resolved[key] && dependencyMap.has(resolved[key])) {
|
||||
|
||||
@@ -1301,6 +1301,15 @@ async function createRideModel(supabase: any, data: any): Promise<string> {
|
||||
if (error) throw new Error(`Failed to update ride model: ${error.message}`);
|
||||
} else {
|
||||
console.log('Creating new ride model');
|
||||
|
||||
// Validate required fields
|
||||
if (!data.manufacturer_id) {
|
||||
throw new Error('Ride model must be associated with a manufacturer');
|
||||
}
|
||||
if (!data.name || !data.slug) {
|
||||
throw new Error('Ride model must have a name and slug');
|
||||
}
|
||||
|
||||
const sanitizedData = sanitizeDateFields(data);
|
||||
const filteredData = filterDatabaseFields(sanitizedData, RIDE_MODEL_FIELDS);
|
||||
const { data: model, error } = await supabase
|
||||
|
||||
Reference in New Issue
Block a user