feat: Add lightbox support to photo galleries

This commit is contained in:
gpt-engineer-app[bot]
2025-10-02 13:31:28 +00:00
parent fbc396f6ed
commit 9cd95951a2

View File

@@ -6,6 +6,7 @@ import { useAuth } from '@/hooks/useAuth';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { UppyPhotoSubmissionUpload } from '@/components/upload/UppyPhotoSubmissionUpload'; import { UppyPhotoSubmissionUpload } from '@/components/upload/UppyPhotoSubmissionUpload';
import { PhotoManagementDialog } from '@/components/upload/PhotoManagementDialog'; import { PhotoManagementDialog } from '@/components/upload/PhotoManagementDialog';
import { PhotoModal } from '@/components/moderation/PhotoModal';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { EntityPhotoGalleryProps } from '@/types/submissions'; import { EntityPhotoGalleryProps } from '@/types/submissions';
import { useUserRole } from '@/hooks/useUserRole'; import { useUserRole } from '@/hooks/useUserRole';
@@ -32,6 +33,8 @@ export function EntityPhotoGallery({
const [showUpload, setShowUpload] = useState(false); const [showUpload, setShowUpload] = useState(false);
const [showManagement, setShowManagement] = useState(false); const [showManagement, setShowManagement] = useState(false);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [selectedPhotoIndex, setSelectedPhotoIndex] = useState<number | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
useEffect(() => { useEffect(() => {
fetchPhotos(); fetchPhotos();
@@ -86,6 +89,16 @@ export function EntityPhotoGallery({
fetchPhotos(); // Refresh photos after submission fetchPhotos(); // Refresh photos after submission
}; };
const handlePhotoClick = (index: number) => {
setSelectedPhotoIndex(index);
setIsModalOpen(true);
};
const handleCloseModal = () => {
setIsModalOpen(false);
setSelectedPhotoIndex(null);
};
if (showUpload) { if (showUpload) {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
@@ -161,13 +174,14 @@ export function EntityPhotoGallery({
{/* Photo Grid */} {/* Photo Grid */}
{photos.length > 0 ? ( {photos.length > 0 ? (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{photos.map((photo) => ( {photos.map((photo, index) => (
<Card key={photo.id} className="overflow-hidden"> <Card key={photo.id} className="overflow-hidden">
<CardContent className="p-0"> <CardContent className="p-0">
<img <img
src={photo.url} src={photo.url}
alt={photo.title || photo.caption || `${entityName} photo`} alt={photo.title || photo.caption || `${entityName} photo`}
className="w-full h-48 object-cover hover:scale-105 transition-transform cursor-pointer" className="w-full h-48 object-cover hover:scale-105 transition-transform cursor-pointer"
onClick={() => handlePhotoClick(index)}
/> />
{(photo.title || photo.caption) && ( {(photo.title || photo.caption) && (
<div className="p-3"> <div className="p-3">
@@ -207,6 +221,21 @@ export function EntityPhotoGallery({
</Button> </Button>
</div> </div>
)} )}
{/* Photo Lightbox Modal */}
{selectedPhotoIndex !== null && (
<PhotoModal
photos={photos.map(photo => ({
id: photo.id,
url: photo.url,
caption: photo.caption,
filename: photo.title,
}))}
initialIndex={selectedPhotoIndex}
isOpen={isModalOpen}
onClose={handleCloseModal}
/>
)}
</div> </div>
); );
} }