Refactor: Complete Photo System Refactor

This commit is contained in:
gpt-engineer-app[bot]
2025-10-01 23:19:35 +00:00
parent 5e4773e54c
commit 1beb8ad2be
7 changed files with 259 additions and 154 deletions

View File

@@ -503,38 +503,29 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
// Handle photo submissions - create photos records when approved
if (action === 'approved' && item.type === 'content_submission' && item.submission_type === 'photo') {
console.log('🖼️ [PHOTO APPROVAL] Starting photo submission approval');
console.log('🖼️ [PHOTO APPROVAL] Raw item:', item);
console.log('🖼️ [PHOTO APPROVAL] Item content type:', typeof item.content);
console.log('🖼️ [PHOTO APPROVAL] Item content keys:', Object.keys(item.content || {}));
try {
// Photo submissions have a simple structure: content contains { context, entity_id, photos }
const content = item.content;
const photosArray = content.photos;
const entityId = content.entity_id;
const entityType = content.context;
// Fetch photo submission from new relational tables
const { data: photoSubmission, error: fetchError } = await supabase
.from('photo_submissions')
.select(`
*,
items:photo_submission_items(*),
submission:content_submissions!inner(user_id, status)
`)
.eq('submission_id', item.id)
.single();
console.log('🖼️ [PHOTO APPROVAL] Extracted data:', {
photosArray,
entityId,
entityType,
hasPhotosArray: !!photosArray,
photosCount: photosArray?.length
});
console.log('🖼️ [PHOTO APPROVAL] Fetched photo submission:', photoSubmission);
if (!photosArray || !Array.isArray(photosArray) || photosArray.length === 0) {
console.error('🖼️ [PHOTO APPROVAL] ERROR: No photos found in submission');
throw new Error('No photos found in submission');
if (fetchError || !photoSubmission) {
console.error('🖼️ [PHOTO APPROVAL] ERROR: Failed to fetch photo submission:', fetchError);
throw new Error('Failed to fetch photo submission data');
}
if (!entityId || !entityType) {
console.error('🖼️ [PHOTO APPROVAL] ERROR: Invalid entity information', {
entityId,
entityType,
contentKeys: Object.keys(content),
fullContent: content
});
throw new Error('Invalid entity information in photo submission');
if (!photoSubmission.items || photoSubmission.items.length === 0) {
console.error('🖼️ [PHOTO APPROVAL] ERROR: No photo items found');
throw new Error('No photos found in submission');
}
// Check if photos already exist for this submission (in case of re-approval)
@@ -559,75 +550,38 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
})
.eq('id', item.id);
if (updateError) throw updateError;
toast({
title: "Photos Re-Approved",
description: `Photo submission re-approved (${existingPhotos.length} existing photo(s))`,
});
fetchItems(activeEntityFilter, activeStatusFilter);
return;
}
// Helper function to extract Cloudflare image ID from URL
const extractImageId = (url: string): string | null => {
try {
// URL format: https://imagedelivery.net/{account_hash}/{image_id}/public
const match = url.match(/\/([a-f0-9-]{36})\/public/i);
return match ? match[1] : null;
} catch (error) {
console.error('🖼️ [PHOTO APPROVAL] Error extracting image ID:', error);
return null;
}
};
// Create photo records in the photos table
const photoRecords = photosArray.map((photo, index) => {
const cloudflareImageUrl = photo.cloudflare_image_url || photo.url;
const cloudflareImageId = photo.cloudflare_image_id || photo.imageId || extractImageId(cloudflareImageUrl);
if (!cloudflareImageId || !cloudflareImageUrl) {
console.error('🖼️ [PHOTO APPROVAL] ERROR: Missing Cloudflare fields', {
photo,
cloudflareImageId,
cloudflareImageUrl
});
throw new Error('Missing required Cloudflare image fields');
}
const record = {
entity_id: entityId,
entity_type: entityType,
cloudflare_image_id: cloudflareImageId,
cloudflare_image_url: cloudflareImageUrl,
title: photo.title || null,
caption: photo.caption || null,
date_taken: photo.date || null,
order_index: photo.order ?? index,
submission_id: item.id,
submitted_by: item.user_id,
} else {
// Create new photo records from photo_submission_items
const photoRecords = photoSubmission.items.map((item) => ({
entity_id: photoSubmission.entity_id,
entity_type: photoSubmission.entity_type,
cloudflare_image_id: item.cloudflare_image_id,
cloudflare_image_url: item.cloudflare_image_url,
title: item.title || null,
caption: item.caption || null,
date_taken: item.date_taken || null,
order_index: item.order_index,
submission_id: photoSubmission.submission_id,
submitted_by: photoSubmission.submission?.user_id,
approved_by: user?.id,
approved_at: new Date().toISOString(),
};
console.log('🖼️ [PHOTO APPROVAL] Photo record to insert:', record);
return record;
});
console.log('🖼️ [PHOTO APPROVAL] Attempting to insert photo records:', photoRecords);
const { data: createdPhotos, error: photoError } = await supabase
.from('photos')
.insert(photoRecords)
.select();
if (photoError) {
console.error('🖼️ [PHOTO APPROVAL] Database error creating photos:', photoError);
throw new Error(`Failed to create photos: ${photoError.message}`);
}));
console.log('🖼️ [PHOTO APPROVAL] Creating photo records:', photoRecords);
const { data: createdPhotos, error: insertError } = await supabase
.from('photos')
.insert(photoRecords)
.select();
if (insertError) {
console.error('🖼️ [PHOTO APPROVAL] ERROR: Failed to insert photos:', insertError);
throw insertError;
}
console.log('🖼️ [PHOTO APPROVAL] ✅ Successfully created photos:', createdPhotos);
}
console.log('🖼️ [PHOTO APPROVAL] Successfully created photo records:', createdPhotos);
// Update submission status
const { error: updateError } = await supabase
.from('content_submissions')
@@ -644,11 +598,11 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
throw updateError;
}
console.log('🖼️ [PHOTO APPROVAL] ✅ Complete! Created', createdPhotos.length, 'photos');
console.log('🖼️ [PHOTO APPROVAL] ✅ Complete! Photos approved and published');
toast({
title: "Photos Approved",
description: `Successfully approved ${createdPhotos.length} photo(s)`,
description: `Successfully approved and published ${photoSubmission.items.length} photo(s)`,
});
// Refresh the queue