thm-p3-configurator 0.0.42 → 0.0.44

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.
Files changed (40) hide show
  1. package/dist/src/shared/App.js +3 -3
  2. package/dist/src/shared/__api__/authenticatedProxyApi.js +13 -0
  3. package/dist/src/shared/__api__/queries.js +36 -6
  4. package/dist/src/shared/__components__/Cards/TogglableCard.js +2 -1
  5. package/dist/src/shared/__components__/Form/DropdownInput.js +3 -1
  6. package/dist/src/shared/__components__/Form/NumericInput.js +2 -2
  7. package/dist/src/shared/__components__/LocationsSelector/LocationAutoComplete.js +2 -0
  8. package/dist/src/shared/__components__/LocationsSelector/LocationClusteredMap.js +49 -23
  9. package/dist/src/shared/__components__/LocationsSelector/LocationClusteredTreeMarkers.js +28 -5
  10. package/dist/src/shared/__components__/LocationsSelector/LocationInfo.js +67 -7
  11. package/dist/src/shared/__components__/LocationsSelector/LocationList.js +2 -1
  12. package/dist/src/shared/__components__/LocationsSelector/LocationListItem.js +3 -2
  13. package/dist/src/shared/__components__/LocationsSelector/LocationTreeMarker.js +37 -21
  14. package/dist/src/shared/__components__/LocationsSelector/index.js +4 -3
  15. package/dist/src/shared/__components__/ProductCard/ProductCardDescription.js +12 -1
  16. package/dist/src/shared/__components__/ProductCard/ProductCardDiscountAlert.js +4 -0
  17. package/dist/src/shared/__components__/ProductCard/ProductCardSpecifications.js +1 -1
  18. package/dist/src/shared/__components__/ProductCard/ProductCardUsps.js +1 -1
  19. package/dist/src/shared/__components__/ProductCard/index.js +6 -3
  20. package/dist/src/shared/__constants__/index.js +3 -2
  21. package/dist/src/shared/__containers__/AppointmentForm.js +4 -17
  22. package/dist/src/shared/__containers__/BoardComputerCard.js +1 -1
  23. package/dist/src/shared/__containers__/DiscountProductsSelector.js +1 -1
  24. package/dist/src/shared/__containers__/ExitIntentModal.js +3 -2
  25. package/dist/src/shared/__containers__/ExtraProductsOverview.js +154 -31
  26. package/dist/src/shared/__containers__/ProductsCartOverview.js +175 -47
  27. package/dist/src/shared/__containers__/ProductsOverview.js +11 -0
  28. package/dist/src/shared/__containers__/internal/InternalAppointmentForm.js +29 -29
  29. package/dist/src/shared/__containers__/internal/InternalDiscountCodeSelector.js +77 -0
  30. package/dist/src/shared/__containers__/internal/InternalQuotationForm.js +12 -12
  31. package/dist/src/shared/__containers__/internal/index.js +7 -0
  32. package/dist/src/shared/__context__/OrderSessionContext.js +2 -0
  33. package/dist/src/shared/__helpers__/dossier.js +5 -8
  34. package/dist/src/shared/__pages__/LicensePlatePage.js +2 -1
  35. package/dist/src/shared/__pages__/ManualSelectionPage.js +2 -1
  36. package/dist/src/shared/__pages__/internal/InternalLicensePlatePage.js +2 -1
  37. package/dist/src/shared/__pages__/internal/InternalManualSelectionPage.js +2 -1
  38. package/dist/src/shared/__pages__/internal/InternalOverviewPage.js +1 -1
  39. package/dist/src/shared/__pages__/internal/__TEST_ONLY_INTERNAL_ROUTES.js +80 -0
  40. package/package.json +1 -1
@@ -25,7 +25,7 @@ var _FormulaContext = require("./__context__/FormulaContext");
25
25
  var _OrderSessionContext = require("./__context__/OrderSessionContext");
26
26
  var _cookiebot = require("./__helpers__/cookiebot");
27
27
  var _queryClient = _interopRequireDefault(require("./__helpers__/queryClient"));
28
- var _pages__ = _interopRequireDefault(require("./__pages__"));
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"));
@@ -69,11 +69,11 @@ const App = () => {
69
69
  (0, _Experiments.default)();
70
70
  });
71
71
  return /*#__PURE__*/_react.default.createElement(_SentryWrapper.default, null, /*#__PURE__*/_react.default.createElement(_FormulaContext.FormulaController, {
72
- defaultFormula: _constants__.CONFIGURATOR_FORMULAS.THC
72
+ defaultFormula: _constants__.CONFIGURATOR_FORMULAS.THM
73
73
  }, /*#__PURE__*/_react.default.createElement(_CountryContext.CountryController, {
74
74
  defaultCountry: APP_CONFIG.country
75
75
  }, /*#__PURE__*/_react.default.createElement(_OrderSessionContext.OrderSessionController, null, /*#__PURE__*/_react.default.createElement(_reactQuery.QueryClientProvider, {
76
76
  client: _queryClient.default
77
- }, /*#__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(_pages__.default, null))))))))));
77
+ }, /*#__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))))))))));
78
78
  };
79
79
  var _default = exports.default = App;
@@ -89,5 +89,18 @@ const authenticatedProxyApi = exports.authenticatedProxyApi = {
89
89
  'Content-Type': 'application/json'
90
90
  }
91
91
  });
92
+ },
93
+ getActiveDiscounts: _ref3 => {
94
+ let {
95
+ formulaCode,
96
+ limit,
97
+ offset
98
+ } = _ref3;
99
+ return authenticateClient("api/v1/discounts?limit=".concat(limit, "&offset=").concat(offset, "&formulaCode=").concat(formulaCode), {
100
+ method: 'GET',
101
+ headers: {
102
+ 'Content-Type': 'application/json'
103
+ }
104
+ });
92
105
  }
93
106
  };
@@ -8,7 +8,7 @@ require("core-js/modules/web.url-search-params.js");
8
8
  Object.defineProperty(exports, "__esModule", {
9
9
  value: true
10
10
  });
11
- exports.useQuestionsQuery = exports.useProductsQuery = exports.useProductFieldLabels = exports.usePrivateDossierByTypeAndIdQuery = exports.useMyBranches = exports.useModelsQuery = exports.useMarketingChannels = exports.useBuildYearsQuery = exports.useBrandsQuery = exports.useBranchesQuery = exports.useBranchTypes = exports.useBranchByIdOrWidgetId = void 0;
11
+ exports.useQuestionsQuery = exports.useProductsQuery = exports.useProductFieldLabels = exports.usePrivateDossierByTypeAndIdQuery = exports.useMyBranches = exports.useModelsQuery = exports.useMarketingChannels = exports.useBuildYearsQuery = exports.useBrandsQuery = exports.useBranchesQuery = exports.useBranchTypes = exports.useBranchByIdOrWidgetId = exports.useActiveDiscounts = void 0;
12
12
  require("core-js/modules/es.symbol.description.js");
13
13
  require("core-js/modules/es.json.stringify.js");
14
14
  require("core-js/modules/es.regexp.to-string.js");
@@ -127,7 +127,7 @@ const useModelsQuery = _ref2 => {
127
127
  */
128
128
  exports.useModelsQuery = useModelsQuery;
129
129
  const useProductsQuery = orderParameters => {
130
- var _productsQuery$data, _productsQuery$data2, _productsQuery$data3, _productsQuery$data4, _productsQuery$data5, _productsQuery$data6, _productsQuery$data7, _productsQuery$data8, _productsQuery$data9, _productsQuery$data$a, _productsQuery$data10, _productsQuery$data11, _productsQuery$data$a2, _productsQuery$data12, _productsQuery$data$a3, _productsQuery$data13, _productsQuery$data$a4, _productsQuery$data14, _productsQuery$data15, _productsQuery$data16;
130
+ var _productsQuery$data, _productsQuery$data2, _productsQuery$data3, _productsQuery$data4, _productsQuery$data5, _productsQuery$data6, _productsQuery$data7, _productsQuery$data8, _productsQuery$data9, _productsQuery$data$a, _productsQuery$data10, _productsQuery$data$c, _productsQuery$data11, _productsQuery$data$a2, _productsQuery$data12, _productsQuery$data$a3, _productsQuery$data13, _productsQuery$data$a4, _productsQuery$data14, _productsQuery$data15, _productsQuery$data16, _productsQuery$data$a5, _productsQuery$data17, _productsQuery$data$t, _productsQuery$data18;
131
131
  const {
132
132
  licensePlate,
133
133
  model
@@ -156,13 +156,15 @@ const useProductsQuery = orderParameters => {
156
156
  },
157
157
  discountCodeInfo: productsQuery === null || productsQuery === void 0 || (_productsQuery$data9 = productsQuery.data) === null || _productsQuery$data9 === void 0 ? void 0 : _productsQuery$data9.discountCodeInfo,
158
158
  discountProducts: (_productsQuery$data$a = productsQuery === null || productsQuery === void 0 || (_productsQuery$data10 = productsQuery.data) === null || _productsQuery$data10 === void 0 || (_productsQuery$data10 = _productsQuery$data10.articles) === null || _productsQuery$data10 === void 0 ? void 0 : _productsQuery$data10.discountCode) !== null && _productsQuery$data$a !== void 0 ? _productsQuery$data$a : [],
159
- cart: productsQuery === null || productsQuery === void 0 || (_productsQuery$data11 = productsQuery.data) === null || _productsQuery$data11 === void 0 ? void 0 : _productsQuery$data11.cart,
159
+ cart: (_productsQuery$data$c = productsQuery === null || productsQuery === void 0 || (_productsQuery$data11 = productsQuery.data) === null || _productsQuery$data11 === void 0 ? void 0 : _productsQuery$data11.cart) !== null && _productsQuery$data$c !== void 0 ? _productsQuery$data$c : [],
160
160
  products: {
161
161
  [_constants__.PRODUCT_CATEGORIES.TOWBAR]: (_productsQuery$data$a2 = productsQuery === null || productsQuery === void 0 || (_productsQuery$data12 = productsQuery.data) === null || _productsQuery$data12 === void 0 || (_productsQuery$data12 = _productsQuery$data12.articles) === null || _productsQuery$data12 === void 0 ? void 0 : _productsQuery$data12.towbars) !== null && _productsQuery$data$a2 !== void 0 ? _productsQuery$data$a2 : [],
162
162
  [_constants__.PRODUCT_CATEGORIES.CABLESET]: (_productsQuery$data$a3 = productsQuery === null || productsQuery === void 0 || (_productsQuery$data13 = productsQuery.data) === null || _productsQuery$data13 === void 0 || (_productsQuery$data13 = _productsQuery$data13.articles) === null || _productsQuery$data13 === void 0 ? void 0 : _productsQuery$data13.cablesets) !== null && _productsQuery$data$a3 !== void 0 ? _productsQuery$data$a3 : [],
163
163
  [_constants__.PRODUCT_CATEGORIES.COMBISET]: (_productsQuery$data$a4 = productsQuery === null || productsQuery === void 0 || (_productsQuery$data14 = productsQuery.data) === null || _productsQuery$data14 === void 0 || (_productsQuery$data14 = _productsQuery$data14.articles) === null || _productsQuery$data14 === void 0 ? void 0 : _productsQuery$data14.combisets) !== null && _productsQuery$data$a4 !== void 0 ? _productsQuery$data$a4 : [],
164
- [_constants__.PRODUCT_CATEGORIES.BOARD_COMPUTER]: productsQuery !== null && productsQuery !== void 0 && (_productsQuery$data15 = productsQuery.data) !== null && _productsQuery$data15 !== void 0 && (_productsQuery$data15 = _productsQuery$data15.articles) !== null && _productsQuery$data15 !== void 0 && _productsQuery$data15.boardComputerUpdate ? [productsQuery === null || productsQuery === void 0 || (_productsQuery$data16 = productsQuery.data) === null || _productsQuery$data16 === void 0 || (_productsQuery$data16 = _productsQuery$data16.articles) === null || _productsQuery$data16 === void 0 ? void 0 : _productsQuery$data16.boardComputerUpdate] : []
165
- }
164
+ [_constants__.PRODUCT_CATEGORIES.BOARD_COMPUTER]: productsQuery !== null && productsQuery !== void 0 && (_productsQuery$data15 = productsQuery.data) !== null && _productsQuery$data15 !== void 0 && (_productsQuery$data15 = _productsQuery$data15.articles) !== null && _productsQuery$data15 !== void 0 && _productsQuery$data15.boardComputerUpdate ? [productsQuery === null || productsQuery === void 0 || (_productsQuery$data16 = productsQuery.data) === null || _productsQuery$data16 === void 0 || (_productsQuery$data16 = _productsQuery$data16.articles) === null || _productsQuery$data16 === void 0 ? void 0 : _productsQuery$data16.boardComputerUpdate] : [],
165
+ [_constants__.PRODUCT_CATEGORIES.EXTRAS]: (_productsQuery$data$a5 = productsQuery === null || productsQuery === void 0 || (_productsQuery$data17 = productsQuery.data) === null || _productsQuery$data17 === void 0 || (_productsQuery$data17 = _productsQuery$data17.articles) === null || _productsQuery$data17 === void 0 ? void 0 : _productsQuery$data17.extras) !== null && _productsQuery$data$a5 !== void 0 ? _productsQuery$data$a5 : []
166
+ },
167
+ totals: (_productsQuery$data$t = productsQuery === null || productsQuery === void 0 || (_productsQuery$data18 = productsQuery.data) === null || _productsQuery$data18 === void 0 ? void 0 : _productsQuery$data18.totals) !== null && _productsQuery$data$t !== void 0 ? _productsQuery$data$t : []
166
168
  };
167
169
  };
168
170
 
@@ -329,4 +331,32 @@ const usePrivateDossierByTypeAndIdQuery = _ref3 => {
329
331
  dossierById: dossierByIdQuery === null || dossierByIdQuery === void 0 ? void 0 : dossierByIdQuery.data
330
332
  };
331
333
  };
332
- exports.usePrivateDossierByTypeAndIdQuery = usePrivateDossierByTypeAndIdQuery;
334
+
335
+ /**
336
+ * @description Query the discounts from Hyper, allows for pagination and filtering with formula
337
+ */
338
+ exports.usePrivateDossierByTypeAndIdQuery = usePrivateDossierByTypeAndIdQuery;
339
+ const useActiveDiscounts = _ref4 => {
340
+ var _discountsQuery$data;
341
+ let {
342
+ formulaCode,
343
+ offset,
344
+ limit,
345
+ authSession
346
+ } = _ref4;
347
+ const discountsQuery = (0, _reactQuery.useQuery)({
348
+ queryKey: ['discounts', formulaCode, offset, limit, authSession],
349
+ queryFn: () => _authenticatedProxyApi.authenticatedProxyApi.getActiveDiscounts({
350
+ formulaCode,
351
+ offset,
352
+ limit
353
+ }),
354
+ retry: true
355
+ });
356
+ return {
357
+ isLoadingDiscounts: discountsQuery.isLoading,
358
+ discountsError: discountsQuery.isError,
359
+ discounts: discountsQuery === null || discountsQuery === void 0 || (_discountsQuery$data = discountsQuery.data) === null || _discountsQuery$data === void 0 ? void 0 : _discountsQuery$data.data
360
+ };
361
+ };
362
+ exports.useActiveDiscounts = useActiveDiscounts;
@@ -36,6 +36,7 @@ function _interopRequireWildcard(e, r) {
36
36
  return n.default = e, t && t.set(e, n), n;
37
37
  }
38
38
  const TogglableCard = _ref => {
39
+ var _APP_CONFIG;
39
40
  let {
40
41
  title,
41
42
  toggleButton,
@@ -52,7 +53,7 @@ const TogglableCard = _ref => {
52
53
  className: (0, _helpers__.withStyle)('card card__default')
53
54
  }, /*#__PURE__*/_react.default.createElement("div", {
54
55
  className: (0, _helpers__.withStyle)('card-header')
55
- }, title, /*#__PURE__*/_react.default.createElement("button", {
56
+ }, title, ((_APP_CONFIG = APP_CONFIG) === null || _APP_CONFIG === void 0 ? void 0 : _APP_CONFIG.internal) && /*#__PURE__*/_react.default.createElement("button", {
56
57
  className: (0, _helpers__.withStyle)("cart__price-switch link-white ".concat(isToggled ? 'active' : '')),
57
58
  type: "button",
58
59
  "data-bs-toggle": "collapse",
@@ -103,7 +103,8 @@ const DropdownInput = _ref => {
103
103
  onChange,
104
104
  form,
105
105
  initialValue,
106
- errorMessage = ''
106
+ errorMessage = '',
107
+ isClearable = false
107
108
  } = _ref;
108
109
  const [value, setValue] = (0, _react.useState)(initialValue);
109
110
  const lgSize = window.matchMedia('(min-width: 960px)');
@@ -122,6 +123,7 @@ const DropdownInput = _ref => {
122
123
  className: (0, _helpers__.withStyle)('form-label')
123
124
  }, label, isRequired && /*#__PURE__*/_react.default.createElement("span", null, "*")), /*#__PURE__*/_react.default.createElement(_reactSelect.default, {
124
125
  id: name,
126
+ isClearable: isClearable,
125
127
  name: name,
126
128
  form: form,
127
129
  value: value,
@@ -79,10 +79,10 @@ const NumericInput = _ref => {
79
79
  setValue(value);
80
80
  onChange(value);
81
81
  };
82
- return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", {
82
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, label && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, ' ', /*#__PURE__*/_react.default.createElement("label", {
83
83
  htmlFor: name,
84
84
  className: (0, _helpers__.withStyle)('form-label')
85
- }, label, isRequired && /*#__PURE__*/_react.default.createElement("span", null, "*")), ' ', /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement(_reactNumericInput.default, {
85
+ }, label, isRequired && /*#__PURE__*/_react.default.createElement("span", null, "*")), ' ', /*#__PURE__*/_react.default.createElement("br", null), ' '), /*#__PURE__*/_react.default.createElement(_reactNumericInput.default, {
86
86
  mobile: true,
87
87
  strict: true,
88
88
  className: (0, _helpers__.withStyle)('form-control react-numeric-input'),
@@ -109,6 +109,7 @@ const LocationAutoComplete = _ref => {
109
109
  fetchPredictions(value);
110
110
  }, [fetchPredictions]);
111
111
  const handleSuggestionClick = (0, _react.useCallback)(placeId => {
112
+ var _document$querySelect;
112
113
  if (!places) return;
113
114
  const detailRequestOptions = {
114
115
  placeId,
@@ -134,6 +135,7 @@ const LocationAutoComplete = _ref => {
134
135
  }
135
136
  };
136
137
  placesService === null || placesService === void 0 || placesService.getDetails(detailRequestOptions, detailsRequestCallback);
138
+ (_document$querySelect = document.querySelector((0, _helpers__.withStyle)("dealer-autocomplete__list"))) === null || _document$querySelect === void 0 || _document$querySelect.scrollTo(0, 0);
137
139
  }, [places, placesService, sessionToken, setUserLocation]);
138
140
  return /*#__PURE__*/_react.default.createElement("form", {
139
141
  className: (0, _helpers__.withStyle)('dealer-autocomplete mb-2')
@@ -2,7 +2,9 @@
2
2
 
3
3
  require("core-js/modules/es.weak-map.js");
4
4
  require("core-js/modules/esnext.iterator.constructor.js");
5
+ require("core-js/modules/esnext.iterator.filter.js");
5
6
  require("core-js/modules/esnext.iterator.for-each.js");
7
+ require("core-js/modules/esnext.iterator.map.js");
6
8
  require("core-js/modules/web.dom-collections.iterator.js");
7
9
  require("core-js/modules/es.weak-map.js");
8
10
  require("core-js/modules/web.dom-collections.iterator.js");
@@ -11,7 +13,9 @@ Object.defineProperty(exports, "__esModule", {
11
13
  });
12
14
  exports.default = void 0;
13
15
  require("core-js/modules/esnext.iterator.constructor.js");
16
+ require("core-js/modules/esnext.iterator.filter.js");
14
17
  require("core-js/modules/esnext.iterator.for-each.js");
18
+ require("core-js/modules/esnext.iterator.map.js");
15
19
  var _reactGoogleMaps = require("@vis.gl/react-google-maps");
16
20
  var _lodash = _interopRequireDefault(require("lodash.debounce"));
17
21
  var _react = _interopRequireWildcard(require("react"));
@@ -49,38 +53,58 @@ function _interopRequireDefault(e) {
49
53
  default: e
50
54
  };
51
55
  }
52
- const LocationClusteredMap = _ref => {
56
+ const LocationClusteredMap = /*#__PURE__*/_react.default.memo(_ref => {
53
57
  let {
54
58
  locationIds,
55
59
  locationsById,
56
60
  userLocation
57
61
  } = _ref;
58
62
  const map = (0, _reactGoogleMaps.useMap)();
63
+ const core = (0, _reactGoogleMaps.useMapsLibrary)('core');
64
+ const bounds = (0, _react.useMemo)(() => {
65
+ return core ? new core.LatLngBounds() : null;
66
+ }, [core]);
59
67
  const fitBoundsToMarkers = (0, _react.useCallback)(() => {
60
- if (!map || locationIds.length === 0) {
61
- return;
62
- }
63
- const bounds = new google.maps.LatLngBounds();
68
+ if (!map || !bounds || locationIds.length === 0) return;
64
69
  if (userLocation) {
65
- bounds.extend(new google.maps.LatLng(userLocation.lat, userLocation.lng));
70
+ bounds.extend(new core.LatLng(userLocation.lat, userLocation.lng));
66
71
  map.fitBounds(bounds);
67
72
  map.setZoom(10);
68
- } else {
69
- locationIds.forEach(locationId => {
70
- const location = locationsById[locationId];
71
- const coordinates = (0, _geolocation.getCoordinatesByString)(location.googleMapsLocation);
72
- if (!coordinates) {
73
- return;
74
- }
75
- bounds.extend(new google.maps.LatLng(coordinates.lat, coordinates.lng));
76
- });
77
- map.fitBounds(bounds);
73
+ return;
78
74
  }
79
- }, [map, locationIds, locationsById, userLocation]);
75
+
76
+ // Batch coordinate calculations
77
+ const validCoordinates = locationIds.map(id => locationsById[id]).map(location => (0, _geolocation.getCoordinatesByString)(location.googleMapsLocation)).filter(Boolean);
78
+ validCoordinates.forEach(_ref2 => {
79
+ let {
80
+ lat,
81
+ lng
82
+ } = _ref2;
83
+ bounds.extend(new core.LatLng(lat, lng));
84
+ });
85
+ map.fitBounds(bounds);
86
+ }, [map, bounds, locationIds, locationsById, userLocation, core]);
87
+
88
+ // Debounce bounds fitting
80
89
  (0, _react.useEffect)(() => {
81
- const debounceFitBounds = (0, _lodash.default)(fitBoundsToMarkers, 300);
90
+ if (!core) return;
91
+ const debounceFitBounds = (0, _lodash.default)(fitBoundsToMarkers, 150);
82
92
  debounceFitBounds();
83
- }, [fitBoundsToMarkers]);
93
+ return () => debounceFitBounds.cancel();
94
+ }, [fitBoundsToMarkers, core]);
95
+ const mapOptions = (0, _react.useMemo)(() => ({
96
+ maxZoom: 18,
97
+ minZoom: 3,
98
+ clickableIcons: false,
99
+ styles: [{
100
+ featureType: 'poi',
101
+ elementType: 'labels',
102
+ stylers: [{
103
+ visibility: 'off'
104
+ }]
105
+ }],
106
+ optimized: true
107
+ }), []);
84
108
  return /*#__PURE__*/_react.default.createElement("div", {
85
109
  className: "dealer-map ".concat((0, _helpers__.withStyle)('dealer-map'))
86
110
  }, /*#__PURE__*/_react.default.createElement(_reactGoogleMaps.Map, {
@@ -91,14 +115,16 @@ const LocationClusteredMap = _ref => {
91
115
  lng: _constants__.DEFAULT_MAP_LONGITUDE
92
116
  },
93
117
  gestureHandling: 'greedy',
94
- disableDefaultUI: true
95
- }, userLocation && /*#__PURE__*/_react.default.createElement(_reactGoogleMaps.Marker, {
118
+ disableDefaultUI: true,
119
+ options: mapOptions
120
+ }, userLocation && core && /*#__PURE__*/_react.default.createElement(_reactGoogleMaps.Marker, {
96
121
  optimized: true,
97
122
  position: userLocation,
98
- name: "Uw locatie"
123
+ title: "Uw locatie",
124
+ zIndex: 2
99
125
  }), locationIds && /*#__PURE__*/_react.default.createElement(_LocationClusteredTreeMarkers.default, {
100
126
  locationIds: locationIds,
101
127
  locationsById: locationsById
102
128
  })));
103
- };
129
+ });
104
130
  var _default = exports.default = LocationClusteredMap;
@@ -148,17 +148,40 @@ const LocationClusteredTreeMarkers = _ref => {
148
148
  const clusterer = (0, _react.useMemo)(() => {
149
149
  if (!map) return null;
150
150
  return new _markerclusterer.MarkerClusterer({
151
- map
151
+ map,
152
+ maxZoom: 15,
153
+ gridSize: 50,
154
+ minimumClusterSize: 2,
155
+ algorithm: _markerclusterer.MarkerClusterer.ALGORITHM_SIMPLE
152
156
  });
153
157
  }, [map]);
154
158
  const updateClustererMarkers = (0, _react.useCallback)((0, _lodash.default)(newMarkers => {
155
159
  if (!clusterer) return;
156
- clusterer.clearMarkers();
157
- clusterer.addMarkers(Object.values(newMarkers));
158
- }, 300), [clusterer]);
160
+
161
+ // Get current markers
162
+ const currentMarkers = clusterer.markers;
163
+ const newMarkerArray = Object.values(newMarkers);
164
+
165
+ // Only update if markers have changed
166
+ if (currentMarkers.length !== newMarkerArray.length) {
167
+ clusterer.clearMarkers();
168
+ if (newMarkerArray.length > 0) {
169
+ clusterer.addMarkers(newMarkerArray);
170
+ }
171
+ }
172
+ }, 150), [clusterer]);
159
173
  (0, _react.useEffect)(() => {
160
174
  updateClustererMarkers(markers);
161
175
  }, [markers, updateClustererMarkers]);
176
+
177
+ // Cleanup clusterer on unmount
178
+ (0, _react.useEffect)(() => {
179
+ return () => {
180
+ if (clusterer) {
181
+ clusterer.clearMarkers();
182
+ }
183
+ };
184
+ }, [clusterer]);
162
185
  const setMarkerRef = (0, _react.useCallback)((marker, key) => {
163
186
  setMarkers(prevMarkers => {
164
187
  if (marker && prevMarkers[key] || !marker && !prevMarkers[key]) return prevMarkers;
@@ -192,7 +215,7 @@ const LocationClusteredTreeMarkers = _ref => {
192
215
  },
193
216
  type: _OrderSessionContext.orderSessionActions.SET_SELECTED_BRANCH
194
217
  });
195
- }, [setActiveMarkerId, dispatch]);
218
+ }, [setActiveMarkerId, dispatch, selectedBranch]);
196
219
  const memoizedTreeMarkers = (0, _react.useMemo)(() => {
197
220
  return trees.map(tree => /*#__PURE__*/_react.default.createElement(_LocationTreeMarker.default, {
198
221
  key: tree === null || tree === void 0 ? void 0 : tree.entityId,
@@ -26,8 +26,38 @@ const LocationInfo = _ref => {
26
26
  city,
27
27
  telephoneNumber,
28
28
  locationImage,
29
- title
29
+ title,
30
+ email,
31
+ website,
32
+ province
30
33
  } = _ref;
34
+ const address = [street, postCode, city].join(', ');
35
+
36
+ /*
37
+ TODO: OPENING HOURS NOT IN PROXY BRANCH DATA FEED
38
+ */
39
+ const openingDays = [{
40
+ day: 'Maandag',
41
+ hours: 'Gesloten'
42
+ }, {
43
+ day: 'Dinsdag',
44
+ hours: '09:00 - 17:00'
45
+ }, {
46
+ day: 'Woensdag',
47
+ hours: '09:00 - 17:00'
48
+ }, {
49
+ day: 'Donderdag',
50
+ hours: '09:00 - 17:00'
51
+ }, {
52
+ day: 'Vrijdag',
53
+ hours: '09:00 - 17:00'
54
+ }, {
55
+ day: 'Zaterdag',
56
+ hours: '09:00 - 17:00'
57
+ }, {
58
+ day: 'Zondag',
59
+ hours: 'Gesloten'
60
+ }];
31
61
  return /*#__PURE__*/_react.default.createElement("div", {
32
62
  className: (0, _helpers__.withStyle)('dealer-map__infowindow p-0 shadow-none')
33
63
  }, /*#__PURE__*/_react.default.createElement("h4", {
@@ -36,14 +66,44 @@ const LocationInfo = _ref => {
36
66
  className: (0, _helpers__.withStyle)('row row__body no-gutters flex-md-nowrap justify-content-between align-items-start')
37
67
  }, /*#__PURE__*/_react.default.createElement("div", {
38
68
  className: (0, _helpers__.withStyle)('col-12 col-md-6 px-0')
39
- }, /*#__PURE__*/_react.default.createElement("ul", null, /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("i", {
69
+ }, /*#__PURE__*/_react.default.createElement("ul", {
70
+ className: (0, _helpers__.withStyle)('mb-2')
71
+ }, /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("i", {
40
72
  className: "fas fa-map-marker-alt ".concat((0, _helpers__.withStyle)('me-1'))
41
- }), ["".concat(street).concat(houseNumber ? " ".concat(houseNumber) : '').concat(houseNumberExtra ? " ".concat(houseNumberExtra) : ''), postCode, city].filter(item => item).join(', ')), telephoneNumber && /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("i", {
42
- className: "fas fa-phone-alt ".concat((0, _helpers__.withStyle)('me-1'))
73
+ }), ["".concat(street).concat(houseNumber ? " ".concat(houseNumber) : '').concat(houseNumberExtra ? " ".concat(houseNumberExtra) : ''), postCode, city].filter(item => item).join(', ')), telephoneNumber && /*#__PURE__*/_react.default.createElement("li", {
74
+ className: (0, _helpers__.withStyle)('mt-1')
75
+ }, /*#__PURE__*/_react.default.createElement("i", {
76
+ className: "fas fa-phone-alt ".concat((0, _helpers__.withStyle)('mx-1'))
77
+ }), /*#__PURE__*/_react.default.createElement("a", {
78
+ href: "tel:".concat(telephoneNumber)
79
+ }, /*#__PURE__*/_react.default.createElement("u", null, telephoneNumber))), email && /*#__PURE__*/_react.default.createElement("li", {
80
+ className: (0, _helpers__.withStyle)('mt-1')
81
+ }, /*#__PURE__*/_react.default.createElement("i", {
82
+ className: "fas fa-envelope ".concat((0, _helpers__.withStyle)('mx-1'))
83
+ }), /*#__PURE__*/_react.default.createElement("a", {
84
+ href: "mailto:".concat(email)
85
+ }, /*#__PURE__*/_react.default.createElement("u", null, email))), website && /*#__PURE__*/_react.default.createElement("li", {
86
+ className: (0, _helpers__.withStyle)('mt-1')
87
+ }, /*#__PURE__*/_react.default.createElement("i", {
88
+ className: "fas fa-globe ".concat((0, _helpers__.withStyle)('mx-1'))
43
89
  }), /*#__PURE__*/_react.default.createElement("a", {
44
- href: "tel:".concat(telephoneNumber),
45
- target: "_self"
46
- }, telephoneNumber)))), /*#__PURE__*/_react.default.createElement("div", {
90
+ href: website
91
+ }, /*#__PURE__*/_react.default.createElement("u", null, website)))), /*#__PURE__*/_react.default.createElement("p", {
92
+ className: (0, _helpers__.withStyle)('font-weight-bold d-none d-md-block')
93
+ }, /*#__PURE__*/_react.default.createElement("i", {
94
+ className: "fas fa-clock ".concat((0, _helpers__.withStyle)('mx-1'))
95
+ }), "Openingstijden"), /*#__PURE__*/_react.default.createElement("ul", {
96
+ className: (0, _helpers__.withStyle)('ml-3 d-none d-md-block')
97
+ }, openingDays.map((_ref2, key) => {
98
+ let {
99
+ day,
100
+ hours
101
+ } = _ref2;
102
+ return /*#__PURE__*/_react.default.createElement("li", {
103
+ key: key,
104
+ className: (0, _helpers__.withStyle)('d-flex align-content-center justify-content-between')
105
+ }, /*#__PURE__*/_react.default.createElement("p", null, day), /*#__PURE__*/_react.default.createElement("p", null, hours));
106
+ }))), /*#__PURE__*/_react.default.createElement("div", {
47
107
  className: (0, _helpers__.withStyle)('col-12 col-md-6 d-flex flex-column justify-content-evenly align-items-center')
48
108
  }, /*#__PURE__*/_react.default.createElement("img", {
49
109
  className: (0, _helpers__.withStyle)('mb-1'),
@@ -167,7 +167,8 @@ const LocationList = _ref => {
167
167
  distance: location.distance ? location.distance : null,
168
168
  id: location.entityId,
169
169
  key: location.entityId,
170
- isSelected: location.entityId === activeMarkerId || location.entityId === selectedBranch
170
+ isSelected: location.entityId === activeMarkerId || location.entityId === selectedBranch,
171
+ userLocation: userLocation
171
172
  })));
172
173
  };
173
174
  var _default = exports.default = LocationList;
@@ -43,7 +43,8 @@ const LocationListItem = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
43
43
  city,
44
44
  distance,
45
45
  id,
46
- isSelected
46
+ isSelected,
47
+ userLocation
47
48
  } = _ref;
48
49
  const [{
49
50
  selectedBranch
@@ -72,7 +73,7 @@ const LocationListItem = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
72
73
  className: (0, _helpers__.withStyle)('fw-bold text-black')
73
74
  }, city), /*#__PURE__*/_react.default.createElement("small", null, title)), /*#__PURE__*/_react.default.createElement("div", {
74
75
  className: (0, _helpers__.withStyle)('col-auto d-flex flex-column align-items-end justify-content-between text-end')
75
- }, isNaN(distance) === false && /*#__PURE__*/_react.default.createElement("p", {
76
+ }, userLocation && isNaN(distance) === false && /*#__PURE__*/_react.default.createElement("p", {
76
77
  className: (0, _helpers__.withStyle)('dealer-item__distance')
77
78
  }, /*#__PURE__*/_react.default.createElement("i", {
78
79
  className: "fas fa-map-marker-alt"
@@ -43,35 +43,51 @@ function _interopRequireWildcard(e, r) {
43
43
  }
44
44
  return n.default = e, t && t.set(e, n), n;
45
45
  }
46
- const LocationTreeMarker = props => {
47
- const {
46
+ const LocationTreeMarker = /*#__PURE__*/_react.default.memo(_ref => {
47
+ let {
48
48
  tree,
49
49
  onClick,
50
50
  setMarkerRef
51
- } = props;
51
+ } = _ref;
52
+ const core = (0, _reactGoogleMaps.useMapsLibrary)('core');
53
+
54
+ // Cache marker icon configuration
55
+ const markerIcon = (0, _react.useMemo)(() => {
56
+ if (!core) return {
57
+ url: _mapMarker.default
58
+ };
59
+ return {
60
+ url: _mapMarker.default,
61
+ size: new core.Size(32, 42),
62
+ anchor: new core.Point(16, 32),
63
+ scaledSize: new core.Size(32, 42)
64
+ };
65
+ }, [core]);
52
66
  const handleClick = (0, _react.useCallback)(() => onClick(tree), [onClick, tree]);
53
67
  const ref = (0, _react.useCallback)(marker => setMarkerRef(marker, tree === null || tree === void 0 ? void 0 : tree.entityId), [setMarkerRef, tree === null || tree === void 0 ? void 0 : tree.entityId]);
54
- const coordinates = tree === null || tree === void 0 ? void 0 : tree.googleMapsLocation;
55
- if (!coordinates) {
56
- return null;
57
- }
58
- const [latStr, lngStr] = coordinates.split(',');
59
- const lat = parseFloat(latStr);
60
- const lng = parseFloat(lngStr);
61
- if (isNaN(lat) || isNaN(lng)) {
62
- return null;
63
- }
68
+
69
+ // Memoize position calculation
70
+ const position = (0, _react.useMemo)(() => {
71
+ const coordinates = tree === null || tree === void 0 ? void 0 : tree.googleMapsLocation;
72
+ if (!coordinates) return null;
73
+ const [latStr, lngStr] = coordinates.split(',');
74
+ const lat = parseFloat(latStr);
75
+ const lng = parseFloat(lngStr);
76
+ return isNaN(lat) || isNaN(lng) ? null : {
77
+ lat,
78
+ lng
79
+ };
80
+ }, [tree === null || tree === void 0 ? void 0 : tree.googleMapsLocation]);
81
+ if (!position) return null;
64
82
  return /*#__PURE__*/_react.default.createElement(_reactGoogleMaps.Marker, {
65
83
  optimized: true,
66
- position: {
67
- lat: lat,
68
- lng: lng
69
- },
84
+ position: position,
70
85
  ref: ref,
71
86
  onClick: handleClick,
72
- icon: {
73
- url: _mapMarker.default
74
- }
87
+ icon: markerIcon,
88
+ clickable: true,
89
+ visible: true,
90
+ zIndex: 1
75
91
  });
76
- };
92
+ });
77
93
  var _default = exports.default = LocationTreeMarker;
@@ -87,10 +87,11 @@ const LocationsSelector = /*#__PURE__*/_react.default.memo(() => {
87
87
  }
88
88
  setVisibleIds([]);
89
89
  const addIdsInBatches = index => {
90
- const nextBatch = allIds.slice(index, index + 20);
90
+ const offset = 10;
91
+ const nextBatch = allIds.slice(index, index + offset);
91
92
  setVisibleIds(prev => [...prev, ...nextBatch]);
92
- if (index + 20 < allIds.length) {
93
- requestAnimationFrame(() => addIdsInBatches(index + 20));
93
+ if (index + offset < allIds.length) {
94
+ requestAnimationFrame(() => addIdsInBatches(index + offset));
94
95
  }
95
96
  };
96
97
  addIdsInBatches(0);
@@ -2,6 +2,7 @@
2
2
 
3
3
  require("core-js/modules/es.symbol.description.js");
4
4
  require("core-js/modules/es.weak-map.js");
5
+ require("core-js/modules/esnext.iterator.map.js");
5
6
  require("core-js/modules/web.dom-collections.iterator.js");
6
7
  require("core-js/modules/es.weak-map.js");
7
8
  Object.defineProperty(exports, "__esModule", {
@@ -9,6 +10,7 @@ Object.defineProperty(exports, "__esModule", {
9
10
  });
10
11
  exports.default = void 0;
11
12
  require("core-js/modules/es.symbol.description.js");
13
+ require("core-js/modules/esnext.iterator.map.js");
12
14
  require("core-js/modules/web.dom-collections.iterator.js");
13
15
  var _react = _interopRequireWildcard(require("react"));
14
16
  var _reactTruncate = _interopRequireDefault(require("react-truncate"));
@@ -48,6 +50,15 @@ const ProductCardDescription = _ref => {
48
50
  description
49
51
  } = _ref;
50
52
  const [isExpanded, setIsExpanded] = (0, _react.useState)(false);
53
+ const renderDescription = () => {
54
+ if (Array.isArray(description === null || description === void 0 ? void 0 : description.ops)) {
55
+ var _description$ops;
56
+ return description === null || description === void 0 || (_description$ops = description.ops) === null || _description$ops === void 0 ? void 0 : _description$ops.map((desc, index) => /*#__PURE__*/_react.default.createElement("span", {
57
+ key: index
58
+ }, desc.insert, index < description.length - 1 && ', '));
59
+ }
60
+ return description;
61
+ };
51
62
  return /*#__PURE__*/_react.default.createElement("p", null, /*#__PURE__*/_react.default.createElement(_reactTruncate.default, {
52
63
  lines: isExpanded ? 20 : 2,
53
64
  ellipsis: /*#__PURE__*/_react.default.createElement("span", null, "...", /*#__PURE__*/_react.default.createElement("a", {
@@ -56,7 +67,7 @@ const ProductCardDescription = _ref => {
56
67
  setIsExpanded(true);
57
68
  }
58
69
  }, "Meer informatie"))
59
- }, description), isExpanded && /*#__PURE__*/_react.default.createElement("a", {
70
+ }, renderDescription()), isExpanded && /*#__PURE__*/_react.default.createElement("a", {
60
71
  className: (0, _helpers__.withStyle)('link-primary mx-1'),
61
72
  onClick: () => {
62
73
  setIsExpanded(false);
@@ -37,6 +37,7 @@ function _interopRequireWildcard(e, r) {
37
37
  }
38
38
  const ProductCardDiscountAlert = _ref => {
39
39
  let {
40
+ label,
40
41
  price,
41
42
  discountedPrice
42
43
  } = _ref;
@@ -44,6 +45,9 @@ const ProductCardDiscountAlert = _ref => {
44
45
  return null;
45
46
  }
46
47
  const discountLabel = (0, _react.useMemo)(() => {
48
+ if (label) {
49
+ return label;
50
+ }
47
51
  return "\u20AC".concat((0, _helpers__.formatPrice)(price - discountedPrice), " Korting");
48
52
  }, []);
49
53
  return /*#__PURE__*/_react.default.createElement("div", {
@@ -30,7 +30,7 @@ const ProductCardSpecifications = _ref => {
30
30
  return /*#__PURE__*/_react.default.createElement("li", {
31
31
  key: key + value,
32
32
  className: (0, _helpers__.withStyle)('d-flex justify-content-between card-text__criterea')
33
- }, /*#__PURE__*/_react.default.createElement("strong", null, key, ":"), " ", value);
33
+ }, Number.isInteger(Number(key)) ? value : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("strong", null, key, ":"), " ", value));
34
34
  }));
35
35
  };
36
36
  var _default = exports.default = ProductCardSpecifications;