/** * PhotoGrid Component * Reusable photo grid display with modal support */ import { memo } from 'react'; import { Eye, AlertCircle } from 'lucide-react'; import { useIsMobile } from '@/hooks/use-mobile'; import type { PhotoItem } from '@/types/photos'; import { generatePhotoAlt } from '@/lib/photoHelpers'; import { LazyImage } from '@/components/common/LazyImage'; interface PhotoGridProps { photos: PhotoItem[]; onPhotoClick?: (photos: PhotoItem[], index: number) => void; maxDisplay?: number; className?: string; } export const PhotoGrid = memo(({ photos, onPhotoClick, maxDisplay, className = '' }: PhotoGridProps) => { const isMobile = useIsMobile(); const defaultMaxDisplay = isMobile ? 2 : 3; const maxToShow = maxDisplay ?? defaultMaxDisplay; const displayPhotos = photos.slice(0, maxToShow); const remainingCount = Math.max(0, photos.length - maxToShow); if (photos.length === 0) { return (
No photos available
); } return (
{displayPhotos.map((photo, index) => (
onPhotoClick?.(photos, index)} > { const target = e.target as HTMLImageElement; target.style.display = 'none'; const parent = target.parentElement; if (parent) { const errorDiv = document.createElement('div'); errorDiv.className = 'absolute inset-0 flex flex-col items-center justify-center text-destructive text-xs p-2'; const icon = document.createElement('div'); icon.textContent = '⚠️'; icon.className = 'text-lg mb-1'; const text = document.createElement('div'); text.textContent = 'Failed to load'; errorDiv.appendChild(icon); errorDiv.appendChild(text); parent.appendChild(errorDiv); } }} />
{photo.caption && (
{photo.caption}
)}
))} {remainingCount > 0 && (
+{remainingCount} more
)}
); }); PhotoGrid.displayName = 'PhotoGrid';