Refactor moderation data fetching

This commit is contained in:
gpt-engineer-app[bot]
2025-11-04 16:56:49 +00:00
parent f32b8bdfee
commit feee859a50
4 changed files with 110 additions and 117 deletions

View File

@@ -48,125 +48,21 @@ export const SubmissionItemsList = memo(function SubmissionItemsList({
}
setError(null);
// Fetch submission items with entity data
// Note: entity_data is pre-loaded from the view, but we need to fetch from raw table
// when this component is used standalone
// Use database function to fetch submission items with entity data in one query
// This eliminates N+1 query problem and properly handles RLS/AAL2 checks
const { data: itemsData, error: itemsError } = await supabase
.from('submission_items')
.select('*')
.eq('submission_id', submissionId)
.order('order_index');
.rpc('get_submission_items_with_entities', {
p_submission_id: submissionId
});
if (itemsError) throw itemsError;
// Fetch entity data for each item based on item_type and typed FK columns
const transformedItems = await Promise.all(
(itemsData || []).map(async (item) => {
// Determine which FK column to use based on item_type
let itemDataId: string | null = null;
switch (item.item_type) {
case 'park':
itemDataId = item.park_submission_id;
break;
case 'ride':
itemDataId = item.ride_submission_id;
break;
case 'photo':
case 'photo_edit':
case 'photo_delete':
itemDataId = item.photo_submission_id;
break;
case 'manufacturer':
case 'operator':
case 'designer':
case 'property_owner':
itemDataId = item.company_submission_id;
break;
case 'ride_model':
itemDataId = item.ride_model_submission_id;
break;
case 'milestone':
case 'timeline_event':
itemDataId = item.timeline_event_submission_id;
break;
}
if (!itemDataId) {
return { ...item, item_data: {}, entity_data: null };
}
try {
let entityData = null;
// Fetch from appropriate table based on item_type
switch (item.item_type) {
case 'park': {
const { data } = await supabase
.from('park_submissions')
.select('*')
.eq('id', itemDataId)
.maybeSingle();
entityData = data as any;
break;
}
case 'ride': {
const { data } = await supabase
.from('ride_submissions')
.select('*')
.eq('id', itemDataId)
.maybeSingle();
entityData = data as any;
break;
}
case 'manufacturer':
case 'operator':
case 'designer':
case 'property_owner': {
const { data } = await supabase
.from('company_submissions')
.select('*')
.eq('id', itemDataId)
.maybeSingle();
entityData = data as any;
break;
}
case 'photo': {
const { data } = await supabase
.from('photo_submissions')
.select('*')
.eq('id', itemDataId)
.maybeSingle();
entityData = data as any;
break;
}
case 'ride_model': {
const { data } = await supabase
.from('ride_model_submissions')
.select('*')
.eq('id', itemDataId)
.maybeSingle();
entityData = data as any;
break;
}
default:
entityData = null;
}
return {
...item,
item_data: entityData || {},
entity_data: entityData
};
} catch (err) {
logger.warn('Failed to fetch entity data for item', {
itemId: item.id,
itemType: item.item_type,
error: getErrorMessage(err)
});
return { ...item, item_data: {}, entity_data: null };
}
})
);
// Transform to expected format
const transformedItems = (itemsData || []).map((item: any) => ({
...item,
item_data: item.entity_data || {},
entity_data: item.entity_data
}));
// Check for photo submissions (using array query to avoid 406)
const { data: photoData, error: photoError } = await supabase