mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 04:31:13 -05:00
Reverted to commit 0091584677
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Camera, Upload, LogIn, Settings, ArrowUpDown } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
@@ -14,10 +14,11 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { UppyPhotoSubmissionUpload } from '@/components/upload/UppyPhotoSubmissionUpload';
|
||||
import { PhotoManagementDialog } from '@/components/upload/PhotoManagementDialog';
|
||||
import { PhotoModal } from '@/components/moderation/PhotoModal';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { EntityPhotoGalleryProps } from '@/types/submissions';
|
||||
import { useUserRole } from '@/hooks/useUserRole';
|
||||
import { useEntityPhotos } from '@/hooks/photos/useEntityPhotos';
|
||||
import { useQueryInvalidation } from '@/lib/queryInvalidation';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { logger } from '@/lib/logger';
|
||||
|
||||
interface Photo {
|
||||
id: string;
|
||||
@@ -37,25 +38,47 @@ export function EntityPhotoGallery({
|
||||
const { user } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const { isModerator } = useUserRole();
|
||||
const [photos, setPhotos] = useState<Photo[]>([]);
|
||||
const [showUpload, setShowUpload] = useState(false);
|
||||
const [showManagement, setShowManagement] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedPhotoIndex, setSelectedPhotoIndex] = useState<number | null>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [sortBy, setSortBy] = useState<'newest' | 'oldest'>('newest');
|
||||
|
||||
// Use optimized photos hook with caching
|
||||
const { data: photos = [], isLoading: loading, refetch } = useEntityPhotos(
|
||||
entityType,
|
||||
entityId,
|
||||
sortBy
|
||||
);
|
||||
useEffect(() => {
|
||||
fetchPhotos();
|
||||
}, [entityId, entityType, sortBy]);
|
||||
|
||||
// Query invalidation for cross-component cache updates
|
||||
const {
|
||||
invalidateEntityPhotos,
|
||||
invalidatePhotoCount,
|
||||
invalidateHomepageData
|
||||
} = useQueryInvalidation();
|
||||
const fetchPhotos = async () => {
|
||||
try {
|
||||
// Fetch photos directly from the photos table
|
||||
const { data: photoData, error } = await supabase
|
||||
.from('photos')
|
||||
.select('id, cloudflare_image_url, title, caption, submitted_by, created_at, order_index')
|
||||
.eq('entity_type', entityType)
|
||||
.eq('entity_id', entityId)
|
||||
.order('created_at', { ascending: sortBy === 'oldest' });
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
// Map to Photo interface
|
||||
const mappedPhotos: Photo[] = photoData?.map((photo) => ({
|
||||
id: photo.id,
|
||||
url: photo.cloudflare_image_url,
|
||||
caption: photo.caption || undefined,
|
||||
title: photo.title || undefined,
|
||||
user_id: photo.submitted_by,
|
||||
created_at: photo.created_at,
|
||||
})) || [];
|
||||
|
||||
setPhotos(mappedPhotos);
|
||||
} catch (error: unknown) {
|
||||
logger.error('Failed to fetch photos', { error: getErrorMessage(error), entityId, entityType });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUploadClick = () => {
|
||||
if (!user) {
|
||||
@@ -67,14 +90,7 @@ export function EntityPhotoGallery({
|
||||
|
||||
const handleSubmissionComplete = () => {
|
||||
setShowUpload(false);
|
||||
|
||||
// Invalidate all related caches
|
||||
invalidateEntityPhotos(entityType, entityId);
|
||||
invalidatePhotoCount(entityType, entityId);
|
||||
invalidateHomepageData(); // Photos affect homepage stats
|
||||
|
||||
// Also refetch local component (immediate UI update)
|
||||
refetch();
|
||||
fetchPhotos(); // Refresh photos after submission
|
||||
};
|
||||
|
||||
const handlePhotoClick = (index: number) => {
|
||||
@@ -174,7 +190,7 @@ export function EntityPhotoGallery({
|
||||
entityType={entityType}
|
||||
open={showManagement}
|
||||
onOpenChange={setShowManagement}
|
||||
onUpdate={() => refetch()}
|
||||
onUpdate={fetchPhotos}
|
||||
/>
|
||||
|
||||
{/* Photo Grid */}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { useEntityName } from '@/hooks/entities/useEntityName';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
@@ -61,9 +60,6 @@ export function PhotoManagementDialog({
|
||||
const [photoToDelete, setPhotoToDelete] = useState<Photo | null>(null);
|
||||
const [deleteReason, setDeleteReason] = useState('');
|
||||
const { toast } = useToast();
|
||||
|
||||
// Fetch entity name once using cached hook (replaces 4 sequential direct queries)
|
||||
const { data: entityName = 'Unknown' } = useEntityName(entityType, entityId);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
@@ -110,6 +106,27 @@ export function PhotoManagementDialog({
|
||||
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 (err) {
|
||||
logger.error('Failed to fetch entity name', { error: getErrorMessage(err), entityType, entityId });
|
||||
}
|
||||
|
||||
// Create content submission
|
||||
const { data: submission, error: submissionError } = await supabase
|
||||
.from('content_submissions')
|
||||
|
||||
Reference in New Issue
Block a user