diff --git a/apps/spa/src/components/ProductImageGallery.tsx b/apps/spa/src/components/ProductImageGallery.tsx new file mode 100644 index 0000000..aa55027 --- /dev/null +++ b/apps/spa/src/components/ProductImageGallery.tsx @@ -0,0 +1,95 @@ +import { useState } from 'react' +import type { ProductImage } from '../types' + +interface ProductImageGalleryProps { + images: ProductImage[] + fallback: string + alt?: string + badgeText?: string +} + +export default function ProductImageGallery({ images, fallback, alt = 'Product Image', badgeText }: ProductImageGalleryProps) { + const [currentIndex, setCurrentIndex] = useState(0) + + // Sort images by order if they exist, else just use the array + const sortedImages = images?.length ? [...images].sort((a, b) => a.order - b.order) : [] + const hasImages = sortedImages.length > 0 + + const currentImageUrl = hasImages ? sortedImages[currentIndex].url : fallback + + const handleNext = () => { + setCurrentIndex((prev) => (prev === sortedImages.length - 1 ? 0 : prev + 1)) + } + + const handlePrev = () => { + setCurrentIndex((prev) => (prev === 0 ? sortedImages.length - 1 : prev - 1)) + } + + return ( +
+ {/* Main Image */} +
+ {alt} { (e.target as HTMLImageElement).src = fallback }} + /> +
+ + {badgeText && ( +
+ {badgeText} +
+ )} + + {/* Navigation Arrows */} + {sortedImages.length > 1 && ( + <> + + + + )} +
+ + {/* Thumbnails */} + {sortedImages.length > 1 && ( +
+ {sortedImages.map((image, idx) => ( + + ))} +
+ )} +
+ ) +} diff --git a/apps/spa/src/pages/ProductDetailPage.tsx b/apps/spa/src/pages/ProductDetailPage.tsx index 51c885b..bbaf29d 100644 --- a/apps/spa/src/pages/ProductDetailPage.tsx +++ b/apps/spa/src/pages/ProductDetailPage.tsx @@ -4,6 +4,7 @@ import Navbar from '../components/Navbar' import Footer from '../components/Footer' import ProductCard from '../components/ProductCard' import ProductReviews from '../components/ProductReviews' +import ProductImageGallery from '../components/ProductImageGallery' import DynamicPageRenderer from '../components/DynamicPageRenderer' import { API_BASE, getCategoryImage, formatPrice, type Category, type Product, type PageSection } from '../types' import { useCartStore } from '../store/cartStore' @@ -149,18 +150,14 @@ export default function ProductDetailPage() { {/* Product Detail */}
- {/* Image */} -
- + { (e.target as HTMLImageElement).style.display = 'none' }} + badgeText={product.category.name} /> -
-
- {product.category.name} -
{/* Info */}