@flowselections/mailbox-orders 1.0.64 → 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/MailboxProposalsPage.d.ts.map +1 -1
- package/dist-lib/components/MailboxProposalsPage.js +18 -12
- package/dist-lib/lib/carrier-autofill.d.ts +29 -0
- package/dist-lib/lib/carrier-autofill.d.ts.map +1 -0
- package/dist-lib/lib/carrier-autofill.js +40 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AA+HA,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD,wBAAgB,oBAAoB,gCAsgBnC"}
|
|
@@ -10,6 +10,7 @@ import { normalizeUnitKind, toPlants, describeConversion, lineTotal, UNIT_KIND_L
|
|
|
10
10
|
import { enabledLoadCarriers, normalizeAllowedLoadCarriers, EMPTY_LOAD_CARRIERS } from "../lib/load-carriers.js";
|
|
11
11
|
import { listTemplateFields, listPlantTypesForPicker, listSuppliersForPicker, } from "../lib/mailbox-template.functions.js";
|
|
12
12
|
import { SearchableSelect } from "./SearchableSelect.js";
|
|
13
|
+
import { carrierHint, decideCarrier } from "../lib/carrier-autofill.js";
|
|
13
14
|
import { AI_AUTH_PATH } from "./MailboxStatusLine.js";
|
|
14
15
|
import { listProposalsPage } from "../lib/mailbox-list.functions.js";
|
|
15
16
|
import { MailboxPageFrame, browserTz } from "./MailboxPageFrame.js";
|
|
@@ -621,19 +622,24 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
|
|
|
621
622
|
setVal("delivery_location", primary[0].id);
|
|
622
623
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
623
624
|
}, [deliveryLocationVal, deliveryLocations.length, customerVal]);
|
|
624
|
-
// Auto-vul vervoerder
|
|
625
|
-
|
|
625
|
+
// Auto-vul vervoerder: ook bij een locatie die al vaststaat bij openen.
|
|
626
|
+
// Ref pas bijwerken als de locatie echt in de geladen lijst staat.
|
|
627
|
+
const lastLocRef = useRef(null);
|
|
626
628
|
useEffect(() => {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
629
|
+
const d = decideCarrier({
|
|
630
|
+
locationId: deliveryLocationVal,
|
|
631
|
+
prevLocationId: lastLocRef.current,
|
|
632
|
+
locations: deliveryLocations,
|
|
633
|
+
carriers,
|
|
634
|
+
currentCarrier: carrierVal,
|
|
635
|
+
});
|
|
636
|
+
if (d.commitLocation !== undefined)
|
|
637
|
+
lastLocRef.current = d.commitLocation;
|
|
638
|
+
if (d.action === "set" && d.carrierId !== carrierVal)
|
|
639
|
+
setVal("carrier", d.carrierId);
|
|
635
640
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
636
|
-
}, [deliveryLocationVal, deliveryLocations.length]);
|
|
641
|
+
}, [deliveryLocationVal, deliveryLocations.length, carriers.length, carrierVal]);
|
|
642
|
+
const carrierHintKind = carrierHint(selectedLocation, carriers, carrierVal);
|
|
637
643
|
const selectedCarrier = carriers.find((c) => c.id === carrierVal) ?? null;
|
|
638
644
|
const pickupLocationVal = values["pickup_location"];
|
|
639
645
|
// ─── Ladingdragers uit de Rule Engine (nooit cachen) ──────────────────────
|
|
@@ -941,7 +947,7 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
|
|
|
941
947
|
: "Kies vervoerder...", clearLabel: "\u2014 Geen \u2014", disabled: !deliveryLocationVal, options: carriers.map((c) => ({
|
|
942
948
|
value: c.id,
|
|
943
949
|
label: c.name + (c.is_default ? " (standaard)" : ""),
|
|
944
|
-
})), onChange: (v) => setVal("carrier", v) }), selectedLocation?.carrier_id && carrierVal !== selectedLocation.carrier_id && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Wijkt af van standaard vervoerder van deze locatie \u2014 geldt alleen voor deze bestelling." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "flex items-center gap-2", children: ["Bezorgdatum ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { type: "date", value: deliveryVal ?? "", onChange: (e) => setVal("delivery_date", e.target.value || null) }), _jsx(ConfBadge, { meta: metaFor("delivery_date"), thresholds: thresholds }), !carrierVal || !deliveryLocationVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Kies een afleverlocatie en vervoerder; daarna controleren we of deze datum haalbaar is." })) : !deliveryVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "De mail noemt geen datum. Kies zelf een datum." })) : previewLoading ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Haalbaarheid controleren\u2026" })) : previewError ? (_jsxs("div", { className: "text-xs text-destructive", children: ["De haalbaarheid kon niet worden gecontroleerd: ", previewError] })) : dateFeasible ? (_jsxs("div", { className: "rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-xs text-primary", children: [fmtDate(deliveryVal), " is haalbaar.", preview?.chosen?.departureAt ? ` Ophaalmoment: ${fmtDateTime(preview.chosen.departureAt)}` : "", preview?.chosen?.signupDeadline ? ` (aanmelden tot ${fmtDateTime(preview.chosen.signupDeadline)}).` : "."] })) : (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs space-y-2", children: [_jsxs("div", { className: "text-destructive", children: [fmtDate(deliveryVal), " is niet haalbaar", preview?.reason ? `: ${preview.reason}` : "."] }), preview?.firstFeasibleDeliveryDate && preview.firstFeasibleDeliveryDate !== deliveryVal && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setVal("delivery_date", preview.firstFeasibleDeliveryDate), children: ["Gebruik ", fmtDate(preview.firstFeasibleDeliveryDate)] })), preview?.ok === true && previewKind === "late_signup" && (_jsx(LateSignupChoice, { open: lateOpen, setOpen: setLateOpen, reason: lateReason, setReason: setLateReason }))] }))] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Referentie klant" }), _jsx(Input, { value: typeof values["reference"] === "string" ? values["reference"] : "", placeholder: "Bijv. ordernummer van de klant", onChange: (e) => setVal("reference", e.target.value) }), _jsx(ConfBadge, { meta: metaFor("reference"), thresholds: thresholds })] }), otherFields.map(renderField)] }));
|
|
950
|
+
})), onChange: (v) => setVal("carrier", v) }), carrierHintKind === "location" && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Standaard vervoerder van deze locatie" })), carrierHintKind === "default" && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Algemene standaard vervoerder \u2014 controleer of dit klopt" })), selectedLocation?.carrier_id && carrierVal !== selectedLocation.carrier_id && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Wijkt af van standaard vervoerder van deze locatie \u2014 geldt alleen voor deze bestelling." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "flex items-center gap-2", children: ["Bezorgdatum ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { type: "date", value: deliveryVal ?? "", onChange: (e) => setVal("delivery_date", e.target.value || null) }), _jsx(ConfBadge, { meta: metaFor("delivery_date"), thresholds: thresholds }), !carrierVal || !deliveryLocationVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Kies een afleverlocatie en vervoerder; daarna controleren we of deze datum haalbaar is." })) : !deliveryVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "De mail noemt geen datum. Kies zelf een datum." })) : previewLoading ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Haalbaarheid controleren\u2026" })) : previewError ? (_jsxs("div", { className: "text-xs text-destructive", children: ["De haalbaarheid kon niet worden gecontroleerd: ", previewError] })) : dateFeasible ? (_jsxs("div", { className: "rounded-md border border-primary/30 bg-primary/10 px-3 py-2 text-xs text-primary", children: [fmtDate(deliveryVal), " is haalbaar.", preview?.chosen?.departureAt ? ` Ophaalmoment: ${fmtDateTime(preview.chosen.departureAt)}` : "", preview?.chosen?.signupDeadline ? ` (aanmelden tot ${fmtDateTime(preview.chosen.signupDeadline)}).` : "."] })) : (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs space-y-2", children: [_jsxs("div", { className: "text-destructive", children: [fmtDate(deliveryVal), " is niet haalbaar", preview?.reason ? `: ${preview.reason}` : "."] }), preview?.firstFeasibleDeliveryDate && preview.firstFeasibleDeliveryDate !== deliveryVal && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setVal("delivery_date", preview.firstFeasibleDeliveryDate), children: ["Gebruik ", fmtDate(preview.firstFeasibleDeliveryDate)] })), preview?.ok === true && previewKind === "late_signup" && (_jsx(LateSignupChoice, { open: lateOpen, setOpen: setLateOpen, reason: lateReason, setReason: setLateReason }))] }))] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Referentie klant" }), _jsx(Input, { value: typeof values["reference"] === "string" ? values["reference"] : "", placeholder: "Bijv. ordernummer van de klant", onChange: (e) => setVal("reference", e.target.value) }), _jsx(ConfBadge, { meta: metaFor("reference"), thresholds: thresholds })] }), otherFields.map(renderField)] }));
|
|
945
951
|
})(), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bestelregels" }), _jsxs("div", { className: "grid grid-cols-12 gap-2 text-xs text-muted-foreground px-1", children: [_jsx("div", { className: "col-span-4", children: "Product" }), _jsx("div", { className: "col-span-3", children: "Belading" }), _jsx("div", { className: "col-span-2", children: "Fusten" }), _jsx("div", { className: "col-span-2", children: "Prijs per stuk" }), _jsx("div", { className: "col-span-1 text-center", children: stickerAvailable ? "Sticker" : "" })] }), lines.map((line, idx) => {
|
|
946
952
|
const product = line.product_id ? products.find((p) => p.id === line.product_id) : null;
|
|
947
953
|
const stdBelading = defaultBelading(product);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface CarrierLocation {
|
|
2
|
+
id: string;
|
|
3
|
+
carrier_id?: string | null;
|
|
4
|
+
}
|
|
5
|
+
export interface CarrierOption {
|
|
6
|
+
id: string;
|
|
7
|
+
is_default?: boolean | null;
|
|
8
|
+
}
|
|
9
|
+
export type CarrierSource = "location" | "default" | null;
|
|
10
|
+
export interface CarrierDecision {
|
|
11
|
+
/** wait = niets doen en ref niet bijwerken; keep = niets wijzigen; set = carrierId invullen (null = leegmaken). */
|
|
12
|
+
action: "wait" | "keep" | "set";
|
|
13
|
+
carrierId: string | null;
|
|
14
|
+
source: CarrierSource;
|
|
15
|
+
/** Nieuwe waarde voor de "vorige locatie"-ref, of undefined als die niet mag wijzigen. */
|
|
16
|
+
commitLocation: string | null | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** Alleen een standaard als precies één vervoerder is_default = true heeft. */
|
|
19
|
+
export declare function uniqueDefaultCarrier(carriers: CarrierOption[]): string | null;
|
|
20
|
+
export declare function decideCarrier(input: {
|
|
21
|
+
locationId: string | null;
|
|
22
|
+
prevLocationId: string | null;
|
|
23
|
+
locations: CarrierLocation[];
|
|
24
|
+
carriers: CarrierOption[];
|
|
25
|
+
currentCarrier: string | null;
|
|
26
|
+
}): CarrierDecision;
|
|
27
|
+
/** Grijze hulptekst onder het veld. */
|
|
28
|
+
export declare function carrierHint(location: CarrierLocation | null, carriers: CarrierOption[], carrierId: string | null): "location" | "default" | "differs" | null;
|
|
29
|
+
//# sourceMappingURL=carrier-autofill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carrier-autofill.d.ts","sourceRoot":"","sources":["../../src/lib/carrier-autofill.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,mHAAmH;IACnH,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,0FAA0F;IAC1F,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC3C;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,GAAG,IAAI,CAG7E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,GAAG,eAAe,CA0BlB;AAED,uCAAuC;AACvC,wBAAgB,WAAW,CACzB,QAAQ,EAAE,eAAe,GAAG,IAAI,EAChC,QAAQ,EAAE,aAAa,EAAE,EACzB,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAI3C"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Bepaalt of het veld "Vervoerder" automatisch ingevuld moet worden op basis
|
|
2
|
+
// van de gekozen afleverlocatie. Pure functie: geen React, geen servercode.
|
|
3
|
+
/** Alleen een standaard als precies één vervoerder is_default = true heeft. */
|
|
4
|
+
export function uniqueDefaultCarrier(carriers) {
|
|
5
|
+
const defs = carriers.filter((c) => c.is_default === true);
|
|
6
|
+
return defs.length === 1 ? defs[0].id : null;
|
|
7
|
+
}
|
|
8
|
+
export function decideCarrier(input) {
|
|
9
|
+
const { locationId, prevLocationId, locations, carriers, currentCarrier } = input;
|
|
10
|
+
if (!locationId) {
|
|
11
|
+
if (!prevLocationId)
|
|
12
|
+
return { action: "wait", carrierId: null, source: null, commitLocation: undefined };
|
|
13
|
+
return { action: "set", carrierId: null, source: null, commitLocation: null };
|
|
14
|
+
}
|
|
15
|
+
const loc = locations.find((l) => l.id === locationId);
|
|
16
|
+
if (!loc)
|
|
17
|
+
return { action: "wait", carrierId: null, source: null, commitLocation: undefined };
|
|
18
|
+
const own = loc.carrier_id || null;
|
|
19
|
+
if (!own && carriers.length === 0) {
|
|
20
|
+
return { action: "wait", carrierId: null, source: null, commitLocation: undefined };
|
|
21
|
+
}
|
|
22
|
+
const def = own ? null : uniqueDefaultCarrier(carriers);
|
|
23
|
+
const target = own ?? def;
|
|
24
|
+
const source = own ? "location" : def ? "default" : null;
|
|
25
|
+
const changed = prevLocationId !== null && prevLocationId !== locationId;
|
|
26
|
+
if (changed)
|
|
27
|
+
return { action: "set", carrierId: target, source, commitLocation: locationId };
|
|
28
|
+
// Zelfde locatie of eerste keer na openen: alleen invullen als het veld leeg is.
|
|
29
|
+
if (!currentCarrier && target)
|
|
30
|
+
return { action: "set", carrierId: target, source, commitLocation: locationId };
|
|
31
|
+
return { action: "keep", carrierId: currentCarrier, source: null, commitLocation: locationId };
|
|
32
|
+
}
|
|
33
|
+
/** Grijze hulptekst onder het veld. */
|
|
34
|
+
export function carrierHint(location, carriers, carrierId) {
|
|
35
|
+
if (!location || !carrierId)
|
|
36
|
+
return null;
|
|
37
|
+
if (location.carrier_id)
|
|
38
|
+
return carrierId === location.carrier_id ? "location" : "differs";
|
|
39
|
+
return carrierId === uniqueDefaultCarrier(carriers) ? "default" : null;
|
|
40
|
+
}
|