import { useState, useEffect, useCallback } from 'react' import { X, ChevronLeft, ChevronRight, Edit2, Trash2, Check } from 'lucide-react' import { useTranslation } from '../../i18n' import type { Photo, Place, Day } from '../../types' interface PhotoLightboxProps { photos: Photo[] initialIndex: number onClose: () => void onUpdate: (photoId: number, data: Partial) => Promise onDelete: (photoId: number) => Promise days: Day[] places: Place[] tripId: number } export function PhotoLightbox({ photos, initialIndex, onClose, onUpdate, onDelete, days, places, tripId }: PhotoLightboxProps) { const { t } = useTranslation() const [index, setIndex] = useState(initialIndex || 0) const [editCaption, setEditCaption] = useState(false) const [caption, setCaption] = useState('') const [isSaving, setIsSaving] = useState(false) const photo = photos[index] useEffect(() => { setIndex(initialIndex || 0) }, [initialIndex]) useEffect(() => { if (photo) setCaption(photo.caption || '') }, [photo]) const prev = useCallback(() => { setIndex(i => Math.max(0, i - 1)) setEditCaption(false) }, []) const next = useCallback(() => { setIndex(i => Math.min(photos.length - 1, i + 1)) setEditCaption(false) }, [photos.length]) useEffect(() => { const handleKey = (e) => { if (e.key === 'Escape') onClose() if (e.key === 'ArrowLeft') prev() if (e.key === 'ArrowRight') next() } window.addEventListener('keydown', handleKey) return () => window.removeEventListener('keydown', handleKey) }, [onClose, prev, next]) const handleSaveCaption = async () => { setIsSaving(true) try { await onUpdate(photo.id, { caption }) setEditCaption(false) } finally { setIsSaving(false) } } const handleDelete = async () => { if (!confirm('Foto löschen?')) return await onDelete(photo.id) if (photos.length <= 1) { onClose() } else { setIndex(i => Math.min(i, photos.length - 2)) } } if (!photo) return null const day = days?.find(d => d.id === photo.day_id) const place = places?.find(p => p.id === photo.place_id) return (
{/* Main area */}
e.stopPropagation()} > {/* Top bar */}
{index + 1} / {photos.length}
{/* Image area */}
{/* Prev button */} {index > 0 && ( )} {photo.caption {/* Next button */} {index < photos.length - 1 && ( )}
{/* Bottom info */}
{/* Caption */}
{editCaption ? ( <> setCaption(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleSaveCaption()} placeholder={t('photos.addCaption')} className="flex-1 bg-white/10 text-white border border-white/20 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:border-white/40" autoFocus /> ) : ( <>

setEditCaption(true)} > {photo.caption || {t('photos.addCaption')}}

)}
{/* Metadata */}
{photo.original_name} {photo.created_at && ( {formatDate(photo.created_at)} )} {day && 📅 Tag {day.day_number}} {place && 📍 {place.name}} {photo.file_size && {formatSize(photo.file_size)}}
{/* Thumbnail strip */} {photos.length > 1 && (
{photos.map((p, i) => ( ))}
)}
) } function formatDate(dateStr, locale = 'en-US') { if (!dateStr) return '' try { return new Date(dateStr).toLocaleDateString(locale, { day: 'numeric', month: 'long', year: 'numeric' }) } catch { return '' } } function formatSize(bytes) { if (!bytes) return '' if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB` return `${(bytes / 1024 / 1024).toFixed(1)} MB` }