Entity lists

Every entity gets a full-featured data table powered by TanStack Table. Lists include sorting, pagination, column visibility, row selection, bulk actions, and CSV export — all wired up automatically based on your entity schema.

Columns by field type

Each field type renders with an appropriate cell format:

Field typeSortableDisplay
TextYesPlain text. The display field renders as a clickable link to the detail view.
IntegerYesRight-aligned number
DecimalYesFormatted with locale-aware decimal separator and scale
DateYesLocalized date string
DatetimeYesLocalized date and time
BooleanYes"Yes" / "No"
EnumeratorYesTranslated label from dictionary
Enumerator multipleNoList of translated labels
TagsNoList of tag values
FilesNoDownload links
ImagesNoAvatar thumbnail of first image

Relationship columns display as links to the related entity. One-to-one shows a single link; many-to-many shows multiple.

Two special columns are always present:

  • Selection (first) — checkbox for row selection with "select all" in the header
  • Actions (last) — sticky-positioned dropdown with view, edit, delete, and archive

Sorting

Click a column header to toggle sort direction. Sorting state is stored in the URL as a query parameter so sorted views are bookmarkable and shareable.

Multiple sort columns are supported. The backend receives the sort configuration and translates it to a Prisma orderBy clause.

Default sort: updatedAt descending (most recently updated first).

Pagination

The table paginates server-side with configurable page sizes: 10, 20, 30, 40, or 50 rows per page.

Controls include:

  • Page size selector
  • Page number buttons (max 5 visible with ellipsis)
  • "Showing X–Y of Z" summary
  • Selected row count when items are checked

Page size preference is persisted to local storage per table, so each entity remembers the user's preferred size.

Column visibility

Users can show or hide columns via the column header dropdown or the view options menu. Visibility preferences are persisted to local storage per entity table.

Audit columns (createdAt, updatedAt, createdByMember, updatedByMember) are available but hidden by default unless the entity has showAuditFieldsOnList enabled.

Bulk actions

When rows are selected, the actions dropdown enables:

ActionDescription
ArchiveBulk archive selected rows (if entity is archivable)
RestoreRestore archived rows
DeleteDelete selected rows with confirmation dialog
Export to CSVExport all rows matching the current filter (not just selected)
ImportNavigate to the CSV importer page

Each action is permission-gated — only actions the current user's role allows are shown. Bulk operations pass an array of IDs and show toast notifications on completion.

URL state

All table state — filters, sorting, and pagination — is encoded in URL query parameters. This means:

  • Views are bookmarkable and shareable
  • The browser back button restores previous table state
  • Refreshing the page preserves the current view

The DataTableQueryParams class handles serialization and deserialization of table state to/from the URL.

Empty states

The list page shows contextual empty states:

  • No data yet — when the entity has zero records. Shows a "New" button and an "Import" link.
  • No results — when a filter is applied but returns nothing. Shows a prompt to adjust filters.

Key files

FilePurpose
src/features/{entity}/pages/{Entity}ListPage.tsxList page with table, filter, and pagination
src/features/{entity}/components/{Entity}ListActions.tsxBulk action dropdown
src/features/{entity}/{entity}ExporterMapper.tsMaps entity data to CSV columns
src/shared/components/dataTable/DataTable.tsxReusable table renderer
src/shared/components/dataTable/DataTableColumnHeader.tsxColumn header with sort toggle
src/shared/components/dataTable/DataTablePagination.tsxPagination controls
src/shared/components/dataTable/DataTableQueryParams.tsxURL state management
src/shared/stores/dataTableStore.tsZustand store for column visibility and page size