import type { PaginatedResponse } from '@edr/types'; import { api as apiClient } from '../auth/http'; import { URL_CONSTANTS } from '@/constants/URLS'; export type LocomotiveType = 'DIESEL' | 'ELECTRIC'; export type LocomotiveStatus = | 'AVAILABLE' | 'UNAVAILABLE' | 'IMPORT_READY' | 'EXPORT_READY' | 'MAINTENANCE' | 'ASSIGNED' | 'OUT_OF_SERVICE'; export interface LocomotiveListFilters { status?: LocomotiveStatus; currentYardId?: string; /** Drop locos already coupled to a built train (train-builder picker). */ excludeCoupled?: boolean; /** With excludeCoupled: keep THIS train's own coupled locos in the list. */ excludeTrainId?: string; /** Free-text over code + name — only honoured by `getPaged`. */ search?: string; /** Registration day range (YYYY-MM-DD), both ends inclusive. */ createdFrom?: string; createdTo?: string; /** Only read by `getPaged`. */ page?: number; pageSize?: number; } const locomotiveListQuery = (filters: LocomotiveListFilters): string => { const params = new URLSearchParams(); if (filters.status) params.set('status', filters.status); if (filters.currentYardId) params.set('currentYardId', filters.currentYardId); if (filters.excludeCoupled) params.set('excludeCoupled', 'true'); if (filters.excludeTrainId) params.set('excludeTrainId', filters.excludeTrainId); if (filters.search?.trim()) params.set('search', filters.search.trim()); if (filters.createdFrom) params.set('createdFrom', filters.createdFrom); if (filters.createdTo) params.set('createdTo', filters.createdTo); if (filters.page) params.set('page', String(filters.page)); if (filters.pageSize) params.set('pageSize', String(filters.pageSize)); const qs = params.toString(); return qs ? `?${qs}` : ''; }; export interface Locomotive { id: string; code: string; name?: string | null; locomotiveType: LocomotiveType; status: LocomotiveStatus; currentYardId: string | null; currentYard?: { id: string; label?: string; code?: string } | null; maxPullWeightTons: number; maxTrainLengthMeters: number; /** Tons a train may exceed maxPullWeightTons by before scheduling blocks it. */ overageToleranceTons?: number | null; /** Metres a train may exceed maxTrainLengthMeters by before scheduling blocks it. */ overageToleranceMeters?: number | null; createdAt: string; updatedAt: string; } export type SaveLocomotivePayload = Omit< Locomotive, 'id' | 'createdAt' | 'updatedAt' >; export const locomotivesService = { getAll: (filters: LocomotiveListFilters = {}) => apiClient.get( `${URL_CONSTANTS.LOCOMOTIVES.BASE}${locomotiveListQuery(filters)}`, ), /** Same filters as `getAll` plus search, server-paginated ({items, meta}). */ getPaged: (filters: LocomotiveListFilters = {}) => apiClient.get>( `${URL_CONSTANTS.LOCOMOTIVES.BASE}/paged${locomotiveListQuery(filters)}`, ), getById: (id: string) => apiClient.get(URL_CONSTANTS.LOCOMOTIVES.BY_ID(id)), create: (data: Partial) => apiClient.post(URL_CONSTANTS.LOCOMOTIVES.BASE, data), update: (id: string, data: Partial) => apiClient.patch(URL_CONSTANTS.LOCOMOTIVES.BY_ID(id), data), decommission: (id: string) => apiClient.post(URL_CONSTANTS.LOCOMOTIVES.DECOMMISSION(id), {}), /** Irreversible purge — the API refuses it while any train references the loco. */ purge: (id: string) => apiClient.delete(`${URL_CONSTANTS.LOCOMOTIVES.BY_ID(id)}/permanent`), };