@@ -146,7 +173,34 @@ export function SubmissionChangesDisplay({
);
}
- // Detailed view
+ // Detailed view - special handling for photo deletions
+ if (item.item_type === 'photo_delete') {
+ return (
+
+
+ {getEntityIcon()}
+
{changes.entityName}
+ {getActionBadge()}
+
+
+ {changes.photoChanges.length > 0 && changes.photoChanges[0].type === 'deleted' && (
+
+ )}
+
diff --git a/src/lib/submissionChangeDetection.ts b/src/lib/submissionChangeDetection.ts
index 8c225d80..1675a8cc 100644
--- a/src/lib/submissionChangeDetection.ts
+++ b/src/lib/submissionChangeDetection.ts
@@ -136,10 +136,13 @@ export async function detectChanges(
const itemData = item.item_data || {};
const originalData = item.original_data || {};
- // Determine action type
- const action: 'create' | 'edit' | 'delete' =
- !originalData || Object.keys(originalData).length === 0 ? 'create' :
- itemData.deleted ? 'delete' : 'edit';
+ // Determine action type - special handling for photo_delete
+ let action: 'create' | 'edit' | 'delete' = 'edit';
+ if (item.item_type === 'photo_delete' || itemData.action === 'delete' || itemData.deleted) {
+ action = 'delete';
+ } else if (!originalData || Object.keys(originalData).length === 0) {
+ action = 'create';
+ }
const fieldChanges: FieldChange[] = [];
const imageChanges: ImageChange[] = [];
@@ -269,22 +272,32 @@ export async function detectChanges(
const entityId = itemData.entity_id;
if (entityType === 'park') {
- const { data } = await supabase.from('parks').select('name').eq('id', entityId).single();
+ const { data } = await supabase.from('parks').select('name').eq('id', entityId).maybeSingle();
if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
} else if (entityType === 'ride') {
- const { data } = await supabase.from('rides').select('name').eq('id', entityId).single();
+ const { data } = await supabase.from('rides').select('name').eq('id', entityId).maybeSingle();
if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
} else if (entityType === 'ride_model') {
- const { data } = await supabase.from('ride_models').select('name').eq('id', entityId).single();
+ const { data } = await supabase.from('ride_models').select('name').eq('id', entityId).maybeSingle();
if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
} else if (['manufacturer', 'operator', 'designer', 'property_owner'].includes(entityType)) {
- const { data } = await supabase.from('companies').select('name').eq('id', entityId).single();
+ const { data } = await supabase.from('companies').select('name').eq('id', entityId).maybeSingle();
if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
}
} catch (err) {
- console.error('Error fetching entity name:', err);
+ console.error('Error fetching entity name for photo operation:', err);
}
}
+
+ // Add debugging warning if critical data is missing
+ if (!itemData.entity_name && item.item_type === 'photo_delete') {
+ console.warn(`[Photo Delete] Missing entity_name for photo_delete item`, {
+ item_type: item.item_type,
+ has_entity_type: !!itemData.entity_type,
+ has_entity_id: !!itemData.entity_id,
+ has_cloudflare_url: !!itemData.cloudflare_image_url
+ });
+ }
} else {
// For regular entities, use name field
entityName = itemData.name || originalData?.name || 'Unknown';
diff --git a/supabase/migrations/20251006182226_6c75308d-dc6d-4942-a793-45ddb48ad7a9.sql b/supabase/migrations/20251006182226_6c75308d-dc6d-4942-a793-45ddb48ad7a9.sql
new file mode 100644
index 00000000..d14082d6
--- /dev/null
+++ b/supabase/migrations/20251006182226_6c75308d-dc6d-4942-a793-45ddb48ad7a9.sql
@@ -0,0 +1,53 @@
+-- Phase 1: Fix existing photo_delete submissions with missing entity_name
+
+-- Create a function to backfill missing entity names for photo_delete submissions
+CREATE OR REPLACE FUNCTION backfill_photo_delete_entity_names()
+RETURNS void
+LANGUAGE plpgsql
+SECURITY DEFINER
+SET search_path TO 'public'
+AS $$
+DECLARE
+ item_record RECORD;
+ entity_name_value TEXT;
+BEGIN
+ -- Find all photo_delete submission_items missing entity_name
+ FOR item_record IN
+ SELECT id, item_data
+ FROM submission_items
+ WHERE item_type = 'photo_delete'
+ AND item_data->>'entity_name' IS NULL
+ AND item_data->>'entity_id' IS NOT NULL
+ AND item_data->>'entity_type' IS NOT NULL
+ LOOP
+ -- Fetch entity name based on entity_type
+ CASE item_record.item_data->>'entity_type'
+ WHEN 'park' THEN
+ SELECT name INTO entity_name_value FROM parks WHERE id = (item_record.item_data->>'entity_id')::uuid;
+ WHEN 'ride' THEN
+ SELECT name INTO entity_name_value FROM rides WHERE id = (item_record.item_data->>'entity_id')::uuid;
+ WHEN 'ride_model' THEN
+ SELECT name INTO entity_name_value FROM ride_models WHERE id = (item_record.item_data->>'entity_id')::uuid;
+ WHEN 'manufacturer', 'operator', 'designer', 'property_owner' THEN
+ SELECT name INTO entity_name_value FROM companies WHERE id = (item_record.item_data->>'entity_id')::uuid;
+ ELSE
+ entity_name_value := NULL;
+ END CASE;
+
+ -- Update the item_data if we found a name
+ IF entity_name_value IS NOT NULL THEN
+ UPDATE submission_items
+ SET item_data = item_data || jsonb_build_object('entity_name', entity_name_value)
+ WHERE id = item_record.id;
+
+ RAISE NOTICE 'Updated submission_item % with entity_name: %', item_record.id, entity_name_value;
+ END IF;
+ END LOOP;
+END;
+$$;
+
+-- Run the backfill function
+SELECT backfill_photo_delete_entity_names();
+
+-- Drop the function after use (optional, but keeps things clean)
+DROP FUNCTION IF EXISTS backfill_photo_delete_entity_names();
\ No newline at end of file