Skip to main content

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

  1. nuqs - Handles URL state management and type-safe query parameter parsing
  2. Filter Mapping - Maps URL parameters to database fields and types
  3. Filter Utils - Processes and applies filters to Prisma queries
  4. Filter Components - UI components for different filter types

Flow Diagram

nuqs Integration

Search Parameters Configuration

The core nuqs configuration is in apps/webapp/app/lib/search-params-config.ts:

URL Parameter Structure

The filtering system uses a specific URL parameter structure:
Parameter Types:
  • filter=true - Enables filtering
  • {field}={value} - Filter value
  • {field}_op={operator} - Filter operator (optional)
  • page={number} - Pagination page
  • size={number} - Page size
  • sort={field} - Sort field
  • asc={boolean} - Sort direction

Filter Types and Operators

String Filters

Available Operators:
  • equals - Exact match
  • contains - Partial match (default)
  • startsWith - Starts with value
  • endsWith - Ends with value
  • not - Not equal to
Examples:

Date Filters

Available Operators:
  • equals - Exact date match (default)
  • gte - Greater than or equal
  • lte - Less than or equal
  • gt - Greater than
  • lt - Less than
  • between - Date range
Timezone-Aware Date Handling: Date filters now properly handle timezones using the organization’s default timezone. When users enter dates like 2025-07-07, the system:
  1. Gets the organization’s default timezone from subsidiary settings
  2. Interprets the date in that timezone (e.g., 2025-07-07 in Europe/Berlin)
  3. Converts the full day range to UTC for database queries
  4. Ensures users get results for the complete day in their timezone
Example:
  • User selects: 2025-07-07
  • Organization timezone: Europe/Berlin (UTC+1)
  • System converts: 2025-07-06T23:00:00Z to 2025-07-07T22:59:59Z (UTC)
  • Result: All documents created on July 7th Berlin time
Examples:

Number Filters

Available Operators:
  • equals - Exact match (default)
  • gt - Greater than
  • gte - Greater than or equal
  • lt - Less than
  • lte - Less than or equal
  • between - Number range
Examples:

Array Filters

Available Operators:
  • in - Contains any of the values (default)
Examples:

Boolean Filters

Available Operators:
  • equals - Exact match (default)
  • not - Not equal to
Examples:

Filter Mapping

The filter-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

  1. Get Organization Timezone: Retrieves default timezone from subsidiary settings
  2. Parse User Input: User-entered dates are interpreted in the organization’s timezone
  3. Convert to UTC: Uses proper timezone conversion with DST handling
  4. Database Queries: All date comparisons are done in UTC with correct ranges
  5. 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 fields
  • NumberFilter - For numeric fields
  • DateFilter - For date fields
  • SelectFilter - For dropdown selections
  • CreditDebitFilter - For boolean credit/debit fields

Base Filter Props

All filter components share common props:

Example Filter Component

Data Processing

Filter Utils

The filter-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: Setting doc_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 the custom_ 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:
Benefits:
  • 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 centralized filterMapping 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 matching
  • fuzzy - Fuzzy text matching
  • geospatial - 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.