Driver Table

Pre-configured table component for displaying simulation drivers

Live Example

Drivers Table

Browse drivers with names and external IDs. Click a row to see the data.

Loading...

DriverTable

A ready-to-use table component for displaying driver information with filtering and sorting capabilities.

Usage

Display drivers in a table with automatic dependent API calls for user and project membership data.

import { useSGERP } from 'sgerp-frontend-lib';
import { DriverTable } from '@/components/sgerp/tables/driver-table';

function MyComponent() {
  const api = useSGERP();
  
  return (
    <DriverTable 
      collection={api?.collections.driver ?? null}
      onRowClick={(row) => console.log('Clicked:', row)}
    />
  );
}

Features

  • Columns: Name, Login (username), Organization, Access to Projects
  • Filters: First Name (text search)
  • Default Sort: -created_at (newest first)
  • Page Size: 20 items per page
  • Dependent API Calls: Automatically fetches related user and project membership data
  • Batched Name Lookups: Organization and project names are fetched in batched requests for optimal performance

Props

PropTypeRequiredDescription
collectionDriverCollection | nullYesThe driver collection to display
columnsColumnDef<Driver>[]NoCustom column definitions (overrides defaults)
filtersFilterDef<Driver>[]NoCustom filter definitions (overrides defaults)
initialOrderBystringNoInitial sort field (default: -created_at)
pageSizenumberNoItems per page (default: 20)
onRowClick(row: Driver) => voidNoCallback when a row is clicked
hideColumnsstring[]NoArray of column keys to hide

Column Details

Name

Displays the driver's first name. Sortable by first_name.

Login

Shows the username from the associated user account. Fetched automatically via dependent API call. Returns "-" if no user account is linked.

Organization

Displays the organization name for the user's organization. Uses the OrganizationName component with batched fetching - all organization names visible on the page are fetched in a single API call (50ms debounce window).

Access to Projects

Lists all projects the driver has access to through project memberships. Uses the ProjectName component with batched fetching. Only shows projects with organization type "participation". Multiple project names are comma-separated.

Dependent API Calls

The DriverTable uses the Collection system's dependent API call feature to automatically fetch related data:

How It Works

  1. Initial Fetch: When you call api.collections.driver.fetch(), the driver records are loaded
  2. Automatic User Fetch: The collection extracts all unique user_id values and makes a single batched API call to fetch user details (username, email, organization_id)
  3. Automatic ProjectMember Fetch: The collection makes another batched call to fetch project memberships for all users, filtered to only "participation" type organizations
  4. Data Merging: The fetched data is merged back into the driver objects:
    • driver.user contains the full user object (one-to-one relationship)
    • driver.projectMembers contains an array of project membership objects (one-to-many relationship)

Batched Name Lookups

The Organization and Project name columns use a separate batching mechanism:

  1. When the table renders, each OrganizationName and ProjectName component requests its data via getAsync(id)
  2. All requests within a 50ms window are batched into a single API call using the id__in parameter
  3. Results are cached - if you scroll back to previously viewed rows, names are returned from cache instantly
  4. Console logs show: [Collection._processBatch] X from cache: [...] | Y to fetch: [...]

This architecture ensures optimal performance even with hundreds of drivers, organizations, and projects.

Filtering

  • First Name: Case-insensitive text search (first_name__icontains)

Customization

Hide Columns

Hide specific columns using the hideColumns prop.

<DriverTable 
  collection={api?.collections.driver ?? null}
  hideColumns={['user_id', 'modified_at']}
/>

Custom Columns

Import default columns and customize them to add or modify columns.

import { defaultDriverColumns } from '@/components/sgerp/tables/driver-table';

const customColumns = [
  ...defaultDriverColumns.slice(0, 2), // Name, Login
  {
    key: 'email',
    label: 'Email',
    render: (_, driver) => driver.user?.email || '-',
  },
  ...defaultDriverColumns.slice(2), // Organization, Access to Projects
];

<DriverTable
  collection={api?.collections.driver ?? null}
  columns={customColumns}
/>

Custom Filters

Override the default filters with your own filter definitions.

const customFilters = [
  {
    key: 'first_name',
    label: 'First Name',
    type: 'text',
    mode: 'server',
    serverParam: 'first_name__icontains',
  },
  {
    key: 'user_id',
    label: 'User ID',
    type: 'number',
    mode: 'server',
    serverParam: 'user_id',
  }
];

<DriverTable
  collection={api?.collections.driver ?? null}
  filters={customFilters}
/>

Examples

Basic Usage with Dependent Data

A single fetch automatically loads driver, user, and project membership data.

function DriverList() {
  const api = useSGERP();

  React.useEffect(() => {
    if (api) {
      // Single fetch automatically loads driver, user, and projectmember data
      api.collections.driver.fetch({ limit: 50 });
    }
  }, [api]);

  return (
    <DriverTable
      collection={api?.collections.driver ?? null}
    />
  );
}

Accessing Dependent Data Programmatically

Access the automatically fetched user and project membership data from driver models.

function DriverInfo() {
  const api = useSGERP();
  const drivers = api?.collections.driver.models ?? [];

  return (
    <div>
      {drivers.map(driver => (
        <div key={driver.id}>
          <h3>{driver.first_name}</h3>
          <p>Username: {driver.user?.username ?? 'No account'}</p>
          <p>Email: {driver.user?.email ?? '-'}</p>
          <p>Projects: {driver.projectMembers?.length ?? 0}</p>
        </div>
      ))}
    </div>
  );
}

With Row Click Handler

Handle row clicks to display detailed driver information.

function DriverList() {
  const api = useSGERP();
  const [selectedDriver, setSelectedDriver] = React.useState<Driver | null>(null);

  return (
    <>
      <DriverTable
        collection={api?.collections.driver ?? null}
        onRowClick={(driver) => setSelectedDriver(driver)}
      />
      {selectedDriver && (
        <div>
          <h3>Selected Driver</h3>
          <p>Name: {selectedDriver.first_name}</p>
          <p>Login: {selectedDriver.user?.username ?? '-'}</p>
          <p>Organization ID: {selectedDriver.user?.organization_id ?? '-'}</p>
          <p>Access to {selectedDriver.projectMembers?.length ?? 0} projects</p>
        </div>
      )}
    </>
  );
}

Performance Notes

  • Dependent calls execute once per fetch: When you fetch 50 drivers, the system makes 3 total API calls (drivers, users, projectmembers)
  • Name lookups are batched: Rendering 50 organizations makes 1 API call, not 50
  • Caching prevents redundant fetches: Scrolling through paginated data reuses cached names
  • 50ms debounce window: Balances responsiveness with batching efficiency