Fix submission flow issues

This commit is contained in:
gpt-engineer-app[bot]
2025-11-02 20:21:10 +00:00
parent 4aa0c02769
commit 6a9df807fa
3 changed files with 83 additions and 37 deletions

View File

@@ -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,

View File

@@ -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)) {
resolved.manufacturer_id = dependencyMap.get(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)) {
resolved.operator_id = dependencyMap.get(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)) {
resolved.property_owner_id = dependencyMap.get(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)) {
resolved.ride_model_id = dependencyMap.get(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])) {

View File

@@ -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