This commit is contained in:
2024-10-06 08:57:55 +05:30
parent 080ce9ee57
commit 990e7ee75b
48 changed files with 1929 additions and 185 deletions

View File

@ -0,0 +1,162 @@
'use client';
import { SearchIcon, SlidersHorizontal } from 'lucide-react';
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Slider } from '@/components/ui/slider';
// Mock product data
const products = [
{ id: 1, name: 'Laptop', category: 'Electronics', price: 999.99 },
{ id: 2, name: 'Smartphone', category: 'Electronics', price: 699.99 },
{ id: 3, name: 'Headphones', category: 'Electronics', price: 199.99 },
{ id: 4, name: 'T-shirt', category: 'Clothing', price: 24.99 },
{ id: 5, name: 'Jeans', category: 'Clothing', price: 49.99 },
{ id: 6, name: 'Sneakers', category: 'Footwear', price: 89.99 },
{ id: 7, name: 'Watch', category: 'Accessories', price: 149.99 },
{ id: 8, name: 'Backpack', category: 'Accessories', price: 79.99 },
];
const categories = ['Electronics', 'Clothing', 'Footwear', 'Accessories'];
export function ProductListComponent() {
const [priceRange, setPriceRange] = useState([0, 1000]);
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
const [searchQuery, setSearchQuery] = useState('');
const [sortBy, setSortBy] = useState('name');
const handleCategoryChange = (category: string) => {
setSelectedCategories((prev) =>
prev.includes(category)
? prev.filter((c) => c !== category)
: [...prev, category],
);
};
const filteredProducts = products
.filter(
(product) =>
(selectedCategories.length === 0 ||
selectedCategories.includes(product.category)) &&
product.price >= priceRange[0] &&
product.price <= priceRange[1] &&
product.name.toLowerCase().includes(searchQuery.toLowerCase()),
)
.sort((a, b) => {
if (sortBy === 'price') return a.price - b.price;
return a.name.localeCompare(b.name);
});
return (
<div className='container mx-auto px-4 py-8'>
<div className='flex flex-col md:flex-row gap-8'>
{/* Sidebar with filters */}
<aside className='w-full md:w-1/4 space-y-6'>
<Card>
<CardHeader>
<CardTitle>Filters</CardTitle>
</CardHeader>
<CardContent className='space-y-6'>
<div>
<h3 className='text-lg font-semibold mb-2'>Categories</h3>
{categories.map((category) => (
<div key={category} className='flex items-center space-x-2'>
<Checkbox
id={category}
checked={selectedCategories.includes(category)}
onCheckedChange={() => handleCategoryChange(category)}
/>
<label
htmlFor={category}
className='text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
>
{category}
</label>
</div>
))}
</div>
<div>
<h3 className='text-lg font-semibold mb-2'>Price Range</h3>
<Slider
min={0}
max={1000}
step={10}
value={priceRange}
onValueChange={setPriceRange}
/>
<div className='flex justify-between mt-2'>
<span>${priceRange[0]}</span>
<span>${priceRange[1]}</span>
</div>
</div>
</CardContent>
</Card>
</aside>
{/* Main content */}
<main className='w-full md:w-3/4'>
<div className='flex flex-col sm:flex-row justify-between items-center mb-6 gap-4'>
<div className='relative w-full sm:w-auto'>
<SearchIcon className='absolute left-2 top-1/2 transform -translate-y-1/2 text-gray-400' />
<Input
type='search'
placeholder='Search products...'
className='pl-8'
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<div className='flex items-center space-x-2 w-full sm:w-auto'>
<Select value={sortBy} onValueChange={setSortBy}>
<SelectTrigger className='w-full sm:w-[180px]'>
<SelectValue placeholder='Sort by' />
</SelectTrigger>
<SelectContent>
<SelectItem value='name'>Name</SelectItem>
<SelectItem value='price'>Price</SelectItem>
</SelectContent>
</Select>
<Button variant='outline' size='icon'>
<SlidersHorizontal className='h-4 w-4' />
</Button>
</div>
</div>
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6'>
{filteredProducts.map((product) => (
<Card key={product.id}>
<CardHeader>
<CardTitle>{product.name}</CardTitle>
</CardHeader>
<CardContent>
<p>Category: {product.category}</p>
<p className='font-bold mt-2'>${product.price.toFixed(2)}</p>
</CardContent>
<CardFooter>
<Button className='w-full'>Add to Cart</Button>
</CardFooter>
</Card>
))}
</div>
</main>
</div>
</div>
);
}