feat([2fd88f42]): redesign filter panel with modern checkbox UI
This commit is contained in:
@@ -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 (
|
||||||
<div className="filter-panel">
|
<>
|
||||||
<h3>Filters</h3>
|
<style>{`
|
||||||
{Object.entries(filters).map(([category, options]) => (
|
.filter-panel { padding-top: 20px; }
|
||||||
<div key={category} className="filter-group">
|
.filter-group { margin-bottom: 15px; }
|
||||||
<label>{category}</label>
|
.filter-group summary { font-weight: bold; cursor: pointer; padding: 5px; background-color: #444; border-radius: 4px; }
|
||||||
<select
|
.filter-options { max-height: 200px; overflow-y: auto; padding: 10px; background-color: #2a2a2a; border-radius: 4px; margin-top: 5px;}
|
||||||
multiple
|
.filter-option { display: flex; align-items: center; margin-bottom: 5px; }
|
||||||
value={selectedFilters[category] || []}
|
.filter-option input { margin-right: 10px; }
|
||||||
onChange={(e) =>
|
.filter-buttons { margin-top: 20px; display: flex; justify-content: space-between; }
|
||||||
handleSelectionChange(category, Array.from(e.target.selectedOptions, option => option.value))
|
.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; }
|
||||||
{options.map(option => (
|
.filter-buttons button:disabled { background-color: #555; cursor: not-allowed; }
|
||||||
<option key={option} value={option}>
|
`}</style>
|
||||||
{option}
|
<div className="filter-panel">
|
||||||
</option>
|
<h3>Filters</h3>
|
||||||
))}
|
{Object.entries(filters).map(([category, options]) => (
|
||||||
</select>
|
<details key={category} className="filter-group" open>
|
||||||
|
<summary>{category}</summary>
|
||||||
|
<div className="filter-options">
|
||||||
|
{options.map(option => (
|
||||||
|
<div key={option} className="filter-option">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={`${category}-${option}`}
|
||||||
|
value={option}
|
||||||
|
checked={(selectedFilters[category] || []).includes(option)}
|
||||||
|
onChange={() => handleCheckboxChange(category, option)}
|
||||||
|
/>
|
||||||
|
<label htmlFor={`${category}-${option}`}>{option}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
))}
|
||||||
|
<div className="filter-buttons">
|
||||||
|
<button onClick={handleApplyClick} disabled={isLoading} className="apply-button">
|
||||||
|
{isLoading ? 'Loading...' : 'Apply Filters'}
|
||||||
|
</button>
|
||||||
|
<button onClick={handleResetClick} disabled={isLoading} className="reset-button">
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
<div className="filter-buttons">
|
|
||||||
<button onClick={handleApplyClick} disabled={isLoading}>
|
|
||||||
{isLoading ? 'Loading...' : 'Apply Filters'}
|
|
||||||
</button>
|
|
||||||
<button onClick={handleResetClick} disabled={isLoading}>
|
|
||||||
Reset Filters
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user