@metron-labs/quote-react 0.1.30 → 0.1.32
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/LICENSE +31 -31
- package/README.md +253 -253
- package/dist/app/QuickQuote.js +16 -7
- package/dist/app/stages/ScheduleResultsStage.js +13 -2
- package/dist/embed/quote.js +6775 -6775
- package/dist/lib/cart/CartContext.d.ts +1 -0
- package/dist/lib/cart/CartContext.js +42 -1
- package/dist/lib/productImage.js +19 -19
- package/dist/styles.css +6766 -6766
- package/dist/util/pricing.js +3 -1
- package/dist/util/types.d.ts +4 -0
- package/package.json +53 -53
|
@@ -13,6 +13,7 @@ interface CartApi {
|
|
|
13
13
|
/** Show the basket. Each app decides what that means for its own navigation. */
|
|
14
14
|
openBasket: () => void;
|
|
15
15
|
}
|
|
16
|
+
export declare function refreshLinkedDependents(cart: Record<string, CartItem>, anchorItem: CartItem): Record<string, CartItem>;
|
|
16
17
|
/**
|
|
17
18
|
* One basket per app. BoQApp and EstimatingToolsApp each mount their own provider, so a
|
|
18
19
|
* quote in progress and a set of calculator results stay separate - this only shares the
|
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { createContext, useCallback, useContext, useMemo, useState } from "react";
|
|
4
|
+
export function refreshLinkedDependents(cart, anchorItem) {
|
|
5
|
+
const next = { ...cart, [anchorItem.lineId]: anchorItem };
|
|
6
|
+
for (const [lineId, dependent] of Object.entries(next)) {
|
|
7
|
+
if (!dependent.linkedContext)
|
|
8
|
+
continue;
|
|
9
|
+
const anchor = dependent.linkedContext.find((context) => context.role === "anchor" && context.line_id && next[context.line_id]);
|
|
10
|
+
const selectedAnchor = anchor?.line_id ? next[anchor.line_id] : undefined;
|
|
11
|
+
if (!anchor || !selectedAnchor || (anchor.product_id === selectedAnchor.productId && anchor.description === selectedAnchor.description))
|
|
12
|
+
continue;
|
|
13
|
+
// Only quantities inferred from the selected anchor should be invalidated.
|
|
14
|
+
// Explicit dependent requests (for example "30m tracks") must survive.
|
|
15
|
+
if (dependent.conversionType !== "basket_line_unit") {
|
|
16
|
+
next[lineId] = {
|
|
17
|
+
...dependent,
|
|
18
|
+
linkedContext: dependent.linkedContext.map((context) => context.line_id === anchor.line_id
|
|
19
|
+
? { ...context, product_id: selectedAnchor.productId, measurements_mm: selectedAnchor.measurementsMm ?? [], description: selectedAnchor.description }
|
|
20
|
+
: context),
|
|
21
|
+
};
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
next[lineId] = {
|
|
25
|
+
...dependent,
|
|
26
|
+
qty: 0,
|
|
27
|
+
sellUnitsOverride: null,
|
|
28
|
+
linkedContext: dependent.linkedContext.map((context) => context.line_id === anchor.line_id
|
|
29
|
+
? { ...context, product_id: selectedAnchor.productId, measurements_mm: selectedAnchor.measurementsMm ?? [], description: selectedAnchor.description }
|
|
30
|
+
: context),
|
|
31
|
+
conversionType: null,
|
|
32
|
+
requestUomsSupported: null,
|
|
33
|
+
salesUomNormalised: null,
|
|
34
|
+
salesUnitSize: null,
|
|
35
|
+
salesUnitSizeUom: null,
|
|
36
|
+
coverageQty: null,
|
|
37
|
+
coverageUom: null,
|
|
38
|
+
roundingRule: null,
|
|
39
|
+
conversionConfidence: null,
|
|
40
|
+
conversionNotes: null,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return next;
|
|
44
|
+
}
|
|
4
45
|
const CartContext = createContext(null);
|
|
5
46
|
/**
|
|
6
47
|
* One basket per app. BoQApp and EstimatingToolsApp each mount their own provider, so a
|
|
@@ -10,7 +51,7 @@ const CartContext = createContext(null);
|
|
|
10
51
|
export function CartProvider({ children, onOpenBasket }) {
|
|
11
52
|
const [cart, setCart] = useState({});
|
|
12
53
|
const addToCart = useCallback((item) => {
|
|
13
|
-
setCart((prev) => (
|
|
54
|
+
setCart((prev) => refreshLinkedDependents(prev, item));
|
|
14
55
|
}, []);
|
|
15
56
|
const addManyToCart = useCallback((items) => {
|
|
16
57
|
setCart((prev) => {
|
package/dist/lib/productImage.js
CHANGED
|
@@ -50,26 +50,26 @@ export function productImageSrc(description, productId, pdpPhotoUrl) {
|
|
|
50
50
|
if (photo)
|
|
51
51
|
return assetUrl(photo.path);
|
|
52
52
|
if (text.includes("insulation")) {
|
|
53
|
-
return encodeSvg(`
|
|
54
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
55
|
-
<rect width="640" height="420" fill="#fbf1cf"/>
|
|
56
|
-
<rect x="88" y="78" width="432" height="264" rx="16" fill="#f0c43f"/>
|
|
57
|
-
<rect x="120" y="110" width="368" height="200" rx="10" fill="#ffd95e"/>
|
|
58
|
-
<g stroke="#e2b12e" stroke-width="8" opacity="0.75">
|
|
59
|
-
<line x1="140" y1="140" x2="468" y2="140"/>
|
|
60
|
-
<line x1="140" y1="190" x2="468" y2="190"/>
|
|
61
|
-
<line x1="140" y1="240" x2="468" y2="240"/>
|
|
62
|
-
</g>
|
|
63
|
-
</svg>
|
|
53
|
+
return encodeSvg(`
|
|
54
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
55
|
+
<rect width="640" height="420" fill="#fbf1cf"/>
|
|
56
|
+
<rect x="88" y="78" width="432" height="264" rx="16" fill="#f0c43f"/>
|
|
57
|
+
<rect x="120" y="110" width="368" height="200" rx="10" fill="#ffd95e"/>
|
|
58
|
+
<g stroke="#e2b12e" stroke-width="8" opacity="0.75">
|
|
59
|
+
<line x1="140" y1="140" x2="468" y2="140"/>
|
|
60
|
+
<line x1="140" y1="190" x2="468" y2="190"/>
|
|
61
|
+
<line x1="140" y1="240" x2="468" y2="240"/>
|
|
62
|
+
</g>
|
|
63
|
+
</svg>
|
|
64
64
|
`);
|
|
65
65
|
}
|
|
66
|
-
return encodeSvg(`
|
|
67
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
68
|
-
<rect width="640" height="420" fill="#edf1f5"/>
|
|
69
|
-
<rect x="132" y="108" width="376" height="204" rx="18" fill="#d5dde6"/>
|
|
70
|
-
<rect x="168" y="144" width="304" height="24" rx="12" fill="#9aa6b2"/>
|
|
71
|
-
<rect x="168" y="188" width="250" height="24" rx="12" fill="#aab5c0"/>
|
|
72
|
-
<rect x="168" y="232" width="220" height="24" rx="12" fill="#aab5c0"/>
|
|
73
|
-
</svg>
|
|
66
|
+
return encodeSvg(`
|
|
67
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
68
|
+
<rect width="640" height="420" fill="#edf1f5"/>
|
|
69
|
+
<rect x="132" y="108" width="376" height="204" rx="18" fill="#d5dde6"/>
|
|
70
|
+
<rect x="168" y="144" width="304" height="24" rx="12" fill="#9aa6b2"/>
|
|
71
|
+
<rect x="168" y="188" width="250" height="24" rx="12" fill="#aab5c0"/>
|
|
72
|
+
<rect x="168" y="232" width="220" height="24" rx="12" fill="#aab5c0"/>
|
|
73
|
+
</svg>
|
|
74
74
|
`);
|
|
75
75
|
}
|