'use client'; import { useState, useEffect, useCallback, useRef } from 'react'; import { Card } from '@/types'; function ImageCarousel({ images }: { images: string[] }) { const [current, setCurrent] = useState(0); const touchStartX = useRef(null); const prev = useCallback(() => setCurrent(i => (i - 1 + images.length) % images.length), [images.length]); const next = useCallback(() => setCurrent(i => (i + 1) % images.length), [images.length]); useEffect(() => { const onKey = (e: KeyboardEvent) => { if (e.key === 'ArrowLeft') prev(); if (e.key === 'ArrowRight') next(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [prev, next]); // Reset to first image when a new card is shown useEffect(() => { setCurrent(0); }, [images]); const onTouchStart = (e: React.TouchEvent) => { touchStartX.current = e.touches[0].clientX; }; const onTouchEnd = (e: React.TouchEvent) => { if (touchStartX.current === null) return; const delta = e.changedTouches[0].clientX - touchStartX.current; if (Math.abs(delta) > 50) delta < 0 ? next() : prev(); touchStartX.current = null; }; if (images.length === 0) { return
No Image
; } return (
{/* Images */} {images.map((src, i) => ( ))} {/* Arrows — only if more than one image */} {images.length > 1 && ( <> {/* Dot indicators */}
{images.map((_, i) => (
{/* Counter badge */}
{current + 1} / {images.length}
)}
); } export default function PublicGrid({ cards, maxCols = 5 }: { cards: Card[], maxCols?: number }) { const [activeCard, setActiveCard] = useState(null); useEffect(() => { if (activeCard) document.body.style.overflow = 'hidden'; else document.body.style.overflow = 'unset'; return () => { document.body.style.overflow = 'unset'; }; }, [activeCard]); const gridClasses: Record = { 3: 'xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 grid-cols-1', 4: 'xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 grid-cols-1', 5: 'xl:grid-cols-5 lg:grid-cols-4 md:grid-cols-3 grid-cols-1', 6: 'xl:grid-cols-6 lg:grid-cols-4 md:grid-cols-3 grid-cols-2', 7: 'xl:grid-cols-7 lg:grid-cols-5 md:grid-cols-4 grid-cols-2', 8: 'xl:grid-cols-8 lg:grid-cols-6 md:grid-cols-4 grid-cols-2', }; const activeGridClass = gridClasses[maxCols] || gridClasses[5]; return ( <>
{cards.map((card) => (
setActiveCard(card)} className="group relative cursor-pointer overflow-hidden rounded-xl shadow-md aspect-square bg-gray-200 transition-all duration-300 hover:shadow-xl hover:-translate-y-1" > {card.imageUrl ? ( {card.title} ) : (
No Image
)} {/* Gallery badge */} {card.extraImages && card.extraImages.length > 0 && (
{1 + card.extraImages.length}
)}

{card.title}

{card.shortDescription}

))}
{activeCard && (
setActiveCard(null)} >
e.stopPropagation()} >
{activeCard.cardType.replace('_', ' ')}

{activeCard.title}

{activeCard.fullContent ? (
) : (

{activeCard.shortDescription}

)}
)} ); }