This commit is contained in:
Vula Builder
2026-10-11 14:20:27 +00:00
parent 756de15194
commit 964bd67656
@@ -0,0 +1,128 @@
'use client'
import { useState } from 'react'
import Image from 'next/image'
import { Flame } from 'lucide-react'
import { useVulaContent } from '@/hooks/useVulaContent'
import Modal from '@/components/ui/Modal'
type GalleryEntry = {
id: string
title: string
description: string
image: string
}
export default function MadadeniFoodGallerySection() {
const { items, loading } = useVulaContent('gallery')
const [active, setActive] = useState<GalleryEntry | null>(null)
if (loading) {
return (
<div className="flex justify-center py-16">
<div className="w-8 h-8 rounded-full border-2 border-current border-t-transparent animate-spin" />
</div>
)
}
if (items.length === 0) return null
const gallery: GalleryEntry[] = items.map((item) => {
const d = item.data as { title?: string; description?: string; image?: string }
return {
id: item.id,
title: d.title ?? '',
description: d.description ?? '',
image: d.image ?? '',
}
})
return (
<section
id="food-venue-gallery"
data-vula-section="madadenifoodgallery"
data-vula-cms="gallery"
className="bg-background text-foreground py-24 sm:py-32"
>
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-3xl text-center">
<div className="flex items-center justify-center gap-4">
<span className="h-px w-14 bg-accent" aria-hidden="true" />
<span className="text-[11px] uppercase tracking-[0.3em] text-accent">Madadeni Section 4, Newcastle</span>
<span className="h-px w-14 bg-accent" aria-hidden="true" />
</div>
<h2 className="font-display mt-6 text-3xl font-light leading-tight tracking-tight sm:text-4xl lg:text-5xl">
Smoke off the wok, and a box still <span className="italic text-accent">too hot to hold</span>.
</h2>
<p className="mx-auto mt-6 max-w-2xl text-base leading-relaxed text-muted-foreground sm:text-lg">
None of this was shot in a studio. These are the plates that leave the corner, the flames they come off, and the Section 4 space where it all happens.
</p>
</div>
<div className="mt-16 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{gallery.map((entry, i) => (
<button
key={entry.id}
type="button"
onClick={() => setActive(entry)}
aria-label={entry.title ? 'Open ' + entry.title + ' full screen' : 'Open photo full screen'}
className={'group relative block cursor-pointer overflow-hidden rounded-lg border border-foreground/20 text-left transition-all duration-200 ease-out hover:border-accent/60 ' + (i === 0 ? 'sm:col-span-2' : '')}
>
<div className={'relative w-full ' + (i === 0 ? 'aspect-[16/9]' : 'aspect-[4/3]')}>
{entry.image ? (
<Image
src={entry.image}
alt={entry.title || 'Food from the wok'}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
className="object-cover transition-transform duration-500 ease-out group-hover:scale-105"
/>
) : (
<div className="flex h-full w-full items-center justify-center bg-foreground/5 text-muted-foreground">
<Flame className="h-10 w-10" />
</div>
)}
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-background via-background/30 to-transparent" />
<div className="absolute inset-x-0 bottom-0 border-t border-foreground/20 bg-foreground/10 p-4 backdrop-blur-md">
<p className="font-display text-lg font-light text-foreground">{entry.title}</p>
{entry.description ? (
<p className="mt-1 text-sm leading-relaxed text-muted-foreground">{entry.description}</p>
) : null}
</div>
</div>
</button>
))}
</div>
<p className="mt-10 text-center text-[11px] uppercase tracking-[0.3em] text-muted-foreground">
Tap a frame to open it full screen
</p>
</div>
<Modal
isOpen={active !== null}
onClose={() => setActive(null)}
title={active?.title}
description={active?.description}
>
{active ? (
<div className="relative aspect-[4/3] w-full overflow-hidden rounded-lg border border-foreground/20 bg-foreground/10">
{active.image ? (
<Image
src={active.image}
alt={active.title || 'Food from the wok'}
fill
sizes="(max-width: 768px) 100vw, 900px"
className="object-cover"
/>
) : (
<div className="flex h-full w-full items-center justify-center text-muted-foreground">
<Flame className="h-12 w-12" />
</div>
)}
</div>
) : null}
</Modal>
</section>
)
}