diff --git a/src/config/gallary.js b/src/config/gallary.js
index 94da7b3..a44bb63 100644
--- a/src/config/gallary.js
+++ b/src/config/gallary.js
@@ -1,4 +1,19 @@
+import img2026_1 from "../assets/2026.jpg";
+import img2026_2 from "../assets/2026 (2).jpg";
+
const images = [
+ {
+ id: 101,
+ src: img2026_1,
+ alt: "Gallery Image 2026 1",
+ year: 2026,
+ },
+ {
+ id: 102,
+ src: img2026_2,
+ alt: "Gallery Image 2026 2",
+ year: 2026,
+ },
{
id: 0,
src: "https://res.cloudinary.com/dbnfkkfov/image/upload/v1759606221/WhatsApp_Image_2025-10-04_at_20.38.01_n5yqjt.jpg",
@@ -161,12 +176,6 @@ const images = [
alt: "Gallery Image 26",
year: 2025,
},
- {
- id: 27,
- src: "https://res.cloudinary.com/dsjxx976j/image/upload/v1756627317/asme126_eqyzzs.jpg",
- alt: "ASME Image 1",
- year: "others",
- },
{
id: 28,
src: "https://res.cloudinary.com/dsjxx976j/image/upload/v1756627315/asme132_vzqgiw.jpg",
@@ -353,12 +362,6 @@ const images = [
alt: "ASME Image 32",
year: "others",
},
- {
- id: 59,
- src: "https://res.cloudinary.com/dsjxx976j/image/upload/v1756627213/asme1_ksyaia.jpg",
- alt: "ASME Image 33",
- year: "others",
- },
];
export default images;
diff --git a/src/config/teammate.js b/src/config/teammate.js
index 7311c12..8f6d10f 100644
--- a/src/config/teammate.js
+++ b/src/config/teammate.js
@@ -11,7 +11,7 @@ const teamMembers = [
{
name: "Aayush Barik",
title: "Vice President",
- img: "https://res.cloudinary.com/ddoeahbpv/image/upload/Aayush_Barik_Vice_President_klgnid.jpg",
+ img: "https://res.cloudinary.com/dm406z4pf/image/upload/v1785069742/Aayush_Barik_Vice_President_2_wbg5bq.jpg",
description: "2",
team: "Executive Body",
linkedin: "https://www.linkedin.com/in/aayush-barik-668843339/",
@@ -139,7 +139,7 @@ const teamMembers = [
{
name: "Yegnesh Sagar",
title: "Captain",
- img: "https://res.cloudinary.com/ddoeahbpv/image/upload/images_1_ujpf6e.jpg",
+ img: "https://res.cloudinary.com/dm406z4pf/image/upload/v1785069027/1784538371641_vmsozp.png",
description: "18",
team: "Team Bluebird",
linkedin: "https://www.linkedin.com/in/yegnesh-sagar-89778b348/",
diff --git a/src/pages/gallery/Gallery.jsx b/src/pages/gallery/Gallery.jsx
index 9639f59..9863d42 100644
--- a/src/pages/gallery/Gallery.jsx
+++ b/src/pages/gallery/Gallery.jsx
@@ -1,174 +1,308 @@
-import { useState, useEffect } from "react";
+import { useState, useEffect, useCallback, useMemo } from "react";
import images from "../../config/gallary";
+import { ChevronLeft, ChevronRight, Maximize2, X } from "lucide-react";
-const NavButton = ({ direction, onClick }) => {
- const isNext = direction === "next";
- return (
-
-
-
-
-
- );
-};
-
-const YearButton = ({ year, isSelected, onClick }) => {
- const label = year === "all" ? "All" : String(year);
- return (
-
- {label === "others" ? "others" : label}
-
- );
-};
-
-const GalleryItem = ({ image }) => (
-
-
-
-);
-
-export default function GallaryPage() {
+export default function GalleryPage() {
const [selectedYear, setSelectedYear] = useState("all");
const [currentSlide, setCurrentSlide] = useState(0);
+ const [lightboxIndex, setLightboxIndex] = useState(null);
+ const [failedImages, setFailedImages] = useState({});
+
+ // Slide Images for top hero (uses first 6 images from dataset)
+ const heroSlides = useMemo(
+ () => images.slice(0, Math.min(images.length, 6)),
+ [],
+ );
+ // Auto Hero Slider (5s interval)
useEffect(() => {
+ if (heroSlides.length === 0) return;
const interval = setInterval(() => {
- setCurrentSlide((prev) => (prev + 1) % images.length);
+ setCurrentSlide((prev) => (prev + 1) % heroSlides.length);
}, 5000);
return () => clearInterval(interval);
+ }, [heroSlides.length]);
+
+ // Build sorted years list (numeric years sorted, then string years)
+ const years = useMemo(() => {
+ const allYears = Array.from(new Set(images.map((img) => img.year)));
+ const numericYears = allYears
+ .filter((y) => typeof y === "number")
+ .sort((a, b) => b - a);
+ const stringYears = allYears
+ .filter((y) => typeof y === "string" && y !== "all")
+ .sort();
+ return ["all", ...numericYears, ...stringYears];
}, []);
- // Build years list keeping numeric years sorted, then string years
- const allYears = Array.from(new Set(images.map((image) => image.year)));
- const numericYears = allYears
- .filter((y) => typeof y === "number")
- .sort((a, b) => a - b);
- const stringYears = allYears
- .filter((y) => typeof y === "string" && y !== "all")
- .sort();
- const years = ["all", ...numericYears, ...stringYears];
-
- const galleryImages = (() => {
+ // Filtered gallery images for grid
+ const galleryImages = useMemo(() => {
if (selectedYear === "all") return images;
- // if selectedYear is a string that is not numeric, filter by exact match
if (typeof selectedYear === "string" && isNaN(Number(selectedYear))) {
- return images.filter((image) => image.year === selectedYear);
+ return images.filter((img) => img.year === selectedYear);
}
- // otherwise treat as numeric year
- return images.filter((image) => image.year === Number(selectedYear));
- })();
+ return images.filter((img) => img.year === Number(selectedYear));
+ }, [selectedYear]);
+
+ // Fallback image helper
+ const getImageSrc = useCallback(
+ (image) => {
+ if (failedImages[image.id]) {
+ return "https://res.cloudinary.com/dbnfkkfov/image/upload/v1759606221/WhatsApp_Image_2025-10-04_at_20.38.01_n5yqjt.jpg";
+ }
+ return image.src;
+ },
+ [failedImages],
+ );
+
+ const handleImageError = (id) => {
+ setFailedImages((prev) => ({ ...prev, [id]: true }));
+ };
+
+ // Lightbox Controls
+ const openLightbox = (index) => {
+ setLightboxIndex(index);
+ document.body.style.overflow = "hidden";
+ };
+
+ const closeLightbox = () => {
+ setLightboxIndex(null);
+ document.body.style.overflow = "auto";
+ };
+
+ const nextLightbox = useCallback(() => {
+ if (lightboxIndex === null || galleryImages.length === 0) return;
+ setLightboxIndex((prev) => (prev + 1) % galleryImages.length);
+ }, [lightboxIndex, galleryImages.length]);
+
+ const prevLightbox = useCallback(() => {
+ if (lightboxIndex === null || galleryImages.length === 0) return;
+ setLightboxIndex((prev) =>
+ prev === 0 ? galleryImages.length - 1 : prev - 1,
+ );
+ }, [lightboxIndex, galleryImages.length]);
+
+ useEffect(() => {
+ const handleKeyDown = (e) => {
+ if (lightboxIndex === null) return;
+ if (e.key === "Escape") closeLightbox();
+ if (e.key === "ArrowRight") nextLightbox();
+ if (e.key === "ArrowLeft") prevLightbox();
+ };
+ window.addEventListener("keydown", handleKeyDown);
+ return () => window.removeEventListener("keydown", handleKeyDown);
+ }, [lightboxIndex, nextLightbox, prevLightbox]);
return (
-
- {/* Hero Banner Carousel */}
-
- {/* Carousel Slides */}
+
+ {/* Clean Large Hero Photo (Textless, clearly visible like Achievement section) */}
+
- {images.map((image, index) => (
+ {heroSlides.map((slide, index) => (
handleImageError(slide.id)}
+ className="w-full h-full object-cover transition-transform duration-[8000ms] ease-out scale-105"
/>
))}
- {/* Carousel Controls */}
-
- {images.map((_, index) => (
-
setCurrentSlide(index)}
- className={`w-2 h-2 rounded-full transition-all ${index === currentSlide ? "bg-white w-4" : "bg-white/50"}`}
- aria-label={`Go to slide ${index + 1}`}
- />
- ))}
+ {/* Minimal Bottom Slide Indicators */}
+
+
+ setCurrentSlide(
+ (prev) => (prev - 1 + heroSlides.length) % heroSlides.length,
+ )
+ }
+ className="p-1.5 rounded-full bg-black/40 hover:bg-black/70 text-white transition-all backdrop-blur-sm"
+ aria-label="Previous Slide"
+ >
+
+
+
+
+ {heroSlides.map((_, index) => (
+ setCurrentSlide(index)}
+ className={`h-2 rounded-full transition-all duration-300 ${
+ index === currentSlide
+ ? "bg-white w-6"
+ : "bg-white/50 hover:bg-white/80 w-2"
+ }`}
+ aria-label={`Go to slide ${index + 1}`}
+ />
+ ))}
+
+
+
+ setCurrentSlide((prev) => (prev + 1) % heroSlides.length)
+ }
+ className="p-1.5 rounded-full bg-black/40 hover:bg-black/70 text-white transition-all backdrop-blur-sm"
+ aria-label="Next Slide"
+ >
+
+
- {/* Gallery Content */}
+ {/* Main Gallery Container */}
- {/* Year Filters and Description Section */}
-
-
+ {/* Header & Controls Section */}
+
+ {/* Title & Description Header */}
+
-
+
Gallery
-
- {years.map((year) => (
- setSelectedYear(year)}
- />
- ))}
-
-
+
Step into our visual storybook — where every image captures a
moment, every frame holds a memory, and every detail speaks of the
- journey we’ve lived and the beauty we’ve created. Welcome to our
- gallery, a celebration of experiences brought to life through the
- lens.
+ journey we’ve lived and the beauty we’ve created.
-
- {/* Gallery Grid */}
-
- {galleryImages.map((image) => (
-
- ))}
+ {/* Clean Controls Bar (Filter Pills) */}
+
+ {/* Year Filters */}
+
+ {years.map((year) => {
+ const isSelected = selectedYear === year;
+ const label =
+ year === "all"
+ ? "All"
+ : typeof year === "string"
+ ? year.charAt(0).toUpperCase() + year.slice(1)
+ : String(year);
+ return (
+ setSelectedYear(year)}
+ className={`px-4 py-1.5 rounded-full text-sm font-medium transition-all duration-200 cursor-pointer ${
+ isSelected
+ ? "bg-[#061946] dark:bg-[#0F2A5F] dark:text-white text-white shadow-md scale-[1.02]"
+ : "bg-gray-100 dark:bg-slate-800 dark:text-slate-200 text-gray-700 hover:bg-gray-200 dark:hover:bg-slate-700"
+ }`}
+ >
+ {label}
+
+ );
+ })}
+
+
- {/* No Images Message */}
- {galleryImages.length === 0 && (
+ {/* Gallery Grid - Fixed to 3 per row on desktop */}
+ {galleryImages.length > 0 ? (
+
+ {galleryImages.map((image, index) => {
+ const imgSrc = getImageSrc(image);
+
+ return (
+
openLightbox(index)}
+ className="group relative cursor-pointer overflow-hidden rounded-2xl bg-gray-100 dark:bg-slate-800 shadow-sm hover:shadow-xl transition-all duration-300 hover:-translate-y-1.5 aspect-[4/3] w-full border border-gray-200/80 dark:border-slate-700/60"
+ >
+
handleImageError(image.id)}
+ loading="lazy"
+ className="w-full h-full object-cover transition-transform duration-500 ease-out group-hover:scale-105"
+ />
+
+ {/* Subtle Hover Overlay */}
+
+
+ );
+ })}
+
+ ) : (
-
+
No images found for selected year.
)}
+
+ {/* Clean Interactive Lightbox Modal */}
+ {lightboxIndex !== null && galleryImages[lightboxIndex] && (
+
+ {/* Header */}
+
e.stopPropagation()}
+ >
+
+ {lightboxIndex + 1} of {galleryImages.length}
+
+
+
+
+
+
+
+ {/* Lightbox Main Photo */}
+
e.stopPropagation()}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Footer */}
+
+ Press Esc to exit
+
+
+ )}
);
}