Files
harheimertc/components/Gallery.vue
2025-12-20 10:17:16 +01:00

113 lines
3.5 KiB
Vue

<template>
<section
v-if="images.length > 0"
id="gallery"
class="py-16 sm:py-20 bg-gradient-to-b from-white to-gray-50"
>
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-4xl sm:text-5xl font-display font-bold text-gray-900 mb-4">
Galerie
</h2>
<div class="w-24 h-1 bg-primary-600 mx-auto mb-6" />
<p class="text-xl text-gray-600 max-w-3xl mx-auto">
Eindrücke von unserem Verein
</p>
</div>
<div class="grid sm:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-2">
<div
v-for="image in images"
:key="image.filename"
class="group relative w-20 h-20 rounded-md overflow-hidden shadow-sm hover:shadow-lg transition-all duration-300 cursor-pointer"
@click="openLightbox(image)"
>
<img
:src="`/galerie/${image.filename}`"
:alt="image.title"
class="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700"
>
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
<p class="text-white font-semibold text-xs p-1 truncate">
{{ image.title }}
</p>
</div>
</div>
</div>
<!-- Lightbox Modal -->
<div
v-if="lightboxImage"
class="fixed inset-0 z-50 bg-black/90 flex items-center justify-center p-4"
@click="closeLightbox"
>
<div class="relative w-full h-full flex items-center justify-center">
<button
class="absolute top-4 right-4 z-10 w-10 h-10 bg-white/20 hover:bg-white/30 rounded-full flex items-center justify-center text-white transition-colors"
@click.stop="closeLightbox"
>
<X :size="24" />
</button>
<img
:src="`/galerie/${lightboxImage.filename}`"
:alt="lightboxImage.title"
class="max-w-[80vw] max-h-[80vh] object-contain rounded-lg"
@click.stop
>
<div class="absolute bottom-4 left-4 right-4 text-center">
<p class="text-white font-semibold text-lg bg-black/50 rounded-lg px-4 py-2">
{{ lightboxImage.title }}
</p>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { X } from 'lucide-vue-next'
const images = ref([])
const lightboxImage = ref(null)
const loadImages = async () => {
try {
const response = await $fetch('/api/galerie')
images.value = response || []
} catch (error) {
console.error('Fehler beim Laden der Galerie-Bilder:', error)
images.value = []
}
}
const openLightbox = (image) => {
lightboxImage.value = image
document.body.style.overflow = 'hidden' // Verhindert Scrollen im Hintergrund
}
const closeLightbox = () => {
lightboxImage.value = null
document.body.style.overflow = 'auto' // Erlaubt wieder Scrollen
}
// ESC-Taste zum Schließen
const handleKeydown = (event) => {
if (event.key === 'Escape' && lightboxImage.value) {
closeLightbox()
}
}
onMounted(() => {
loadImages()
document.addEventListener('keydown', handleKeydown)
})
onUnmounted(() => {
document.removeEventListener('keydown', handleKeydown)
document.body.style.overflow = 'auto' // Cleanup
})
</script>