Files
edr-platform/apps/edr-freight-web/backoffice/src/features/bookings/shipmentDay.ts

89 lines
2.7 KiB
TypeScript

/**
* Shared helpers for the staff shipment-day / export-train pickers (the
* operation reschedule modal and the GL "returned for changes" resubmit).
*/
export const EAT_TIMEZONE = "Africa/Addis_Ababa";
/** YYYY-MM-DD of an instant in East Africa Time — the booking day key. */
export function eatDay(value: string | Date): string {
const date = typeof value === "string" ? new Date(value) : value;
return new Intl.DateTimeFormat("en-CA", {
timeZone: EAT_TIMEZONE,
year: "numeric",
month: "2-digit",
day: "2-digit",
}).format(date);
}
/** "Mon, 07 Sep, 09:00" in EAT; "—" for a missing or invalid value. */
export function formatEat(value: string | Date | null | undefined): string {
if (!value) return "—";
const date = typeof value === "string" ? new Date(value) : value;
if (Number.isNaN(date.getTime())) return "—";
return new Intl.DateTimeFormat("en-GB", {
timeZone: EAT_TIMEZONE,
weekday: "short",
day: "2-digit",
month: "short",
hour: "2-digit",
minute: "2-digit",
}).format(date);
}
/** "Wed, 09 Sep 2026" for a YYYY-MM-DD EAT day key. */
export function formatEatDay(dayKey: string): string {
const date = new Date(`${dayKey}T12:00:00.000Z`);
if (Number.isNaN(date.getTime())) return dayKey;
return new Intl.DateTimeFormat("en-GB", {
timeZone: EAT_TIMEZONE,
weekday: "short",
day: "2-digit",
month: "short",
year: "numeric",
}).format(date);
}
/** Mirrors the API road-service rule: ServiceType.code ROAD, TRUCK, ROAD_*, TRUCK_* */
export function isRoadServiceCode(code: string | null | undefined): boolean {
const c = (code ?? "").toUpperCase();
return (
c === "ROAD" ||
c === "TRUCK" ||
c.startsWith("ROAD_") ||
c.startsWith("TRUCK_")
);
}
/** Export rail bookings are the only ones that carry a train pick. */
export function isExportRailBooking(booking: {
tradeDirection?: string | null;
serviceType?: { code?: string | null } | null;
}): boolean {
return (
booking.tradeDirection === "EXPORT" &&
!isRoadServiceCode(booking.serviceType?.code)
);
}
/** Select option for one export train; closed or too-small trains are disabled. */
export function exportTrainOption(t: {
scheduleId: string;
trainNumber: string | null;
trainName: string | null;
departure: string;
isOpen: boolean;
fits: boolean;
freeWagons: number;
neededWagons: number;
}): { value: string; label: string; disabled: boolean } {
return {
value: t.scheduleId,
label:
`${t.trainNumber ?? t.trainName ?? "Train"} · departs ${formatEat(t.departure)} · ` +
`${t.freeWagons} free / needs ${t.neededWagons}` +
(!t.isOpen ? " · closed" : !t.fits ? " · no room" : ""),
disabled: !t.isOpen || !t.fits,
};
}