mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 13:28:11 +00:00
feat(rates): multi-tier distance band entry in last-mile rate form
- tierList field type in rule-engine form dialog (add/remove rows, overlap + open-ended validation, From km auto-continues) - create submits one rate row per tier sequentially - editing a band row keeps the single From/To/value form
This commit is contained in:
@@ -306,7 +306,34 @@ const RuleEngineResourcePage = () => {
|
||||
|
||||
const formFields = useMemo(() => {
|
||||
if (!config) return [];
|
||||
return config.formFields.map((field) => {
|
||||
// Last-mile container bands: creating uses the multi-row tier list (one
|
||||
// rate per tier); editing an existing band row keeps the single
|
||||
// From/To/value fields (a rate row IS one band).
|
||||
const bandFields = config.formFields.filter((field) => {
|
||||
if (config.slug !== "rates") return true;
|
||||
if (field.type === "tierList") return !editing;
|
||||
if (editing) return true;
|
||||
return field.name !== "minKm" && field.name !== "maxKm";
|
||||
});
|
||||
return bandFields.map((field) => {
|
||||
// On create, the tier rows carry the per-band rate values — the single
|
||||
// last-mile "Rate value" field then only applies to bulk mode.
|
||||
if (
|
||||
config.slug === "rates" &&
|
||||
!editing &&
|
||||
field.name === "rateValue" &&
|
||||
field.showWhen?.field === "appliesTo" &&
|
||||
field.showWhen.equals.includes("LAST_MILE")
|
||||
) {
|
||||
return {
|
||||
...field,
|
||||
showWhen: undefined,
|
||||
showIf: (values: Record<string, unknown>) =>
|
||||
values.appliesTo === "LAST_MILE" && values.lastMileMode === "BULK",
|
||||
};
|
||||
}
|
||||
return field;
|
||||
}).map((field) => {
|
||||
if (isPriorityRules && field.name === "minWagonCount") {
|
||||
return {
|
||||
...field,
|
||||
@@ -624,6 +651,31 @@ const RuleEngineResourcePage = () => {
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Container-mode create: the tier list becomes one rate row per tier,
|
||||
// created sequentially so an overlap/duplicate rejection stops the batch
|
||||
// with its own toast instead of half-failing in parallel.
|
||||
const tiers = (
|
||||
payload as {
|
||||
tiers?: Array<{ minKm: number; maxKm: number | null; rateValue: number }>;
|
||||
}
|
||||
).tiers;
|
||||
if (!editing?.id && Array.isArray(tiers)) {
|
||||
const { tiers: _omitted, ...base } = payload as Record<string, unknown>;
|
||||
void _omitted;
|
||||
void (async () => {
|
||||
try {
|
||||
for (const tier of tiers) {
|
||||
await create.mutateAsync({ ...base, ...tier });
|
||||
}
|
||||
setFormOpen(false);
|
||||
setEditing(null);
|
||||
} catch {
|
||||
// The create mutation already toasted the failure; keep the dialog
|
||||
// open so the admin can fix the tier set and retry.
|
||||
}
|
||||
})();
|
||||
return;
|
||||
}
|
||||
} else if (isPriorityRules) {
|
||||
// Label is required by the backend but hidden in the UI for now.
|
||||
payload = { ...values, label: String(Date.now()) };
|
||||
|
||||
Reference in New Issue
Block a user