mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(freight): surface scheduling clock and gate pay during drain
This commit is contained in:
@@ -44,6 +44,27 @@ function formatRelative(iso: string, nowMs: number): string {
|
||||
return past ? `${span} ago` : `in ${span}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of a window as "1h 30m" / "45m". Null unless both ends are real and
|
||||
* ordered — the pay window is configurable per schedule, so this is read off the
|
||||
* actual stamps rather than assuming any fixed duration.
|
||||
*/
|
||||
function formatDuration(
|
||||
from: string | null | undefined,
|
||||
to: string | null | undefined,
|
||||
): string | null {
|
||||
if (!from || !to) return null;
|
||||
const fromMs = new Date(from).getTime();
|
||||
const toMs = new Date(to).getTime();
|
||||
if (!Number.isFinite(fromMs) || !Number.isFinite(toMs)) return null;
|
||||
const minutes = Math.round((toMs - fromMs) / 60_000);
|
||||
if (minutes <= 0) return null;
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const rest = minutes % 60;
|
||||
if (!hours) return `${rest}m`;
|
||||
return rest ? `${hours}h ${rest}m` : `${hours}h`;
|
||||
}
|
||||
|
||||
function Row({
|
||||
label,
|
||||
value,
|
||||
@@ -98,8 +119,18 @@ export function BookingSchedulingWindowCard({
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
// How long the customer actually had to pay: start → the raw deadline, NOT the
|
||||
// drain end (the drain is settlement grace, not payable time).
|
||||
const windowDuration = formatDuration(
|
||||
booking.selectedForBatchAt,
|
||||
booking.paymentDeadline,
|
||||
);
|
||||
|
||||
const hasAnything =
|
||||
Boolean(schedule) || Boolean(payWindowEndsAt) || Boolean(booking.holdExpiresAt);
|
||||
Boolean(schedule) ||
|
||||
Boolean(payWindowEndsAt) ||
|
||||
Boolean(booking.selectedForBatchAt) ||
|
||||
Boolean(booking.holdExpiresAt);
|
||||
if (!hasAnything) return null;
|
||||
|
||||
const payWindowClosed = payWindowEndsAt
|
||||
@@ -157,6 +188,18 @@ export function BookingSchedulingWindowCard({
|
||||
</Group>
|
||||
) : null}
|
||||
|
||||
{booking.selectedForBatchAt ? (
|
||||
<Row
|
||||
label="Payment window started"
|
||||
value={formatStamp(booking.selectedForBatchAt) ?? "—"}
|
||||
hint={
|
||||
windowDuration
|
||||
? `${windowDuration} window`
|
||||
: formatRelative(booking.selectedForBatchAt, nowMs)
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{payWindowEndsAt ? (
|
||||
<Row
|
||||
label="Payment window ends"
|
||||
|
||||
@@ -206,6 +206,11 @@ export interface BookingDetail {
|
||||
trainScheduleStatus?: string | null;
|
||||
/** The allocated train's identity + clock, attached by the detail endpoint. */
|
||||
trainScheduleSummary?: BookingTrainScheduleSummary | null;
|
||||
/**
|
||||
* When the batch engine picked this booking and opened its pay window — the
|
||||
* start paired with `paymentDeadline` (both are set and cleared together).
|
||||
*/
|
||||
selectedForBatchAt?: string | null;
|
||||
/** End of this booking's pay window (batch/offer deadline). */
|
||||
paymentDeadline?: string | null;
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user