diff --git a/app/components/gallery/GalleryPageClient.tsx b/app/components/gallery/GalleryPageClient.tsx index 9d18172..767135b 100644 --- a/app/components/gallery/GalleryPageClient.tsx +++ b/app/components/gallery/GalleryPageClient.tsx @@ -13,15 +13,21 @@ type EventItem = { date: string; description: string; images: string[]; + googleDriveUrl: string; }; export default function GalleryPageClient() { - const { gallery } = useTranslation(); + const { gallery, lang } = useTranslation(); + // Active Event Index (0: latest event, 7: oldest event) + const [activeEventIndex, setActiveEventIndex] = useState(0); + // Lightbox State - const [lightboxEventId, setLightboxEventId] = useState(null); const [lightboxImageIndex, setLightboxImageIndex] = useState(null); + // Active event object + const activeEvent = gallery.events[activeEventIndex] as EventItem; + // Helper to format image source path const getImgSrc = (src: string) => { if (src.startsWith("http")) return src; @@ -30,10 +36,7 @@ export default function GalleryPageClient() { // Keyboard navigation for Lightbox useEffect(() => { - if (lightboxEventId === null || lightboxImageIndex === null) return; - - const activeEvent = gallery.events.find((e: EventItem) => e.id === lightboxEventId); - if (!activeEvent) return; + if (lightboxImageIndex === null || !activeEvent) return; const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") { @@ -49,28 +52,63 @@ export default function GalleryPageClient() { return () => { window.removeEventListener("keydown", handleKeyDown); }; - }, [lightboxEventId, lightboxImageIndex, gallery.events]); + }, [lightboxImageIndex, activeEvent]); - const openLightbox = (eventId: number, imgIndex: number) => { - setLightboxEventId(eventId); + const openLightbox = (imgIndex: number) => { setLightboxImageIndex(imgIndex); document.body.style.overflow = "hidden"; }; const closeLightbox = () => { - setLightboxEventId(null); setLightboxImageIndex(null); document.body.style.overflow = ""; }; - // Find active lightbox image and event - const activeEvent = lightboxEventId !== null - ? gallery.events.find((e: EventItem) => e.id === lightboxEventId) - : null; + const goToNewerEvent = () => { + if (activeEventIndex > 0) { + setActiveEventIndex(activeEventIndex - 1); + } + }; + + const goToOlderEvent = () => { + if (activeEventIndex < gallery.events.length - 1) { + setActiveEventIndex(activeEventIndex + 1); + } + }; + const activeImage = activeEvent && lightboxImageIndex !== null ? activeEvent.images[lightboxImageIndex] : null; + // Helper to determine CSS classes for the dynamic mosaic + const getMosaicClasses = (i: number, total: number) => { + // If very few images, keep it simple + if (total < 3) { + return "h-[240px] sm:h-[320px]"; + } + + // Dynamic grid classes + switch (i) { + case 0: + // Spotlight spans 2 columns & 2 rows on desktop + return "md:col-span-2 md:row-span-2 h-[260px] sm:h-[360px] md:h-[500px]"; + default: + // Adjust the last image to prevent layout gaps + if (i === total - 1) { + if (total === 4 || total === 7) { + return "md:col-span-2 h-[180px] sm:h-[240px]"; + } + if (total === 5 || total === 8) { + return "md:col-span-2 h-[180px] sm:h-[240px]"; + } + if (total === 10) { + return "md:col-span-3 h-[200px] sm:h-[280px]"; + } + } + return "h-[180px] sm:h-[240px]"; + } + }; + return (
{/* Hero Header */} @@ -88,93 +126,158 @@ export default function GalleryPageClient() { - {/* Visual Gallery section */} + {/* Gallery Section */}
-
- {gallery.events.map((event: EventItem) => ( + + {/* Step Timeline Navigation */} +
+
+ {/* Timeline track behind steps */} +
- {/* Event details */} -
-
-

- {event.title} -

-

- {event.description} -

+ className="absolute left-0 h-[2px] bg-primary transition-all duration-500 -z-10" + style={{ width: `${(activeEventIndex / (gallery.events.length - 1)) * 100}%` }} + /> + + {gallery.events.map((event: EventItem, idx: number) => { + const isActive = idx === activeEventIndex; + const isPassed = idx < activeEventIndex; + + return ( + + ); + })} +
+
+ + {/* Active Event Grid Container */} + {activeEvent && ( +
+ + {/* Top Navigation Control Header */} +
+ + + + {lang === "vi" + ? `SỰ KIỆN ${activeEventIndex + 1} / ${gallery.events.length}` + : `EVENT ${activeEventIndex + 1} OF ${gallery.events.length}` + } + + + +
+ + {/* Event Info Header */} +
+

+ {activeEvent.title} +

+ +
+
+ calendar_today + {activeEvent.date}
- {/* Meta details */} -
-
- location_on - {event.location} -
-
- calendar_today - {event.date} -
-
-
- - {/* Collage gallery grid */} -
- {/* Large image (left) */} -
openLightbox(event.id, 0)} - > - {/* eslint-disable-next-line @next/next/no-img-element */} - {`${event.title} -
-
- zoom_in -
-
-
- - {/* Stacked images (right) */} -
- {event.images.slice(1, 3).map((imgUrl, i) => ( -
openLightbox(event.id, i + 1)} - > - {/* eslint-disable-next-line @next/next/no-img-element */} - {`${event.title} -
-
- zoom_in -
-
-
- ))} -
+ {activeEvent.googleDriveUrl && activeEvent.googleDriveUrl.trim() !== "" && ( + + + {lang === "vi" ? "Xem Full Album trên Drive" : "View Full Album on Drive"} + + )}
- ))} -
+ + {/* Dynamic Mosaic Grid or Coming Soon Placeholder */} + {activeEvent.images.length === 0 ? ( +
+ image +

+ {lang === "vi" + ? "Hình ảnh nổi bật cho sự kiện này hiện đang được cập nhật." + : "Highlight images for this event are currently being updated." + } +

+
+ ) : ( +
+ {activeEvent.images.map((imgUrl, i) => ( +
openLightbox(i)} + > + {/* eslint-disable-next-line @next/next/no-img-element */} + {`${activeEvent.title} +
+
+ zoom_in +
+
+
+ ))} +
+ )} + +
+ )}
{/* Invitation Section */} {/* Lightbox Overlay */} - {lightboxEventId !== null && lightboxImageIndex !== null && activeEvent && activeImage && ( + {lightboxImageIndex !== null && activeEvent && activeImage && (
@@ -197,7 +300,7 @@ export default function GalleryPageClient() { {/* Prev arrow */}