diff --git a/src/components/moderation/EntityEditPreview.tsx b/src/components/moderation/EntityEditPreview.tsx new file mode 100644 index 00000000..1d4261f3 --- /dev/null +++ b/src/components/moderation/EntityEditPreview.tsx @@ -0,0 +1,191 @@ +import { useState, useEffect } from 'react'; +import { Badge } from '@/components/ui/badge'; +import { Card, CardContent } from '@/components/ui/card'; +import { supabase } from '@/integrations/supabase/client'; +import { Image as ImageIcon } from 'lucide-react'; + +interface EntityEditPreviewProps { + submissionId: string; + entityType: string; + entityName?: string; +} + +interface ImageAssignments { + uploaded: Array<{ + url: string; + cloudflare_id: string; + }>; + banner_assignment: number | null; + card_assignment: number | null; +} + +interface SubmissionItemData { + id: string; + item_data: any; + original_data?: any; +} + +export const EntityEditPreview = ({ submissionId, entityType, entityName }: EntityEditPreviewProps) => { + const [loading, setLoading] = useState(true); + const [itemData, setItemData] = useState(null); + const [originalData, setOriginalData] = useState(null); + const [changedFields, setChangedFields] = useState([]); + const [bannerImageUrl, setBannerImageUrl] = useState(null); + const [cardImageUrl, setCardImageUrl] = useState(null); + + useEffect(() => { + fetchSubmissionItems(); + }, [submissionId]); + + const fetchSubmissionItems = async () => { + try { + setLoading(true); + + const { data: items, error } = await supabase + .from('submission_items') + .select('*') + .eq('submission_id', submissionId) + .order('order_index', { ascending: true }); + + if (error) throw error; + + if (items && items.length > 0) { + const firstItem = items[0]; + setItemData(firstItem.item_data); + setOriginalData(firstItem.original_data); + + // Parse changed fields + const changed: string[] = []; + const data = firstItem.item_data as any; + + // Check for image changes + if (data.images) { + const images: ImageAssignments = data.images; + + // Extract banner image + if (images.banner_assignment !== null && images.banner_assignment !== undefined) { + const bannerImg = images.uploaded[images.banner_assignment]; + if (bannerImg) { + setBannerImageUrl(bannerImg.url); + changed.push('banner_image'); + } + } + + // Extract card image + if (images.card_assignment !== null && images.card_assignment !== undefined) { + const cardImg = images.uploaded[images.card_assignment]; + if (cardImg) { + setCardImageUrl(cardImg.url); + changed.push('card_image'); + } + } + } + + // Check for other field changes by comparing with original_data + if (firstItem.original_data) { + const originalData = firstItem.original_data as any; + const excludeFields = ['images', 'updated_at', 'created_at']; + Object.keys(data).forEach(key => { + if (!excludeFields.includes(key) && + data[key] !== originalData[key]) { + changed.push(key); + } + }); + } + + setChangedFields(changed); + } + } catch (error) { + console.error('Error fetching submission items:', error); + } finally { + setLoading(false); + } + }; + + if (loading) { + return ( +
+ Loading preview... +
+ ); + } + + if (!itemData) { + return ( +
+ No preview available +
+ ); + } + + return ( +
+
+ + {entityType} + + + Edit + +
+ + {entityName && ( +
+ {entityName} +
+ )} + + {changedFields.length > 0 && ( +
+ Changed fields: + + {changedFields.map(field => field.replace(/_/g, ' ')).join(', ')} + +
+ )} + + {(bannerImageUrl || cardImageUrl) && ( +
+
+ + Image Changes: +
+
+ {bannerImageUrl && ( + + + New banner +
+ Banner +
+
+
+ )} + {cardImageUrl && ( + + + New card +
+ Card +
+
+
+ )} +
+
+ )} + +
+ Click "Review Items" for full details +
+
+ ); +}; diff --git a/src/components/moderation/ModerationQueue.tsx b/src/components/moderation/ModerationQueue.tsx index e56078cc..aaf4c14c 100644 --- a/src/components/moderation/ModerationQueue.tsx +++ b/src/components/moderation/ModerationQueue.tsx @@ -16,6 +16,7 @@ import { PhotoModal } from './PhotoModal'; import { SubmissionReviewManager } from './SubmissionReviewManager'; import { useRealtimeSubmissions } from '@/hooks/useRealtimeSubmissions'; import { useIsMobile } from '@/hooks/use-mobile'; +import { EntityEditPreview } from './EntityEditPreview'; interface ModerationItem { id: string; @@ -1332,20 +1333,11 @@ export const ModerationQueue = forwardRef((props, ref) => { item.submission_type === 'property_owner' || item.submission_type === 'park' || item.submission_type === 'ride') ? ( -
-
- - {item.submission_type} - - - {item.content.action === 'create' ? 'New' : 'Edit'} - -
- -
- This is a complex submission with items. Click "Review Items" to see details. -
-
+ ) : (