import type { FleetResourceConfig } from "./resources"; /** * A plate is two or three letters, a hyphen, then two to six digits — ET-9875, * AA-8642. Mirrors VEHICLE_PLATE_REGEX on the API so the form and the server * agree on what a plate looks like. */ const PLATE_PATTERN = { regex: /^[A-Z]{2,3}-\d{2,6}$/, message: "Use letters and numbers like ET-9875 or AA-8642", }; /** * Legacy static list. Truck configurations now live in `freight.truck_types` * and are edited in the back office (Rule Engine → Truck Types), so the form * loads them through `dynamicOptions: "truckTypes"` instead. * * Kept only for the driver "authorized vehicle types" multiselect, which stores * free-text categories rather than truck-type ids. * * @deprecated prefer the managed truck types */ const VEHICLE_TYPE_OPTIONS = [ { label: "Truck", value: "TRUCK" }, { label: "Van", value: "VAN" }, { label: "Car", value: "CAR" }, { label: "Bus", value: "BUS" }, { label: "Trailer", value: "TRAILER" }, { label: "Tanker", value: "TANKER" }, { label: "Flatbed", value: "FLATBED" }, ]; const OWNERSHIP_OPTIONS = [ { label: "Owned", value: "OWNED" }, { label: "Outsourced", value: "OUTSOURCED" }, ]; const FUEL_TYPE_OPTIONS = [ { label: "Petrol", value: "PETROL" }, { label: "Diesel", value: "DIESEL" }, { label: "Electric", value: "ELECTRIC" }, { label: "Hybrid", value: "HYBRID" }, ]; const VEHICLE_STATUS_OPTIONS = [ { label: "Active", value: "ACTIVE" }, { label: "Maintenance", value: "MAINTENANCE" }, { label: "Retired", value: "RETIRED" }, { label: "Out of service", value: "OUT_OF_SERVICE" }, ]; const VEHICLE_AVAILABILITY_OPTIONS = [ { label: "Free", value: "FREE" }, { label: "Busy", value: "BUSY" }, ]; export const vehiclesConfig: FleetResourceConfig = { slug: "vehicles", label: "Vehicles", subtitle: "Manage vehicle master data for fleet operations", basePath: "/dashboard/vehicles", detailPath: "/dashboard/vehicles/:id", addLabel: "Add Vehicle", entityLabel: "Vehicle", searchPlaceholder: "Search vehicles…", supportsSearch: true, removeAction: "delete", cardTitleKey: "plateNumber", cardCodeKey: "plateNumber", cardSubtitleKey: "status", listFilters: [ { key: "status", label: "Status", allLabel: "All statuses", options: VEHICLE_STATUS_OPTIONS, }, { key: "availability", label: "Availability", allLabel: "All availability", options: VEHICLE_AVAILABILITY_OPTIONS, }, ], searchKeys: ["plateNumber", "registrationNumber", "manufacturer", "model", "vehicleType", "vin", "status"], columns: [ { id: "code", header: "Code", accessorKey: "code", size: 90 }, { id: "plateNumber", header: "Plate Number", accessorKey: "plateNumber", size: 120 }, { id: "trailerPlateNo", header: "Trailer Plate No", accessorKey: "trailerPlateNo", size: 130 }, { id: "manufacturer", header: "Manufacturer", accessorKey: "manufacturer", size: 120 }, { id: "model", header: "Model", accessorKey: "model", size: 100 }, { id: "truckTypeId", header: "Truck Type", accessorKey: "truckTypeId", format: "entityLabel", size: 130 }, { id: "capacity", header: "Capacity (tons)", accessorKey: "capacity", format: "number", size: 100 }, { id: "ownership", header: "Ownership", accessorKey: "ownership", size: 100 }, { id: "status", header: "Status", accessorKey: "status", format: "statusBadge", size: 100 }, { id: "availability", header: "Availability", accessorKey: "availability", format: "statusBadge", size: 100 }, ], // Registration captures what the vehicle IS. Location, distances and haulage // pricing are per-trip operational data and live on the vehicle's Operations // tab instead (VehicleDetailPage) — they are not part of registering a truck. formFields: [ { name: "code", label: "Code", type: "text" }, { name: "plateNumber", label: "Power Plate No", type: "text", required: true, pattern: PLATE_PATTERN }, // The truck type decides whether a trailer exists at all: a rigid truck // (Casoni) has none, so the field disappears and submits null. Mirrored // server-side in VehiclesService — hiding a field is not enforcement. { name: "trailerPlateNo", label: "Trailer Plate No", type: "text", pattern: PLATE_PATTERN, showIf: (values) => values._hasTrailer !== false, }, { name: "truckTypeId", label: "Truck Type", type: "select", required: true, dynamicOptions: "truckTypes", description: "Managed in Rule Engine → Truck Types", // Capacity is a property of the type, not of each individual truck. // `_hasTrailer` is form-local scratch (stripped before submit) that drives // the trailer plate's visibility. onOptionSelected: (option) => ({ _hasTrailer: option?.meta?.hasTrailer ?? true, ...(option?.meta?.capacityTons != null ? { capacity: option.meta.capacityTons } : {}), }), }, { name: "vin", label: "VIN", type: "text", description: "Vehicle Identification Number" }, { name: "ownership", label: "Ownership", type: "radio", options: OWNERSHIP_OPTIONS }, { name: "manufacturer", label: "Manufacturer", type: "text", required: true }, { name: "model", label: "Model", type: "text", required: true }, { name: "year", label: "Year", type: "number", required: true }, { name: "fuelType", label: "Fuel Type", type: "select", required: true, options: FUEL_TYPE_OPTIONS }, { name: "capacity", label: "Capacity (tons)", type: "number", required: true, description: "Pre-filled from the truck type — override only for a one-off", }, { name: "pricePerKm", label: "Price per KM (ETB)", type: "number", description: "Haulage rate charged per kilometre" }, { name: "status", label: "Status", type: "select", required: true, options: VEHICLE_STATUS_OPTIONS }, { name: "availability", label: "Availability", type: "select", required: true, options: VEHICLE_AVAILABILITY_OPTIONS }, { name: "description", label: "Description", type: "textarea" }, ], emptyValues: { code: "03-ET", plateNumber: "", trailerPlateNo: "", truckTypeId: "", vin: "", ownership: "OWNED", manufacturer: "", model: "", year: new Date().getFullYear(), fuelType: "DIESEL", capacity: 0, pricePerKm: 0, status: "ACTIVE", availability: "FREE", description: "", }, }; export { VEHICLE_TYPE_OPTIONS, FUEL_TYPE_OPTIONS, VEHICLE_STATUS_OPTIONS, VEHICLE_AVAILABILITY_OPTIONS };