'use client'; import React, { useState, useEffect, useRef } from 'react'; import Link from 'next/link'; import { ArrowRight, PackageX, ChevronLeft, ChevronRight } from 'lucide-react'; import { Swiper, SwiperSlide } from 'swiper/react'; import { Navigation, A11y } from 'swiper/modules'; import type { Swiper as SwiperType } from 'swiper'; import { ProductCard } from '../components/ProductCard'; import { Product } from '../types'; import { mapCatalogProductToProduct } from '../utils/productMapper'; import { SectionHeaderSkeleton, ProductCardSkeleton, } from '../components/ui/Skeleton'; import { getSectionTitle } from '../lib/homepageDefaults'; import 'swiper/css'; import 'swiper/css/navigation'; interface NewArrivalsSectionProps { config?: any; products?: Product[]; loading?: boolean; error?: boolean; } export const NewArrivalsSection: React.FC = ({ config, products, loading, error, }) => { const [newArrivals, setNewArrivals] = useState([]); const [canPrev, setCanPrev] = useState(false); const [canNext, setCanNext] = useState(false); /** Only true when slides overflow the viewport */ const [showNav, setShowNav] = useState(false); const swiperRef = useRef(null); useEffect(() => { const pinnedSlugs: string[] = config?.metadata_json?.pinned_product_slugs || config?.metadata?.pinned_product_slugs || []; if (pinnedSlugs.length > 0 && products && products.length > 0) { const pinned = pinnedSlugs .map((slug) => products.find((p) => p.slug === slug || p.id === slug)) .filter(Boolean) as Product[]; setNewArrivals(pinned.length > 0 ? pinned : products.slice(0, 10)); return; } if (products && products.length > 0) { const arrivals = products.filter((p) => p.isNewArrival); setNewArrivals((arrivals.length >= 5 ? arrivals : products).slice(0, 10)); return; } import('../services/api/catalogService').then(({ catalogService }) => { catalogService .getProductsPaginated({ sort: 'newest', limit: 10 }) .then((res: any) => { if (res?.products?.length > 0) { const mapped = res.products.map((p: any) => mapCatalogProductToProduct(p) ); setNewArrivals(mapped); } }) .catch(() => {}); }); }, [config, products, error]); const title = getSectionTitle(config, 'editorial_story'); const syncNav = (swiper: SwiperType) => { if (!swiper || !swiper.slides) return; const overflow = !swiper.isLocked && (swiper.slides?.length || 0) > 0; setShowNav(overflow); setCanPrev(overflow && !swiper.isBeginning); setCanNext(overflow && !swiper.isEnd); }; useEffect(() => { const swiper = swiperRef.current; if (!swiper || !swiper.slides) return; requestAnimationFrame(() => syncNav(swiper)); }, [newArrivals.length]); return (
{loading ? (
{[1, 2, 3, 4, 5].map((i) => (
))}
) : !loading && !error && newArrivals.length === 0 ? (

No Products Available

Check back later for new arrivals in our catalog.

) : (
{/* Header — TechShop reference */}

{title}

View All
{/* Slider — both arrows always fully visible on hover (same style) */}
{showNav ? ( <> ) : null}
{ swiperRef.current = swiper; requestAnimationFrame(() => syncNav(swiper)); }} onSlideChange={syncNav} onResize={syncNav} onBreakpoint={syncNav} onLock={() => { setShowNav(false); setCanPrev(false); setCanNext(false); }} onUnlock={(swiper) => syncNav(swiper)} watchOverflow spaceBetween={0} slidesPerView={2} breakpoints={{ 640: { slidesPerView: 3 }, 1024: { slidesPerView: 4 }, 1280: { slidesPerView: 5 }, }} > {newArrivals.map((product) => ( ))}
)}
); };