README.md101 lines · main
1# Table Filtering and Sorting Developer notes
2
3## Overview
4
5The table filtering and sorting system uses a URL-based state persistence pattern combined with custom hooks that abstract the implementation details from consuming components. This architecture provides several benefits:
6
7- **Persistent state**: Filters and sorts are stored in URL parameters, enabling bookmarking and sharing
8- **Separation of concerns**: Logic is separated from UI components
9- **Draft-then-apply pattern**: UI components maintain draft state until explicitly applied
10
11## Core Hooks
12
13### `useTableFilter`
14
15```typescript
16// Returns: { filters, urlFilters, onApplyFilters }
17```
18
19The `useTableFilter` hook manages filter state with these responsibilities:
20
21- Retrieves raw filter parameters from URL
22- Formats filter parameters into usable Filter[] objects
23- Provides a callback to apply new filters
24- Persists changes to URL parameters
25- Triggers side effects through `saveFiltersAndTriggerSideEffects`
26
27Key design aspects:
28
29- No direct snapshot interaction, keeping it focused solely on filter management
30- Uses URL parameters as the source of truth
31- Forwards filter changes to URL and triggers application-specific side effects
32
33### `useTableSort`
34
35```typescript
36// Returns: { sorts, urlSorts, onApplySorts }
37```
38
39The `useTableSort` hook manages sort state with these responsibilities:
40
41- Retrieves raw filter parameters from URL
42- Formats sort parameters into usable Sort[] objects (needs table name)
43- Provides a callback to apply new sorts
44- Persists changes to URL parameters
45- Triggers side effects through `saveSortsAndTriggerSideEffects`
46
47Key design aspects:
48
49- Handles applying table name to sort objects
50- Maintains URL parameters as source of truth
51- Forwards sort changes to URL and triggers application-specific side effects
52
53## Component Implementation
54
55### FilterPopoverPrimitive and SortPopoverPrimitive
56
57These components follow a "draft and apply" pattern:
58
591. **Local state management**: Both components maintain a local state copy of filters/sorts
602. **Edit operations**: Changes like adding, modifying, or deleting are made to the local state
613. **Apply operations**: Only when the user clicks "Apply" are the changes committed via the callback
624. **Synchronization**: Local state is synchronized with props when external changes occur
63
64## Data Flow
65
661. URL parameters store the raw filter/sort state
672. Hooks read and format these parameters into usable objects
683. UI components receive formatted objects and callbacks
694. Components maintain draft state for editing
705. When "Apply" is clicked, callbacks update URL parameters
716. Side effects are triggered via dedicated save hooks
72
73## Component Usage
74
75Components using these hooks should follow this pattern:
76
77```tsx
78function TableComponent() {
79 // Get filter data and callbacks
80 const { filters, onApplyFilters } = useTableFilter()
81
82 // Get sort data and callbacks
83 const { sorts, onApplySorts } = useTableSort()
84
85 return (
86 <>
87 <FilterPopoverPrimitive filters={filters} onApplyFilters={onApplyFilters} />
88
89 <SortPopoverPrimitive sorts={sorts} onApplySorts={onApplySorts} />
90
91 {/* Table rendering with filters and sorts applied */}
92 </>
93 )
94}
95```
96
97## Implementation Notes
98
99- Filter and sort parameters are stored in URL using specific formats
100- Conversion utilities (`formatFilterURLParams`, `formatSortURLParams`, etc.) handle translation between URL strings and typed objects
101- Side effect hooks manage database persistence and related operations
Preview

Table Filtering and Sorting Developer notes

Overview

The table filtering and sorting system uses a URL-based state persistence pattern combined with custom hooks that abstract the implementation details from consuming components. This architecture provides several benefits:

  • Persistent state: Filters and sorts are stored in URL parameters, enabling bookmarking and sharing
  • Separation of concerns: Logic is separated from UI components
  • Draft-then-apply pattern: UI components maintain draft state until explicitly applied

Core Hooks

useTableFilter

// Returns: { filters, urlFilters, onApplyFilters }

The useTableFilter hook manages filter state with these responsibilities:

  • Retrieves raw filter parameters from URL
  • Formats filter parameters into usable Filter[] objects
  • Provides a callback to apply new filters
  • Persists changes to URL parameters
  • Triggers side effects through saveFiltersAndTriggerSideEffects

Key design aspects:

  • No direct snapshot interaction, keeping it focused solely on filter management
  • Uses URL parameters as the source of truth
  • Forwards filter changes to URL and triggers application-specific side effects

useTableSort

// Returns: { sorts, urlSorts, onApplySorts }

The useTableSort hook manages sort state with these responsibilities:

  • Retrieves raw filter parameters from URL
  • Formats sort parameters into usable Sort[] objects (needs table name)
  • Provides a callback to apply new sorts
  • Persists changes to URL parameters
  • Triggers side effects through saveSortsAndTriggerSideEffects

Key design aspects:

  • Handles applying table name to sort objects
  • Maintains URL parameters as source of truth
  • Forwards sort changes to URL and triggers application-specific side effects

Component Implementation

FilterPopoverPrimitive and SortPopoverPrimitive

These components follow a "draft and apply" pattern:

  1. Local state management: Both components maintain a local state copy of filters/sorts
  2. Edit operations: Changes like adding, modifying, or deleting are made to the local state
  3. Apply operations: Only when the user clicks "Apply" are the changes committed via the callback
  4. Synchronization: Local state is synchronized with props when external changes occur

Data Flow

  1. URL parameters store the raw filter/sort state
  2. Hooks read and format these parameters into usable objects
  3. UI components receive formatted objects and callbacks
  4. Components maintain draft state for editing
  5. When "Apply" is clicked, callbacks update URL parameters
  6. Side effects are triggered via dedicated save hooks

Component Usage

Components using these hooks should follow this pattern:

function TableComponent() {
  // Get filter data and callbacks
  const { filters, onApplyFilters } = useTableFilter()

  // Get sort data and callbacks
  const { sorts, onApplySorts } = useTableSort()

  return (
    <>
      <FilterPopoverPrimitive filters={filters} onApplyFilters={onApplyFilters} />

      <SortPopoverPrimitive sorts={sorts} onApplySorts={onApplySorts} />

      {/* Table rendering with filters and sorts applied */}
    </>
  )
}

Implementation Notes

  • Filter and sort parameters are stored in URL using specific formats
  • Conversion utilities (formatFilterURLParams, formatSortURLParams, etc.) handle translation between URL strings and typed objects
  • Side effect hooks manage database persistence and related operations