Skip to content

Commit 5d300f0

Browse files
authored
Merge pull request #58 from lambda-curry/codegen-bot/data-table-filter-fixes
2 parents 7be3144 + 877be65 commit 5d300f0

7 files changed

Lines changed: 964 additions & 35 deletions

File tree

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
# Data Table Filter Component
2+
3+
This component provides a powerful filtering system for data tables, with support for various filter types, URL synchronization, and real-time data updates.
4+
5+
## Features
6+
7+
- **Filter Types**: Support for text, option, multi-option, number, and date filters
8+
- **URL Synchronization**: Filters are synchronized with URL query parameters for shareable and bookmarkable filter states
9+
- **Real-time Data Updates**: Data is updated in real-time as filters change
10+
- **Faceted Counts**: Display counts for each filter option based on the current data
11+
- **Responsive Design**: Works on both desktop and mobile devices
12+
13+
## Usage
14+
15+
### Basic Usage with `useFilteredData` Hook (Recommended)
16+
17+
The easiest way to use the data table filter is with the `useFilteredData` hook, which handles all the complexity for you:
18+
19+
```tsx
20+
import { useFilteredData } from '@lambdacurry/forms/ui/utils/use-filtered-data';
21+
import { DataTableFilter } from '@lambdacurry/forms/ui/data-table-filter/components/data-table-filter';
22+
23+
function MyDataTable() {
24+
// Define your column configurations
25+
const columnsConfig = [
26+
{
27+
id: 'status',
28+
type: 'option',
29+
displayName: 'Status',
30+
accessor: (item) => item.status,
31+
icon: () => null,
32+
options: [
33+
{ value: 'active', label: 'Active' },
34+
{ value: 'inactive', label: 'Inactive' },
35+
],
36+
},
37+
// Add more columns as needed
38+
];
39+
40+
// Use the hook to handle everything
41+
const {
42+
filters,
43+
columns,
44+
actions,
45+
data,
46+
isLoading,
47+
} = useFilteredData({
48+
endpoint: '/api/items', // Your API endpoint
49+
columnsConfig,
50+
initialData: [], // Optional initial data
51+
});
52+
53+
return (
54+
<div>
55+
{/* Render the filter component */}
56+
<DataTableFilter
57+
columns={columns}
58+
filters={filters}
59+
actions={actions}
60+
strategy="client"
61+
/>
62+
63+
{/* Render your data table with the filtered data */}
64+
{isLoading ? (
65+
<div>Loading...</div>
66+
) : (
67+
<table>
68+
{/* Your table implementation */}
69+
</table>
70+
)}
71+
</div>
72+
);
73+
}
74+
```
75+
76+
### Advanced Usage with Manual Setup
77+
78+
If you need more control, you can set up the filters manually:
79+
80+
```tsx
81+
import { useFilterSync } from '@lambdacurry/forms/ui/utils/use-filter-sync';
82+
import { useDataQuery } from '@lambdacurry/forms/ui/utils/use-issues-query';
83+
import { createColumns } from '@lambdacurry/forms/ui/data-table-filter/core/filters';
84+
import { DataTableFilter } from '@lambdacurry/forms/ui/data-table-filter/components/data-table-filter';
85+
86+
function MyDataTable() {
87+
// Sync filters with URL
88+
const [filters, setFilters] = useFilterSync();
89+
90+
// Fetch data with filters
91+
const { data, isLoading } = useDataQuery('/api/items', filters);
92+
93+
// Define column configurations
94+
const columnsConfig = [/* your column configs */];
95+
96+
// Create columns with faceted counts
97+
const columns = useMemo(() => {
98+
if (!data) return createColumns([], columnsConfig, 'client');
99+
100+
// Apply faceted counts from the API
101+
const enhancedConfig = columnsConfig.map(config => {
102+
if (config.type === 'option' && data.facetedCounts?.[config.id]) {
103+
return {
104+
...config,
105+
facetedOptions: new Map(
106+
Object.entries(data.facetedCounts[config.id])
107+
.map(([key, count]) => [key, count])
108+
)
109+
};
110+
}
111+
return config;
112+
});
113+
114+
return createColumns(data.data || [], enhancedConfig, 'client');
115+
}, [data, columnsConfig]);
116+
117+
// Create filter actions
118+
const actions = useMemo(() => {
119+
return {
120+
addFilterValue: (column, values) => {
121+
// Implementation
122+
},
123+
removeFilterValue: (column, values) => {
124+
// Implementation
125+
},
126+
setFilterValue: (column, values) => {
127+
// Implementation
128+
},
129+
setFilterOperator: (columnId, operator) => {
130+
// Implementation
131+
},
132+
removeFilter: (columnId) => {
133+
// Implementation
134+
},
135+
removeAllFilters: () => {
136+
// Implementation
137+
}
138+
};
139+
}, [setFilters]);
140+
141+
return (
142+
<div>
143+
<DataTableFilter
144+
columns={columns}
145+
filters={filters}
146+
actions={actions}
147+
strategy="client"
148+
/>
149+
150+
{/* Your table implementation */}
151+
</div>
152+
);
153+
}
154+
```
155+
156+
## API Reference
157+
158+
### `DataTableFilter` Component
159+
160+
```tsx
161+
<DataTableFilter
162+
columns={columns}
163+
filters={filters}
164+
actions={actions}
165+
strategy="client"
166+
locale="en"
167+
/>
168+
```
169+
170+
#### Props
171+
172+
- `columns`: Array of column definitions with filter options
173+
- `filters`: Current filter state
174+
- `actions`: Object containing filter action functions
175+
- `strategy`: Filter strategy, either "client" or "server"
176+
- `locale`: Optional locale for internationalization (default: "en")
177+
178+
### `useFilteredData` Hook
179+
180+
```tsx
181+
const {
182+
filters,
183+
setFilters,
184+
columns,
185+
actions,
186+
data,
187+
facetedCounts,
188+
isLoading,
189+
isError,
190+
error,
191+
refetch,
192+
} = useFilteredData({
193+
endpoint,
194+
columnsConfig,
195+
strategy,
196+
initialData,
197+
queryOptions,
198+
});
199+
```
200+
201+
#### Parameters
202+
203+
- `endpoint`: API endpoint to fetch data from
204+
- `columnsConfig`: Array of column configurations
205+
- `strategy`: Filter strategy, either "client" or "server" (default: "client")
206+
- `initialData`: Optional initial data to use before API data is loaded
207+
- `queryOptions`: Additional options for the query
208+
209+
#### Returns
210+
211+
- `filters`: Current filter state
212+
- `setFilters`: Function to update filters
213+
- `columns`: Columns with faceted counts
214+
- `actions`: Filter action functions
215+
- `data`: Filtered data
216+
- `facetedCounts`: Counts for each filter option
217+
- `isLoading`: Whether data is currently loading
218+
- `isError`: Whether an error occurred
219+
- `error`: Error object if an error occurred
220+
- `refetch`: Function to manually refetch data
221+
222+
## Server-Side Implementation
223+
224+
For the filters to work correctly with faceted counts, your API should return data in the following format:
225+
226+
```json
227+
{
228+
"data": [
229+
// Your data items
230+
],
231+
"facetedCounts": {
232+
"status": {
233+
"active": 10,
234+
"inactive": 5
235+
},
236+
"category": {
237+
"electronics": 7,
238+
"clothing": 8
239+
}
240+
}
241+
}
242+
```
243+
244+
The `facetedCounts` object should contain counts for each filter option, organized by column ID.
245+
246+
## Examples
247+
248+
See the `examples` directory for complete working examples:
249+
250+
- `data-table-filter-example.tsx`: Comprehensive example with API integration
251+
- `simplified-example.tsx`: Simplified example using the `useFilteredData` hook
252+

0 commit comments

Comments
 (0)