mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 01:20:55 +00:00
feat: implement shipping line bookings management
- Add ShippingLineBookingsPage for listing and managing shipping line bookings. - Create ShippingLineDocumentsModal for document uploads related to bookings. - Introduce ShippingLineInitiateModal for initiating new shipping line bookings. - Implement booking document state management with booking-doc-state utility. - Add shipping line bookings service for API interactions. - Update index to export new components and services. - Enhance types for freight to include shipping line credits.
This commit is contained in:
@@ -257,6 +257,34 @@ const RuleEngineFormDialog = ({
|
||||
next.cargoTypeId = "";
|
||||
next.rateUnit = "";
|
||||
}
|
||||
// Turning the shipping-line toggle on or off swaps the entire form, so
|
||||
// nothing answered under the other shape may survive into the payload.
|
||||
if (name === "isShippingLineRate") {
|
||||
next.shippingLineCompanyId = "";
|
||||
next.shippingLineRateKind = "";
|
||||
next.shippingLineCargoKind = "";
|
||||
next.appliesTo = "";
|
||||
next.trigger = "";
|
||||
next.containerTypeId = "";
|
||||
next.cargoTypeId = "";
|
||||
next.originYardId = "";
|
||||
next.destinationYardId = "";
|
||||
next.rateUnit = "";
|
||||
}
|
||||
// Base-vs-surcharge and container-vs-bulk each decide the scope field and
|
||||
// the legal units for a shipping-line rate, exactly as appliesTo and
|
||||
// cargoKind do on the customer form.
|
||||
if (name === "shippingLineRateKind" || name === "shippingLineCargoKind") {
|
||||
next.containerTypeId = "";
|
||||
next.cargoTypeId = "";
|
||||
next.rateUnit = "";
|
||||
if (name === "shippingLineRateKind") {
|
||||
next.shippingLineCargoKind = "";
|
||||
next.trigger = "";
|
||||
next.originYardId = "";
|
||||
next.destinationYardId = "";
|
||||
}
|
||||
}
|
||||
return next;
|
||||
});
|
||||
};
|
||||
@@ -347,12 +375,23 @@ const RuleEngineFormDialog = ({
|
||||
borderRadius: "var(--mantine-radius-md)",
|
||||
}}
|
||||
>
|
||||
<Text size="sm" fw={600}>
|
||||
{field.label}
|
||||
</Text>
|
||||
<Stack gap={2}>
|
||||
<Text size="sm" fw={600}>
|
||||
{field.label}
|
||||
</Text>
|
||||
{field.description ? (
|
||||
<Text size="xs" c="dimmed">
|
||||
{field.description}
|
||||
</Text>
|
||||
) : null}
|
||||
</Stack>
|
||||
<Switch
|
||||
checked={Boolean(values[field.name])}
|
||||
onChange={(e) => setField(field.name, e.currentTarget.checked)}
|
||||
// A toggle that re-targets what an existing record means (e.g. who
|
||||
// a rate is priced for) is create-only — flipping it on a saved row
|
||||
// would silently change every booking that prices off it.
|
||||
disabled={field.disabled || (field.disabledOnEdit && !!initialRecord)}
|
||||
size="md"
|
||||
color="edr-green"
|
||||
/>
|
||||
@@ -493,6 +532,12 @@ const RuleEngineFormDialog = ({
|
||||
// Dynamic options (e.g. rate unit) resolve from the live form values so
|
||||
// the choices track the other fields the admin has picked.
|
||||
const options = field.optionsFromValues ? field.optionsFromValues(values) : (field.options ?? []);
|
||||
// A derived select shows (and submits) its computed value and is locked,
|
||||
// matching the text-input branch — used by fields the shape decides on the
|
||||
// admin's behalf, e.g. a shipping-line rate's import-only direction.
|
||||
const computedSelect = field.computeValue
|
||||
? String(field.computeValue(values) ?? "")
|
||||
: undefined;
|
||||
return (
|
||||
<Select
|
||||
key={field.name}
|
||||
@@ -501,9 +546,18 @@ const RuleEngineFormDialog = ({
|
||||
placeholder={
|
||||
selectOptionsLoading ? "Loading options..." : (field.placeholder ?? "Select an option")
|
||||
}
|
||||
value={resolveSelectValue(field, values)}
|
||||
value={
|
||||
computedSelect !== undefined
|
||||
? computedSelect
|
||||
: resolveSelectValue(field, values)
|
||||
}
|
||||
onChange={(v) => setField(field.name, v === RULE_ENGINE_SELECT_NONE ? "" : v)}
|
||||
disabled={selectOptionsLoading}
|
||||
disabled={
|
||||
selectOptionsLoading ||
|
||||
field.disabled ||
|
||||
(field.disabledOnEdit && !!initialRecord) ||
|
||||
computedSelect !== undefined
|
||||
}
|
||||
// Mantine's Select is not a native input, so `required` only marks it
|
||||
// visually — handleSubmit is what actually blocks an empty one.
|
||||
required={field.required}
|
||||
|
||||
Reference in New Issue
Block a user