1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
# ClientVirtualTable V3 Guide
This guide documents the table components in `components/client-table-v2`, with an emphasis on server fetching (`fetchMode="server"`) and how supporting components fit together.
## Module Map
- `client-virtual-table.tsx`: Core table (virtualized, DnD columns, pin/hide, presets hook point, toolbar, pagination).
- `client-table-column-header.tsx`: Header cell with sort toggle, filter UI, context menu (hide/pin/group/reorder hook).
- `client-table-toolbar.tsx` (from `components/client-table`): Search box, export button, view options, preset entry point.
- `client-table-view-options.tsx` (from `components/client-table`): Column visibility toggles.
- `client-table-filter.tsx`: Column filter UI (text/select/boolean).
- `client-table-preset.tsx`: Save/load/delete presets per `tableKey` + user.
- `client-table-save-view.tsx`, `client-table-preset.tsx`, `client-table-toolbar.tsx`: Preset and view controls.
- `client-virtual-table` dependencies: `ClientDataTablePagination` (`components/client-data-table`), `export-utils`, `import-utils`.
- Server helpers: `adapter/create-table-service.ts`, `adapter/drizzle-table-adapter.ts`.
- Types: `types.ts`, `preset-types.ts`.
## Core Behaviors (ClientVirtualTable)
- Virtualization: `height` is required; `estimateRowHeight` defaults to 40.
- Drag & Drop: Columns reorder across pin sections; drag between pin states updates pinning.
- Pin/Hide/Reorder: Managed client-side; state is exposed via `columnVisibility`, `columnPinning`, `columnOrder`.
- Sorting/Filtering/Pagination/Grouping:
- `fetchMode="client"`: uses TanStack models (`getSortedRowModel`, `getFilteredRowModel`, `getPaginationRowModel`, etc.).
- `fetchMode="server"`: sets manual flags true and skips client models; **server must return already-sorted/filtered/paged data**.
- Export: Uses current row model; in server mode it exports only the loaded rows unless you supply all data yourself via `onExport`.
- Presets: When `enableUserPreset` and `tableKey` are set, toolbar shows the preset control; loading a preset resets pageIndex to 0 to avoid invalid pages on server mode.
## Key Props (ClientVirtualTable)
- `fetchMode`: `"client"` | `"server"` (default `"client"`).
- Data: `data`, `rowCount?`, `pageCount?`.
- State + handlers (controlled or uncontrolled):
- Pagination: `pagination`, `onPaginationChange`, `enablePagination`, `manualPagination?`.
- Sorting: `sorting`, `onSortingChange`.
- Filters: `columnFilters`, `onColumnFiltersChange`, `globalFilter`, `onGlobalFilterChange`.
- Grouping: `grouping`, `onGroupingChange`, `expanded`, `onExpandedChange`, `enableGrouping`.
- Visibility/Pinning/Order: `columnVisibility`, `onColumnVisibilityChange`, `columnPinning`, `onColumnPinningChange`, `columnOrder`, `onColumnOrderChange`.
- Selection: `enableRowSelection`, `enableMultiRowSelection`, `rowSelection`, `onRowSelectionChange`.
- UX: `actions`, `customToolbar`, `enableExport`, `onExport`, `renderHeaderVisualFeedback`, `getRowClassName`, `onRowClick`.
- Presets: `enableUserPreset`, `tableKey`.
- Meta: `meta`, `getRowId`.
## Server Fetching Patterns
### Pattern 1: Client-Side (baseline)
- `fetchMode="client"`, pass full dataset; TanStack handles sorting/filtering/grouping locally.
### Pattern 2: Factory Service (`createTableService`)
- Server action: `createTableService({ db, schema, columns, defaultWhere?, customQuery? })`.
- The adapter maps `sorting`, `columnFilters`, `globalFilter`, `pagination`, `grouping` → Drizzle `where`, `orderBy`, `limit`, `offset`, `groupBy`.
- Returns `{ data, totalRows, pageCount }`; always forward `totalRows` to the client and wire `rowCount`.
- Client wiring: control `pagination`, `sorting`, `columnFilters`, `globalFilter`; refetch in `useEffect` on those deps.
### Pattern 2-B: Server Grouping
- Uses `getProductTableDataWithGrouping` sample: if `grouping` is empty → normal server fetch; else returns `{ groups }` built from DB `GROUP BY`.
- Columns must be marked `meta.serverGroupable` in server column defs.
- Expanded groups fetch child rows per group key; grouping change clears expanded state.
- UI may render a custom grouped view (not the virtual table) when grouped.
### Pattern 3: Custom Service
- For joins/derived columns: read `tableState` and manually map `sorting` IDs to joined columns; supply a default order when no sort is present.
- Filtering/global filter are not automatic—implement them if needed.
- Grouping is manual; see `getOrderTableDataGroupedByStatus` pattern for a grouped response shape.
## State → Query Mapping (Server)
- Sorting: `tableState.sorting` (id, desc) → map to DB columns; ignore unknown ids.
- Filters: `columnFilters` supports text (ilike), boolean, number, range `[min,max]`, multi-select (IN).
- Global filter: ilike OR across mapped columns.
- Pagination: pageIndex/pageSize → limit/offset; return `rowCount`.
- Grouping: `grouping` → `GROUP BY` for supported columns only.
## Presets (Server-Friendly)
- Saved keys: sorting, columnFilters, globalFilter, columnVisibility, columnPinning, columnOrder, grouping, pageSize.
- On load: applies `table.set*` and resets pageIndex to 0; parent `on*Change` handlers should trigger refetch.
- Use unique `tableKey` per screen to avoid collisions; requires authenticated session.
## Feature Matrix (Server Mode)
- Sorting: Yes—server implemented.
- Filtering: Yes—server implemented.
- Pagination: Yes—manual; provide `rowCount`.
- Grouping: Not automatic; implement via server grouping or custom grouped view.
- Column hide/pin/reorder: Client-only (visual); does not change server query unless you opt to read it.
- Export: Only current rows unless you provide `onExport` with full data.
## Implementation Tips
- Always set `rowCount` when `fetchMode="server"`.
- Refetch on `pagination`, `sorting`, `columnFilters`, `globalFilter`, and `grouping` (if used).
- Provide a default sort on the server when `sorting` is empty.
- Reset `expanded` or group expand state when grouping changes in server grouping flows.
- Ensure `height` is set; virtualization needs a scroll container.
## Quick Examples
- Client: `fetchMode="client"` with `data` = full list; optional grouping enabled.
- Factory server: `fetchMode="server"`, `createTableService` action, controlled state with `rowCount`.
- Server grouping: `grouping` drives `{ groups }` vs `{ data }` response; only `serverGroupable` columns allowed.
- Custom join: Manually map `sorting` ids; apply filters/global; return `rowCount`.
|