Undangan/proyek-frontend/app/components/templates/wedding/Gallery.vue
2025-10-24 17:05:32 +07:00

197 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<section class="bg-transparent py-12 px-4">
<!-- Gallery Grid - Masonry Style -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 max-w-6xl mx-auto px-4" data-aos="fade-up">
<img
v-for="(img, index) in displayImages"
:key="index"
:src="img"
alt="Gallery photo"
class="rounded-lg object-cover w-full shadow-lg hover:shadow-xl transition-shadow duration-300 cursor-pointer"
:class="getGridClass(index)"
@click="openLightbox(index)"
/>
</div>
<!-- Quote Section -->
<div class="max-w-3xl mx-auto mt-12 px-6 text-center" data-aos="fade-up" data-aos-delay="200">
<p class="text-gray-600 text-sm md:text-base leading-relaxed">
"And among His Signs is this, that He created for you mates from among yourselves,
that ye may dwell in tranquility with them, and He has put love and mercy between your (hearts):
verily in that are Signs for those who reflect."
</p>
<p class="mt-4 text-amber-600 font-semibold text-sm">- QS. Ar-Rum: 21 -</p>
</div>
<!-- Lightbox Modal -->
<Teleport to="body">
<div
v-if="lightboxOpen"
class="fixed inset-0 z-50 bg-black/90 flex items-center justify-center p-4"
@click="closeLightbox"
>
<button
class="absolute top-4 right-4 text-white text-4xl hover:text-amber-400 transition-colors"
@click="closeLightbox"
>
&times;
</button>
<button
v-if="currentImageIndex > 0"
class="absolute left-4 text-white text-4xl hover:text-amber-400 transition-colors"
@click.stop="prevImage"
>
</button>
<img
:src="displayImages[currentImageIndex]"
class="max-w-full max-h-[90vh] object-contain rounded-lg"
@click.stop
/>
<button
v-if="currentImageIndex < displayImages.length - 1"
class="absolute right-4 text-white text-4xl hover:text-amber-400 transition-colors"
@click.stop="nextImage"
>
</button>
<div class="absolute bottom-4 text-white text-sm">
{{ currentImageIndex + 1 }} / {{ displayImages.length }}
</div>
</div>
</Teleport>
</section>
</template>
<script setup>
import { ref, computed } from 'vue'
const props = defineProps({
images: {
type: Array,
default: () => [
"/logo1.png",
"/logo2.png",
"/pria.jpg",
"/wanita.jpg",
"/iphone.png",
"/templat.jpg",
"/logo1.png",
"/logo2.png"
]
}
})
const lightboxOpen = ref(false)
const currentImageIndex = ref(0)
const displayImages = computed(() => {
const images = props.images && props.images.length > 0 ? props.images : [
"/images/logo1.png",
"/images/logo2.png",
"/images/pria.jpg",
"/images/wanita.jpg",
"/images/iphone.png",
"/images/templat.jpg",
"/images/logo1.png",
"/images/logo2.png"
]
console.log('displayImages:', images)
return images
})
// Masonry grid layout pattern
const getGridClass = (index) => {
const pattern = index % 8
switch (pattern) {
case 0:
return "col-span-1 row-span-2 h-[400px]" // Tall left
case 1:
return "col-span-1 h-[195px]" // Small top right
case 2:
return "col-span-1 h-[195px]" // Small middle
case 3:
return "col-span-2 h-[250px]" // Wide bottom
case 4:
return "col-span-1 h-[200px]" // Standard
case 5:
return "col-span-1 row-span-2 h-[400px]" // Tall right
case 6:
return "col-span-2 h-[195px]" // Wide top
case 7:
return "col-span-1 h-[200px]" // Standard
default:
return "h-[200px]"
}
}
const openLightbox = (index) => {
currentImageIndex.value = index
lightboxOpen.value = true
document.body.style.overflow = 'hidden'
}
const closeLightbox = () => {
lightboxOpen.value = false
document.body.style.overflow = ''
}
const nextImage = () => {
if (currentImageIndex.value < displayImages.value.length - 1) {
currentImageIndex.value++
}
}
const prevImage = () => {
if (currentImageIndex.value > 0) {
currentImageIndex.value--
}
}
// Keyboard navigation
const handleKeydown = (e) => {
if (!lightboxOpen.value) return
if (e.key === 'Escape') closeLightbox()
if (e.key === 'ArrowRight') nextImage()
if (e.key === 'ArrowLeft') prevImage()
}
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeydown)
}
</script>
<style scoped>
/* Smooth transitions */
img {
transition: transform 0.3s ease, shadow 0.3s ease;
}
img:hover {
transform: scale(1.02);
}
/* Custom scrollbar for lightbox if needed */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: #f59e0b;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #d97706;
}
</style>