Files
edr-platform/apps/edr-freight-web/backoffice/src/utils/groupBookingsByThreeHourWindow.ts

92 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { compareSchedulingPriority } from "./compareSchedulingPriority";
export interface ThreeHourSchedulable {
id: string;
priorityScore?: number;
scheduledDate?: string;
preferredDepartureDate?: string;
isGovernment?: boolean;
}
export interface ThreeHourBookingBucket<T extends ThreeHourSchedulable = ThreeHourSchedulable> {
key: string;
label: string;
start: Date;
end: Date;
bookings: T[];
}
function bucketStart(date: Date): Date {
const start = new Date(date);
start.setUTCMinutes(0, 0, 0);
const hour = start.getUTCHours();
start.setUTCHours(Math.floor(hour / 3) * 3);
return start;
}
function formatBucketLabel(start: Date, end: Date): string {
const dateFmt = new Intl.DateTimeFormat("en-GB", {
day: "2-digit",
month: "short",
year: "numeric",
timeZone: "UTC",
});
const timeFmt = new Intl.DateTimeFormat("en-GB", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: "UTC",
});
return `${dateFmt.format(start)} · ${timeFmt.format(start)} ${timeFmt.format(end)} UTC`;
}
function getScheduledDate(booking: ThreeHourSchedulable): Date {
const raw = booking.scheduledDate ?? booking.preferredDepartureDate;
if (!raw) return new Date(0);
return new Date(raw);
}
function toPriorityRow(booking: ThreeHourSchedulable) {
return {
isGovernment: booking.isGovernment,
priorityScore: booking.priorityScore,
scheduledDate: booking.scheduledDate ?? booking.preferredDepartureDate ?? "",
};
}
export function groupBookingsByThreeHourWindow<T extends ThreeHourSchedulable>(
bookings: T[],
): ThreeHourBookingBucket<T>[] {
const map = new Map<string, ThreeHourBookingBucket<T>>();
for (const booking of bookings) {
const scheduled = getScheduledDate(booking);
const start = bucketStart(scheduled);
const end = new Date(start);
end.setUTCHours(end.getUTCHours() + 3);
const key = start.toISOString();
const existing = map.get(key);
if (existing) {
existing.bookings.push(booking);
} else {
map.set(key, {
key,
label: formatBucketLabel(start, end),
start,
end,
bookings: [booking],
});
}
}
return [...map.values()]
.map((bucket) => ({
...bucket,
bookings: [...bucket.bookings].sort((a, b) =>
compareSchedulingPriority(toPriorityRow(a), toPriorityRow(b)),
),
}))
.sort((a, b) => a.start.getTime() - b.start.getTime());
}