import React, { useState, useEffect } from 'react'; import { Package } from 'lucide-react'; import { toast as toastify } from 'react-toastify'; import { useTranslation } from 'react-i18next'; import type { Photo } from '../../types'; import { useDownloadPhoto } from '../../hooks/useGallery'; import { PhotoLightbox } from './PhotoLightbox'; import { Button } from '../common'; import { galleryService } from '../../services/gallery.service'; import { analyticsService } from '../../services/analytics.service'; import { useTheme } from '../../contexts/ThemeContext'; // Import all layouts import { GridGalleryLayout, MasonryGalleryLayout, CarouselGalleryLayout, TimelineGalleryLayout, HeroGalleryLayout, MosaicGalleryLayout, } from './layouts'; interface PhotoGridWithLayoutsProps { photos: Photo[]; slug: string; categoryId?: number | null; isSelectionMode?: boolean; selectedPhotos?: Set; onSelectionChange?: (photos: Set) => void; onToggleSelectionMode?: () => void; showSelectionControls?: boolean; eventName?: string; eventLogo?: string | null; eventDate?: string; expiresAt?: string; feedbackEnabled?: boolean; } export const PhotoGridWithLayouts: React.FC = ({ photos, slug, categoryId, isSelectionMode: parentSelectionMode, selectedPhotos: parentSelectedPhotos, feedbackEnabled, onSelectionChange, onToggleSelectionMode: parentToggleSelectionMode, showSelectionControls = true, eventName, eventLogo, eventDate, expiresAt }) => { const { t } = useTranslation(); const { theme } = useTheme(); const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(null); const [localSelectedPhotos, setLocalSelectedPhotos] = useState>(new Set()); const [localSelectionMode, setLocalSelectionMode] = useState(false); const downloadPhotoMutation = useDownloadPhoto(); // Use parent state if provided, otherwise use local state const selectedPhotos = parentSelectedPhotos ?? localSelectedPhotos; const isSelectionMode = parentSelectionMode ?? localSelectionMode; const setSelectedPhotos = onSelectionChange ?? setLocalSelectedPhotos; const toggleSelectionMode = parentToggleSelectionMode ?? (() => setLocalSelectionMode(!localSelectionMode)); // Clear selection when category changes useEffect(() => { setSelectedPhotos(new Set()); }, [categoryId]); const handlePhotoClick = (index: number) => { setSelectedPhotoIndex(index); }; const handlePhotoSelect = (photoId: number) => { const newSelected = new Set(selectedPhotos); if (newSelected.has(photoId)) { newSelected.delete(photoId); } else { newSelected.add(photoId); } setSelectedPhotos(newSelected); }; const handleDownload = (photo: Photo, e: React.MouseEvent) => { e.stopPropagation(); // Track individual photo download analyticsService.trackDownload(photo.id, slug, false); downloadPhotoMutation.mutate({ slug, photoId: photo.id, filename: photo.filename, }); }; const selectAll = () => { setSelectedPhotos(new Set(photos.map(p => p.id))); }; const deselectAll = () => { setSelectedPhotos(new Set()); }; const handleDownloadSelected = async () => { if (selectedPhotos.size === 0) return; const selectedPhotosList = photos.filter(p => selectedPhotos.has(p.id)); toastify.info(t('gallery.downloading', { count: selectedPhotos.size })); // Download each selected photo const downloadPromises = selectedPhotosList.map(photo => galleryService.downloadPhoto(slug, photo.id, photo.filename) .catch(err => { // Download failed - error handled by UI return null; }) ); try { await Promise.all(downloadPromises); toastify.success(t('gallery.downloadedPhotos', { count: selectedPhotos.size })); // Track bulk download analyticsService.trackGalleryEvent('bulk_download', { gallery: slug, photo_count: selectedPhotos.size }); // Clear selection after download setSelectedPhotos(new Set()); if (parentToggleSelectionMode) { parentToggleSelectionMode(); } else { setLocalSelectionMode(false); } } catch (error) { toastify.error(t('gallery.downloadError')); } }; if (photos.length === 0) { return (

{t('gallery.noPhotosFound')}

); } // Get the current layout from theme const galleryLayout = theme.galleryLayout || 'grid'; // Select the appropriate layout component const layoutProps = { photos, slug, onPhotoClick: handlePhotoClick, onDownload: handleDownload, selectedPhotos, isSelectionMode, onPhotoSelect: handlePhotoSelect, eventName, eventLogo, eventDate, expiresAt, }; let LayoutComponent; switch (galleryLayout) { case 'masonry': LayoutComponent = MasonryGalleryLayout; break; case 'carousel': LayoutComponent = CarouselGalleryLayout; break; case 'timeline': LayoutComponent = TimelineGalleryLayout; break; case 'hero': LayoutComponent = HeroGalleryLayout; break; case 'mosaic': LayoutComponent = MosaicGalleryLayout; break; default: LayoutComponent = GridGalleryLayout; } return ( <> {/* Selection Mode Controls - Not shown for carousel layout or when controls are hidden */} {showSelectionControls && photos.length > 1 && galleryLayout !== 'carousel' && (
{!isSelectionMode && ( )}
{isSelectionMode && (
{t('gallery.photosSelected', { count: selectedPhotos.size })}
{selectedPhotos.size > 0 && ( )}
)}
)} {/* Render the selected layout */} {/* Lightbox */} {selectedPhotoIndex !== null && ( setSelectedPhotoIndex(null)} slug={slug} feedbackEnabled={feedbackEnabled || false} /> )} ); };