Filtering System with nuqs Integration
Overview
CONA uses a sophisticated filtering system that combines nuqs for URL state management with Prisma database queries. This system provides type-safe, URL-synchronized filtering across all data tables in the application.Architecture
Core Components
- nuqs - Handles URL state management and type-safe query parameter parsing
- Filter Mapping - Maps URL parameters to database fields and types
- Filter Utils - Processes and applies filters to Prisma queries
- Filter Components - UI components for different filter types
Flow Diagram
nuqs Integration
Search Parameters Configuration
The core nuqs configuration is inapps/webapp/app/lib/search-params-config.ts
:
URL Parameter Structure
The filtering system uses a specific URL parameter structure:filter=true
- Enables filtering{field}={value}
- Filter value{field}_op={operator}
- Filter operator (optional)page={number}
- Pagination pagesize={number}
- Page sizesort={field}
- Sort fieldasc={boolean}
- Sort direction
Filter Types and Operators
String Filters
Available Operators:equals
- Exact matchcontains
- Partial match (default)startsWith
- Starts with valueendsWith
- Ends with valuenot
- Not equal to
Date Filters
Available Operators:equals
- Exact date match (default)gte
- Greater than or equallte
- Less than or equalgt
- Greater thanlt
- Less thanbetween
- Date range
2025-07-07
, the system:
- Gets the organization’s default timezone from subsidiary settings
- Interprets the date in that timezone (e.g.,
2025-07-07
inEurope/Berlin
) - Converts the full day range to UTC for database queries
- Ensures users get results for the complete day in their timezone
- User selects:
2025-07-07
- Organization timezone:
Europe/Berlin
(UTC+1) - System converts:
2025-07-06T23:00:00Z
to2025-07-07T22:59:59Z
(UTC) - Result: All documents created on July 7th Berlin time
Number Filters
Available Operators:equals
- Exact match (default)gt
- Greater thangte
- Greater than or equallt
- Less thanlte
- Less than or equalbetween
- Number range
Array Filters
Available Operators:in
- Contains any of the values (default)
Boolean Filters
Available Operators:equals
- Exact match (default)not
- Not equal to
Filter Mapping
Thefilter-mapping.ts
file defines how URL parameters map to database fields:
Implementation in Search Actions
Basic Search Action Structure
Default Operator Logic
The system automatically determines operators based on field types:Timezone-Aware Date Processing
The filtering system now properly handles timezone conversion using date-fns-tz:How It Works
- Get Organization Timezone: Retrieves default timezone from subsidiary settings
- Parse User Input: User-entered dates are interpreted in the organization’s timezone
- Convert to UTC: Uses proper timezone conversion with DST handling
- Database Queries: All date comparisons are done in UTC with correct ranges
- Consistent Results: Users get results for complete days in their timezone
Implementation
Date Processing Example
Benefits
- Timezone Accuracy: Proper handling of user timezones with DST support
- User-Friendly: Users see results for complete days in their timezone
- Robust: Uses date-fns-tz for reliable timezone conversion
- Consistent: Same behavior across different deployments and timezones
Custom Properties Filtering
The system supports filtering by custom properties using a special syntax:UI Components
Filter Input Components
Each filter type has its own component:TextFilter
- For string fieldsNumberFilter
- For numeric fieldsDateFilter
- For date fieldsSelectFilter
- For dropdown selectionsCreditDebitFilter
- For boolean credit/debit fields
Base Filter Props
All filter components share common props:Example Filter Component
Data Processing
Filter Utils
Thefilter-utils.ts
file handles the core filtering logic:
Value Processing
Values are processed based on their type:Common Issues and Solutions
Issue 1: Date Filtering Not Working
Problem: Settingdoc_date=2025-07-07
doesn’t filter correctly.
Solution: Ensure the default operator is equals
and timezone is handled properly:
Issue 2: Custom Properties Not Filtering
Problem: Custom property filters don’t work. Solution: Use thecustom_
prefix in URL parameters:
Issue 3: Nested Field Filtering
Problem: Filtering on related entity fields fails. Solution: Use dot notation in filter mapping:Issue 4: Number Format Issues
Problem: European number formats (1.234,56) not working. Solution: The system handles both formats automatically:Issue 5: Date Filtering and Timezones
Problem: Date filters show incorrect results due to timezone differences. ✅ Solution Implemented: The system now properly handles timezone conversion:- Users get complete day results in their timezone
- Proper DST handling with date-fns-tz
- No more half-day results from neighboring timezones
Best Practices
1. Always Use Filter Mapping
Don’t hardcode field mappings. Use the centralizedfilterMapping
object:
2. Handle Optional Operators
Always provide fallback operators:3. Validate Filter Values
Check for null/undefined values:4. Use Consistent URL Keys
Map internal names to user-friendly URL keys:5. Log Filter Operations
Add logging for debugging:6. Handle Timezone for Date Filters
Always retrieve and pass timezone information for accurate date filtering:Testing Filters
Unit Tests
Test the filter utility functions:Integration Tests
Test complete filtering workflows:Future Enhancements
1. Advanced Operators
Add more sophisticated operators:regex
- Regular expression matchingfuzzy
- Fuzzy text matchinggeospatial
- Location-based filtering
2. Filter Presets
Allow users to save and reuse filter combinations:3. Real-time Filtering
Implement debounced real-time filtering:This filtering system provides a powerful, type-safe, and URL-synchronized filtering experience across all CONA data tables. The nuqs integration ensures that filter states are preserved in URLs and can be shared or bookmarked by users.