Entity filters
Every entity list includes a collapsible filter form that generates type-aware queries. Filters are stored in the URL, previewed as removable badges, and translated to Prisma where clauses on the backend.
Filter inputs by field type
| Field type | Filter input | Backend query |
|---|---|---|
| Text | Text input | contains (case-insensitive) |
| Integer | Range input (min / max) | gte / lte |
| Decimal | Range input (min / max) | gte / lte |
| Date | Date range picker | gte / lte |
| Datetime | Datetime range picker | gte / lte |
| Boolean | Yes / No / Clear select | Exact boolean match |
| Enumerator | Single-select dropdown | Exact value match |
| Enumerator multiple | Multi-select dropdown | hasSome (matches any selected value) |
| Tags | Multi-select input | hasSome |
| Files / Images | — | Not filterable |
| Relationship (one) | Autocomplete input | Filter by related entity ID |
| Relationship (many) | Multi autocomplete input | some with ID in list |
Audit filters
Every entity list includes built-in audit filters regardless of field configuration:
- Created by — member autocomplete
- Updated by — member autocomplete
- Created at — datetime range
- Updated at — datetime range
- Archived — toggle to show archived records (for archivable entities)
By default, archived records are hidden. Setting the archived filter to "Yes" shows only archived items.
Filter preview
Active filters display as badges above the table. Each badge shows the field label and formatted value. Clicking the X on a badge removes that individual filter without affecting others.
Value formatting adapts to the field type:
- Range values: shown as
> 100(open-ended) or100 – 500(bounded) - Date ranges: shown as
> 2024-01-01or2024-01-01 – 2024-02-01 - Enumerators: display the translated label, not the raw value
- Relationships: display the related entity's label
- Booleans: display "Yes" or "No"
URL state
Filter state is serialized into URL query parameters. This means filtered views are bookmarkable, shareable, and preserved on page refresh. The browser back button restores the previous filter state.
When a filter changes, the page index resets to 0 so results always start from the first page.
Backend processing
The backend receives filters as query parameters and builds a Prisma where clause:
- All filter conditions are combined with AND logic
- Organization scoping is always applied (via RLS)
- Archived records are excluded by default
- Each field type maps to the appropriate Prisma operator (
contains,gte,lte,hasSome,some, etc.)
The filter schema is validated with Zod before any database query runs, rejecting malformed input.
Disabling filters
You can disable filtering for specific fields or relationships in your entity schema:
- Fields — set
filter: falsein the field's properties - Relationships — set
filterA: falseorfilterB: falseon the relationship
Disabled filters won't appear in the filter form or be accepted by the backend schema.
Key files
| File | Purpose |
|---|---|
src/features/{entity}/components/{Entity}ListFilter.tsx | Filter form with all field-specific inputs |
src/shared/components/dataTable/DataTableFilterPreview.tsx | Badge display of active filters |
src/shared/components/dataTable/dataTableFilterRenders.tsx | Formatting functions for filter preview values |
src/shared/lib/isFilterEmpty.ts | Utility to check if all filter values are empty |
backend/src/features/{entity}/{entity}Schemas.ts | Zod filter input schema |
backend/src/features/{entity}/controllers/{entity}FindManyController.ts | Filter-to-Prisma query translation |