implement update train details feature: add DTO, service method, and UI modal for editing train name and run numbers

This commit is contained in:
Marshal
2026-07-15 20:14:39 +00:00
parent d7d9db9c3a
commit fc44eee25e
44 changed files with 970 additions and 14 deletions

View File

@@ -14,6 +14,7 @@ import { useNavigate } from "react-router-dom";
import type { Freight } from "@edr/types";
import { PayClearanceFeeButton } from "@/pages/bookings/payments/PayClearanceFeeButton";
import { PayNowButton } from "@/pages/bookings/payments/PayNowButton";
import { api } from "@/services/api";
import { ContractClearanceAction } from "./ContractClearanceAction";
@@ -69,6 +70,17 @@ export function ContractCustomerAction({
);
}
if (action.type === "pay-clearance") {
return (
<PayClearanceFeeButton
sourceId={action.contractId}
currency={contract.paymentCurrency}
label={action.label}
size={size}
/>
);
}
if (action.type === "initiate") {
return (
<InitiateBookingButton

View File

@@ -80,6 +80,14 @@ export type ContractCustomerAction =
label: string;
primary: boolean;
icon: LucideIcon;
}
| {
/** Prepaid customs clearance service fee (contract-level, ONE_TIME Path B). */
type: "pay-clearance";
contractId: string;
label: string;
primary: boolean;
icon: LucideIcon;
};
function findPayableBookingForContract(
@@ -137,6 +145,17 @@ export function deriveContractCustomerAction(
};
}
// Prepaid clearance service fee gate — must settle before document upload.
if (contract.status === "AWAITING_CLEARANCE_PAYMENT") {
return {
type: "pay-clearance",
contractId: id,
label: "Pay clearance fee",
primary: true,
icon: CreditCard,
};
}
const payable = findPayableBookingForContract(id, bookings);
if (payable) {
return {