import React, { useCallback, useRef } from 'react' import { Search, Filter, RotateCcw, Info } from 'lucide-react' import { FilterState } from '../types' import { getCostTierLabel } from '../utils/formatters' interface FilterBarProps { filterState: FilterState onFilterChange: (key: keyof FilterState, value: any) => void onClearFilters: () => void availableProviders: string[] filterStats: { total: number; filtered: number } } const COST_TIERS = ['free', 'low', 'medium', 'high'] export function FilterBar({ filterState, onFilterChange, onClearFilters, availableProviders, filterStats }: FilterBarProps) { // Debounced search to avoid excessive filtering const timeoutRef = useRef>() const debouncedSearch = useCallback((value: string) => { if (timeoutRef.current) { clearTimeout(timeoutRef.current) } timeoutRef.current = setTimeout(() => { onFilterChange('searchTerm', value) }, 300) }, [onFilterChange]) const handleSearchChange = (e: React.ChangeEvent) => { debouncedSearch(e.target.value) } const handleProviderToggle = (provider: string) => { const newProviders = filterState.selectedProviders.includes(provider) ? filterState.selectedProviders.filter(p => p !== provider) : [...filterState.selectedProviders, provider] onFilterChange('selectedProviders', newProviders) } const handleCostTierToggle = (tier: string) => { const newTiers = filterState.selectedCostTiers.includes(tier) ? filterState.selectedCostTiers.filter(t => t !== tier) : [...filterState.selectedCostTiers, tier] onFilterChange('selectedCostTiers', newTiers) } const hasActiveFilters = filterState.searchTerm || filterState.selectedProviders.length > 0 || filterState.selectedCostTiers.length > 0 || filterState.showMultimodal || filterState.showReasoning || filterState.showStreamCancel || filterState.hideExperimental return (
{/* Search Bar */}
{/* Filter Controls */}
Filters:
{/* Clear Filters */} {hasActiveFilters && ( )}
{/* Provider Filter */}
Provider:
{availableProviders.map(provider => ( ))}
{/* Cost Tier Filter */}
Cost: {COST_TIERS.map(tier => ( ))}
{/* Model Type Filters */}
{/* Multimodal Filter */} {/* Reasoning Filter with Warning */}
{/* Stream Cancel Filter with Warning */}
{/* Hide Experimental Filter */}
{/* Results Counter */}
Showing {filterStats.filtered} of {filterStats.total} models {filterStats.filtered < filterStats.total && ( {filterStats.total - filterStats.filtered} hidden by filters )}
) }