import { useState, useMemo } from 'react'; // Sample product data (since we can't use Redux) const initialProducts = [ { _id: '1', title: 'Smartphone X', brand_name: 'TechBrand', category: 'Electronics', price: 799, color: 'Black' }, { _id: '2', title: 'Laptop Pro', brand_name: 'ComputeCo', category: 'Computers', price: 1299, color: 'Silver' }, { _id: '3', title: 'Wireless Earbuds', brand_name: 'AudioTech', category: 'Audio', price: 199, color: 'White' }, { _id: '4', title: 'Smartwatch Ultra', brand_name: 'TechBrand', category: 'Wearables', price: 349, color: 'Blue' }, { _id: '5', title: 'Tablet Mini', brand_name: 'ComputeCo', category: 'Tablets', price: 499, color: 'Rose Gold' } ]; const Brand = () => { const [selectedCategories, setSelectedCategories] = useState([]); const [priceRange, setPriceRange] = useState([0, 1500]); const [selectedBrand, setSelectedBrand] = useState(''); const [selectedColors, setSelectedColors] = useState([]); // Derived data const categories = [...new Set(initialProducts.map(p => p.category))]; const brands = [...new Set(initialProducts.map(p => p.brand_name))]; const colors = [...new Set(initialProducts.map(p => p.color))]; // Filtering logic const filteredProducts = useMemo(() => { return initialProducts.filter(product => { // Category filter const categoryMatch = selectedCategories.length === 0 || selectedCategories.includes(product.category); // Price range filter const priceMatch = product.price >= priceRange[0] && product.price <= priceRange[1]; // Brand filter const brandMatch = !selectedBrand || product.brand_name === selectedBrand; // Color filter const colorMatch = selectedColors.length === 0 || selectedColors.includes(product.color); return categoryMatch && priceMatch && brandMatch && colorMatch; }); }, [selectedCategories, priceRange, selectedBrand, selectedColors]); // Category checkbox handler const handleCategoryToggle = (category) => { setSelectedCategories(prev => prev.includes(category) ? prev.filter(c => c !== category) : [...prev, category] ); }; // Color checkbox handler const handleColorToggle = (color) => { setSelectedColors(prev => prev.includes(color) ? prev.filter(c => c !== color) : [...prev, color] ); }; return ( <div className='mt-36'> <div className="grid md:grid-cols-4 gap-6"> {/* Categories Checkbox Filter */} <div className="border p-4 rounded"> <h3 className="font-semibold mb-2">Categories</h3> {categories.map(category => ( <div key={category} className="flex items-center mb-2"> <input type="checkbox" id={category} checked={selectedCategories.includes(category)} onChange={() => handleCategoryToggle(category)} className="mr-2" /> <label htmlFor={category}>{category}</label> </div> ))} </div> {/* Price Range Slider */} <div className="border p-4 rounded"> <h3 className="font-semibold mb-2">Price Range</h3> <div className="flex items-center space-x-4"> <span>${priceRange[0]}</span> <input type="range" min="0" max="1500" color='red' value={priceRange[1]} onChange={(e) => setPriceRange([priceRange[0], Number(e.target.value)])} className="flex-grow" /> <span>${priceRange[1]}</span> </div> <div className="mt-2 text-sm text-gray-600"> Price: ${priceRange[0]} - ${priceRange[1]} </div> </div> {/* Brand Select Dropdown */} <div className="border p-4 rounded"> <h3 className="font-semibold mb-2">Brand</h3> <div className="relative"> <select value={selectedBrand} onChange={(e) => setSelectedBrand(e.target.value)} className="w-full appearance-none border rounded p-2 pr-8" > <option value="">All Brands</option> {brands.map(brand => ( <option key={brand} value={brand}>{brand}</option> ))} </select> </div> </div> {/* Color Checkbox Filter */} <div className="border p-4 rounded"> <h3 className="font-semibold mb-2">Colors</h3> {colors.map(color => ( <div key={color} className="flex items-center mb-2"> <input type="checkbox" id={color} checked={selectedColors.includes(color)} onChange={() => handleColorToggle(color)} className="mr-2" /> <label htmlFor={color} className="flex items-center" > <span className="w-4 h-4 mr-2 rounded-full inline-block" style={{ backgroundColor: color.toLowerCase() }} ></span> {color} </label> </div> ))} </div> </div> {/* Filtered Products Display */} <div className="mt-6"> <h3 className="text-xl font-semibold mb-4"> Filtered Products ({filteredProducts.length}) </h3> <div className="grid md:grid-cols-3 gap-4"> {filteredProducts.map(product => ( <div key={product._id} className="border p-4 rounded hover:shadow-md transition" > <h4 className="font-medium">{product.title}</h4> <p className="text-gray-600">{product.brand_name}</p> <div className="flex items-center mt-2"> <span className="w-4 h-4 mr-2 rounded-full inline-block" style={{ backgroundColor: product.color.toLowerCase() }} ></span> <span>{product.color}</span> </div> <p className="font-bold">${product.price}</p> </div> ))} </div> </div> </div> ) } export default Brand
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter