thm-p3-configurator 0.0.441 → 0.0.443
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/src/shared/__api__/__tests__/queryKeyFactory.test.js +26 -0
- package/dist/src/shared/__api__/queries.js +9 -4
- package/dist/src/shared/__api__/queryKeyFactory.js +10 -5
- package/dist/src/shared/__components__/ProductCard/index.js +4 -1
- package/dist/src/shared/__components__/SingleOrderCartCard.js +8 -2
- package/dist/src/shared/__components__/SingleOrderProductCard.js +43 -16
- package/dist/src/shared/__containers__/AppointmentForm.js +6 -3
- package/dist/src/shared/__containers__/ExitIntentModal.js +6 -3
- package/dist/src/shared/__containers__/ProductCartSide.js +5 -2
- package/dist/src/shared/__containers__/ProductsCartOverview.js +5 -5
- package/dist/src/shared/__containers__/ProductsOverview.js +3 -1
- package/dist/src/shared/__containers__/QuotationForm.js +6 -3
- package/dist/src/shared/__containers__/internal/InternalAppointmentForm.js +6 -3
- package/dist/src/shared/__containers__/internal/InternalQuotationForm.js +6 -3
- package/dist/src/shared/__containers__/internal/InternalSingleOrderCart.js +13 -6
- package/dist/src/shared/__containers__/internal/InternalSingleOrderProductOverview.js +3 -3
- package/dist/src/shared/__helpers__/__tests__/product.test.js +11 -0
- package/dist/src/shared/__helpers__/__tests__/singleOrderArticleRules.test.js +82 -0
- package/dist/src/shared/__helpers__/product.js +30 -14
- package/dist/src/shared/__helpers__/singleOrderArticleRules.js +54 -0
- package/dist/src/shared/__helpers__/singleOrderArticles.js +4 -1
- package/dist/src/shared/__style__/components/card/_card-horizontal.scss +6 -0
- package/package.json +1 -1
|
@@ -82,6 +82,32 @@ describe('queryKeyFactory', () => {
|
|
|
82
82
|
extraPriceAmount: null
|
|
83
83
|
})).toBe('licensePlate=12AB34&formula=THC');
|
|
84
84
|
});
|
|
85
|
+
|
|
86
|
+
// Hyper adds the board-computer update when selectBoardComputerUpdate is
|
|
87
|
+
// absent, so an opt-out only survives when the false is serialized
|
|
88
|
+
it('keeps selectBoardComputerUpdate for both true and false', () => {
|
|
89
|
+
expect((0, _queryKeyFactory.serializeOrderParams)({
|
|
90
|
+
licensePlate: '12AB34',
|
|
91
|
+
formula: 'THC',
|
|
92
|
+
selectBoardComputerUpdate: false
|
|
93
|
+
})).toBe('licensePlate=12AB34&formula=THC&selectBoardComputerUpdate=false');
|
|
94
|
+
expect((0, _queryKeyFactory.serializeOrderParams)({
|
|
95
|
+
licensePlate: '12AB34',
|
|
96
|
+
formula: 'THC',
|
|
97
|
+
selectBoardComputerUpdate: true
|
|
98
|
+
})).toBe('licensePlate=12AB34&formula=THC&selectBoardComputerUpdate=true');
|
|
99
|
+
});
|
|
100
|
+
it('gives opting in and opting out of the board computer distinct query keys', () => {
|
|
101
|
+
expect((0, _queryKeyFactory.getOrderQueryKey)({
|
|
102
|
+
licensePlate: '12AB34',
|
|
103
|
+
formula: 'THC',
|
|
104
|
+
selectBoardComputerUpdate: true
|
|
105
|
+
})).not.toEqual((0, _queryKeyFactory.getOrderQueryKey)({
|
|
106
|
+
licensePlate: '12AB34',
|
|
107
|
+
formula: 'THC',
|
|
108
|
+
selectBoardComputerUpdate: false
|
|
109
|
+
}));
|
|
110
|
+
});
|
|
85
111
|
it('builds order query keys from serialized order params', () => {
|
|
86
112
|
expect((0, _queryKeyFactory.getOrderQueryKey)({
|
|
87
113
|
licensePlate: '12AB34',
|
|
@@ -41,6 +41,7 @@ var _OrderSessionContext = require("../__context__/OrderSessionContext");
|
|
|
41
41
|
var _usePricingFormula = require("../__hooks__/usePricingFormula");
|
|
42
42
|
var _helpers__ = require("../__helpers__");
|
|
43
43
|
var _singleOrderArticles = require("../__helpers__/singleOrderArticles");
|
|
44
|
+
var _singleOrderArticleRules = require("../__helpers__/singleOrderArticleRules");
|
|
44
45
|
var _singleOrderCartArticles = require("../__helpers__/singleOrderCartArticles");
|
|
45
46
|
var _product = require("../__helpers__/product");
|
|
46
47
|
var _useSessionContextReady = require("../__hooks__/useSessionContextReady");
|
|
@@ -423,7 +424,8 @@ const useSingleOrderCart = () => {
|
|
|
423
424
|
return {
|
|
424
425
|
articles: [],
|
|
425
426
|
totals: emptyTotals,
|
|
426
|
-
validationError: null
|
|
427
|
+
validationError: null,
|
|
428
|
+
hasQuantityErrors: false
|
|
427
429
|
};
|
|
428
430
|
}
|
|
429
431
|
|
|
@@ -458,7 +460,8 @@ const useSingleOrderCart = () => {
|
|
|
458
460
|
totalExclVat: Math.round(totalExclVat * 100) / 100,
|
|
459
461
|
totalInclVat: Math.round(totalInclVat * 100) / 100
|
|
460
462
|
},
|
|
461
|
-
validationError: null
|
|
463
|
+
validationError: null,
|
|
464
|
+
hasQuantityErrors: (0, _singleOrderArticleRules.hasSingleOrderQuantityErrors)(articlesWithPrice)
|
|
462
465
|
};
|
|
463
466
|
}
|
|
464
467
|
|
|
@@ -486,7 +489,8 @@ const useSingleOrderCart = () => {
|
|
|
486
489
|
return {
|
|
487
490
|
articles: [],
|
|
488
491
|
totals: emptyTotals,
|
|
489
|
-
validationError
|
|
492
|
+
validationError,
|
|
493
|
+
hasQuantityErrors: false
|
|
490
494
|
};
|
|
491
495
|
}
|
|
492
496
|
const articleLookup = await fetchCartArticleLookup(cart.map(article => article.articleNumber), singleOrderFormula);
|
|
@@ -518,7 +522,8 @@ const useSingleOrderCart = () => {
|
|
|
518
522
|
totalExclVat: Math.round(totalExclVat * 100) / 100,
|
|
519
523
|
totalInclVat: Math.round(totalInclVat * 100) / 100
|
|
520
524
|
},
|
|
521
|
-
validationError
|
|
525
|
+
validationError,
|
|
526
|
+
hasQuantityErrors: (0, _singleOrderArticleRules.hasSingleOrderQuantityErrors)(articlesWithPrice)
|
|
522
527
|
};
|
|
523
528
|
}
|
|
524
529
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
require("core-js/modules/es.array.includes.js");
|
|
3
4
|
require("core-js/modules/es.array.reduce.js");
|
|
4
5
|
require("core-js/modules/es.array.sort.js");
|
|
5
6
|
require("core-js/modules/es.json.stringify.js");
|
|
@@ -15,6 +16,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
15
16
|
value: true
|
|
16
17
|
});
|
|
17
18
|
exports.serializeOrderParams = exports.normalizeOrderParams = exports.getSingleOrderArticlesKey = exports.getOrderQueryKey = exports.getBuildYearsQueryKey = exports.getBrandsQueryKey = void 0;
|
|
19
|
+
require("core-js/modules/es.array.includes.js");
|
|
18
20
|
require("core-js/modules/es.array.reduce.js");
|
|
19
21
|
require("core-js/modules/es.array.sort.js");
|
|
20
22
|
require("core-js/modules/es.json.stringify.js");
|
|
@@ -77,11 +79,17 @@ const removeNullishEntries = function removeNullishEntries() {
|
|
|
77
79
|
return entryValue != null;
|
|
78
80
|
}));
|
|
79
81
|
};
|
|
82
|
+
|
|
83
|
+
// Hyper adds the board-computer update to the cart whenever
|
|
84
|
+
// selectBoardComputerUpdate is absent, so an explicit false has to survive
|
|
85
|
+
// serialization. Every other empty-ish value still drops out of the canonical
|
|
86
|
+
// URL, so variant client URLs keep collapsing to one Hyper URL.
|
|
87
|
+
const ORDER_PARAMS_KEPT_WHEN_FALSE = ['selectBoardComputerUpdate'];
|
|
80
88
|
const removeLegacyEmptyOrderEntries = function removeLegacyEmptyOrderEntries() {
|
|
81
89
|
let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
82
90
|
return Object.fromEntries(Object.entries(value).filter(_ref2 => {
|
|
83
|
-
let [, entryValue] = _ref2;
|
|
84
|
-
return Boolean(entryValue);
|
|
91
|
+
let [key, entryValue] = _ref2;
|
|
92
|
+
return Boolean(entryValue) || entryValue === false && ORDER_PARAMS_KEPT_WHEN_FALSE.includes(key);
|
|
85
93
|
}));
|
|
86
94
|
};
|
|
87
95
|
const sortObjectKeys = function sortObjectKeys() {
|
|
@@ -98,9 +106,6 @@ const normalizeOrderParams = exports.normalizeOrderParams = function normalizeOr
|
|
|
98
106
|
normalizedParams.constructionYear = normalizedParams.buildYear;
|
|
99
107
|
delete normalizedParams.buildYear;
|
|
100
108
|
}
|
|
101
|
-
if (normalizedParams.selectBoardComputerUpdate === false || normalizedParams.selectBoardComputerUpdate === 'false') {
|
|
102
|
-
delete normalizedParams.selectBoardComputerUpdate;
|
|
103
|
-
}
|
|
104
109
|
if (Array.isArray(normalizedParams.cart) && normalizedParams.cart.length === 0) {
|
|
105
110
|
delete normalizedParams.cart;
|
|
106
111
|
}
|
|
@@ -109,6 +109,7 @@ const ProductCard = _ref => {
|
|
|
109
109
|
isRecommended = false,
|
|
110
110
|
productId,
|
|
111
111
|
productTitle,
|
|
112
|
+
productOrientation,
|
|
112
113
|
productDescription,
|
|
113
114
|
stock = null,
|
|
114
115
|
productUsps = [],
|
|
@@ -186,7 +187,9 @@ const ProductCard = _ref => {
|
|
|
186
187
|
}, /*#__PURE__*/_react.default.createElement(_ProductCardPrice.default, {
|
|
187
188
|
price: productDiscountedPrice < productPrice ? productPrice : productDiscountedPrice,
|
|
188
189
|
discountedPrice: productDiscountedPrice < productPrice ? productDiscountedPrice : productPrice
|
|
189
|
-
}))), /*#__PURE__*/_react.default.createElement("
|
|
190
|
+
}))), productOrientation && /*#__PURE__*/_react.default.createElement("p", {
|
|
191
|
+
className: (0, _helpers__.withStyle)('card-title__orientation')
|
|
192
|
+
}, /*#__PURE__*/_react.default.createElement("strong", null, productOrientation)), /*#__PURE__*/_react.default.createElement("div", {
|
|
190
193
|
className: (0, _helpers__.withStyle)('card-text row no-gutters flex-wrap align-items-bottom justify-content-start')
|
|
191
194
|
}, /*#__PURE__*/_react.default.createElement(_ProductCardUsps.default, {
|
|
192
195
|
usps: productUsps
|
|
@@ -8,6 +8,7 @@ exports.default = void 0;
|
|
|
8
8
|
require("core-js/modules/es.number.to-fixed.js");
|
|
9
9
|
var _react = _interopRequireDefault(require("react"));
|
|
10
10
|
var _helpers__ = require("../__helpers__");
|
|
11
|
+
var _singleOrderArticleRules = require("../__helpers__/singleOrderArticleRules");
|
|
11
12
|
var _LinkButton = _interopRequireDefault(require("./Buttons/LinkButton"));
|
|
12
13
|
var _NumericInput = _interopRequireDefault(require("./Form/NumericInput"));
|
|
13
14
|
function _interopRequireDefault(e) {
|
|
@@ -43,8 +44,10 @@ const SingleOrderCartCard = _ref2 => {
|
|
|
43
44
|
productBrandNumber,
|
|
44
45
|
quantity = 0,
|
|
45
46
|
handleQuantityChange,
|
|
46
|
-
removeFromCart
|
|
47
|
+
removeFromCart,
|
|
48
|
+
orderRules
|
|
47
49
|
} = _ref2;
|
|
50
|
+
const quantityError = (0, _singleOrderArticleRules.getSingleOrderQuantityError)(quantity, orderRules);
|
|
48
51
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
49
52
|
key: "".concat(productId, "-").concat(Date.now()),
|
|
50
53
|
className: (0, _helpers__.withStyle)('w-100 mb-3')
|
|
@@ -69,11 +72,14 @@ const SingleOrderCartCard = _ref2 => {
|
|
|
69
72
|
width: "100px",
|
|
70
73
|
height: "40px",
|
|
71
74
|
defaultValue: quantity,
|
|
75
|
+
max: 9999,
|
|
72
76
|
onChange: value => handleQuantityChange(productId, value, productPriceExclVat, productPriceInclVat, productBrandNumber),
|
|
73
77
|
buttonTransformY: 40
|
|
74
78
|
}), /*#__PURE__*/_react.default.createElement(_LinkButton.default, {
|
|
75
79
|
label: "Verwijder",
|
|
76
80
|
onClick: () => removeFromCart(productId)
|
|
77
|
-
}))
|
|
81
|
+
})), quantityError && /*#__PURE__*/_react.default.createElement("small", {
|
|
82
|
+
className: (0, _helpers__.withStyle)('text-danger mt-1')
|
|
83
|
+
}, quantityError)))));
|
|
78
84
|
};
|
|
79
85
|
var _default = exports.default = SingleOrderCartCard;
|
|
@@ -31,6 +31,7 @@ var _queries = require("../__api__/queries");
|
|
|
31
31
|
var _NumericInput = _interopRequireDefault(require("../__components__/Form/NumericInput"));
|
|
32
32
|
var _constants__ = require("../__constants__");
|
|
33
33
|
var _helpers__ = require("../__helpers__");
|
|
34
|
+
var _singleOrderArticleRules = require("../__helpers__/singleOrderArticleRules");
|
|
34
35
|
var _singleOrderArticles = require("../__helpers__/singleOrderArticles");
|
|
35
36
|
var _OutlinedButton = _interopRequireDefault(require("./Buttons/OutlinedButton"));
|
|
36
37
|
var _PrimaryButton = _interopRequireDefault(require("./Buttons/PrimaryButton"));
|
|
@@ -139,13 +140,16 @@ const ProductActions = _ref2 => {
|
|
|
139
140
|
productBrandNumber,
|
|
140
141
|
hasPreferredPart = false,
|
|
141
142
|
isWebshop = false,
|
|
142
|
-
isLoadingPartStockLevel = false
|
|
143
|
+
isLoadingPartStockLevel = false,
|
|
144
|
+
quantityError
|
|
143
145
|
} = _ref2;
|
|
144
146
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
145
147
|
className: (0, _helpers__.withStyle)('d-flex justify-content-end')
|
|
146
148
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
147
149
|
className: (0, _helpers__.withStyle)('d-flex flex-column align-items-end')
|
|
148
|
-
},
|
|
150
|
+
}, quantityError && /*#__PURE__*/_react.default.createElement("div", {
|
|
151
|
+
className: (0, _helpers__.withStyle)('text-danger mb-1')
|
|
152
|
+
}, quantityError), !isWebshop && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isOutOfStock ? /*#__PURE__*/_react.default.createElement("div", {
|
|
149
153
|
className: (0, _helpers__.withStyle)('text-danger mb-1')
|
|
150
154
|
}, "Niet op voorraad") : stockStatus === _constants__.StockStatus.InsufficientStock ? /*#__PURE__*/_react.default.createElement("div", {
|
|
151
155
|
className: (0, _helpers__.withStyle)('text-warning mb-1')
|
|
@@ -165,6 +169,7 @@ const ProductActions = _ref2 => {
|
|
|
165
169
|
width: "100px",
|
|
166
170
|
height: "55px",
|
|
167
171
|
defaultValue: quantity,
|
|
172
|
+
max: 9999,
|
|
168
173
|
onChange: value => handleQuantityChange(productId, value, productPrice, productPriceInclVat, productBrandNumber),
|
|
169
174
|
buttonTransformY: 40
|
|
170
175
|
}), quantity === 0 ? /*#__PURE__*/_react.default.createElement(_PrimaryButton.default, {
|
|
@@ -204,7 +209,22 @@ const ProductCategories = _ref3 => {
|
|
|
204
209
|
className: (0, _helpers__.withStyle)(partStockLevels.status === _constants__.StockStatus.OutOfStock ? 'text-danger' : partStockLevels.status === _constants__.StockStatus.InsufficientStock ? 'text-warning' : 'text-success')
|
|
205
210
|
}, partStockLevels.status === _constants__.StockStatus.OutOfStock ? 'Niet op voorraad' : partStockLevels.status === _constants__.StockStatus.InsufficientStock ? 'Weinig op voorraad' : 'Op voorraad'), partStockLevels.quantity ? /*#__PURE__*/_react.default.createElement("small", null, ": ".concat(partStockLevels.quantity)) : ''));
|
|
206
211
|
};
|
|
207
|
-
const
|
|
212
|
+
const SingleOrderOrderRules = _ref4 => {
|
|
213
|
+
let {
|
|
214
|
+
rules
|
|
215
|
+
} = _ref4;
|
|
216
|
+
const ruleLines = (0, _singleOrderArticleRules.describeSingleOrderArticleRules)(rules);
|
|
217
|
+
if (!ruleLines.length) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
221
|
+
className: (0, _helpers__.withStyle)('mt-2')
|
|
222
|
+
}, ruleLines.map(ruleLine => /*#__PURE__*/_react.default.createElement("p", {
|
|
223
|
+
key: ruleLine,
|
|
224
|
+
className: (0, _helpers__.withStyle)('fw-bold mb-0')
|
|
225
|
+
}, ruleLine)));
|
|
226
|
+
};
|
|
227
|
+
const SingleOrderProductCard = _ref5 => {
|
|
208
228
|
let {
|
|
209
229
|
productId,
|
|
210
230
|
isSelected,
|
|
@@ -232,8 +252,10 @@ const SingleOrderProductCard = _ref4 => {
|
|
|
232
252
|
parts = [],
|
|
233
253
|
branchId,
|
|
234
254
|
brandName = null,
|
|
235
|
-
isWebshop = false
|
|
236
|
-
|
|
255
|
+
isWebshop = false,
|
|
256
|
+
productDescription,
|
|
257
|
+
orderRules
|
|
258
|
+
} = _ref5;
|
|
237
259
|
const {
|
|
238
260
|
productFieldLabels
|
|
239
261
|
} = (0, _queries.useProductFieldLabels)();
|
|
@@ -250,12 +272,12 @@ const SingleOrderProductCard = _ref4 => {
|
|
|
250
272
|
return typeof (part === null || part === void 0 ? void 0 : part.preferredPart) === 'string' ? (_part$preferredPart$s = part.preferredPart.split('|')[0]) === null || _part$preferredPart$s === void 0 ? void 0 : _part$preferredPart$s.trim() : null;
|
|
251
273
|
};
|
|
252
274
|
const getPreferredPartNumber = part => {
|
|
253
|
-
var
|
|
254
|
-
return (
|
|
275
|
+
var _ref6, _ref7, _ref8, _part$articleNumber;
|
|
276
|
+
return (_ref6 = (_ref7 = (_ref8 = (_part$articleNumber = part === null || part === void 0 ? void 0 : part.articleNumber) !== null && _part$articleNumber !== void 0 ? _part$articleNumber : part === null || part === void 0 ? void 0 : part.partArticleNumber) !== null && _ref8 !== void 0 ? _ref8 : part === null || part === void 0 ? void 0 : part.preferredPartNumber) !== null && _ref7 !== void 0 ? _ref7 : part === null || part === void 0 ? void 0 : part.partNumber) !== null && _ref6 !== void 0 ? _ref6 : getPreferredPartDisplayArticleNumber(part);
|
|
255
277
|
};
|
|
256
278
|
const getPreferredPartBrandNumber = part => {
|
|
257
|
-
var
|
|
258
|
-
return (
|
|
279
|
+
var _ref9, _ref10, _ref11, _ref12, _part$articleBrandNum;
|
|
280
|
+
return (_ref9 = (_ref10 = (_ref11 = (_ref12 = (_part$articleBrandNum = part === null || part === void 0 ? void 0 : part.articleBrandNumber) !== null && _part$articleBrandNum !== void 0 ? _part$articleBrandNum : part === null || part === void 0 ? void 0 : part.partArticleBrandNumber) !== null && _ref12 !== void 0 ? _ref12 : part === null || part === void 0 ? void 0 : part.preferredPartBrandNumber) !== null && _ref11 !== void 0 ? _ref11 : part === null || part === void 0 ? void 0 : part.partBrandNumber) !== null && _ref10 !== void 0 ? _ref10 : part === null || part === void 0 ? void 0 : part.brandNumber) !== null && _ref9 !== void 0 ? _ref9 : part === null || part === void 0 ? void 0 : part.partBrandId;
|
|
259
281
|
};
|
|
260
282
|
(0, _react.useEffect)(() => {
|
|
261
283
|
if (showPartStockLevel && preferredPart) {
|
|
@@ -289,17 +311,17 @@ const SingleOrderProductCard = _ref4 => {
|
|
|
289
311
|
setPartStockLevels(null);
|
|
290
312
|
}
|
|
291
313
|
}, [parts]);
|
|
292
|
-
const filteredProductSpecifications = productSpecifications.filter(
|
|
314
|
+
const filteredProductSpecifications = productSpecifications.filter(_ref13 => {
|
|
293
315
|
let {
|
|
294
316
|
key,
|
|
295
317
|
value
|
|
296
|
-
} =
|
|
318
|
+
} = _ref13;
|
|
297
319
|
return (productFieldLabels === null || productFieldLabels === void 0 ? void 0 : productFieldLabels[key]) && (value !== 'kg' || key !== 'weight');
|
|
298
|
-
}).map(
|
|
320
|
+
}).map(_ref14 => {
|
|
299
321
|
let {
|
|
300
322
|
key,
|
|
301
323
|
value
|
|
302
|
-
} =
|
|
324
|
+
} = _ref14;
|
|
303
325
|
return {
|
|
304
326
|
key: productFieldLabels[key],
|
|
305
327
|
value
|
|
@@ -320,7 +342,9 @@ const SingleOrderProductCard = _ref4 => {
|
|
|
320
342
|
className: (0, _helpers__.withStyle)('card-title mb-3')
|
|
321
343
|
}, productTitle, /*#__PURE__*/_react.default.createElement("span", {
|
|
322
344
|
className: (0, _helpers__.withStyle)('ms-2 d-flex flex-column align-items-end')
|
|
323
|
-
}, locationPriceExclVat != null && /*#__PURE__*/_react.default.createElement("span", null, "Vestigingprijs excl BTW: \u20AC", locationPriceExclVat.toFixed(2)), consumerPriceExclVat != null && /*#__PURE__*/_react.default.createElement("small", null, "Consumentenprijs excl BTW: \u20AC", consumerPriceExclVat.toFixed(2)))), /*#__PURE__*/_react.default.createElement("
|
|
345
|
+
}, locationPriceExclVat != null && /*#__PURE__*/_react.default.createElement("span", null, "Vestigingprijs excl BTW: \u20AC", locationPriceExclVat.toFixed(2)), consumerPriceExclVat != null && /*#__PURE__*/_react.default.createElement("small", null, "Consumentenprijs excl BTW: \u20AC", consumerPriceExclVat.toFixed(2)))), productDescription && /*#__PURE__*/_react.default.createElement("h6", {
|
|
346
|
+
className: (0, _helpers__.withStyle)('card-subtitle mb-3')
|
|
347
|
+
}, productDescription), /*#__PURE__*/_react.default.createElement("div", {
|
|
324
348
|
className: (0, _helpers__.withStyle)(isModelArticle ? 'd-flex justify-content-between' : '')
|
|
325
349
|
}, (productSubgroup || articleNumber || preferredPart) && /*#__PURE__*/_react.default.createElement(ProductCategories, {
|
|
326
350
|
brandName: brandName,
|
|
@@ -334,7 +358,9 @@ const SingleOrderProductCard = _ref4 => {
|
|
|
334
358
|
}), (filteredProductSpecifications === null || filteredProductSpecifications === void 0 ? void 0 : filteredProductSpecifications.length) > 0 && /*#__PURE__*/_react.default.createElement(_ProductCardSpecifications.default, {
|
|
335
359
|
specifications: filteredProductSpecifications,
|
|
336
360
|
className: isModelArticle ? '' : 'w-100'
|
|
337
|
-
})),
|
|
361
|
+
})), /*#__PURE__*/_react.default.createElement(SingleOrderOrderRules, {
|
|
362
|
+
rules: orderRules
|
|
363
|
+
}), (productUsps === null || productUsps === void 0 ? void 0 : productUsps.length) > 0 && !productUsps.every(usp => usp.text === null) && /*#__PURE__*/_react.default.createElement(_ProductCardUsps.default, {
|
|
338
364
|
usps: productUsps,
|
|
339
365
|
className: isModelArticle ? 'mr-2' : 'w-100'
|
|
340
366
|
})), /*#__PURE__*/_react.default.createElement(ProductActions, {
|
|
@@ -354,7 +380,8 @@ const SingleOrderProductCard = _ref4 => {
|
|
|
354
380
|
productBrandNumber: productBrandNumber,
|
|
355
381
|
hasPreferredPart: Boolean(preferredPart),
|
|
356
382
|
isWebshop: isWebshop,
|
|
357
|
-
isLoadingPartStockLevel: isLoadingPartStockLevel
|
|
383
|
+
isLoadingPartStockLevel: isLoadingPartStockLevel,
|
|
384
|
+
quantityError: (0, _singleOrderArticleRules.getSingleOrderQuantityError)(quantity, orderRules)
|
|
358
385
|
})))));
|
|
359
386
|
};
|
|
360
387
|
var _default = exports.default = SingleOrderProductCard;
|
|
@@ -208,7 +208,11 @@ const AppointmentForm = () => {
|
|
|
208
208
|
});
|
|
209
209
|
const prospectId = (0, _prospectTracking.createProspectId)();
|
|
210
210
|
prospectIdRef.current = prospectId;
|
|
211
|
-
const appointmentRequestPayload = (
|
|
211
|
+
const appointmentRequestPayload = _objectSpread({
|
|
212
|
+
// Note: outside removeNullishProps(), which strips a `false`. Hyper
|
|
213
|
+
// adds the board-computer update whenever this flag is absent
|
|
214
|
+
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection)
|
|
215
|
+
}, (0, _helpers__.removeNullishProps)({
|
|
212
216
|
prospectId,
|
|
213
217
|
licensePlate: licensePlate === null || licensePlate === void 0 ? void 0 : licensePlate.replace(/-/g, ''),
|
|
214
218
|
model,
|
|
@@ -227,7 +231,6 @@ const AppointmentForm = () => {
|
|
|
227
231
|
})),
|
|
228
232
|
formula,
|
|
229
233
|
branchId: selectedBranch,
|
|
230
|
-
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection),
|
|
231
234
|
skipFilters,
|
|
232
235
|
discount: (() => {
|
|
233
236
|
if (!(discountCode !== null && discountCode !== void 0 && discountCode.length)) return null;
|
|
@@ -246,7 +249,7 @@ const AppointmentForm = () => {
|
|
|
246
249
|
isTowmotiveFormula: isTowmotive,
|
|
247
250
|
vehicleCodingDiscountPercentage
|
|
248
251
|
}))
|
|
249
|
-
});
|
|
252
|
+
}));
|
|
250
253
|
await createAppointmentRequest(appointmentRequestPayload);
|
|
251
254
|
} catch (ex) {
|
|
252
255
|
(0, _Datalayer.pushToDataLayer)({
|
|
@@ -243,7 +243,11 @@ const ExitIntentModal = () => {
|
|
|
243
243
|
});
|
|
244
244
|
const prospectId = (0, _prospectTracking.createProspectId)();
|
|
245
245
|
prospectIdRef.current = prospectId;
|
|
246
|
-
await createQuotation((
|
|
246
|
+
await createQuotation(_objectSpread({
|
|
247
|
+
// Note: outside removeNullishProps(), which strips a `false`. Hyper
|
|
248
|
+
// adds the board-computer update whenever this flag is absent
|
|
249
|
+
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection)
|
|
250
|
+
}, (0, _helpers__.removeNullishProps)({
|
|
247
251
|
prospectId,
|
|
248
252
|
isExitIntent: true,
|
|
249
253
|
licensePlate,
|
|
@@ -263,7 +267,6 @@ const ExitIntentModal = () => {
|
|
|
263
267
|
lastName: (_customer$lastName = customer === null || customer === void 0 ? void 0 : customer.lastName) !== null && _customer$lastName !== void 0 ? _customer$lastName : undefined
|
|
264
268
|
})),
|
|
265
269
|
branchId: selectedBranch,
|
|
266
|
-
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection),
|
|
267
270
|
skipFilters,
|
|
268
271
|
cart: (0, _product.buildCartInput)(_objectSpread(_objectSpread({
|
|
269
272
|
selectedCableset,
|
|
@@ -275,7 +278,7 @@ const ExitIntentModal = () => {
|
|
|
275
278
|
isTowmotiveFormula: isTowmotive,
|
|
276
279
|
vehicleCodingDiscountPercentage
|
|
277
280
|
}))
|
|
278
|
-
}));
|
|
281
|
+
})));
|
|
279
282
|
} catch (ex) {
|
|
280
283
|
(0, _Datalayer.pushToDataLayer)({
|
|
281
284
|
event: 'form',
|
|
@@ -109,7 +109,8 @@ const ProductCartSide = () => {
|
|
|
109
109
|
montageRate,
|
|
110
110
|
extraPriceAmount,
|
|
111
111
|
discountCode,
|
|
112
|
-
priceCalculationDate
|
|
112
|
+
priceCalculationDate,
|
|
113
|
+
skipFilters
|
|
113
114
|
} = order;
|
|
114
115
|
const isTmg = (0, _useIsTmg.useIsTmg)();
|
|
115
116
|
const isTowmotive = (0, _useIsTowmotive.useIsTowmotive)();
|
|
@@ -128,7 +129,9 @@ const ProductCartSide = () => {
|
|
|
128
129
|
consumerDiscounts,
|
|
129
130
|
touchedConsumerDiscounts
|
|
130
131
|
});
|
|
131
|
-
|
|
132
|
+
// Use the session skipFilters so this query matches the product page's;
|
|
133
|
+
// an unfiltered request can return a different catalogue than the page.
|
|
134
|
+
const shouldRequestUnfilteredProducts = skipFilters || Boolean(existingDossierId && (allArticleNumbers === null || allArticleNumbers === void 0 ? void 0 : allArticleNumbers.length) > 0);
|
|
132
135
|
const {
|
|
133
136
|
cart,
|
|
134
137
|
totals,
|
|
@@ -280,7 +280,8 @@ const ProductCartTable = () => {
|
|
|
280
280
|
touchedConsumerDiscounts,
|
|
281
281
|
montageRate,
|
|
282
282
|
isMontageTariffFixed,
|
|
283
|
-
extraPriceAmount
|
|
283
|
+
extraPriceAmount,
|
|
284
|
+
skipFilters
|
|
284
285
|
}, dispatch] = (0, _OrderSessionContext.useOrderSession)();
|
|
285
286
|
|
|
286
287
|
// Determine display mode
|
|
@@ -354,10 +355,9 @@ const ProductCartTable = () => {
|
|
|
354
355
|
consumerDiscounts,
|
|
355
356
|
touchedConsumerDiscounts
|
|
356
357
|
});
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
const shouldRequestUnfilteredProducts = (0, _product.shouldRequestUnfilteredProductsForCart)(cartInput) || Boolean(existingDossierId && (allArticleNumbers === null || allArticleNumbers === void 0 ? void 0 : allArticleNumbers.length) > 0);
|
|
358
|
+
// Use the session skipFilters so this query matches the product page's;
|
|
359
|
+
// an unfiltered request can return a different catalogue than the page.
|
|
360
|
+
const shouldRequestUnfilteredProducts = skipFilters || Boolean(existingDossierId && (allArticleNumbers === null || allArticleNumbers === void 0 ? void 0 : allArticleNumbers.length) > 0);
|
|
361
361
|
const durationAnswerForQuery = durationAnswerIsPrefilled ? undefined : durationAnswer;
|
|
362
362
|
const {
|
|
363
363
|
cart,
|
|
@@ -456,6 +456,7 @@ const ProductsOverview = () => {
|
|
|
456
456
|
})
|
|
457
457
|
});
|
|
458
458
|
}
|
|
459
|
+
const towbarOrientation = !APP_CONFIG.internal && (productCategory === _constants__.PRODUCT_CATEGORIES.TOWBAR || productCategory === _constants__.PRODUCT_CATEGORIES.COMBISET) ? (0, _product.getDetachableTowbarOrientation)(product === null || product === void 0 ? void 0 : product.subgroupName) : null;
|
|
459
460
|
return /*#__PURE__*/_react.default.createElement(_ProductCard.default, {
|
|
460
461
|
isTmg: isTmg,
|
|
461
462
|
stock: (_product$consumerPric = product === null || product === void 0 || (_product$consumerPric2 = product.consumerPrices) === null || _product$consumerPric2 === void 0 ? void 0 : _product$consumerPric2.stock) !== null && _product$consumerPric !== void 0 ? _product$consumerPric : product === null || product === void 0 || (_product$locationPric = product.locationPrices) === null || _product$locationPric === void 0 ? void 0 : _product$locationPric.stock,
|
|
@@ -463,7 +464,8 @@ const ProductsOverview = () => {
|
|
|
463
464
|
hasCheckbox: (productsPerCategory === null || productsPerCategory === void 0 ? void 0 : productsPerCategory.length) > 1,
|
|
464
465
|
isRecommended: isRecommended,
|
|
465
466
|
productId: product === null || product === void 0 ? void 0 : product.articleNumber,
|
|
466
|
-
productTitle: product === null || product === void 0 ? void 0 : product.subgroupName,
|
|
467
|
+
productTitle: towbarOrientation ? (0, _product.getTowbarInfoTitle)(product === null || product === void 0 ? void 0 : product.subgroupName) : product === null || product === void 0 ? void 0 : product.subgroupName,
|
|
468
|
+
productOrientation: towbarOrientation,
|
|
467
469
|
productDescription: product === null || product === void 0 ? void 0 : product.productDescription,
|
|
468
470
|
productUsps: [{
|
|
469
471
|
type: 'excl',
|
|
@@ -210,7 +210,11 @@ const QuotationForm = () => {
|
|
|
210
210
|
});
|
|
211
211
|
const prospectId = (0, _prospectTracking.createProspectId)();
|
|
212
212
|
prospectIdRef.current = prospectId;
|
|
213
|
-
await createQuotation((
|
|
213
|
+
await createQuotation(_objectSpread({
|
|
214
|
+
// Note: outside removeNullishProps(), which strips a `false`. Hyper
|
|
215
|
+
// adds the board-computer update whenever this flag is absent
|
|
216
|
+
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection)
|
|
217
|
+
}, (0, _helpers__.removeNullishProps)({
|
|
214
218
|
prospectId,
|
|
215
219
|
isExitIntent: false,
|
|
216
220
|
licensePlate,
|
|
@@ -230,7 +234,6 @@ const QuotationForm = () => {
|
|
|
230
234
|
formula,
|
|
231
235
|
customer: (0, _helpers__.removeNullishProps)(customer),
|
|
232
236
|
branchId: selectedBranch,
|
|
233
|
-
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection),
|
|
234
237
|
skipFilters,
|
|
235
238
|
cart: (0, _product.buildCartInput)(_objectSpread(_objectSpread({
|
|
236
239
|
selectedCableset,
|
|
@@ -242,7 +245,7 @@ const QuotationForm = () => {
|
|
|
242
245
|
isTowmotiveFormula: isTowmotive,
|
|
243
246
|
vehicleCodingDiscountPercentage
|
|
244
247
|
}))
|
|
245
|
-
}));
|
|
248
|
+
})));
|
|
246
249
|
} catch (ex) {
|
|
247
250
|
(0, _Datalayer.pushToDataLayer)({
|
|
248
251
|
event: 'form',
|
|
@@ -656,7 +656,11 @@ const InternalAppointmentForm = _ref => {
|
|
|
656
656
|
isPlannedAppointment: appointmentType === _constants__.DOSSIER_TYPES.PlannedAppointment
|
|
657
657
|
}
|
|
658
658
|
});
|
|
659
|
-
const payload =
|
|
659
|
+
const payload = _objectSpread({
|
|
660
|
+
// Note: outside removeNullishProps(), which strips a `false`. Hyper
|
|
661
|
+
// adds the board-computer update whenever this flag is absent
|
|
662
|
+
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection)
|
|
663
|
+
}, (0, _helpers__.removeNullishProps)(_objectSpread(_objectSpread({
|
|
660
664
|
vehicle,
|
|
661
665
|
customer: (0, _helpers__.removeNullishProps)(_objectSpread(_objectSpread({}, customer), {}, {
|
|
662
666
|
firstName: (_customer$firstName = customer === null || customer === void 0 ? void 0 : customer.firstName) !== null && _customer$firstName !== void 0 ? _customer$firstName : undefined,
|
|
@@ -704,7 +708,6 @@ const InternalAppointmentForm = _ref => {
|
|
|
704
708
|
formula
|
|
705
709
|
}), {}, {
|
|
706
710
|
branchId: selectedBranch,
|
|
707
|
-
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection),
|
|
708
711
|
skipFilters,
|
|
709
712
|
cart: (0, _product.buildCartInput)(_objectSpread(_objectSpread({
|
|
710
713
|
selectedCableset,
|
|
@@ -719,7 +722,7 @@ const InternalAppointmentForm = _ref => {
|
|
|
719
722
|
touchedConsumerDiscounts
|
|
720
723
|
})),
|
|
721
724
|
montageRate: montageRate !== null && montageRate !== void 0 ? montageRate : undefined
|
|
722
|
-
}));
|
|
725
|
+
})));
|
|
723
726
|
payload.vehicle = _objectSpread(_objectSpread({}, payload.vehicle), {}, {
|
|
724
727
|
leaseNumber: activeOwnershipType === _constants__.VEHICLE_OWNERSHIP_TYPE.Leasemaatschappij ? (_vehicle$leaseNumber = vehicle === null || vehicle === void 0 ? void 0 : vehicle.leaseNumber) !== null && _vehicle$leaseNumber !== void 0 ? _vehicle$leaseNumber : '' : '',
|
|
725
728
|
leaseNumberUnknown: activeOwnershipType === _constants__.VEHICLE_OWNERSHIP_TYPE.Leasemaatschappij ? (_vehicle$leaseNumberU = vehicle === null || vehicle === void 0 ? void 0 : vehicle.leaseNumberUnknown) !== null && _vehicle$leaseNumberU !== void 0 ? _vehicle$leaseNumberU : false : false
|
|
@@ -558,7 +558,11 @@ const InternalQuotationForm = _ref => {
|
|
|
558
558
|
}
|
|
559
559
|
});
|
|
560
560
|
const isAnwbCode = discountCode === null || discountCode === void 0 ? void 0 : discountCode.toLocaleLowerCase().includes('anwb');
|
|
561
|
-
const payload =
|
|
561
|
+
const payload = _objectSpread({
|
|
562
|
+
// Note: outside removeNullishProps(), which strips a `false`. Hyper
|
|
563
|
+
// adds the board-computer update whenever this flag is absent
|
|
564
|
+
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection)
|
|
565
|
+
}, (0, _helpers__.removeNullishProps)(_objectSpread(_objectSpread({
|
|
562
566
|
vehicle,
|
|
563
567
|
customer: (0, _helpers__.removeNullishProps)(_objectSpread(_objectSpread({}, customer), {}, {
|
|
564
568
|
firstName: (_customer$firstName = customer === null || customer === void 0 ? void 0 : customer.firstName) !== null && _customer$firstName !== void 0 ? _customer$firstName : undefined,
|
|
@@ -601,7 +605,6 @@ const InternalQuotationForm = _ref => {
|
|
|
601
605
|
formula
|
|
602
606
|
}), {}, {
|
|
603
607
|
branchId: selectedBranch,
|
|
604
|
-
selectBoardComputerUpdate: (0, _product.shouldSelectBoardComputerUpdate)(boardComputerSelection),
|
|
605
608
|
skipFilters,
|
|
606
609
|
cart: (0, _product.buildCartInput)(_objectSpread(_objectSpread({
|
|
607
610
|
selectedCableset,
|
|
@@ -616,7 +619,7 @@ const InternalQuotationForm = _ref => {
|
|
|
616
619
|
touchedConsumerDiscounts
|
|
617
620
|
})),
|
|
618
621
|
montageRate: montageRate !== null && montageRate !== void 0 ? montageRate : undefined
|
|
619
|
-
}));
|
|
622
|
+
})));
|
|
620
623
|
payload.vehicle = _objectSpread(_objectSpread({}, payload.vehicle), {}, {
|
|
621
624
|
leaseNumber: activeOwnershipType === _constants__.VEHICLE_OWNERSHIP_TYPE.Leasemaatschappij ? (_vehicle$leaseNumber = vehicle === null || vehicle === void 0 ? void 0 : vehicle.leaseNumber) !== null && _vehicle$leaseNumber !== void 0 ? _vehicle$leaseNumber : '' : '',
|
|
622
625
|
leaseNumberUnknown: activeOwnershipType === _constants__.VEHICLE_OWNERSHIP_TYPE.Leasemaatschappij ? (_vehicle$leaseNumberU = vehicle === null || vehicle === void 0 ? void 0 : vehicle.leaseNumberUnknown) !== null && _vehicle$leaseNumberU !== void 0 ? _vehicle$leaseNumberU : false : false
|
|
@@ -16,6 +16,7 @@ var _DangerAlert = _interopRequireDefault(require("../../__components__/DangerAl
|
|
|
16
16
|
var _ExpandableCard = _interopRequireDefault(require("../../__components__/Cards/ExpandableCard"));
|
|
17
17
|
var _SingleOrderCartCard = _interopRequireDefault(require("../../__components__/SingleOrderCartCard"));
|
|
18
18
|
var _helpers__ = require("../../__helpers__");
|
|
19
|
+
var _singleOrderArticleRules = require("../../__helpers__/singleOrderArticleRules");
|
|
19
20
|
function _interopRequireDefault(e) {
|
|
20
21
|
return e && e.__esModule ? e : {
|
|
21
22
|
default: e
|
|
@@ -30,7 +31,7 @@ const EmptyState = _ref => {
|
|
|
30
31
|
}, message));
|
|
31
32
|
};
|
|
32
33
|
const InternalSingleOrderCart = _ref2 => {
|
|
33
|
-
var _cart$
|
|
34
|
+
var _cart$articles, _cart$totals$totalExc, _cart$totals, _cart$totals$totalBtw, _cart$totals2, _cart$totals$totalInc, _cart$totals3;
|
|
34
35
|
let {
|
|
35
36
|
handleQuantityChange,
|
|
36
37
|
removeFromCart: _removeFromCart,
|
|
@@ -42,9 +43,14 @@ const InternalSingleOrderCart = _ref2 => {
|
|
|
42
43
|
} = _ref2;
|
|
43
44
|
const {
|
|
44
45
|
cart,
|
|
45
|
-
isLoadingCart
|
|
46
|
+
isLoadingCart,
|
|
47
|
+
isCartError
|
|
46
48
|
} = (0, _queries.useSingleOrderCart)();
|
|
47
|
-
const
|
|
49
|
+
const blockingMessage = cart !== null && cart !== void 0 && cart.validationError ? "".concat(cart.validationError, " Pas de artikelen aan voordat je kunt bevestigen.") : cart !== null && cart !== void 0 && cart.hasQuantityErrors ? 'Een of meer aantallen voldoen niet aan de besteleenheid of het minimum. Pas de aantallen aan voordat je kunt bevestigen.' : null;
|
|
50
|
+
// Every quantity change mints a new query key and the cart holds no previous
|
|
51
|
+
// data, so confirming stays blocked until the answer is back — otherwise the
|
|
52
|
+
// rules can be skipped through that window.
|
|
53
|
+
const isConfirmBlocked = isLoadingCart || isCartError || Boolean(blockingMessage);
|
|
48
54
|
const confirmButtonClicked = () => {
|
|
49
55
|
if (showProductOverview) {
|
|
50
56
|
toggleOverview();
|
|
@@ -71,6 +77,7 @@ const InternalSingleOrderCart = _ref2 => {
|
|
|
71
77
|
productBrandNumber: article.brandNumber,
|
|
72
78
|
removeFromCart: () => _removeFromCart(article.articleNumber),
|
|
73
79
|
quantity: article.quantity,
|
|
80
|
+
orderRules: (0, _singleOrderArticleRules.resolveSingleOrderArticleRules)(article),
|
|
74
81
|
handleQuantityChange: handleQuantityChange
|
|
75
82
|
});
|
|
76
83
|
}) : /*#__PURE__*/_react.default.createElement(EmptyState, {
|
|
@@ -91,11 +98,11 @@ const InternalSingleOrderCart = _ref2 => {
|
|
|
91
98
|
}, /*#__PURE__*/_react.default.createElement(_LinkButton.default, {
|
|
92
99
|
label: "Bestelling herstarten",
|
|
93
100
|
onClick: () => resetOrderSession()
|
|
94
|
-
}),
|
|
101
|
+
}), blockingMessage && /*#__PURE__*/_react.default.createElement(_DangerAlert.default, {
|
|
95
102
|
className: "mx-2 mb-0",
|
|
96
|
-
message:
|
|
103
|
+
message: blockingMessage
|
|
97
104
|
}), /*#__PURE__*/_react.default.createElement(_PrimaryButton.default, {
|
|
98
|
-
isDisabled: disabledCreateOrder ||
|
|
105
|
+
isDisabled: disabledCreateOrder || isConfirmBlocked,
|
|
99
106
|
label: !showProductOverview ? 'Bevestigen' : 'Bestellen',
|
|
100
107
|
onClick: confirmButtonClicked
|
|
101
108
|
})));
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
require("core-js/modules/es.symbol.description.js");
|
|
4
3
|
require("core-js/modules/es.number.to-fixed.js");
|
|
5
4
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
6
5
|
require("core-js/modules/esnext.iterator.filter.js");
|
|
@@ -14,7 +13,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
14
13
|
value: true
|
|
15
14
|
});
|
|
16
15
|
exports.default = void 0;
|
|
17
|
-
require("core-js/modules/es.symbol.description.js");
|
|
18
16
|
require("core-js/modules/es.number.to-fixed.js");
|
|
19
17
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
20
18
|
require("core-js/modules/esnext.iterator.find.js");
|
|
@@ -30,6 +28,7 @@ var _FormulaContext = require("../../__context__/FormulaContext");
|
|
|
30
28
|
var _OrderSessionContext = require("../../__context__/OrderSessionContext");
|
|
31
29
|
var _helpers__ = require("../../__helpers__");
|
|
32
30
|
var _product = require("../../__helpers__/product");
|
|
31
|
+
var _singleOrderArticleRules = require("../../__helpers__/singleOrderArticleRules");
|
|
33
32
|
var _singleOrderArticles = require("../../__helpers__/singleOrderArticles");
|
|
34
33
|
var _useIsTmg = require("../../__hooks__/useIsTmg");
|
|
35
34
|
function _interopRequireDefault(e) {
|
|
@@ -170,7 +169,8 @@ const InternalSingleOrderProductOverview = _ref => {
|
|
|
170
169
|
}],
|
|
171
170
|
articleNumber: article.articleNumber,
|
|
172
171
|
handleQuantityChange: handleQuantityChange,
|
|
173
|
-
productDescription: article === null || article === void 0 ? void 0 : article.
|
|
172
|
+
productDescription: article === null || article === void 0 ? void 0 : article.singleOrderDescription,
|
|
173
|
+
orderRules: (0, _singleOrderArticleRules.resolveSingleOrderArticleRules)(article),
|
|
174
174
|
productImage: article.image,
|
|
175
175
|
productSpecifications: (0, _product.extractProductSpecsArray)(article),
|
|
176
176
|
productTitle: article.name,
|
|
@@ -46,4 +46,15 @@ describe('product helpers', () => {
|
|
|
46
46
|
expect(result.priceInclVat).toBe(189);
|
|
47
47
|
expect(result.priceExclVat).toBeCloseTo(156.2, 2);
|
|
48
48
|
});
|
|
49
|
+
});
|
|
50
|
+
describe('getDetachableTowbarOrientation', () => {
|
|
51
|
+
it('returns horizontaal or verticaal for detachable towbars', () => {
|
|
52
|
+
expect((0, _product.getDetachableTowbarOrientation)('Trekhaken horizontaal afneembaar')).toBe('horizontaal');
|
|
53
|
+
expect((0, _product.getDetachableTowbarOrientation)('Trekhaken verticaal afneembaar')).toBe('verticaal');
|
|
54
|
+
});
|
|
55
|
+
it('does not infer a type for other hitch names', () => {
|
|
56
|
+
expect((0, _product.getDetachableTowbarOrientation)('Afneembare trekhaak')).toBeNull();
|
|
57
|
+
expect((0, _product.getDetachableTowbarOrientation)('Trekhaken vast')).toBeNull();
|
|
58
|
+
expect((0, _product.getDetachableTowbarOrientation)('')).toBeNull();
|
|
59
|
+
});
|
|
49
60
|
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _singleOrderArticleRules = require("../singleOrderArticleRules");
|
|
4
|
+
describe('singleOrderArticleRules', () => {
|
|
5
|
+
it('ignores absent and non-positive Hyper values', () => {
|
|
6
|
+
expect((0, _singleOrderArticleRules.resolveSingleOrderArticleRules)({})).toEqual({
|
|
7
|
+
minimumQuantity: null,
|
|
8
|
+
orderUnit: null
|
|
9
|
+
});
|
|
10
|
+
expect((0, _singleOrderArticleRules.resolveSingleOrderArticleRules)({
|
|
11
|
+
singleOrderMinimumAantalTeBestellen: 0,
|
|
12
|
+
singleOrderBesteleenheid: ''
|
|
13
|
+
})).toEqual({
|
|
14
|
+
minimumQuantity: null,
|
|
15
|
+
orderUnit: null
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
it('reads the rules off the article', () => {
|
|
19
|
+
expect((0, _singleOrderArticleRules.resolveSingleOrderArticleRules)({
|
|
20
|
+
singleOrderMinimumAantalTeBestellen: '4',
|
|
21
|
+
singleOrderBesteleenheid: 2
|
|
22
|
+
})).toEqual({
|
|
23
|
+
minimumQuantity: 4,
|
|
24
|
+
orderUnit: 2
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it('describes only the filled rules', () => {
|
|
28
|
+
expect((0, _singleOrderArticleRules.describeSingleOrderArticleRules)({
|
|
29
|
+
minimumQuantity: null,
|
|
30
|
+
orderUnit: null
|
|
31
|
+
})).toEqual([]);
|
|
32
|
+
expect((0, _singleOrderArticleRules.describeSingleOrderArticleRules)({
|
|
33
|
+
minimumQuantity: 4,
|
|
34
|
+
orderUnit: null
|
|
35
|
+
})).toEqual(['Minimaal aantal te bestellen: 4']);
|
|
36
|
+
expect((0, _singleOrderArticleRules.describeSingleOrderArticleRules)({
|
|
37
|
+
minimumQuantity: 4,
|
|
38
|
+
orderUnit: 2
|
|
39
|
+
})).toEqual(['Besteleenheid: 2', 'Minimaal aantal te bestellen: 4']);
|
|
40
|
+
});
|
|
41
|
+
it('accepts any quantity for an unconstrained article', () => {
|
|
42
|
+
expect((0, _singleOrderArticleRules.getSingleOrderQuantityError)(3, (0, _singleOrderArticleRules.resolveSingleOrderArticleRules)({}))).toBeNull();
|
|
43
|
+
});
|
|
44
|
+
it('rejects a quantity below the minimum', () => {
|
|
45
|
+
expect((0, _singleOrderArticleRules.getSingleOrderQuantityError)(2, {
|
|
46
|
+
minimumQuantity: 4,
|
|
47
|
+
orderUnit: null
|
|
48
|
+
})).toBe('Minimaal 4 stuks bestellen.');
|
|
49
|
+
});
|
|
50
|
+
it('rejects a quantity that is not a multiple of the order unit', () => {
|
|
51
|
+
expect((0, _singleOrderArticleRules.getSingleOrderQuantityError)(5, {
|
|
52
|
+
minimumQuantity: null,
|
|
53
|
+
orderUnit: 2
|
|
54
|
+
})).toBe('Alleen te bestellen per 2 stuks.');
|
|
55
|
+
expect((0, _singleOrderArticleRules.getSingleOrderQuantityError)(6, {
|
|
56
|
+
minimumQuantity: 4,
|
|
57
|
+
orderUnit: 2
|
|
58
|
+
})).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
it('does not flag an article that is not in the cart', () => {
|
|
61
|
+
expect((0, _singleOrderArticleRules.getSingleOrderQuantityError)(0, {
|
|
62
|
+
minimumQuantity: 4,
|
|
63
|
+
orderUnit: 2
|
|
64
|
+
})).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
it('flags a cart holding an article with an invalid quantity', () => {
|
|
67
|
+
const validLine = {
|
|
68
|
+
articleNumber: 'A',
|
|
69
|
+
name: 'Kabelset',
|
|
70
|
+
quantity: 2
|
|
71
|
+
};
|
|
72
|
+
const invalidLine = {
|
|
73
|
+
articleNumber: 'B',
|
|
74
|
+
name: 'Kogelstang',
|
|
75
|
+
quantity: 1,
|
|
76
|
+
singleOrderMinimumAantalTeBestellen: 4
|
|
77
|
+
};
|
|
78
|
+
expect((0, _singleOrderArticleRules.hasSingleOrderQuantityErrors)([validLine, invalidLine])).toBe(true);
|
|
79
|
+
expect((0, _singleOrderArticleRules.hasSingleOrderQuantityErrors)([validLine])).toBe(false);
|
|
80
|
+
expect((0, _singleOrderArticleRules.hasSingleOrderQuantityErrors)([])).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -9,12 +9,11 @@ require("core-js/modules/esnext.iterator.filter.js");
|
|
|
9
9
|
require("core-js/modules/esnext.iterator.flat-map.js");
|
|
10
10
|
require("core-js/modules/esnext.iterator.for-each.js");
|
|
11
11
|
require("core-js/modules/esnext.iterator.map.js");
|
|
12
|
-
require("core-js/modules/esnext.iterator.some.js");
|
|
13
12
|
require("core-js/modules/web.dom-collections.iterator.js");
|
|
14
13
|
Object.defineProperty(exports, "__esModule", {
|
|
15
14
|
value: true
|
|
16
15
|
});
|
|
17
|
-
exports.validateCartInput = exports.shouldSelectBoardComputerUpdate = exports.
|
|
16
|
+
exports.validateCartInput = exports.shouldSelectBoardComputerUpdate = exports.resolveSingleOrderArticlePrices = exports.parseProductSpecifications = exports.getTowbarInfoTitle = exports.getEffectiveBoardComputerSelection = exports.getDetachableTowbarOrientation = exports.formatHyperDescription = exports.extractProductSpecsArray = exports.checkIfTowbarIsRecommended = exports.buildCartInput = void 0;
|
|
18
17
|
require("core-js/modules/es.array.flat-map.js");
|
|
19
18
|
require("core-js/modules/es.array.includes.js");
|
|
20
19
|
require("core-js/modules/es.array.unscopables.flat-map.js");
|
|
@@ -24,7 +23,6 @@ require("core-js/modules/esnext.iterator.filter.js");
|
|
|
24
23
|
require("core-js/modules/esnext.iterator.flat-map.js");
|
|
25
24
|
require("core-js/modules/esnext.iterator.for-each.js");
|
|
26
25
|
require("core-js/modules/esnext.iterator.map.js");
|
|
27
|
-
require("core-js/modules/esnext.iterator.some.js");
|
|
28
26
|
require("core-js/modules/web.dom-collections.iterator.js");
|
|
29
27
|
var _constants__ = require("../__constants__");
|
|
30
28
|
function ownKeys(e, r) {
|
|
@@ -98,16 +96,6 @@ const validateCartInput = exports.validateCartInput = function validateCartInput
|
|
|
98
96
|
}
|
|
99
97
|
return;
|
|
100
98
|
};
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* @description Cart overviews resolve selected articles from the order article lists.
|
|
104
|
-
* If the user selected an article that only appears with skipFilters enabled,
|
|
105
|
-
* those read-only lookups must request the unfiltered product list too.
|
|
106
|
-
*/
|
|
107
|
-
const shouldRequestUnfilteredProductsForCart = exports.shouldRequestUnfilteredProductsForCart = function shouldRequestUnfilteredProductsForCart() {
|
|
108
|
-
let cart = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
109
|
-
return Array.isArray(cart) && cart.some(lineItem => (lineItem === null || lineItem === void 0 ? void 0 : lineItem.articleNumber) != null);
|
|
110
|
-
};
|
|
111
99
|
const getEffectiveBoardComputerSelection = exports.getEffectiveBoardComputerSelection = function getEffectiveBoardComputerSelection() {
|
|
112
100
|
var _ref3;
|
|
113
101
|
let {
|
|
@@ -227,11 +215,39 @@ const checkIfTowbarIsRecommended = _ref8 => {
|
|
|
227
215
|
} = _ref8;
|
|
228
216
|
return category === _constants__.PRODUCT_CATEGORIES.TOWBAR && ((product === null || product === void 0 ? void 0 : product.subgroupName.toLowerCase().includes('afneembaar')) || (product === null || product === void 0 || (_product$subgroupName = product.subgroupName) === null || _product$subgroupName === void 0 ? void 0 : _product$subgroupName.toLowerCase().includes('afneembare')));
|
|
229
217
|
};
|
|
218
|
+
exports.checkIfTowbarIsRecommended = checkIfTowbarIsRecommended;
|
|
219
|
+
const getTowbarInfoTitle = title => {
|
|
220
|
+
const lower = (title || '').toLowerCase();
|
|
221
|
+
if (lower.includes('afneemba')) {
|
|
222
|
+
return 'Afneembare trekhaak';
|
|
223
|
+
}
|
|
224
|
+
if (lower.includes('wegklapba') || lower.includes('wegdraai')) {
|
|
225
|
+
return 'Wegklapbare trekhaak';
|
|
226
|
+
}
|
|
227
|
+
if (lower.includes('vast')) {
|
|
228
|
+
return 'Vaste trekhaak';
|
|
229
|
+
}
|
|
230
|
+
return title;
|
|
231
|
+
};
|
|
232
|
+
exports.getTowbarInfoTitle = getTowbarInfoTitle;
|
|
233
|
+
const getDetachableTowbarOrientation = title => {
|
|
234
|
+
const lower = (title || '').toLowerCase();
|
|
235
|
+
if (!lower.includes('afneemba')) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
if (lower.includes('horizontaal')) {
|
|
239
|
+
return 'horizontaal';
|
|
240
|
+
}
|
|
241
|
+
if (lower.includes('verticaal')) {
|
|
242
|
+
return 'verticaal';
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
};
|
|
230
246
|
|
|
231
247
|
/**
|
|
232
248
|
* @description Formats the description of a product
|
|
233
249
|
*/
|
|
234
|
-
exports.
|
|
250
|
+
exports.getDetachableTowbarOrientation = getDetachableTowbarOrientation;
|
|
235
251
|
const formatHyperDescription = description => {
|
|
236
252
|
return description === null || description === void 0 ? void 0 : description.ops.map(phrase => phrase.insert).join('');
|
|
237
253
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
4
|
+
require("core-js/modules/esnext.iterator.filter.js");
|
|
5
|
+
require("core-js/modules/esnext.iterator.some.js");
|
|
6
|
+
Object.defineProperty(exports, "__esModule", {
|
|
7
|
+
value: true
|
|
8
|
+
});
|
|
9
|
+
exports.resolveSingleOrderArticleRules = exports.hasSingleOrderQuantityErrors = exports.getSingleOrderQuantityError = exports.describeSingleOrderArticleRules = void 0;
|
|
10
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
11
|
+
require("core-js/modules/esnext.iterator.filter.js");
|
|
12
|
+
require("core-js/modules/esnext.iterator.some.js");
|
|
13
|
+
/**
|
|
14
|
+
* Hyper can constrain how an article is ordered in a single order: a minimum
|
|
15
|
+
* quantity and/or an order unit the quantity must be a multiple of. Articles
|
|
16
|
+
* without either field order without restrictions.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const toPositiveNumber = value => {
|
|
20
|
+
const number = Number(value);
|
|
21
|
+
return number > 0 ? number : null;
|
|
22
|
+
};
|
|
23
|
+
const resolveSingleOrderArticleRules = article => ({
|
|
24
|
+
minimumQuantity: toPositiveNumber(article.singleOrderMinimumAantalTeBestellen),
|
|
25
|
+
orderUnit: toPositiveNumber(article.singleOrderBesteleenheid)
|
|
26
|
+
});
|
|
27
|
+
exports.resolveSingleOrderArticleRules = resolveSingleOrderArticleRules;
|
|
28
|
+
const describeSingleOrderArticleRules = _ref => {
|
|
29
|
+
let {
|
|
30
|
+
minimumQuantity,
|
|
31
|
+
orderUnit
|
|
32
|
+
} = _ref;
|
|
33
|
+
return [orderUnit && "Besteleenheid: ".concat(orderUnit), minimumQuantity && "Minimaal aantal te bestellen: ".concat(minimumQuantity)].filter(Boolean);
|
|
34
|
+
};
|
|
35
|
+
exports.describeSingleOrderArticleRules = describeSingleOrderArticleRules;
|
|
36
|
+
const getSingleOrderQuantityError = (quantity, _ref2) => {
|
|
37
|
+
let {
|
|
38
|
+
minimumQuantity,
|
|
39
|
+
orderUnit
|
|
40
|
+
} = _ref2;
|
|
41
|
+
if (!quantity) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
if (minimumQuantity && quantity < minimumQuantity) {
|
|
45
|
+
return "Minimaal ".concat(minimumQuantity, " stuks bestellen.");
|
|
46
|
+
}
|
|
47
|
+
if (orderUnit && quantity % orderUnit !== 0) {
|
|
48
|
+
return "Alleen te bestellen per ".concat(orderUnit, " stuks.");
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
};
|
|
52
|
+
exports.getSingleOrderQuantityError = getSingleOrderQuantityError;
|
|
53
|
+
const hasSingleOrderQuantityErrors = articles => articles.some(article => getSingleOrderQuantityError(article.quantity, resolveSingleOrderArticleRules(article)));
|
|
54
|
+
exports.hasSingleOrderQuantityErrors = hasSingleOrderQuantityErrors;
|
|
@@ -442,8 +442,11 @@ const formatGenericArticle = article => {
|
|
|
442
442
|
return "".concat(label, ": ").concat(value);
|
|
443
443
|
}).join(' \n ');
|
|
444
444
|
return _objectSpread(_objectSpread({}, article), {}, {
|
|
445
|
-
name: article.name,
|
|
445
|
+
name: article.singleOrderArtikelNaam || article.name,
|
|
446
446
|
description: null,
|
|
447
|
+
// Separate from `description`, which formatModelArticle fills with
|
|
448
|
+
// unrelated copy.
|
|
449
|
+
singleOrderDescription: article.singleOrderArtikelOmschrijving || null,
|
|
447
450
|
subTitle: null,
|
|
448
451
|
specifications: specification === '' ? null : specification,
|
|
449
452
|
image: article !== null && article !== void 0 && article.computedImages ? (0, _image.getImageFromHyper)({
|