feat([2fd88f42]): redesign filter panel with modern checkbox UI

This commit is contained in:
2026-02-04 12:38:10 +00:00
parent 3bbcdcb3a2
commit 76be805a3f

View File

@@ -14,61 +14,80 @@ interface FilterPanelProps {
const FilterPanel: React.FC<FilterPanelProps> = ({ filters, onFilterChange, isLoading }) => { const FilterPanel: React.FC<FilterPanelProps> = ({ filters, onFilterChange, isLoading }) => {
const [selectedFilters, setSelectedFilters] = useState<FilterOptions>({}); const [selectedFilters, setSelectedFilters] = useState<FilterOptions>({});
// Reset selected filters when a new file is uploaded (filters prop changes)
useEffect(() => { useEffect(() => {
setSelectedFilters({}); setSelectedFilters({});
}, [filters]); }, [filters]);
const handleSelectionChange = (category: string, values: string[]) => { const handleCheckboxChange = (category: string, value: string) => {
setSelectedFilters(prev => ({ setSelectedFilters(prev => {
...prev, const currentSelection = prev[category] || [];
[category]: values, const newSelection = currentSelection.includes(value)
})); ? currentSelection.filter(item => item !== value)
// Ensure "N/A" is not sorted to the top if that's not desired
: [...currentSelection, value].sort((a, b) => a === 'N/A' ? 1 : b === 'N/A' ? -1 : a.localeCompare(b));
return { ...prev, [category]: newSelection };
});
}; };
const handleApplyClick = () => { const handleApplyClick = () => {
onFilterChange(selectedFilters); onFilterChange(selectedFilters);
} };
const handleResetClick = () => { const handleResetClick = () => {
setSelectedFilters({}); setSelectedFilters({});
onFilterChange({}); onFilterChange({});
} };
if (Object.keys(filters).length === 0) { if (Object.keys(filters).length === 0) {
return <div>Upload a file to see filter options.</div>; return <div>Upload a file to see filter options.</div>;
} }
return ( return (
<>
<style>{`
.filter-panel { padding-top: 20px; }
.filter-group { margin-bottom: 15px; }
.filter-group summary { font-weight: bold; cursor: pointer; padding: 5px; background-color: #444; border-radius: 4px; }
.filter-options { max-height: 200px; overflow-y: auto; padding: 10px; background-color: #2a2a2a; border-radius: 4px; margin-top: 5px;}
.filter-option { display: flex; align-items: center; margin-bottom: 5px; }
.filter-option input { margin-right: 10px; }
.filter-buttons { margin-top: 20px; display: flex; justify-content: space-between; }
.filter-buttons button { width: 48%; padding: 10px; border: none; border-radius: 4px; cursor: pointer; }
.apply-button { background-color: #4CAF50; color: white; }
.reset-button { background-color: #f44336; color: white; }
.filter-buttons button:disabled { background-color: #555; cursor: not-allowed; }
`}</style>
<div className="filter-panel"> <div className="filter-panel">
<h3>Filters</h3> <h3>Filters</h3>
{Object.entries(filters).map(([category, options]) => ( {Object.entries(filters).map(([category, options]) => (
<div key={category} className="filter-group"> <details key={category} className="filter-group" open>
<label>{category}</label> <summary>{category}</summary>
<select <div className="filter-options">
multiple
value={selectedFilters[category] || []}
onChange={(e) =>
handleSelectionChange(category, Array.from(e.target.selectedOptions, option => option.value))
}
>
{options.map(option => ( {options.map(option => (
<option key={option} value={option}> <div key={option} className="filter-option">
{option} <input
</option> type="checkbox"
))} id={`${category}-${option}`}
</select> value={option}
checked={(selectedFilters[category] || []).includes(option)}
onChange={() => handleCheckboxChange(category, option)}
/>
<label htmlFor={`${category}-${option}`}>{option}</label>
</div> </div>
))} ))}
</div>
</details>
))}
<div className="filter-buttons"> <div className="filter-buttons">
<button onClick={handleApplyClick} disabled={isLoading}> <button onClick={handleApplyClick} disabled={isLoading} className="apply-button">
{isLoading ? 'Loading...' : 'Apply Filters'} {isLoading ? 'Loading...' : 'Apply Filters'}
</button> </button>
<button onClick={handleResetClick} disabled={isLoading}> <button onClick={handleResetClick} disabled={isLoading} className="reset-button">
Reset Filters Reset
</button> </button>
</div> </div>
</div> </div>
</>
); );
}; };