From c73e035b3d641b28a8e57f5106a8d86822e97d98 Mon Sep 17 00:00:00 2001 From: sebastjanartic <45803536-sebastjanartic@users.noreply.replit.com> Date: Sat, 28 Feb 2026 18:27:34 +0000 Subject: [PATCH] Update photo gallery to display images one by one in a carousel Introduce a new `SingleImageCarousel` component and refactor the `PhotoGalleryWidget` to utilize it, enabling slideshow functionality for images with auto-play and navigation controls. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 413891e8-d784-4bea-b9f5-91a5a68316b4 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 2c340511-09fa-48b2-b531-1a040ae0b5e1 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/413891e8-d784-4bea-b9f5-91a5a68316b4/RVXhOPb Replit-Helium-Checkpoint-Created: true --- client/src/components/photo-gallery.tsx | 156 +++++++++++++++++------- 1 file changed, 110 insertions(+), 46 deletions(-) diff --git a/client/src/components/photo-gallery.tsx b/client/src/components/photo-gallery.tsx index 71c7db7..3a8e3fa 100644 --- a/client/src/components/photo-gallery.tsx +++ b/client/src/components/photo-gallery.tsx @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/react-query"; import { useState, useEffect, useCallback } from "react"; -import { ChevronLeft, ChevronRight, X, Images } from "lucide-react"; +import { ChevronLeft, ChevronRight, X, Images, Maximize2 } from "lucide-react"; interface GalleryImage { folder: string; @@ -79,6 +79,92 @@ function Lightbox({ ); } +function SingleImageCarousel({ + images, + autoPlay = true, + interval = 5000, + onExpand, +}: { + images: GalleryImage[]; + autoPlay?: boolean; + interval?: number; + onExpand?: (index: number) => void; +}) { + const [index, setIndex] = useState(0); + const [paused, setPaused] = useState(false); + + const prev = useCallback(() => setIndex((i) => (i - 1 + images.length) % images.length), [images.length]); + const next = useCallback(() => setIndex((i) => (i + 1) % images.length), [images.length]); + + useEffect(() => { + if (!autoPlay || paused || images.length <= 1) return; + const timer = setInterval(next, interval); + return () => clearInterval(timer); + }, [autoPlay, paused, next, interval, images.length]); + + if (images.length === 0) return null; + + return ( +
setPaused(true)} + onMouseLeave={() => setPaused(false)} + > +
+ {images[index].fileName} + +
+ + + + + + {onExpand && ( + + )} + +
+ {images.slice(0, Math.min(images.length, 20)).map((_, i) => ( +
+
+
+ ); +} + export function PhotoGalleryWidget() { const { data: images, isLoading } = useQuery({ queryKey: ["/api/gallery"], @@ -93,19 +179,13 @@ export function PhotoGalleryWidget() {

Fotogalerie

-
- {Array.from({ length: 6 }).map((_, i) => ( -
- ))} -
+
); } if (!images || images.length === 0) return null; - const preview = images.slice(0, 6); - return ( <>
@@ -113,23 +193,12 @@ export function PhotoGalleryWidget() {

Fotogalerie

-
- {preview.map((img, i) => ( - - ))} -
+ setLightboxIndex(i)} + />
{lightboxIndex !== null && ( @@ -153,29 +222,24 @@ export default function GalleryPage() { return (
{isLoading ? ( -
- {Array.from({ length: 20 }).map((_, i) => ( -
- ))} +
+
+
+ ) : images && images.length > 0 ? ( +
+
+ setLightboxIndex(i)} + /> +
+

+ {images.length} Fotos +

) : ( -
- {(images || []).map((img, i) => ( - - ))} -
+

Keine Fotos vorhanden

)} {lightboxIndex !== null && images && (