222 lines
8.1 KiB
TypeScript
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.

'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>
);
}