mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
feat: implement wagon transfer management modals and page
- Add TransferFulfillModal for fulfilling wagon transfer requests. - Create TransferRequestFormModal for filing new wagon transfer requests. - Introduce TransferCloseShortModal for closing requests that cannot be fully fulfilled. - Develop WagonTransfersPage to manage and display wagon transfer requests. - Implement utility functions for handling wagon transfer request data and UI components. - Enhance UI with Mantine components for better user experience.
This commit is contained in:
@@ -110,10 +110,93 @@ Cypress.Commands.add("mantineSelect", (label: string | RegExp, option: string |
|
||||
.then((id) => {
|
||||
cy.get(`[id="${id}"]`).click({ force: true });
|
||||
});
|
||||
// :visible — closed dropdowns can linger in the DOM, and two selects on one
|
||||
// page may list the same option text (e.g. the intercity wizard's origin +
|
||||
// destination both list every Ethiopian yard).
|
||||
cy.get('[role="option"]:visible').contains(option).click();
|
||||
// Scope to the OPEN listbox: closed dropdowns linger in the DOM, and two
|
||||
// selects on one page may list the same option text (e.g. the intercity
|
||||
// wizard's origin + destination both list every Ethiopian yard).
|
||||
//
|
||||
// The scope has to be the listbox rather than the options themselves. A long
|
||||
// list scrolls inside a max-height dropdown, and Cypress counts the clipped
|
||||
// rows as not-visible — matching on `[role="option"]:visible` silently drops
|
||||
// whatever sits past the fold (this hid the alphabetically-last trains).
|
||||
// force: the click still has to land on a row that needs scrolling to.
|
||||
cy.get('[role="listbox"]:visible')
|
||||
.last()
|
||||
.contains('[role="option"]', option)
|
||||
.click({ force: true });
|
||||
});
|
||||
|
||||
/**
|
||||
* Fill the accept-contract modal's validity window. The modal used to offer a
|
||||
* dropdown of configured durations that defaulted to the first option; it now
|
||||
* takes explicit Start/End dates and pre-fills neither, so "Accept & start
|
||||
* approval" stays disabled until both are set.
|
||||
*
|
||||
* Mantine's DateInput parses typed text with its valueFormat, which defaults to
|
||||
* "MMMM D, YYYY" — the same shape en-US toLocaleDateString produces.
|
||||
*/
|
||||
Cypress.Commands.add("acceptValidityWindow", (days = 365) => {
|
||||
const start = new Date();
|
||||
const end = new Date(start.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
const asInput = (d: Date) =>
|
||||
d.toLocaleDateString("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
});
|
||||
|
||||
for (const [label, value] of [
|
||||
["Start date", start],
|
||||
["End date", end],
|
||||
] as const) {
|
||||
cy.contains("label", label)
|
||||
.invoke("attr", "for")
|
||||
.then((id) => {
|
||||
cy.get(`[id="${id}"]`)
|
||||
.clear({ force: true })
|
||||
.type(asInput(value), { force: true })
|
||||
// DateInput commits on blur; it also closes the calendar popover,
|
||||
// which would otherwise sit over the submit button.
|
||||
.blur();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Attach a company stamp in the open sign-contract modal. The stamp became a
|
||||
* REQUIRED field on signing — "Continue to verification" stays disabled without
|
||||
* one — and StampUpload only checks the MIME type and size before reading the
|
||||
* file as a data URL, so the smallest valid PNG is enough. The input is
|
||||
* `hidden` (a dropzone drives it), hence force.
|
||||
*/
|
||||
const STAMP_PNG =
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==";
|
||||
|
||||
Cypress.Commands.add("uploadCompanyStamp", () => {
|
||||
cy.get('.mantine-Modal-content input[type="file"]')
|
||||
.first()
|
||||
.selectFile(
|
||||
{
|
||||
contents: Cypress.Buffer.from(STAMP_PNG, "base64"),
|
||||
fileName: "stamp.png",
|
||||
mimeType: "image/png",
|
||||
},
|
||||
{ force: true },
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Fill the per-booking "Cargo description" on the new-shipment form. It is
|
||||
* REQUIRED for container shipments (it moved from the contract to the booking),
|
||||
* and the form validates through react-hook-form's handleSubmit — so leaving it
|
||||
* blank aborts silently: no price modal, no request, no error toast.
|
||||
* No-op for bulk shipments, which have no such field.
|
||||
*/
|
||||
Cypress.Commands.add("fillCargoDescription", (text = "Electronics") => {
|
||||
cy.get("body").then(($b) => {
|
||||
const field = $b.find('[placeholder^="e.g. Electronics"]');
|
||||
if (!field.length) return;
|
||||
cy.wrap(field.first()).clear({ force: true }).type(text, { force: true });
|
||||
});
|
||||
});
|
||||
|
||||
/** Type a 6-digit code into a Mantine PinInput. */
|
||||
@@ -168,6 +251,12 @@ declare global {
|
||||
getOtp(target: string): Chainable<string>;
|
||||
/** Open a Mantine Select by label, pick an option. */
|
||||
mantineSelect(label: string | RegExp, option: string | RegExp): Chainable<void>;
|
||||
/** Fill the accept-contract modal's Start/End validity dates. */
|
||||
acceptValidityWindow(days?: number): Chainable<void>;
|
||||
/** Attach the required company stamp in the sign-contract modal. */
|
||||
uploadCompanyStamp(): Chainable<void>;
|
||||
/** Fill the required per-booking cargo description (container only). */
|
||||
fillCargoDescription(text?: string): Chainable<void>;
|
||||
/** Fill a Mantine PinInput with a code. */
|
||||
typeOtp(code: string): Chainable<void>;
|
||||
/** Scribble on the signature-pad canvas inside the open modal. */
|
||||
|
||||
Reference in New Issue
Block a user