import { useState, useEffect } from 'react'; import { supabase } from '@/lib/supabaseClient'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { useToast } from '@/hooks/use-toast'; import { Trash2, Pencil } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { getErrorMessage } from '@/lib/errorHandler'; interface Photo { id: string; cloudflare_image_id: string; cloudflare_image_url: string; title: string | null; caption: string | null; order_index: number; is_featured: boolean; } interface PhotoManagementDialogProps { entityId: string; entityType: string; open: boolean; onOpenChange: (open: boolean) => void; onUpdate?: () => void; } export function PhotoManagementDialog({ entityId, entityType, open, onOpenChange, onUpdate, }: PhotoManagementDialogProps) { const [photos, setPhotos] = useState([]); const [loading, setLoading] = useState(false); const [editingPhoto, setEditingPhoto] = useState(null); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [photoToDelete, setPhotoToDelete] = useState(null); const [deleteReason, setDeleteReason] = useState(''); const { toast } = useToast(); useEffect(() => { if (open) { fetchPhotos(); } }, [open, entityId, entityType]); const fetchPhotos = async () => { setLoading(true); try { const { data, error } = await supabase .from('photos') .select('id, cloudflare_image_id, cloudflare_image_url, title, caption, order_index, is_featured') .eq('entity_type', entityType) .eq('entity_id', entityId) .order('order_index', { ascending: true }); if (error) throw error; setPhotos((data || []).map(p => ({ ...p, order_index: p.order_index ?? 0, is_featured: p.is_featured ?? false })) as Photo[]); } catch (error: unknown) { toast({ title: 'Error', description: getErrorMessage(error), variant: 'destructive', }); } finally { setLoading(false); } }; const handleDeleteClick = (photo: Photo) => { setPhotoToDelete(photo); setDeleteReason(''); setDeleteDialogOpen(true); }; const requestPhotoDelete = async () => { if (!photoToDelete || !deleteReason.trim()) return; try { // Get current user const { data: { user } } = await supabase.auth.getUser(); if (!user) throw new Error('Not authenticated'); // Fetch entity name from database based on entity type let entityName = 'Unknown'; try { if (entityType === 'park') { const { data } = await supabase.from('parks').select('name').eq('id', entityId).single(); if (data?.name) entityName = data.name; } else if (entityType === 'ride') { const { data } = await supabase.from('rides').select('name').eq('id', entityId).single(); if (data?.name) entityName = data.name; } else if (entityType === 'ride_model') { const { data } = await supabase.from('ride_models').select('name').eq('id', entityId).single(); if (data?.name) entityName = data.name; } else if (['manufacturer', 'operator', 'designer', 'property_owner'].includes(entityType)) { const { data } = await supabase.from('companies').select('name').eq('id', entityId).single(); if (data?.name) entityName = data.name; } } catch { // Failed to fetch entity name - use default } // Create content submission const { data: submission, error: submissionError } = await supabase .from('content_submissions') .insert([{ user_id: user.id, submission_type: 'photo_delete', content: { action: 'delete', photo_id: photoToDelete.id } }]) .select() .single(); if (submissionError) throw submissionError; // Create submission item with all necessary data const { error: itemError } = await supabase .from('submission_items') .insert({ submission_id: submission.id, item_type: 'photo_delete', item_data: { photo_id: photoToDelete.id, cloudflare_image_id: photoToDelete.cloudflare_image_id, entity_type: entityType, entity_id: entityId, entity_name: entityName, cloudflare_image_url: photoToDelete.cloudflare_image_url, title: photoToDelete.title, caption: photoToDelete.caption, deletion_reason: deleteReason }, status: 'pending' }); if (itemError) throw itemError; toast({ title: 'Delete request submitted', description: 'Your photo deletion request has been submitted for moderation', }); setDeleteDialogOpen(false); setPhotoToDelete(null); setDeleteReason(''); onOpenChange(false); } catch (error: unknown) { toast({ title: 'Error', description: getErrorMessage(error), variant: 'destructive', }); } }; const requestPhotoEdit = async () => { if (!editingPhoto) return; try { // Get current user const { data: { user } } = await supabase.auth.getUser(); if (!user) throw new Error('Not authenticated'); // Get original photo data const originalPhoto = photos.find(p => p.id === editingPhoto.id); if (!originalPhoto) throw new Error('Original photo not found'); // Create content submission const { data: submission, error: submissionError } = await supabase .from('content_submissions') .insert([{ user_id: user.id, submission_type: 'photo_edit', content: { action: 'edit', photo_id: editingPhoto.id } }]) .select() .single(); if (submissionError) throw submissionError; // Create submission item const { error: itemError } = await supabase .from('submission_items') .insert({ submission_id: submission.id, item_type: 'photo_edit', item_data: { photo_id: editingPhoto.id, entity_type: entityType, entity_id: entityId, new_caption: editingPhoto.caption, cloudflare_image_url: editingPhoto.cloudflare_image_url, }, original_data: { caption: originalPhoto.caption, }, status: 'pending' }); if (itemError) throw itemError; setEditingPhoto(null); toast({ title: 'Edit request submitted', description: 'Your photo edit has been submitted for moderation', }); onOpenChange(false); } catch (error: unknown) { toast({ title: 'Error', description: getErrorMessage(error), variant: 'destructive', }); } }; if (editingPhoto) { return ( Edit Photo Update photo caption
{editingPhoto.caption