222 lines
8.1 KiB
TypeScript
222 lines
8.1 KiB
TypeScript
'use client'
|
||
|
||
import { useState } from 'react';
|
||
import Navbar from "@/components/Navbar/Navbar";
|
||
import Footer from "@/components/Footer/Footer";
|
||
import Image from "next/image";
|
||
import Link from "next/link";
|
||
import styles from "./gallery.module.css";
|
||
import { galleryData } from "@/utils/constant";
|
||
import { motion, AnimatePresence } from "framer-motion";
|
||
|
||
const categories = ['All', 'Food', 'Interior'];
|
||
|
||
export default function GalleryContent() {
|
||
const [activeTab, setActiveTab] = useState('All');
|
||
const [lightboxOpen, setLightboxOpen] = useState(false);
|
||
const [currentIndex, setCurrentIndex] = useState(0);
|
||
|
||
// Animation variants
|
||
const heroVariants = {
|
||
hidden: { opacity: 0, y: -20 },
|
||
visible: {
|
||
opacity: 1,
|
||
y: 0,
|
||
transition: { duration: 0.8 }
|
||
}
|
||
};
|
||
|
||
const tabsVariants = {
|
||
hidden: { opacity: 0, y: 20 },
|
||
visible: {
|
||
opacity: 1,
|
||
y: 0,
|
||
transition: {
|
||
duration: 0.6,
|
||
staggerChildren: 0.1
|
||
}
|
||
}
|
||
};
|
||
|
||
const tabVariants = {
|
||
hidden: { opacity: 0, y: 10 },
|
||
visible: {
|
||
opacity: 1,
|
||
y: 0,
|
||
transition: { duration: 0.4 }
|
||
}
|
||
};
|
||
|
||
const gridVariants = {
|
||
hidden: { opacity: 0 },
|
||
visible: {
|
||
opacity: 1,
|
||
transition: {
|
||
staggerChildren: 0.08,
|
||
delayChildren: 0.1
|
||
}
|
||
}
|
||
};
|
||
|
||
const imageVariants = {
|
||
hidden: { opacity: 0, scale: 0.9 },
|
||
visible: {
|
||
opacity: 1,
|
||
scale: 1,
|
||
transition: { duration: 0.5 }
|
||
}
|
||
};
|
||
|
||
const filteredImages = activeTab === 'All'
|
||
? galleryData
|
||
: galleryData.filter(img => img.category === activeTab);
|
||
|
||
const openLightbox = (index: number) => {
|
||
setCurrentIndex(index);
|
||
setLightboxOpen(true);
|
||
};
|
||
|
||
const closeLightbox = () => {
|
||
setLightboxOpen(false);
|
||
};
|
||
|
||
const nextImage = (e: React.MouseEvent) => {
|
||
e.stopPropagation();
|
||
setCurrentIndex((prev) => (prev + 1) % filteredImages.length);
|
||
};
|
||
|
||
const prevImage = (e: React.MouseEvent) => {
|
||
e.stopPropagation();
|
||
setCurrentIndex((prev) => (prev - 1 + filteredImages.length) % filteredImages.length);
|
||
};
|
||
|
||
return (
|
||
<main className={styles.main}>
|
||
<Navbar />
|
||
|
||
<motion.section
|
||
className={styles.hero}
|
||
initial="hidden"
|
||
animate="visible"
|
||
variants={heroVariants}
|
||
>
|
||
<div className={styles.heroContent}>
|
||
<h1 className={styles.heroTitle}>Our Gallery</h1>
|
||
<p className={styles.breadcrumb}>
|
||
<Link href="/">Home</Link> / Gallery
|
||
</p>
|
||
</div>
|
||
</motion.section>
|
||
|
||
<section className={styles.sectionHeading}>
|
||
<div className={styles.smallHeading} style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '10px' }}>
|
||
<Image src="/images/dinner.png" alt="Antalya Dinner Icon" width={24} height={24} />
|
||
<span>ANTALYA</span>
|
||
<Image src="/images/eat.png" alt="Antalya Cutlery Icon" width={24} height={24} />
|
||
</div>
|
||
<h2 className={styles.mainHeading}>A Visual Journey Through Authentic Turkish Dining</h2>
|
||
<p className={styles.description}>
|
||
Explore our gallery that captures the flavours, artistry, and elegance of Antalya. From charcoal-grilled kebabs to handcrafted baklava and vibrant interiors, every image reflects our passion for culinary excellence and warm Turkish hospitality.
|
||
</p>
|
||
</section>
|
||
|
||
<section className={styles.section}>
|
||
<motion.div
|
||
className={styles.tabs}
|
||
initial="hidden"
|
||
whileInView="visible"
|
||
viewport={{ once: true }}
|
||
variants={tabsVariants}
|
||
>
|
||
{categories.map(category => (
|
||
<motion.button
|
||
key={category}
|
||
className={`${styles.tab} ${activeTab === category ? styles.activeTab : ''}`}
|
||
onClick={() => setActiveTab(category)}
|
||
variants={tabVariants}
|
||
whileHover={{ scale: 1.05 }}
|
||
whileTap={{ scale: 0.95 }}
|
||
>
|
||
{category}
|
||
</motion.button>
|
||
))}
|
||
</motion.div>
|
||
|
||
<motion.div
|
||
className={styles.grid}
|
||
key={activeTab}
|
||
initial="hidden"
|
||
animate="visible"
|
||
variants={gridVariants}
|
||
>
|
||
{filteredImages.map((img, index) => (
|
||
<motion.div
|
||
key={img.id}
|
||
className={styles.imageWrapper}
|
||
onClick={() => openLightbox(index)}
|
||
variants={imageVariants}
|
||
whileHover={{
|
||
scale: 1.05,
|
||
transition: { duration: 0.3 }
|
||
}}
|
||
>
|
||
<Image
|
||
src={img.src}
|
||
alt={img.alt}
|
||
fill
|
||
className={styles.image}
|
||
/>
|
||
<div className={styles.overlay}>
|
||
<span className={styles.viewText}>View</span>
|
||
</div>
|
||
</motion.div>
|
||
))}
|
||
</motion.div>
|
||
</section>
|
||
|
||
<AnimatePresence>
|
||
{lightboxOpen && (
|
||
<motion.div
|
||
className={styles.lightbox}
|
||
onClick={closeLightbox}
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
exit={{ opacity: 0 }}
|
||
transition={{ duration: 0.3 }}
|
||
>
|
||
<motion.div
|
||
className={styles.lightboxContent}
|
||
onClick={(e) => e.stopPropagation()}
|
||
initial={{ scale: 0.8, opacity: 0 }}
|
||
animate={{ scale: 1, opacity: 1 }}
|
||
exit={{ scale: 0.8, opacity: 0 }}
|
||
transition={{ duration: 0.3 }}
|
||
>
|
||
<button className={styles.closeBtn} onClick={closeLightbox}>×</button>
|
||
<button className={`${styles.navBtn} ${styles.prevBtn}`} onClick={prevImage}>‹</button>
|
||
<motion.div
|
||
className={styles.lightboxImageWrapper}
|
||
key={currentIndex}
|
||
initial={{ opacity: 0, scale: 0.9 }}
|
||
animate={{ opacity: 1, scale: 1 }}
|
||
exit={{ opacity: 0, scale: 0.9 }}
|
||
transition={{ duration: 0.3 }}
|
||
>
|
||
<Image
|
||
src={filteredImages[currentIndex].src}
|
||
alt={filteredImages[currentIndex].alt}
|
||
fill
|
||
style={{ objectFit: 'contain' }}
|
||
/>
|
||
</motion.div>
|
||
<button className={`${styles.navBtn} ${styles.nextBtn}`} onClick={nextImage}>›</button>
|
||
</motion.div>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
|
||
<Footer />
|
||
</main>
|
||
);
|
||
}
|