/** * Filter Panel Component * Provides filtering options for analytics data */ import { useState } from 'react'; interface FilterOption { value: string; label: string; } interface FilterConfig { key: string; label: string; type: 'select' | 'multiselect' | 'search'; options?: FilterOption[]; } interface FilterPanelProps { filters: FilterConfig[]; values: Record; onChange: (values: Record) => void; onReset?: () => void; } export default function FilterPanel({ filters, values, onChange, onReset, }: FilterPanelProps) { const [isExpanded, setIsExpanded] = useState(false); const handleChange = (key: string, value: any) => { onChange({ ...values, [key]: value }); }; const handleMultiSelect = (key: string, value: string) => { const current = values[key] || []; const updated = current.includes(value) ? current.filter((v: string) => v !== value) : [...current, value]; handleChange(key, updated); }; const activeFilterCount = Object.values(values).filter( (v) => v && (Array.isArray(v) ? v.length > 0 : true) ).length; return (
{/* Header */} {/* Filter content */} {isExpanded && (
{filters.map((filter) => (
{filter.type === 'select' && filter.options && ( )} {filter.type === 'multiselect' && filter.options && (
{filter.options.map((opt) => ( ))}
)} {filter.type === 'search' && ( handleChange(filter.key, e.target.value || null)} placeholder={`Search ${filter.label.toLowerCase()}...`} className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" /> )}
))}
{/* Actions */}
{onReset && ( )}
)}
); }