VehicleType Editor

Form component for creating and editing vehicle types with capacity constraints

Live Example

Create New Vehicle Type

Fill in the form to create a new vehicle type with capacity constraints. The editor features an interactive capacity widget with preset options and custom keys.

Edit Existing Vehicle Type

Select a vehicle type from the autocomplete dropdown to edit. The editor will load the current data including capacity constraints and allow you to update it.

Select a vehicle type to edit:

Capacity Constraints Widget

The capacity editor provides preset options (passenger, wheelchair, CBCM, G, units) and supports custom keys for specialized capacity types.

Click "Create New Vehicle Type" above to see the interactive capacity widget in action.

Example Capacity Configuration:

{
  "passenger": 4,
  "wheelchair": 2,
  "cbcm": 100,
  "luggage": 8
}

VehicleType Editor

A comprehensive form component for creating new vehicle types or editing existing ones. Features advanced capacity constraint management with key-value pairs and supports the dual-API pattern.

Usage

Create New Vehicle Type

import { VehicleTypeEditor } from '@/components/sgerp/editors/vehicletype-editor';
import { useState } from 'react';

function MyComponent() {
  const [showEditor, setShowEditor] = useState(false);

  return (
    <>
      <button onClick={() => setShowEditor(true)}>
        Create Vehicle Type
      </button>

      {showEditor && (
        <VehicleTypeEditor
          onSuccess={(vehicleType) => {
            console.log('Created:', vehicleType);
            setShowEditor(false);
          }}
          onCancel={() => setShowEditor(false)}
        />
      )}
    </>
  );
}

Edit Existing Vehicle Type (by ID)

import { VehicleTypeEditor } from '@/components/sgerp/editors/vehicletype-editor';

function MyComponent() {
  const vehicleTypeId = 123; // The vehicle type you want to edit

  return (
    <VehicleTypeEditor
      vehicleTypeId={vehicleTypeId}
      onSuccess={(vehicleType) => {
        console.log('Updated:', vehicleType);
      }}
      onCancel={() => {
        // Handle cancel
      }}
    />
  );
}

Edit with Initial Data and Shared API

When you already have the vehicle type data and API instance (e.g., from a table), pass them directly:

import { VehicleTypeEditor } from '@/components/sgerp/editors/vehicletype-editor';
import { useSGERP } from 'sgerp-frontend-lib';
import type { VehicleType } from 'sgerp-frontend-lib/lib/sgerp/types/simulation/vehicletype';

function MyComponent({ vehicleType }: { vehicleType: VehicleType }) {
  const api = useSGERP(); // Shared API instance

  return (
    <VehicleTypeEditor
      vehicleTypeId={vehicleType.id}
      initialData={vehicleType}
      api={api}
      onSuccess={(updatedVehicleType) => {
        console.log('Updated:', updatedVehicleType);
      }}
      onCancel={() => {
        // Handle cancel
      }}
    />
  );
}

Features

  • Create Mode: When vehicleTypeId is not provided, creates a new vehicle type
  • Edit Mode: When vehicleTypeId is provided, loads and updates existing vehicle type
  • Capacity Widget: Interactive key-value editor for capacity constraints with preset options and custom keys
  • Dual-API Pattern: Writes to Tastypie API, refreshes from GET API for consistency
  • Form Validation: Required field validation (name and project are required)
  • Error Handling: Displays error messages from API
  • Loading States: Shows loading indicator while fetching/saving
  • Collection Integration: Automatically updates the vehicletype collection on success
  • Shared API Support: Accepts API instance to share collections with parent components

Props

PropTypeRequiredDescription
vehicleTypeIdnumberNoID of vehicle type to edit (omit for create mode)
initialDataVehicleTypeNoPre-loaded vehicle type data to avoid fetching. When provided, editor uses this data immediately without API call
apiReturnType<typeof useSGERP>NoShared API instance to ensure collection updates are reflected in parent components
onSuccess(vehicleType: VehicleType) => voidNoCallback when save succeeds with fresh vehicle type data
onCancel() => voidNoCallback when user cancels editing

Form Fields

Required Fields

  • Name: Vehicle type name (string, required, no spaces)
  • Project: Project to which the vehicle type belongs (required, autocomplete)

Optional Fields

  • Capacity: Key-value pairs for capacity constraints (object)
    • Preset keys: passenger, wheelchair, cbcm, g, units
    • Custom keys: Enter any custom key for specialized capacity types
    • Values: Integer capacities
  • Vehicle Cost: Cost per vehicle (number)
  • Max Trip Duration: Maximum trip duration in seconds (number)
  • LIFO Order Check: Whether to check Last In First Out order (boolean)

Capacity Widget

The capacity editor provides an intuitive interface for managing capacity constraints:

Features

  • Preset Options: Quick selection for common capacity types (passenger, wheelchair, CBCM, G, units)
  • Custom Keys: Switch to custom input mode to define specialized capacity types
  • Add/Remove: Dynamically add or remove capacity constraints
  • Visual Feedback: Clear display of all capacity constraints

Example Capacity Object

{
  "passenger": 4,
  "wheelchair": 2,
  "luggage": 8
}

Dual-API Implementation

The editor follows the dual-API pattern documented in CLAUDE.md:

  1. Write Operation: POST/PATCH to /api/v2/vehicletype/ (Tastypie API)
  2. Refresh Operation: GET from /api/v2/microservices/get?model=vehicletype&id={id} (GET API)
  3. Collection Update: Uses add() to merge into api.collections.vehicletype without clearing other models

This ensures all data in collections maintains consistent format from the GET API.

Example: In VehicleTypeTable with Integrated Editor

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

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

  return (
    <VehicleTypeTable
      collection={api?.collections.vehicletype ?? null}
      api={api}
      enableEditor={true}
      onEditSuccess={(vehicleType) => {
        console.log('Vehicle type updated:', vehicleType);
        // Collection is automatically updated by editor
      }}
    />
  );
}

Example: In a Drawer

import { VehicleTypeEditor } from '@/components/sgerp/editors/vehicletype-editor';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { useState } from 'react';

function MyComponent() {
  const [drawerOpen, setDrawerOpen] = useState(false);

  return (
    <>
      <button onClick={() => setDrawerOpen(true)}>
        Create Vehicle Type
      </button>

      <Sheet open={drawerOpen} onOpenChange={setDrawerOpen}>
        <SheetContent>
          <SheetHeader>
            <SheetTitle>Create Vehicle Type</SheetTitle>
          </SheetHeader>
          <div className="mt-6">
            <VehicleTypeEditor
              onSuccess={(vehicleType) => {
                console.log('Created:', vehicleType);
                setDrawerOpen(false);
              }}
              onCancel={() => setDrawerOpen(false)}
            />
          </div>
        </SheetContent>
      </Sheet>
    </>
  );
}

Error Handling

The editor handles various error scenarios:

  • Network Errors: Displays error message from API response
  • Validation Errors: Browser validation for required fields
  • Loading Errors: Shows error if vehicle type fails to load in edit mode
<VehicleTypeEditor
  vehicleTypeId={123}
  onSuccess={(vehicleType) => {
    // Success handling
    toast.success(`Updated: ${vehicleType.name}`);
  }}
  onCancel={() => {
    // User cancelled
  }}
/>

Styling

The editor uses Tailwind CSS classes and inherits theme colors. All form elements are styled consistently with the design system.