'use client' import { useState, useMemo } from 'react' import { useMedusaProducts } from '@/hooks/useMedusaProducts' import { useMedusaCart } from '@/hooks/useMedusaCart' import ProductFilters, { FilterState } from '@/components/shop/ProductFilters' import ProductSort, { SortOption } from '@/components/shop/ProductSort' import Image from 'next/image' import Link from 'next/link' import { Search, ShoppingBag, ShoppingCart, SlidersHorizontal, X } from 'lucide-react' const CURRENCY_SYMBOLS: Record = { zar: 'R', usd: '$', eur: '€', gbp: '£', kes: 'KSh', ngn: '₦', ghs: '₵' } const formatPrice = (amount: number, code?: string) => { const sym = CURRENCY_SYMBOLS[(code ?? '').toLowerCase()] ?? (code?.toUpperCase() ?? '') return `${sym}${(amount / 100).toFixed(2)}` } export default function ProductsPage() { const { products, loading, error } = useMedusaProducts(100) const { addToCart } = useMedusaCart() const [sort, setSort] = useState('featured') const [filters, setFilters] = useState({ category: '', maxPrice: 0, inStockOnly: false }) const [search, setSearch] = useState('') const [filtersOpen, setFiltersOpen] = useState(false) const categories = useMemo(() => { const seen = new Map() products.forEach(p => { if (p.categories?.length) { p.categories.forEach((cat: { id: string; name: string }) => seen.set(cat.id, cat.name)) } else if (p.collection?.id) { seen.set(p.collection.id, p.collection.title ?? p.collection.id) } }) return Array.from(seen.entries()).map(([id, title]) => ({ id, title })) }, [products]) const displayed = useMemo(() => { let list = [...products] if (search.trim()) { const q = search.toLowerCase() list = list.filter(p => p.title?.toLowerCase().includes(q) || p.description?.toLowerCase().includes(q)) } if (filters.category) list = list.filter(p => p.categories?.some((c: { id: string }) => c.id === filters.category) || p.collection?.id === filters.category ) if (filters.maxPrice > 0) list = list.filter(p => { const price = p.variants?.[0]?.prices?.[0]?.amount ?? 0 return price > 0 && price / 100 <= filters.maxPrice }) if (filters.inStockOnly) list = list.filter(p => (p.variants?.length ?? 0) > 0) switch (sort) { case 'price-asc': list.sort((a, b) => (a.variants?.[0]?.prices?.[0]?.amount ?? 0) - (b.variants?.[0]?.prices?.[0]?.amount ?? 0)); break case 'price-desc': list.sort((a, b) => (b.variants?.[0]?.prices?.[0]?.amount ?? 0) - (a.variants?.[0]?.prices?.[0]?.amount ?? 0)); break case 'newest': list.sort((a, b) => new Date(b.created_at ?? 0).getTime() - new Date(a.created_at ?? 0).getTime()); break case 'name-asc': list.sort((a, b) => (a.title ?? '').localeCompare(b.title ?? '')); break } return list }, [products, filters, sort, search]) const resetFilters = () => setFilters({ category: '', maxPrice: 0, inStockOnly: false }) if (loading) return (

Loading products...

) if (error) return (

Failed to load products. Please try again.

) return (
{/* Header */}

Products

{/* Search */}
setSearch(e.target.value)} className="w-full pl-10 pr-4 py-2.5 bg-background border border-border rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-primary/50" /> {search && ( )}
{/* Sidebar filters — desktop */} {categories.length > 0 && ( )} {/* Mobile filter toggle */}
{categories.length > 0 && ( )} {/* Sort bar */}
{/* Grid */} {displayed.length === 0 ? (

No products found.

) : (
{displayed.map((product) => { const variant = product.variants?.[0] const price = variant?.prices?.[0] const imageUrl = product.thumbnail || product.images?.[0]?.url return (
{imageUrl ? (
{product.title
) : (
)}

{product.title}

{product.collection?.title && ( {product.collection.title} )} {product.description && (

{product.description}

)} {price && (

{formatPrice(price.amount, price.currency_code)}

)}
) })}
)}
{/* Mobile filter drawer */} {filtersOpen && (
setFiltersOpen(false)} />
setFiltersOpen(false)} />
)}
) }