import React, { useState, useEffect } from 'react'; import { motion } from 'framer-motion'; import { useInView } from 'react-intersection-observer'; import { Swiper, SwiperSlide } from 'swiper/react'; import { Navigation, Pagination } from 'swiper/modules'; import { ChevronLeft, ChevronRight, Image as ImageIcon, Filter, Search, X } from 'lucide-react'; import { Link } from 'react-router-dom'; import { supabase } from '../lib/supabase'; import 'swiper/css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; import PageVisibilityWrapper from '../components/PageVisibilityWrapper'; import { Helmet } from "react-helmet"; type PortfolioAlbumWithCover = { id: string; title: string; description: string | null; category: string | null; cover_image: string | null; display_order: number; is_featured: boolean; image_count: number; created_at: string; updated_at: string; }; type PortfolioImage = { id: string; image_url: string; caption: string | null; // Add other fields if needed based on your 'portfolio_images' table }; // Category filters const CATEGORIES = ['All', 'Wedding', 'Corporate', 'Anniversary', 'Festival', 'Cultural', 'Social']; // Loading progress animation styles const loadingProgressVariants = { initial: { width: "0%" }, loading: { width: "90%", transition: { duration: 1.5, ease: "easeInOut" } }, complete: { width: "100%", transition: { duration: 0.3, ease: "easeOut" } } }; const Gallery = () => { const [albums, setAlbums] = useState([]); const [filteredAlbums, setFilteredAlbums] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [activeCategory, setActiveCategory] = useState('All'); const [activeSliderIndex, setActiveSliderIndex] = useState(null); const [albumImages, setAlbumImages] = useState([]); const [isModalLoading, setIsModalLoading] = useState(false); const [modalError, setModalError] = useState(null); const [ref, inView] = useInView({ triggerOnce: true, threshold: 0.1, }); // Fetch initial albums useEffect(() => { const fetchAlbums = async () => { try { setLoading(true); setError(null); const { data, error } = await supabase.rpc('get_portfolio_albums_with_cover'); if (error) throw error; const albumsData = data as PortfolioAlbumWithCover[]; setAlbums(albumsData); setFilteredAlbums(albumsData); } catch (err) { console.error('Error fetching portfolio albums:', err); setError('Failed to load portfolio albums'); } finally { setLoading(false); } }; fetchAlbums(); }, []); // Filter albums when category changes useEffect(() => { if (activeCategory === 'All') { setFilteredAlbums(albums); } else { setFilteredAlbums(albums.filter(album => album.category === activeCategory)); } }, [activeCategory, albums]); // Function to fetch images for a specific album const fetchAlbumImages = async (albumId: string) => { if (!albumId) { setModalError("Invalid album ID"); return; } console.log('[Gallery Modal] Fetching images for album ID:', albumId); setIsModalLoading(true); setModalError(null); setAlbumImages([]); // Clear previous images try { // Simplified query that avoids reliance on specific columns const { data, error } = await supabase .from('portfolio_images') .select('id, image_url, album_id') .eq('album_id', albumId); console.log('[Gallery Modal] Supabase response:', { data: data?.length || 0, error: error?.message || 'none', albumId }); if (error) { throw new Error(`Database error: ${error.message}`); } if (!data || data.length === 0) { console.log('[Gallery Modal] No images found for album ID:', albumId); setModalError(`No images found for this album. Please add some images or try another album.`); return; } // Validate image data before setting state const validImages = data.filter(img => img.image_url && img.id); if (validImages.length === 0) { setModalError('The images in this album don\'t have proper URLs'); return; } setAlbumImages(validImages as PortfolioImage[]); console.log('[Gallery Modal] Successfully loaded', validImages.length, 'images'); } catch (err) { console.error('[Gallery Modal] Error fetching album images:', err); const message = err instanceof Error ? err.message : 'An unknown error occurred'; setModalError(`Failed to load album images. ${message}`); } finally { setIsModalLoading(false); } }; // Handle opening the modal const handleOpenModal = (index: number) => { console.log('[Gallery] Opening modal for album index:', index); const album = filteredAlbums[index]; console.log('[Gallery] Album details:', album); setActiveSliderIndex(index); if (album?.id) { fetchAlbumImages(album.id); } else { console.error('[Gallery] No album ID found for index:', index); setModalError('Could not find album ID to fetch images'); } }; // Handle closing the modal const handleCloseModal = () => { console.log('[Gallery] Closing modal'); setActiveSliderIndex(null); setAlbumImages([]); // Clear images when closing setModalError(null); }; // Add debug log for rendered state useEffect(() => { console.log('[Gallery] Current state:', { albumCount: filteredAlbums.length, activeSliderIndex, albumImagesCount: albumImages.length, modalError, isModalLoading }); }, [filteredAlbums.length, activeSliderIndex, albumImages.length, modalError, isModalLoading]); return (
Gallery | Amoeba Productions - Event Photos & Highlights Patna {/* Structured Data for Gallery Albums */} {/* Hero section */}

Event Portfolio

Explore our collection of successful events and celebrations

{/* Gallery section */}
{/* Category Filters */}
{CATEGORIES.map((category) => ( ))}
{loading ? (
) : error ? (

{error}

) : filteredAlbums.length === 0 ? (

No albums found in this category

) : (
{filteredAlbums.map((album, idx) => ( handleOpenModal(idx)} >
{album.cover_image ? ( {album.title} { (e.target as HTMLImageElement).src = 'https://via.placeholder.com/400x250?text=Image+Not+Found'; }} /> ) : (
)}
View Preview
{album.is_featured && (
Featured
)}
{album.image_count} photos

{album.title}

{album.description}

{album.category && (
{album.category}
)} e.stopPropagation()} // Prevent modal open when clicking link > View Full Album
))}
)} {/* Image Slider Modal */} {activeSliderIndex !== null && (
e.stopPropagation()} // Prevent close when clicking inside modal > {/* Close Button */} {/* Modal Header */}

{filteredAlbums[activeSliderIndex]?.title || 'Album Preview'}

{/* Modal Body with Slider */}
{isModalLoading ? (

Loading album images...

) : modalError ? (

{modalError}

Try refreshing the page or contact support if the issue persists.

) : albumImages.length === 0 ? (

No images found for this album.

) : ( 1} className="w-full h-full" > {albumImages.map((image) => ( {`Album { (e.target as HTMLImageElement).src = 'https://via.placeholder.com/400x300?text=Image+Loading+Error'; }} /> ))} {/* Custom Navigation Buttons */} {albumImages.length > 1 && ( <> )} )}
)}
); }; export default Gallery;