76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
/**
|
|
* @component ProductGrid
|
|
* @purpose Product Showcase grid with dynamic tab switching (All Products, Featured, On Sale, Best Sellers).
|
|
* @a11y Accessible tab list, focus indicators
|
|
* @dependencies ProductCard, catalogService
|
|
*/
|
|
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { catalogService, ProductResponse } from '@/services/api/catalogService';
|
|
import { ProductCard } from './ProductCard';
|
|
|
|
type FilterTab = 'all' | 'featured' | 'sale' | 'bestsellers';
|
|
|
|
export function ProductGrid() {
|
|
const [products, setProducts] = useState<ProductResponse[]>([]);
|
|
const [activeTab, setActiveTab] = useState<FilterTab>('all');
|
|
|
|
useEffect(() => {
|
|
catalogService.getProducts().then(setProducts);
|
|
}, []);
|
|
|
|
const filteredProducts = products
|
|
.filter((p) => {
|
|
if (activeTab === 'featured') return p.badge === 'HOT' || p.badge === 'NEW';
|
|
if (activeTab === 'sale') return p.badge === 'SALE' || p.variants[0]?.compare_price;
|
|
if (activeTab === 'bestsellers') return (p.rating || 5) >= 4.8;
|
|
return true;
|
|
})
|
|
.slice(0, 8); // Limit to 8 items in the grid for supreme performance!
|
|
|
|
return (
|
|
<section className="w-full max-w-7xl mx-auto px-4 py-8">
|
|
{/* Header & Dynamic Filter Tabs */}
|
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6 border-b border-gray-200 pb-4">
|
|
<div>
|
|
<span className="text-[10px] font-bold text-[#e4382f] uppercase tracking-wider">
|
|
Our Catalog
|
|
</span>
|
|
<h2 className="text-xl font-extrabold text-[#1b2559]">Featured Products</h2>
|
|
</div>
|
|
|
|
{/* Dynamic Filter Tabs */}
|
|
<div className="flex items-center gap-2 overflow-x-auto pb-2 md:pb-0">
|
|
{(
|
|
[
|
|
{ id: 'all', label: 'All Products' },
|
|
{ id: 'featured', label: 'Featured' },
|
|
{ id: 'sale', label: 'On Sale' },
|
|
{ id: 'bestsellers', label: 'Best Sellers' },
|
|
] as const
|
|
).map((tab) => (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => setActiveTab(tab.id)}
|
|
className={`px-4 py-2 rounded-full text-xs font-bold transition-all cursor-pointer whitespace-nowrap ${
|
|
activeTab === tab.id
|
|
? 'bg-[#e4382f] text-white shadow-xs'
|
|
: 'bg-gray-100 hover:bg-gray-200 text-[#1b2559]'
|
|
}`}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Grid */}
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
|
{filteredProducts.map((product) => (
|
|
<ProductCard key={product.product_id} product={product} />
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|