import React, { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { Page } from './_util'; import { useParams, useSearchParams } from 'react-router-dom'; import { usePollGalleryDelta } from '../polling/usePollGalleryDelta'; import { Card, CardContent } from '@/components/ui/card'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Button } from '@/components/ui/button'; import FiltersBar, { type GalleryFilter } from '../components/FiltersBar'; import { Heart } from 'lucide-react'; import { likePhoto } from '../services/photosApi'; import PhotoLightbox from './PhotoLightbox'; export default function GalleryPage() { const { slug } = useParams(); const { photos, loading, newCount, acknowledgeNew } = usePollGalleryDelta(slug!); const [filter, setFilter] = React.useState('latest'); const [currentPhotoIndex, setCurrentPhotoIndex] = React.useState(null); const [hasOpenedPhoto, setHasOpenedPhoto] = useState(false); const [searchParams] = useSearchParams(); const photoIdParam = searchParams.get('photoId'); // Auto-open lightbox if photoId in query params useEffect(() => { if (photoIdParam && photos.length > 0 && currentPhotoIndex === null && !hasOpenedPhoto) { const index = photos.findIndex((photo: any) => photo.id === parseInt(photoIdParam, 10)); if (index !== -1) { setCurrentPhotoIndex(index); setHasOpenedPhoto(true); } } }, [photos, photoIdParam, currentPhotoIndex, hasOpenedPhoto]); const myPhotoIds = React.useMemo(() => { try { const raw = localStorage.getItem('my-photo-ids'); return new Set(raw ? JSON.parse(raw) : []); } catch { return new Set(); } }, []); const list = React.useMemo(() => { let arr = photos.slice(); if (filter === 'popular') { arr.sort((a: any, b: any) => (b.likes_count ?? 0) - (a.likes_count ?? 0)); } else if (filter === 'mine') { arr = arr.filter((p: any) => myPhotoIds.has(p.id)); } else { arr.sort((a: any, b: any) => new Date(b.created_at ?? 0).getTime() - new Date(a.created_at ?? 0).getTime()); } return arr; }, [photos, filter, myPhotoIds]); const [liked, setLiked] = React.useState>(new Set()); const [counts, setCounts] = React.useState>({}); async function onLike(id: number) { if (liked.has(id)) return; setLiked(new Set(liked).add(id)); try { const c = await likePhoto(id); setCounts((m) => ({ ...m, [id]: c })); // keep a simple record of liked items try { const raw = localStorage.getItem('liked-photo-ids'); const arr: number[] = raw ? JSON.parse(raw) : []; if (!arr.includes(id)) localStorage.setItem('liked-photo-ids', JSON.stringify([...arr, id])); } catch {} } catch { const s = new Set(liked); s.delete(id); setLiked(s); } } return ( {newCount > 0 && ( {newCount} neue Fotos verfügbar.{' '} )} {loading &&

Lade…

}
{list.map((p: any) => { // Debug: Log image URLs const imgSrc = p.thumbnail_path || p.file_path; // Normalize image URL let imageUrl = imgSrc; let cleanPath = ''; if (imageUrl) { // Remove leading/trailing slashes for processing cleanPath = imageUrl.replace(/^\/+|\/+$/g, ''); // Check if path already contains storage prefix if (cleanPath.startsWith('storage/')) { // Already has storage prefix, just ensure it starts with / imageUrl = `/${cleanPath}`; } else { // Add storage prefix imageUrl = `/storage/${cleanPath}`; } // Remove double slashes imageUrl = imageUrl.replace(/\/+/g, '/'); } // Production: avoid heavy console logging for each image return (
{ const index = list.findIndex(photo => photo.id === p.id); setCurrentPhotoIndex(index >= 0 ? index : null); }} className="cursor-pointer" > {`Foto { (e.target as HTMLImageElement).src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjRjNGNEY2Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPk5vIEltYWdlPC90ZXh0Pjwvc3ZnPg=='; }} loading="lazy" />
{p.task_title && (

{p.task_title}

)}
{counts[p.id] ?? (p.likes_count || 0)}
); })}
{currentPhotoIndex !== null && list.length > 0 && ( setCurrentPhotoIndex(null)} onIndexChange={(index: number) => setCurrentPhotoIndex(index)} slug={slug} /> )}
); }