Skip to content

Commit

Permalink
Filter component and documentation added.
Browse files Browse the repository at this point in the history
  • Loading branch information
Aunshon committed Jan 17, 2025
1 parent c12dd7b commit 8182a1c
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 1 deletion.
148 changes: 148 additions & 0 deletions docs/frontend/filter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Filter Component

The Filter component provides a standardized way to implement filtering functionality across your application. It creates a consistent user experience by managing filter fields, filter triggers, and reset functionality.

## Features

- Unified interface for multiple filter fields
- Configurable filter and reset buttons
- Namespace support for unique identification
- Flexible field composition

## Installation

#### Dokan lite

```jsx
import Filter from '../components';
```

#### Dokan pro or external plugins

```jsx
import { Filter } from '@dokan/components';
```

## Usage

```jsx
<Filter
fields={[
<CustomerFilter key="customer_filter" {...props} />,
<DateFilter key="date_filter" {...props} />
]}
onFilter={handleFilter}
onReset={clearFilter}
showFilter={true}
showReset={true}
namespace="product_table_filters"
/>
```

## Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `fields` | `ReactNode[]` | No | Array of filter field components to be rendered |
| `onFilter` | `() => void` | No | Handler function called when the filter button is clicked |
| `onReset` | `() => void` | No | Handler function called when the reset button is clicked |
| `showFilter` | `boolean` | No | Controls visibility of the filter button (default: true) |
| `showReset` | `boolean` | No | Controls visibility of the reset button (default: true) |
| `namespace` | `string` | Yes | Unique identifier for the filter group |

## Example Implementation

```jsx
import { Filter, CustomerFilter, DateFilter } from '@your-package/components';

const MyTableComponent = () => {
const [filterArgs, setFilterArgs] = useState({});
const [searchedCustomer, setSearchedCustomer] = useState(null);

const handleFilter = () => {
// Implement your filter logic here
fetchFilteredData(filterArgs);
};

const clearFilter = () => {
setFilterArgs({});
setSearchedCustomer(null);
};

const handleCustomerSearch = (customer) => {
setSearchedCustomer(customer);
};

return (
<div>
<Filter
fields={[
<CustomerFilter
key="customer_filter"
filterArgs={filterArgs}
setFilterArgs={setFilterArgs}
searchedCustomer={searchedCustomer}
handleCustomerSearch={handleCustomerSearch}
/>,
<DateFilter
key="date_filter"
filterArgs={filterArgs}
setFilterArgs={setFilterArgs}
/>
]}
onFilter={handleFilter}
onReset={clearFilter}
showFilter={true}
showReset={true}
namespace="my_table_filters"
/>
{/* Table component */}
</div>
);
};
```

## Creating Custom Filter Fields

When creating custom filter field components to use with the Filter component:

1. Each field component should manage its own state
2. Field components should update the parent's filterArgs through props
3. Include a unique key prop for each field
4. Handle reset functionality through props

Example custom filter field:

```jsx
const CustomFilter = ({ filterArgs, setFilterArgs }) => {
const handleChange = (value) => {
setFilterArgs({
...filterArgs,
customField: value
});
};

return (
<input
type="text"
value={filterArgs.customField || ''}
onChange={(e) => handleChange(e.target.value)}
/>
);
};
```

## Best Practices

1. Always provide unique keys for field components
2. Implement proper type checking for filter arguments
3. Handle edge cases in reset functionality
4. Use consistent naming conventions for filter arguments
5. Include error handling in filter and reset handlers

## Notes

- The Filter component is designed to work with table components but can be used in other contexts
- All filter fields should be controlled components
- The namespace prop is used internally for generating unique identifiers
- Filter and reset functionality should be implemented in the parent component
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"vue-wp-list-table": "^1.3.0",
"vue2-daterange-picker": "^0.6.8",
"vuedraggable": "^2.24.3",
"wp-readme-to-markdown": "^1.0.1"
"wp-readme-to-markdown": "^1.0.1",
"tailwind-merge": "^2.6.0"
},
"dependencies": {
"@getdokan/dokan-ui": "^1.0.18",
Expand Down
78 changes: 78 additions & 0 deletions src/components/Filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Button } from '@getdokan/dokan-ui';
import { __ } from '@wordpress/i18n';
import { twMerge } from 'tailwind-merge';
// @ts-ignore
// eslint-disable-next-line import/no-unresolved
import { snakeCase, kebabCase } from '../utilities';

interface FilterProps {
/** Namespace for the filter, used to generate unique IDs */
namespace: string;
/** Array of React nodes representing the filter fields */
fields?: React.ReactNode[];
/** Whether to show the reset button */
showReset?: boolean;
/** Whether to show the filter button */
showFilter?: boolean;
/** Callback function to handle filter action */
onFilter?: () => void;
/** Callback function to handle reset action */
onReset?: () => void;
/** Additional class names for the filter container */
className?: string;
}

const Filter = ( {
namespace = '',
fields = [],
showReset = true,
showFilter = true,
onFilter = () => {},
onReset = () => {},
className = '',
}: FilterProps ) => {
const snakeCaseNamespace = snakeCase( namespace );
const filterId = `dokan_${ snakeCaseNamespace }_filters`;

// @ts-ignore
const filteredFields = wp.hooks.applyFilters( filterId, fields );

return (
<div
className={ twMerge(
'flex gap-4 flex-row flex-wrap pb-5 items-end dokan-dashboard-filters',
className
) }
id={ kebabCase( filterId ) }
data-filter-id={ filterId }
>
{ filteredFields.map( ( fieldNode: React.ReactNode, index ) => {
return (
<div className="dokan-dashboard-filter-item" key={ index }>
{ fieldNode }
</div>
);
} ) }

{ showFilter && (
<Button
color="primary"
className="bg-dokan-btn hover:dokan-btn-hover h-10"
label={ __( 'Filter', 'dokan' ) }
onClick={ onFilter }
/>
) }

{ showReset && (
<Button
color="primary"
className="bg-dokan-btn hover:dokan-btn-hover h-10"
label={ __( 'Reset', 'dokan' ) }
onClick={ onReset }
/>
) }
</div>
);
};

export default Filter;
2 changes: 2 additions & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export {
filterSortAndPaginate,
isItemValid
} from '@wordpress/dataviews/wp';

export { default as Filter } from './Filter';

0 comments on commit 8182a1c

Please sign in to comment.