thm-p3-configurator 0.0.111 → 0.0.113

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.
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "__esModule", {
8
8
  value: true
9
9
  });
10
10
  exports.default = void 0;
11
- var _TEST_ONLY_INTERNAL_ROUTES = _interopRequireDefault(require("./__pages__/internal/__TEST_ONLY_INTERNAL_ROUTES"));
12
11
  var _react = _interopRequireWildcard(require("react"));
13
12
  require("react-datepicker/src/stylesheets/datepicker-cssmodules.scss");
14
13
  var _reactGtmModule = _interopRequireDefault(require("react-gtm-module"));
@@ -26,9 +25,15 @@ var _FormulaContext = require("./__context__/FormulaContext");
26
25
  var _OrderSessionContext = require("./__context__/OrderSessionContext");
27
26
  var _cookiebot = require("./__helpers__/cookiebot");
28
27
  var _queryClient = _interopRequireDefault(require("./__helpers__/queryClient"));
28
+ var _index = _interopRequireDefault(require("./__pages__/index"));
29
29
  var _Experiments = _interopRequireDefault(require("./__services__/Experiments"));
30
30
  var _mainExternal = _interopRequireDefault(require("./__style__/main-external.scss"));
31
31
  var _main = _interopRequireDefault(require("./__style__/main.scss"));
32
+ function _interopRequireDefault(e) {
33
+ return e && e.__esModule ? e : {
34
+ default: e
35
+ };
36
+ }
32
37
  function _getRequireWildcardCache(e) {
33
38
  if ("function" != typeof WeakMap) return null;
34
39
  var r = new WeakMap(),
@@ -54,12 +59,7 @@ function _interopRequireWildcard(e, r) {
54
59
  }
55
60
  return n.default = e, t && t.set(e, n), n;
56
61
  }
57
- function _interopRequireDefault(e) {
58
- return e && e.__esModule ? e : {
59
- default: e
60
- };
61
- }
62
- // import Routes from './__pages__/index';
62
+ // import TEST_ONLY_INTERNAL_ROUTES from './__pages__/internal/__TEST_ONLY_INTERNAL_ROUTES';
63
63
 
64
64
  _reactGtmModule.default.initialize({
65
65
  gtmId: APP_CONFIG.googleTagManagerId || 'GTM-TC67SZ4'
@@ -76,6 +76,6 @@ const App = () => {
76
76
  defaultCountry: APP_CONFIG.country
77
77
  }, /*#__PURE__*/_react.default.createElement(_OrderSessionContext.OrderSessionController, null, /*#__PURE__*/_react.default.createElement(_reactQuery.QueryClientProvider, {
78
78
  client: _queryClient.default
79
- }, /*#__PURE__*/_react.default.createElement(_reactRouterDom.BrowserRouter, null, /*#__PURE__*/_react.default.createElement(_reactHotLoader.AppContainer, null, /*#__PURE__*/_react.default.createElement(_ActiveMarkerContext.ActiveMarkerProvider, null, /*#__PURE__*/_react.default.createElement(_StyleWrapper.default, null, !APP_CONFIG.internal && /*#__PURE__*/_react.default.createElement(_Navbar.default, null), APP_CONFIG.internal && /*#__PURE__*/_react.default.createElement(_InternalBranchSelectorModal.default, null), APP_CONFIG.nodeEnv === 'development' && APP_CONFIG.internal === true && /*#__PURE__*/_react.default.createElement(_TEST_ONLY_INTERNAL_ROUTES.default, null))))))))));
79
+ }, /*#__PURE__*/_react.default.createElement(_reactRouterDom.BrowserRouter, null, /*#__PURE__*/_react.default.createElement(_reactHotLoader.AppContainer, null, /*#__PURE__*/_react.default.createElement(_ActiveMarkerContext.ActiveMarkerProvider, null, /*#__PURE__*/_react.default.createElement(_StyleWrapper.default, null, !APP_CONFIG.internal && /*#__PURE__*/_react.default.createElement(_Navbar.default, null), APP_CONFIG.internal && /*#__PURE__*/_react.default.createElement(_InternalBranchSelectorModal.default, null), /*#__PURE__*/_react.default.createElement(_index.default, null))))))))));
80
80
  };
81
81
  var _default = exports.default = App;
@@ -75,7 +75,6 @@ const TextInput = _ref => {
75
75
  }, label, isRequired && /*#__PURE__*/_react.default.createElement("span", null, "*")), /*#__PURE__*/_react.default.createElement("input", {
76
76
  placeholder: placeholder,
77
77
  as: 'input',
78
- id: name,
79
78
  name: name,
80
79
  type: 'text',
81
80
  onClick: onClick,
@@ -32,6 +32,7 @@ require("core-js/modules/esnext.iterator.reduce.js");
32
32
  require("core-js/modules/web.dom-collections.iterator.js");
33
33
  var _react = _interopRequireWildcard(require("react"));
34
34
  var _logoPrimary = _interopRequireDefault(require("../../../public/assets/images/logo-primary.png"));
35
+ var _montagePlaceholder = _interopRequireDefault(require("../../../public/assets/images/montage-placeholder.png"));
35
36
  var _queries = require("../__api__/queries");
36
37
  var _TogglableCard = _interopRequireDefault(require("../__components__/Cards/TogglableCard"));
37
38
  var _ProductTableEditableRow = _interopRequireDefault(require("../__components__/ProductTable/ProductTableEditableRow"));
@@ -139,70 +140,197 @@ const ProductCartSide = () => {
139
140
  if (isLoadingProducts) {
140
141
  return /*#__PURE__*/_react.default.createElement(_FullPageSpinner.default, null);
141
142
  }
142
- const getItemPrice = cartItem => {
143
- var _product$consumerPric;
144
- if (!cartItem) return 0;
143
+
144
+ /**
145
+ * Calculate item prices from a cart item
146
+ * @param {Object} cartItem - Cart item object
147
+ * @return {Object} Calculated prices for the item
148
+ */
149
+ const getItemPrices = cartItem => {
150
+ var _product$locationPric, _product$consumerPric, _product$consumerPric2;
151
+ if (!cartItem) {
152
+ return {
153
+ purchasePrice: 0,
154
+ salesPrice: 0,
155
+ salesPriceInclVat: 0,
156
+ margin: 0,
157
+ marginPercentage: 0
158
+ };
159
+ }
145
160
 
146
161
  // Find the corresponding product
147
162
  const product = [...mainProducts, ...accessoireProducts].find(p => p.articleNumber === cartItem.articleNumber);
148
- if (isToggled) {
149
- var _product$locationPric;
150
- return ((product === null || product === void 0 || (_product$locationPric = product.locationPrices) === null || _product$locationPric === void 0 ? void 0 : _product$locationPric.priceExclVat) || 0) * (cartItem.quantity || 1);
163
+ if (!product) {
164
+ return {
165
+ purchasePrice: 0,
166
+ salesPrice: 0,
167
+ salesPriceInclVat: 0,
168
+ margin: 0,
169
+ marginPercentage: 0
170
+ };
151
171
  }
152
- return cartItem.consumerTotal || ((product === null || product === void 0 || (_product$consumerPric = product.consumerPrices) === null || _product$consumerPric === void 0 ? void 0 : _product$consumerPric.priceInclVat) || 0) * (cartItem.quantity || 1);
172
+
173
+ // Get prices directly from product objects
174
+ const purchasePrice = (product === null || product === void 0 || (_product$locationPric = product.locationPrices) === null || _product$locationPric === void 0 ? void 0 : _product$locationPric.priceExclVat) || 0;
175
+ const salesPrice = (product === null || product === void 0 || (_product$consumerPric = product.consumerPrices) === null || _product$consumerPric === void 0 ? void 0 : _product$consumerPric.priceExclVat) || 0;
176
+ const salesPriceInclVat = (product === null || product === void 0 || (_product$consumerPric2 = product.consumerPrices) === null || _product$consumerPric2 === void 0 ? void 0 : _product$consumerPric2.priceInclVat) || 0;
177
+ const margin = salesPrice - purchasePrice;
178
+ const marginPercentage = purchasePrice ? margin / purchasePrice * 100 : 0;
179
+ return {
180
+ purchasePrice,
181
+ salesPrice,
182
+ salesPriceInclVat,
183
+ margin,
184
+ marginPercentage: Math.round(marginPercentage * 100) / 100
185
+ };
153
186
  };
154
187
 
155
- // Calculate subtotal for products
156
- const subtotalPriceProducts = (cart === null || cart === void 0 ? void 0 : cart.reduce((acc, item) => {
188
+ // ===== MAIN PRODUCTS PRICING =====
189
+ /**
190
+ * Calculate sum of main products price (excluding montage) including VAT
191
+ */
192
+ const mainProductsInclVat = (cart === null || cart === void 0 ? void 0 : cart.reduce((acc, item) => {
157
193
  if (mainProducts.find(product => product.articleNumber === item.articleNumber)) {
158
- return acc + parseFloat(getItemPrice(item));
194
+ const {
195
+ salesPriceInclVat
196
+ } = getItemPrices(item);
197
+ return acc + salesPriceInclVat;
198
+ }
199
+ return acc;
200
+ }, 0)) || 0;
201
+
202
+ /**
203
+ * Calculate sum of main products price (excluding montage) excluding VAT
204
+ */
205
+ const mainProductsExclVat = mainProductsInclVat / 1.21;
206
+
207
+ /**
208
+ * Calculate sum of main products purchase price (excluding montage)
209
+ */
210
+ const mainProductsPurchase = (cart === null || cart === void 0 ? void 0 : cart.reduce((acc, item) => {
211
+ if (mainProducts.find(product => product.articleNumber === item.articleNumber)) {
212
+ const {
213
+ purchasePrice
214
+ } = getItemPrices(item);
215
+ return acc + purchasePrice;
216
+ }
217
+ return acc;
218
+ }, 0)) || 0;
219
+
220
+ // ===== MONTAGE PRICING =====
221
+ /**
222
+ * Montage price including VAT
223
+ */
224
+ const montageInclVat = parseFloat(totals === null || totals === void 0 ? void 0 : totals.montagePricePlusMarketCorrectionInclVat) || 0;
225
+
226
+ /**
227
+ * Montage price excluding VAT
228
+ */
229
+ const montageExclVat = parseFloat(totals === null || totals === void 0 ? void 0 : totals.montagePricePlusMarketCorrectionExclVat) || 0;
230
+
231
+ // ===== ACCESSORIES PRICING =====
232
+ /**
233
+ * Calculate sum of accessories price including VAT
234
+ */
235
+ const accessoriesInclVat = (cart === null || cart === void 0 ? void 0 : cart.reduce((acc, item) => {
236
+ if (accessoireProducts.find(product => product.articleNumber === item.articleNumber)) {
237
+ const {
238
+ salesPriceInclVat
239
+ } = getItemPrices(item);
240
+ const quantity = selectedExtras[item.articleNumber.toString()] || 1;
241
+ return acc + salesPriceInclVat * quantity;
159
242
  }
160
243
  return acc;
161
244
  }, 0)) || 0;
162
245
 
163
- // Calculate subtotal for accessories
164
- const subtotalPriceAccessoires = (cart === null || cart === void 0 ? void 0 : cart.reduce((acc, item) => {
246
+ /**
247
+ * Calculate sum of accessories price excluding VAT
248
+ */
249
+ const accessoriesExclVat = accessoriesInclVat / 1.21;
250
+
251
+ /**
252
+ * Calculate sum of accessories purchase price
253
+ */
254
+ const accessoriesPurchase = (cart === null || cart === void 0 ? void 0 : cart.reduce((acc, item) => {
165
255
  if (accessoireProducts.find(product => product.articleNumber === item.articleNumber)) {
166
- return acc + parseFloat(getItemPrice(item));
256
+ const {
257
+ purchasePrice
258
+ } = getItemPrices(item);
259
+ const quantity = selectedExtras[item.articleNumber.toString()] || 1;
260
+ return acc + purchasePrice * quantity;
167
261
  }
168
262
  return acc;
169
263
  }, 0)) || 0;
170
264
 
171
- // Calculate total discount
172
- const calculateTotalDiscount = () => {
173
- const totalPrice = subtotalPriceProducts + subtotalPriceAccessoires;
265
+ // ===== SUBTOTALS =====
266
+ /**
267
+ * Subtotal for main products + montage including VAT
268
+ */
269
+ const mainSubtotalInclVat = mainProductsInclVat + montageInclVat;
270
+
271
+ /**
272
+ * Subtotal for main products + montage excluding VAT
273
+ */
274
+ const mainSubtotalExclVat = mainProductsExclVat + montageExclVat;
275
+
276
+ // ===== TOTALS BEFORE DISCOUNT =====
277
+ /**
278
+ * Total purchase price (without montage)
279
+ */
280
+ const totalPurchase = mainProductsPurchase + accessoriesPurchase;
281
+
282
+ /**
283
+ * Total price excluding VAT
284
+ */
285
+ const totalExclVat = mainSubtotalExclVat + accessoriesExclVat;
286
+
287
+ /**
288
+ * Total price including VAT
289
+ */
290
+ const totalInclVat = mainSubtotalInclVat + accessoriesInclVat;
291
+
292
+ /**
293
+ * VAT amount
294
+ */
295
+ const totalVat = totalInclVat - totalExclVat;
296
+
297
+ // ===== DISCOUNT CALCULATIONS =====
298
+ /**
299
+ * Calculate discount amount
300
+ */
301
+ const getDiscountAmount = () => {
174
302
  if (discountPercentage) {
175
- return totalPrice * discountPercentage / 100;
303
+ return totalInclVat * discountPercentage / 100;
176
304
  }
177
305
  if (discountAmount) {
178
306
  return discountAmount;
179
307
  }
180
308
  return 0;
181
309
  };
310
+ const discountTotal = getDiscountAmount();
311
+ const discountExclVat = discountTotal / 1.21;
312
+ const discountVat = discountTotal - discountExclVat;
182
313
 
183
- // Calculate original total
184
- const calculateOriginalTotal = () => {
185
- return subtotalPriceProducts + subtotalPriceAccessoires;
186
- };
314
+ // ===== TOTALS AFTER DISCOUNT =====
315
+ /**
316
+ * Final price excluding VAT (after discount)
317
+ */
318
+ const finalExclVat = Math.max(0, totalExclVat - discountExclVat);
187
319
 
188
- // Calculate final totals
189
- const calculateFinalTotals = () => {
190
- const totalDiscount = calculateTotalDiscount();
191
- const originalTotal = calculateOriginalTotal();
320
+ /**
321
+ * Final VAT amount (after discount)
322
+ */
323
+ const finalVat = Math.max(0, totalVat - discountVat);
192
324
 
193
- // Calculate the proportion of the discount that applies to the excl. VAT amount
194
- const discountExclVat = totalDiscount / 1.21; // Remove VAT from discount
195
- const discountVat = totalDiscount - discountExclVat;
196
- const baseExclVat = originalTotal / 1.21; // Original price excl VAT
197
- const baseVat = originalTotal - baseExclVat; // Original VAT amount
325
+ /**
326
+ * Final price including VAT (after discount)
327
+ */
328
+ const finalInclVat = Math.max(0, totalInclVat - discountTotal);
198
329
 
199
- return {
200
- exclVat: Math.max(0, baseExclVat - discountExclVat),
201
- vat: Math.max(0, baseVat - discountVat),
202
- total: Math.max(0, originalTotal - totalDiscount),
203
- originalTotal
204
- };
205
- };
330
+ /**
331
+ * Final purchase price after discount
332
+ */
333
+ const finalPurchase = Math.max(0, totalPurchase - discountExclVat * totalPurchase / totalExclVat);
206
334
  return /*#__PURE__*/_react.default.createElement("div", {
207
335
  className: (0, _helpers__.withStyle)("col-lg mt-3")
208
336
  }, /*#__PURE__*/_react.default.createElement(_TogglableCard.default, {
@@ -225,30 +353,50 @@ const ProductCartSide = () => {
225
353
  heading: 'Trekhaakmontage'
226
354
  }, mainProducts.map(product => {
227
355
  var _product$images, _product$images2;
356
+ const cartItem = cart === null || cart === void 0 ? void 0 : cart.find(item => item.articleNumber === product.articleNumber);
357
+ const {
358
+ purchasePrice,
359
+ salesPriceInclVat
360
+ } = getItemPrices(cartItem);
228
361
  return /*#__PURE__*/_react.default.createElement(_ProductTableStaticRow.default, {
229
362
  key: product.articleNumber,
230
- productTitle: product.name || product.subgroupName,
363
+ productTitle: product.name || product.title || product.subgroupName,
231
364
  productImage: product !== null && product !== void 0 && (_product$images = product.images) !== null && _product$images !== void 0 && _product$images[0] ? (0, _image.getImageFromHyper)({
232
365
  imageId: (_product$images2 = product.images) === null || _product$images2 === void 0 ? void 0 : _product$images2[0]
233
366
  }) : _logoPrimary.default,
234
367
  extraCells: [{}, {
235
- text: (0, _helpers__.formatPrice)(getItemPrice(cart === null || cart === void 0 ? void 0 : cart.find(item => item.articleNumber === product.articleNumber)) || 0),
368
+ text: (0, _helpers__.formatPrice)(isToggled ? purchasePrice : salesPriceInclVat),
236
369
  className: 'cart__table-purchase-price text-end'
237
370
  }]
238
371
  });
372
+ }), /*#__PURE__*/_react.default.createElement(_ProductTableStaticRow.default, {
373
+ productTitle: "Montage",
374
+ productImage: _montagePlaceholder.default,
375
+ extraCells: [{}, {
376
+ text: isToggled ? montageExclVat > 0 ? (0, _helpers__.formatPrice)(montageExclVat) : 'N.v.t.' : (0, _helpers__.formatPrice)(montageInclVat),
377
+ className: 'cart__table-purchase-price text-end'
378
+ }]
239
379
  }), /*#__PURE__*/_react.default.createElement(_ProductTableSectionTotal.default, {
240
- isEditable: false,
380
+ isEditable: true,
381
+ editLabel: 'Wijzig je trekhaakpakket',
382
+ editLink: '/configurator/trekhaakpakket',
241
383
  extraCells: [{}, {
242
384
  text: isToggled ? 'Subtotaal (excl. btw)' : 'Subtotaal (incl. btw)',
243
385
  className: 'fw-bold text-end pb-2'
244
386
  }, {
245
- text: (0, _helpers__.formatPrice)(subtotalPriceProducts),
387
+ text: (0, _helpers__.formatPrice)(isToggled ? mainSubtotalExclVat : mainSubtotalInclVat),
246
388
  className: 'fw-bold text-end pb-2'
247
389
  }]
248
390
  })), accessoireProducts.length > 0 && /*#__PURE__*/_react.default.createElement(_ProductTableSection.default, {
249
391
  heading: 'Toebehoren'
250
392
  }, accessoireProducts.map(product => {
251
393
  var _product$images3, _product$images4;
394
+ const cartItem = cart === null || cart === void 0 ? void 0 : cart.find(item => item.articleNumber === product.articleNumber);
395
+ const {
396
+ purchasePrice,
397
+ salesPriceInclVat
398
+ } = getItemPrices(cartItem);
399
+ const quantity = selectedExtras[product.articleNumber] || 1;
252
400
  return /*#__PURE__*/_react.default.createElement(_ProductTableEditableRow.default, {
253
401
  key: product.articleNumber,
254
402
  productTitle: product.name,
@@ -256,7 +404,7 @@ const ProductCartSide = () => {
256
404
  imageId: (_product$images4 = product.images) === null || _product$images4 === void 0 ? void 0 : _product$images4[0]
257
405
  }) : _logoPrimary.default,
258
406
  extraCells: [{}, {
259
- text: (0, _helpers__.formatPrice)(getItemPrice(cart === null || cart === void 0 ? void 0 : cart.find(item => item.articleNumber === product.articleNumber)) || 0),
407
+ text: (0, _helpers__.formatPrice)(isToggled ? purchasePrice * quantity : salesPriceInclVat * quantity),
260
408
  className: 'cart__table-purchase-price text-end'
261
409
  }],
262
410
  productAmount: selectedExtras[product.articleNumber],
@@ -285,41 +433,29 @@ const ProductCartSide = () => {
285
433
  text: isToggled ? 'Subtotaal (excl. btw)' : 'Subtotaal (incl. btw)',
286
434
  className: 'fw-bold text-end pb-2'
287
435
  }, {
288
- text: (0, _helpers__.formatPrice)(subtotalPriceAccessoires),
436
+ text: (0, _helpers__.formatPrice)(isToggled ? accessoriesExclVat : accessoriesInclVat),
289
437
  className: 'fw-bold text-end pb-2'
290
438
  }]
291
439
  })), /*#__PURE__*/_react.default.createElement(_ProductTableTotal.default, {
292
- rows: [...(isToggled ? [[{}, {
440
+ rows: [[{}, {
293
441
  text: 'Producten (excl. btw)',
294
442
  className: 'text-end pt-2'
295
443
  }, {
296
- text: (0, _helpers__.formatPrice)(calculateFinalTotals().exclVat),
444
+ text: (0, _helpers__.formatPrice)(totalExclVat),
297
445
  className: 'text-end pt-2'
298
- }], [{}, {
446
+ }], ...(isToggled ? [[{}, {
299
447
  text: 'btw',
300
448
  className: 'text-end'
301
449
  }, {
302
- text: (0, _helpers__.formatPrice)(calculateFinalTotals().vat),
450
+ text: (0, _helpers__.formatPrice)(totalVat),
303
451
  className: 'text-end'
304
- }], [{}, {
305
- text: 'Totaal (incl. btw)',
306
- className: 'fw-bold text-end'
307
- }, {
308
- text: (0, _helpers__.formatPrice)(calculateOriginalTotal()),
309
- className: 'fw-bold text-end'
310
- }]] : [[{}, {
311
- text: 'Producten (excl. btw)',
312
- className: 'text-end pt-2'
313
- }, {
314
- text: (0, _helpers__.formatPrice)(calculateFinalTotals().exclVat),
315
- className: 'text-end pt-2'
316
- }], [{}, {
452
+ }]] : []), [{}, {
317
453
  text: 'Totaal (incl. btw)',
318
454
  className: 'fw-bold text-end'
319
455
  }, {
320
- text: (0, _helpers__.formatPrice)(calculateOriginalTotal()),
456
+ text: (0, _helpers__.formatPrice)(totalInclVat),
321
457
  className: 'fw-bold text-end'
322
- }]])]
458
+ }]]
323
459
  }), (discountAmount || discountPercentage) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("td", {
324
460
  colSpan: "3",
325
461
  className: (0, _helpers__.withStyle)('pt-4 pb-2')
@@ -328,25 +464,25 @@ const ProductCartSide = () => {
328
464
  text: discountPercentage ? "Correctie (".concat(discountPercentage, "%)") : 'Correctie',
329
465
  className: 'text-end text-success'
330
466
  }, {
331
- text: "-".concat((0, _helpers__.formatPrice)(calculateTotalDiscount())),
467
+ text: "-".concat((0, _helpers__.formatPrice)(discountTotal)),
332
468
  className: 'text-end text-success'
333
- }], ...(isToggled ? [[{}, {
469
+ }], [{}, {
334
470
  text: 'Totaal na correctie (excl. btw)',
335
471
  className: 'text-end'
336
472
  }, {
337
- text: (0, _helpers__.formatPrice)(calculateFinalTotals().exclVat),
473
+ text: (0, _helpers__.formatPrice)(finalExclVat),
338
474
  className: 'text-end'
339
- }], [{}, {
340
- text: 'Correctie btw',
475
+ }], ...(isToggled ? [[{}, {
476
+ text: 'btw',
341
477
  className: 'text-end'
342
478
  }, {
343
- text: (0, _helpers__.formatPrice)(calculateFinalTotals().vat),
479
+ text: (0, _helpers__.formatPrice)(finalVat),
344
480
  className: 'text-end'
345
481
  }]] : []), [{}, {
346
482
  text: 'Totaal na correctie (incl. btw)',
347
483
  className: 'fw-bold text-end'
348
484
  }, {
349
- text: (0, _helpers__.formatPrice)(calculateFinalTotals().total),
485
+ text: (0, _helpers__.formatPrice)(finalInclVat),
350
486
  className: 'fw-bold text-end'
351
487
  }]]
352
488
  }))))));