feat: Implement multi-select combobox filters

This commit is contained in:
gpt-engineer-app[bot]
2025-10-16 15:52:00 +00:00
parent e881778659
commit d9e05125fe
2 changed files with 192 additions and 52 deletions

View File

@@ -4,6 +4,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Slider } from '@/components/ui/slider';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { MultiSelectCombobox } from '@/components/ui/multi-select-combobox';
import { RideCreditFilters as FilterTypes } from '@/types/ride-credits';
import { UserRideCredit } from '@/types/database';
import { Search, X, ChevronDown, MapPin, Building2, Factory, Calendar, Star, MessageSquare, Image } from 'lucide-react';
@@ -159,38 +160,36 @@ export function RideCreditFilters({
</CollapsibleTrigger>
<CollapsibleContent className="p-4 space-y-3 bg-card border rounded-lg mt-1">
{filterOptions.countries.length > 0 && (
<div className="space-y-2">
<div className={sectionSpacing}>
<Label className="text-sm font-medium">Countries</Label>
<div className="flex flex-wrap gap-2">
{filterOptions.countries.map(country => (
<Badge
key={country}
variant={(filters.countries || []).includes(country) ? 'default' : 'outline'}
className="cursor-pointer"
onClick={() => toggleArrayFilter('countries', country)}
>
{country}
</Badge>
))}
</div>
<MultiSelectCombobox
options={filterOptions.countries.map(c => ({ label: c, value: c }))}
value={filters.countries || []}
onValueChange={(values) =>
onFilterChange('countries', values.length > 0 ? values : undefined)
}
placeholder="Select countries..."
searchPlaceholder="Search countries..."
emptyText="No countries found"
className={compact ? "h-9 text-sm" : ""}
/>
</div>
)}
{filterOptions.states.length > 0 && (
<div className="space-y-2">
<div className={sectionSpacing}>
<Label className="text-sm font-medium">States/Provinces</Label>
<div className="flex flex-wrap gap-2">
{filterOptions.states.map(state => (
<Badge
key={state}
variant={(filters.statesProvinces || []).includes(state) ? 'default' : 'outline'}
className="cursor-pointer"
onClick={() => toggleArrayFilter('statesProvinces', state)}
>
{state}
</Badge>
))}
</div>
<MultiSelectCombobox
options={filterOptions.states.map(s => ({ label: s, value: s }))}
value={filters.statesProvinces || []}
onValueChange={(values) =>
onFilterChange('statesProvinces', values.length > 0 ? values : undefined)
}
placeholder="Select states/provinces..."
searchPlaceholder="Search states/provinces..."
emptyText="No states/provinces found"
className={compact ? "h-9 text-sm" : ""}
/>
</div>
)}
</CollapsibleContent>
@@ -210,20 +209,19 @@ export function RideCreditFilters({
</CollapsibleTrigger>
<CollapsibleContent className="p-4 space-y-3 bg-card border rounded-lg mt-1">
{filterOptions.parks.length > 0 && (
<div className="space-y-2">
<div className={sectionSpacing}>
<Label className="text-sm font-medium">Specific Parks</Label>
<div className="flex flex-wrap gap-2">
{filterOptions.parks.map(park => (
<Badge
key={park.id}
variant={(filters.parks || []).includes(park.id) ? 'default' : 'outline'}
className="cursor-pointer"
onClick={() => toggleArrayFilter('parks', park.id)}
>
{park.name}
</Badge>
))}
</div>
<MultiSelectCombobox
options={filterOptions.parks.map(p => ({ label: p.name, value: p.id }))}
value={filters.parks || []}
onValueChange={(values) =>
onFilterChange('parks', values.length > 0 ? values : undefined)
}
placeholder="Select parks..."
searchPlaceholder="Search parks..."
emptyText="No parks found"
className={compact ? "h-9 text-sm" : ""}
/>
</div>
)}
</CollapsibleContent>
@@ -243,20 +241,19 @@ export function RideCreditFilters({
</CollapsibleTrigger>
<CollapsibleContent className="p-4 space-y-3 bg-card border rounded-lg mt-1">
{filterOptions.manufacturers.length > 0 && (
<div className="space-y-2">
<div className={sectionSpacing}>
<Label className="text-sm font-medium">Manufacturers</Label>
<div className="flex flex-wrap gap-2">
{filterOptions.manufacturers.map(mfr => (
<Badge
key={mfr.id}
variant={(filters.manufacturers || []).includes(mfr.id) ? 'default' : 'outline'}
className="cursor-pointer"
onClick={() => toggleArrayFilter('manufacturers', mfr.id)}
>
{mfr.name}
</Badge>
))}
</div>
<MultiSelectCombobox
options={filterOptions.manufacturers.map(m => ({ label: m.name, value: m.id }))}
value={filters.manufacturers || []}
onValueChange={(values) =>
onFilterChange('manufacturers', values.length > 0 ? values : undefined)
}
placeholder="Select manufacturers..."
searchPlaceholder="Search manufacturers..."
emptyText="No manufacturers found"
className={compact ? "h-9 text-sm" : ""}
/>
</div>
)}