86 lines
3.4 KiB
TypeScript
86 lines
3.4 KiB
TypeScript
'use client'
|
||
|
||
import { useEmDashContent } from '@/hooks/useEmDashContent'
|
||
import Image from 'next/image'
|
||
import { useState } from 'react'
|
||
|
||
const galleryFields = ["title", "description", 'image'] as const
|
||
|
||
export default function BushveldLodgeGallerySection() {
|
||
const { items, loading } = useEmDashContent('gallery')
|
||
const [lightbox, setLightbox] = useState<number | null>(null)
|
||
|
||
if (loading) {
|
||
return (
|
||
<div className="flex justify-center py-16">
|
||
<div className="w-8 h-8 rounded-full border-2 border-[#C0392B] border-t-transparent animate-spin" />
|
||
</div>
|
||
)
|
||
}
|
||
if (items.length === 0) return null
|
||
|
||
const openLightbox = (i: number) => setLightbox(i)
|
||
const closeLightbox = () => setLightbox(null)
|
||
|
||
return (
|
||
<section id="lodge-life-gallery" data-vula-section="bushveldlodgegallery" data-vula-cms="gallery" className="bg-[#FDF6EC] py-24 px-4">
|
||
<div className="max-w-7xl mx-auto">
|
||
<h2 className="text-4xl font-bold text-[#2C1810] text-center mb-4">Lodge Life in Pictures</h2>
|
||
<p className="text-center text-[#2C1810]/70 mb-12 max-w-xl mx-auto">
|
||
Genuine moments captured around KwaNtofontofo – the pool, the lounge, wildlife at the border fence.
|
||
</p>
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||
{items.map((item, i) => {
|
||
const d = item.data as { title?: string; description?: string; image?: string }
|
||
return (
|
||
<div
|
||
key={item.id}
|
||
className="rounded-xl overflow-hidden bg-white shadow-[var(--shadow-card)] hover:shadow-[var(--shadow-lifted)] hover:-translate-y-0.5 transition-all duration-200 ease-out cursor-pointer"
|
||
onClick={() => openLightbox(i)}
|
||
>
|
||
<div className="aspect-video overflow-hidden">
|
||
<Image
|
||
src={d.image || '/placeholder.svg'}
|
||
alt={d.title || ''}
|
||
width={800}
|
||
height={450}
|
||
className="object-cover w-full h-full hover:scale-105 transition-transform duration-500 ease-out"
|
||
/>
|
||
</div>
|
||
<div className="p-5">
|
||
<h3 className="text-lg font-semibold text-[#2C1810] mb-2">{d.title}</h3>
|
||
<p className="text-sm text-[#2C1810]/70 leading-relaxed">{d.description}</p>
|
||
</div>
|
||
</div>
|
||
)
|
||
})}
|
||
</div>
|
||
</div>
|
||
|
||
{lightbox !== null && (
|
||
<div
|
||
className="fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4"
|
||
onClick={closeLightbox}
|
||
>
|
||
<div className="relative max-w-3xl w-full" onClick={(e) => e.stopPropagation()}>
|
||
<button
|
||
onClick={closeLightbox}
|
||
className="absolute top-2 right-2 text-white bg-[#C0392B] rounded-full w-8 h-8 flex items-center justify-center z-10"
|
||
aria-label="Close lightbox"
|
||
>
|
||
✕
|
||
</button>
|
||
<Image
|
||
src={items[lightbox].data?.image || ''}
|
||
alt={items[lightbox].data?.title || ''}
|
||
width={1200}
|
||
height={800}
|
||
className="rounded-lg object-contain w-full h-auto max-h-[85vh]"
|
||
/>
|
||
<p className="text-white text-center mt-2 text-sm">{items[lightbox].data?.description}</p>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</section>
|
||
)
|
||
} |