import { useCallback, useEffect } from 'react'; import { ChevronLeft, ChevronRight, Users } from 'lucide-react'; import { Dialog, DialogContent, DialogTitle, DialogDescription, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { ImageWithFallback } from '@/components/ImageWithFallback'; export interface LightboxImage { url: string; caption?: string; /** Owner-uploaded images carry no "Community" badge. */ isOwner?: boolean; } interface ImageLightboxProps { images: LightboxImage[]; /** Index of the open image, or null when closed. */ index: number | null; onIndexChange: (index: number) => void; onClose: () => void; } /** * Full-screen photo viewer for spot/shop galleries. * * Detail-page grids previously rendered images that did nothing on click and * showed at most five of them. This lets users view every photo at full size, * with arrow-key / button navigation. Images come from arbitrary Blossom hosts, * so it reuses ImageWithFallback to degrade gracefully on dead URLs. */ export function ImageLightbox({ images, index, onIndexChange, onClose }: ImageLightboxProps) { const open = index !== null && index >= 0 && index < images.length; const current = open ? images[index as number] : undefined; const go = useCallback( (delta: number) => { if (images.length === 0) return; const base = index ?? 0; onIndexChange((base + delta + images.length) % images.length); }, [images.length, index, onIndexChange], ); useEffect(() => { if (!open) return; const onKey = (e: KeyboardEvent) => { if (e.key === 'ArrowLeft') { e.preventDefault(); go(-1); } else if (e.key === 'ArrowRight') { e.preventDefault(); go(1); } else if (e.key === 'Escape') { e.preventDefault(); onClose(); } }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [open, go, onClose]); return ( { if (!o) onClose(); }}> {current?.caption || 'Photo'} Photo viewer {current && (
{/* Position counter */}
{(index as number) + 1} / {images.length}
{/* Prev / next */} {images.length > 1 && ( <> )} {/* Caption / attribution */} {((current.caption ?? '') !== '' || current.isOwner === false) && (
{current.caption && (

{current.caption}

)} {current.isOwner === false && ( Community photo )}
)}
)}
); }