anycoder-adadf141 / components /ProductGrid.jsx
puwanath's picture
Upload components/ProductGrid.jsx with huggingface_hub
f36d113 verified
import React, { useState, useEffect } from 'react';
import {
Plus,
Minus,
ShoppingBag,
Heart,
Search,
Filter,
Grid,
List
} from 'lucide-react';
const ProductGrid = ({
products,
activeCategory,
onAddToCart,
onProductClick
}) => {
const [searchQuery, setSearchQuery] = useState('');
const [gridView, setGridView] = useState(true);
const [filteredProducts, setFilteredProducts] = useState([]);
useEffect(() => {
let result = products;
// Filter by category
if (activeCategory !== 'all') {
result = result.filter(product => product.category === activeCategory);
}
// Filter by search query
if (searchQuery) {
result = result.filter(product =>
product.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
product.description.toLowerCase().includes(searchQuery.toLowerCase())
);
}
setFilteredProducts(result);
}, [products, activeCategory, searchQuery]);
const formatPrice = (price) => {
return new Intl.NumberFormat('th-TH', {
style: 'currency',
currency: 'THB'
}).format(price);
};
return (
<div className="flex-1 overflow-y-auto p-4">
{/* Search and Filter */}
<div className="mb-6 space-y-4">
<div className="flex flex-col sm:flex-row gap-4">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-pos-text-secondary w-5 h-5" />
<input
type="text"
placeholder="ค้นหาสินค้า..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full pl-10 pr-4 py-3 rounded-xl border border-pos-border focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-all"
/>
</div>
<div className="flex gap-2">
<button
onClick={() => setGridView(true)}
className={`p-3 rounded-xl border ${gridView
? 'bg-primary-600 text-white border-primary-600'
: 'border-pos-border text-pos-text-secondary hover:bg-pos-bg'}`}
>
<Grid className="w-5 h-5" />
</button>
<button
onClick={() => setGridView(false)}
className={`p-3 rounded-xl border ${!gridView
? 'bg-primary-600 text-white border-primary-600'
: 'border-pos-border text-pos-text-secondary hover:bg-pos-bg'}`}
>
<List className="w-5 h-5" />
</button>
<button className="p-3 rounded-xl border border-pos-border text-pos-text-secondary hover:bg-pos-bg">
<Filter className="w-5 h-5" />
</button>
</div>
</div>
</div>
{/* Products */}
<div className={gridView ? "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4" : "space-y-3"}>
{filteredProducts.length > 0 ? (
filteredProducts.map((product) => (
<div
key={product.id}
onClick={() => onProductClick(product)}
className="group bg-white rounded-2xl border border-pos-border overflow-hidden hover:shadow-xl transition-all duration-300 hover:border-primary-200 cursor-pointer"
>
<div className="relative aspect-square overflow-hidden">
<img
src={product.image}
alt={product.name}
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-300"
/>
<div className="absolute top-2 right-2">
<button className="p-2 bg-white/90 rounded-full hover:bg-white shadow-sm transition-colors">
<Heart className="w-4 h-4 text-red-500" />
</button>
</div>
{product.discount > 0 && (
<div className="absolute top-2 left-2 bg-danger text-white px-2 py-1 rounded-lg text-xs font-bold">
-{product.discount}%
</div>
)}
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent p-4">
<p className="text-white text-xs font-medium">{product.categoryName}</p>
</div>
</div>
<div className="p-3">
<h3 className="font-bold text-pos-text mb-1 truncate">{product.name}</h3>
<div className="flex justify-between items-center">
<div className="flex flex-col">
{product.discount > 0 ? (
<>
<span className="text-xs text-pos-text-secondary line-through">
{formatPrice(product.price)}
</span>
<span className="text-lg font-bold text-primary-600">
{formatPrice(product.price * (1 - product.discount/100))}
</span>
</>
) : (
<span className="text-lg font-bold text-pos-text">
{formatPrice(product.price)}
</span>
)}
</div>
<button
onClick={(e) => {
e.stopPropagation();
onAddToCart(product);
className="p-2 bg-primary-50 text-primary-600 rounded-xl hover:bg-primary-600 hover:text-white transition-colors"
>
<ShoppingBag className="w-5 h-5" />
</button>
</div>
</div>
</div>
))
) : (
<div className="col-span-full py-12 text-center">
<div className="w-20 h-20 bg-pos-bg rounded-full flex items-center justify-center mx-auto mb-4">
<Search className="w-10 h-10 text-pos-text-secondary" />
</div>
<h3 className="text-lg font-medium text-pos-text mb-2">ไม่พบสินค้า</h3>
<p className="text-pos-text-secondary">
{searchQuery
? `ไม่พบผลลัพธ์สำหรับ "${searchQuery}"`
: "โปรดเลือกหมวดหมู่หรือลองค้นหาใหม่"}
</p>
</div>
)}
</div>
{/* Product count */}
<div className="mt-4 text-center">
<p className="text-sm text-pos-text-secondary">
แสดง {filteredProducts.length} ของ {products.length} ผลิตภัณฑ์
</p>
</div>
</div>
);
};
export default ProductGrid;