persistent filters
This commit is contained in:
@@ -49,6 +49,7 @@ interface FiltersProps {
|
||||
className?: string;
|
||||
fieldClassName?: string;
|
||||
searchField?: string;
|
||||
showClearButton?: boolean;
|
||||
}
|
||||
|
||||
const Filters: FC<FiltersProps> = ({
|
||||
@@ -57,7 +58,8 @@ const Filters: FC<FiltersProps> = ({
|
||||
initialValues = {},
|
||||
className = "flex flex-col md:flex-row justify-between items-start md:items-center gap-4",
|
||||
fieldClassName = "flex flex-col sm:flex-row gap-3 md:gap-4 w-full md:w-auto",
|
||||
searchField = "search"
|
||||
searchField = "search",
|
||||
showClearButton = false,
|
||||
}) => {
|
||||
const [filters, setFilters] = useState<FilterValues>({});
|
||||
const [isFiltersOpen, setIsFiltersOpen] = useState(false);
|
||||
@@ -155,6 +157,42 @@ const Filters: FC<FiltersProps> = ({
|
||||
setInputValues(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const hasActiveFilters = fields.some((field) => {
|
||||
const value = field.type === 'input'
|
||||
? inputValues[field.name]
|
||||
: field.type === 'multiselect'
|
||||
? multiSelectValues[field.name]
|
||||
: filters[field.name];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
|
||||
return Boolean(value);
|
||||
});
|
||||
|
||||
const handleClear = () => {
|
||||
setFilters({});
|
||||
setInputValues({});
|
||||
setMultiSelectValues({});
|
||||
onChange({});
|
||||
};
|
||||
|
||||
const renderClearButton = () => {
|
||||
if (!showClearButton) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
label="پاک کردن فیلترها"
|
||||
onClick={handleClear}
|
||||
disabled={!hasActiveFilters}
|
||||
className="w-fit min-w-[140px] px-4 bg-transparent text-foreground border border-border hover:bg-secondary disabled:opacity-50"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderField = (field: FieldType) => {
|
||||
const currentValue = field.type === 'input' ? inputValues[field.name] : filters[field.name];
|
||||
const currentMultiSelectValue = field.type === 'multiselect'
|
||||
@@ -179,7 +217,7 @@ const Filters: FC<FiltersProps> = ({
|
||||
key={field.name}
|
||||
placeholder={field.placeholder}
|
||||
onChange={(e) => handleChange(field.name, e.target.value)}
|
||||
defaultValue={currentValue as string || field.defaultValue || ''}
|
||||
value={(currentValue as string) || field.defaultValue || ''}
|
||||
items={field.options}
|
||||
className='min-w-[170px]'
|
||||
/>
|
||||
@@ -237,6 +275,7 @@ const Filters: FC<FiltersProps> = ({
|
||||
<div className="hidden md:flex md:flex-row justify-between items-center gap-4 w-full">
|
||||
<div className={fieldClassName}>
|
||||
{fields.map(renderField)}
|
||||
{renderClearButton()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -258,7 +297,18 @@ const Filters: FC<FiltersProps> = ({
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className='mt-6'>
|
||||
<div className='mt-6 flex flex-col gap-3'>
|
||||
{showClearButton && (
|
||||
<Button
|
||||
label="پاک کردن فیلترها"
|
||||
onClick={() => {
|
||||
handleClear();
|
||||
setIsFiltersOpen(false);
|
||||
}}
|
||||
disabled={!hasActiveFilters}
|
||||
className="w-full bg-transparent text-foreground border border-border hover:bg-secondary disabled:opacity-50"
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
label='بستن'
|
||||
onClick={() => setIsFiltersOpen(false)}
|
||||
|
||||
Reference in New Issue
Block a user