import { type FC, useEffect, useState, type ChangeEvent, useRef } from 'react'; import { Filter } from 'iconsax-react'; import DatePicker from './DatePicker'; import Input from './Input'; import Select, { type ItemsSelectType } from './Select'; import DefaulModal from './DefaulModal'; import moment from 'moment-jalaali' import Button from './Button'; export type DateFieldType = { type: 'date'; name: string; placeholder: string; defaultValue?: string; }; export type SelectFieldType = { type: 'select'; name: string; placeholder: string; options: ItemsSelectType[]; defaultValue?: string; }; export type InputFieldType = { type: 'input'; name: string; placeholder: string; defaultValue?: string; }; export type FieldType = DateFieldType | SelectFieldType | InputFieldType; export type FilterValues = Record; interface FiltersProps { fields: FieldType[]; onChange: (filters: FilterValues) => void; initialValues?: FilterValues; className?: string; fieldClassName?: string; searchField?: string; } const Filters: FC = ({ fields, onChange, 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" }) => { const [filters, setFilters] = useState({}); const [isFiltersOpen, setIsFiltersOpen] = useState(false); const [inputValues, setInputValues] = useState>({}); const onChangeRef = useRef(onChange); useEffect(() => { onChangeRef.current = onChange; }, [onChange]); useEffect(() => { if (Object.keys(initialValues).length > 0) { setFilters(initialValues); const inputFields: Record = {}; fields.forEach(field => { if (field.type === 'input' && initialValues[field.name]) { inputFields[field.name] = initialValues[field.name] as string; } }); setInputValues(inputFields); } else { const defaultValues: FilterValues = {}; const defaultInputs: Record = {}; fields.forEach(field => { if ('defaultValue' in field && field.defaultValue !== undefined) { defaultValues[field.name] = field.defaultValue; if (field.type === 'input') { defaultInputs[field.name] = field.defaultValue; } } }); if (Object.keys(defaultValues).length > 0) { setFilters(defaultValues); setInputValues(defaultInputs); onChange(defaultValues); } } }, [fields, initialValues, onChange]); useEffect(() => { const timeouts: Record> = {}; Object.keys(inputValues).forEach(fieldName => { timeouts[fieldName] = setTimeout(() => { setFilters(currentFilters => { const currentFilter = currentFilters[fieldName]; const newValue = inputValues[fieldName]; if (currentFilter !== newValue) { const newFilters = { ...currentFilters, [fieldName]: newValue || null }; onChangeRef.current(newFilters); return newFilters; } return currentFilters; }); }, 1000); }); return () => { Object.values(timeouts).forEach(timeout => clearTimeout(timeout)); }; }, [inputValues]); const handleChange = (name: string, value: string | null) => { const newFilters = { ...filters, [name]: value }; setFilters(newFilters); onChange(newFilters); }; const handleInputChange = (name: string, event: ChangeEvent) => { const value = event.target.value; setInputValues(prev => ({ ...prev, [name]: value })); }; const renderField = (field: FieldType) => { const currentValue = field.type === 'input' ? inputValues[field.name] : filters[field.name]; switch (field.type) { case 'date': return ( handleChange(field.name, moment(value, 'jYYYY/jMM/jDD').format('YYYY-MM-DD'))} defaulValue={currentValue || field.defaultValue || ''} /> ); case 'select': return ( handleInputChange(field.name, e)} /> ); } }; const searchFieldObj = fields.find(field => field.name === searchField); const otherFields = fields.filter(field => field.name !== searchField); return (
{searchFieldObj && (
{renderField(searchFieldObj)}
)}
{fields.map(renderField)}
setIsFiltersOpen(false)} isHeader={true} title_header="فیلتر کردن نتایج" >
{otherFields.map(field => (
{renderField(field)}
))}
); }; export default Filters;