mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 05:58:18 +00:00
feat(train-crew): implement crew assignment functionality
- Added TrainCrewAssignment module with controller and service for managing crew assignments. - Integrated TrainCrewAssignmentService into TrainSchedulingService to ensure crew readiness before train dispatch. - Updated TrainScheduling module to include TrainCrewModule for dependency injection. - Introduced new permissions for assigning train crew in freight permissions registry. - Enhanced front-end ScheduleCrewPage to allow assignment of crew members to train schedules, including validation and UI for adding/removing drivers and support crew. - Created trainCrewAssignment.service to handle API interactions for crew assignments.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { api as apiClient } from '../auth/http';
|
||||
import type { TrainCrewMember, TrainCrewRole } from './trainCrew.service';
|
||||
|
||||
export type CrewDutyRole = 'PRIMARY' | 'ASSISTANT' | 'BENCH_RELIEF';
|
||||
|
||||
/** A yard on the schedule's route, ordered along the corridor. */
|
||||
export interface CorridorYard {
|
||||
id: string;
|
||||
label: string;
|
||||
country: string;
|
||||
displayOrder: number;
|
||||
}
|
||||
|
||||
export interface CrewAssignment {
|
||||
id: string;
|
||||
trainScheduleId: string;
|
||||
crewMemberId: string;
|
||||
role: TrainCrewRole;
|
||||
dutyRole?: CrewDutyRole | null;
|
||||
fromYardId?: string | null;
|
||||
toYardId?: string | null;
|
||||
status: string;
|
||||
crewMember?: TrainCrewMember;
|
||||
}
|
||||
|
||||
/** What the consist and its cargo demand (§1.2), detected server-side. */
|
||||
export interface CrewDemand {
|
||||
hasBadOrderWagon: boolean;
|
||||
badOrderWagonLabels: string[];
|
||||
hasReeferCargo: boolean;
|
||||
reeferSources: string[];
|
||||
hasHazmatCargo: boolean;
|
||||
hazmatSources: string[];
|
||||
hasBreakBulkCargo: boolean;
|
||||
breakBulkSources: string[];
|
||||
hasLivestockCargo: boolean;
|
||||
livestockSources: string[];
|
||||
}
|
||||
|
||||
export interface CrewRequirement {
|
||||
role: TrainCrewRole;
|
||||
/** Hard floor — 0 unless the cargo or consist forces someone aboard. */
|
||||
min: number;
|
||||
/** The count §1.2 suggests. A hint only; nothing enforces it. */
|
||||
typical: number;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface CrewValidation {
|
||||
complete: boolean;
|
||||
issues: Array<{ code: string; message: string }>;
|
||||
runType: 'SHORT_RUN' | 'LONG_RUN' | null;
|
||||
}
|
||||
|
||||
export interface ScheduleCrewResponse {
|
||||
scheduleId: string;
|
||||
assignments: CrewAssignment[];
|
||||
/** Yards a driver leg may use — bounded by the schedule's own endpoints. */
|
||||
corridorYards: CorridorYard[];
|
||||
demand: CrewDemand;
|
||||
requirements: {
|
||||
technician: CrewRequirement;
|
||||
specialized: CrewRequirement[];
|
||||
};
|
||||
validation: CrewValidation;
|
||||
}
|
||||
|
||||
export interface SaveCrewPayload {
|
||||
assignments: Array<{
|
||||
crewMemberId: string;
|
||||
role: TrainCrewRole;
|
||||
dutyRole?: CrewDutyRole;
|
||||
fromYardId?: string;
|
||||
toYardId?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
const base = (scheduleId: string) => `/train-schedules/${scheduleId}/crew`;
|
||||
|
||||
export const trainCrewAssignmentService = {
|
||||
get: (scheduleId: string) =>
|
||||
apiClient.get<ScheduleCrewResponse>(base(scheduleId)),
|
||||
eligibleDrivers: (scheduleId: string, fromYardId: string, toYardId: string) =>
|
||||
apiClient.get<TrainCrewMember[]>(
|
||||
`${base(scheduleId)}/eligible-drivers?fromYardId=${fromYardId}&toYardId=${toYardId}`,
|
||||
),
|
||||
corridorYards: (scheduleId: string) =>
|
||||
apiClient.get<CorridorYard[]>(`${base(scheduleId)}/corridor-yards`),
|
||||
save: (scheduleId: string, payload: SaveCrewPayload) =>
|
||||
apiClient.put<CrewValidation>(base(scheduleId), payload),
|
||||
};
|
||||
|
||||
export const DUTY_ROLE_OPTIONS: Array<{ value: CrewDutyRole; label: string }> = [
|
||||
{ value: 'PRIMARY', label: 'Primary Driver' },
|
||||
{ value: 'ASSISTANT', label: 'Assistant Driver' },
|
||||
{ value: 'BENCH_RELIEF', label: 'Bench/Relief Driver' },
|
||||
];
|
||||
|
||||
export const dutyRoleLabel = (dutyRole: CrewDutyRole): string =>
|
||||
({
|
||||
PRIMARY: 'Primary Driver',
|
||||
ASSISTANT: 'Assistant Driver',
|
||||
BENCH_RELIEF: 'Bench/Relief Driver',
|
||||
})[dutyRole];
|
||||
Reference in New Issue
Block a user