thm-p3-configurator 0.0.202 → 0.0.204

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.
@@ -47,6 +47,7 @@ var _helpers__ = require("../../__helpers__");
47
47
  var _product = require("../../__helpers__/product");
48
48
  var _ui = require("../../__helpers__/ui");
49
49
  var _useIsTmg = require("../../__hooks__/useIsTmg");
50
+ var _AddressLookupService = _interopRequireDefault(require("../../__services__/AddressLookupService"));
50
51
  var _LicensePlateValidator = _interopRequireDefault(require("../../__services__/LicensePlateValidator"));
51
52
  var _LocalStorageWorker = require("../../__services__/LocalStorageWorker");
52
53
  var _InternalAppointmentSuccessModal = _interopRequireDefault(require("./InternalAppointmentSuccessModal"));
@@ -124,6 +125,7 @@ function _toPrimitive(t, r) {
124
125
  return ("string" === r ? String : Number)(t);
125
126
  }
126
127
  const licensePlateValidator = new _LicensePlateValidator.default();
128
+ const addressLookupService = new _AddressLookupService.default();
127
129
  const internalAppointmentFormSchema = (0, _yup.object)({
128
130
  ownershipType: (0, _yup.string)().required(_constants__.FORM_ERROR_MESSAGES.required),
129
131
  leaseNumber: (0, _yup.string)().nullable(),
@@ -174,6 +176,8 @@ const InternalAppointmentForm = _ref => {
174
176
  const [refreshKey, setRefreshKey] = (0, _react.useState)(Date.now());
175
177
  const [companySearchTerm, setCompanySearchTerm] = (0, _react.useState)('');
176
178
  const [isCompanyInputFocused, setIsCompanyInputFocused] = (0, _react.useState)(false);
179
+ const [addressLookupLoading, setAddressLookupLoading] = (0, _react.useState)(false);
180
+ const [addressLookupTimeoutId, setAddressLookupTimeoutId] = (0, _react.useState)(null);
177
181
  const {
178
182
  customerAgreed,
179
183
  customer,
@@ -557,6 +561,62 @@ const InternalAppointmentForm = _ref => {
557
561
  label: marketingChannels === null || marketingChannels === void 0 || (_marketingChannels$fi = marketingChannels.find(marketingC => (marketingC === null || marketingC === void 0 ? void 0 : marketingC.entityId) === (channel === null || channel === void 0 ? void 0 : channel.channelId))) === null || _marketingChannels$fi === void 0 ? void 0 : _marketingChannels$fi.title,
558
562
  value: marketingChannels === null || marketingChannels === void 0 ? void 0 : marketingChannels.find(marketingC => (marketingC === null || marketingC === void 0 ? void 0 : marketingC.entityId) === (channel === null || channel === void 0 ? void 0 : channel.channelId))
559
563
  } : null;
564
+
565
+ /**
566
+ * @description Debounced address lookup function
567
+ */
568
+ const performAddressLookup = async (postcode, houseNumber) => {
569
+ if (!postcode || !houseNumber) return;
570
+ try {
571
+ setAddressLookupLoading(true);
572
+ const addressInfo = await addressLookupService.lookup(postcode, houseNumber);
573
+ if (addressInfo && addressInfo.street && addressInfo.city) {
574
+ // Auto-fill street and city fields
575
+ dispatch({
576
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_STREET_NAME,
577
+ payload: {
578
+ streetName: addressInfo.street
579
+ }
580
+ });
581
+ dispatch({
582
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_CITY,
583
+ payload: {
584
+ city: addressInfo.city
585
+ }
586
+ });
587
+ }
588
+ } catch (error) {
589
+ console.error('Address lookup failed:', error);
590
+ } finally {
591
+ setAddressLookupLoading(false);
592
+ }
593
+ };
594
+
595
+ /**
596
+ * @description Handles address lookup with debouncing
597
+ */
598
+ const handleAddressLookup = (postcode, houseNumber) => {
599
+ // Clear existing timeout
600
+ if (addressLookupTimeoutId) {
601
+ clearTimeout(addressLookupTimeoutId);
602
+ }
603
+
604
+ // Set new timeout for debounced lookup
605
+ const newTimeoutId = setTimeout(() => {
606
+ performAddressLookup(postcode, houseNumber);
607
+ }, 800); // 800ms delay
608
+
609
+ setAddressLookupTimeoutId(newTimeoutId);
610
+ };
611
+
612
+ // Cleanup timeout on unmount
613
+ (0, _react.useEffect)(() => {
614
+ return () => {
615
+ if (addressLookupTimeoutId) {
616
+ clearTimeout(addressLookupTimeoutId);
617
+ }
618
+ };
619
+ }, [addressLookupTimeoutId]);
560
620
  return /*#__PURE__*/_react.default.createElement("div", {
561
621
  className: (0, _helpers__.withStyle)('row gx-5 mt-3 mt-lg-5')
562
622
  }, /*#__PURE__*/_react.default.createElement("div", {
@@ -619,7 +679,136 @@ const InternalAppointmentForm = _ref => {
619
679
  options: Object.values(_constants__.VEHICLE_OWNERSHIP_TYPE),
620
680
  isRequired: true,
621
681
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['ownershipType']
622
- })), /*#__PURE__*/_react.default.createElement("h5", {
682
+ }), (vehicle === null || vehicle === void 0 ? void 0 : vehicle.ownershipType) === _constants__.VEHICLE_OWNERSHIP_TYPE.Leasemaatschappij && /*#__PURE__*/_react.default.createElement("div", {
683
+ className: (0, _helpers__.withStyle)('company-search-container position-relative mt-2 mb-2')
684
+ }, /*#__PURE__*/_react.default.createElement(_TextInput.default, {
685
+ placeholder: "Zoek leasemaatschappijen...",
686
+ value: customer.companyName,
687
+ name: "companyName",
688
+ onChange: value => {
689
+ dispatch({
690
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_COMPANY_NAME,
691
+ payload: {
692
+ companyName: value
693
+ }
694
+ });
695
+
696
+ // Also update search term if value is different
697
+ if (value !== companySearchTerm) {
698
+ setCompanySearchTerm(value);
699
+ setIsCompanyInputFocused(true);
700
+ }
701
+ },
702
+ onFocus: () => {
703
+ setIsCompanyInputFocused(true);
704
+ },
705
+ onBlur: () => {
706
+ setTimeout(() => {
707
+ setIsCompanyInputFocused(false);
708
+ }, 300); // Increased delay for better chance of click completion
709
+ },
710
+ isRequired: false,
711
+ form: "quotation",
712
+ label: "Leasemaatschappij:",
713
+ errorMessage: errors === null || errors === void 0 ? void 0 : errors['companyName']
714
+ }), isCompanyInputFocused && companySearchTerm && companySearchTerm.length >= 3 && branchesByType && branchesByType.length > 0 && /*#__PURE__*/_react.default.createElement("div", {
715
+ className: (0, _helpers__.withStyle)('dropdown-results position-absolute w-100 border rounded bg-white shadow'),
716
+ style: {
717
+ maxHeight: '200px',
718
+ overflowY: 'auto',
719
+ zIndex: 1050,
720
+ top: '100%',
721
+ left: 0,
722
+ right: 0
723
+ },
724
+ onMouseDown: e => {
725
+ e.preventDefault();
726
+ }
727
+ }, isLoadingBranchesByType && /*#__PURE__*/_react.default.createElement("div", {
728
+ className: (0, _helpers__.withStyle)('p-2 text-center')
729
+ }, /*#__PURE__*/_react.default.createElement("span", null, "Zoeken...")), branchesByType.map(branch => /*#__PURE__*/_react.default.createElement("div", {
730
+ key: branch.entityId,
731
+ className: (0, _helpers__.withStyle)('dropdown-item p-2 border-bottom'),
732
+ style: {
733
+ cursor: 'pointer'
734
+ },
735
+ onMouseDown: e => {
736
+ e.preventDefault();
737
+ dispatch({
738
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_COMPANY_NAME,
739
+ payload: {
740
+ companyName: branch.name
741
+ }
742
+ });
743
+ if (branch.postalCode) {
744
+ dispatch({
745
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
746
+ payload: {
747
+ zipCode: branch.postalCode
748
+ }
749
+ });
750
+ }
751
+ if (branch.street) {
752
+ dispatch({
753
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_STREET_NAME,
754
+ payload: {
755
+ streetName: branch.street
756
+ }
757
+ });
758
+ }
759
+ if (branch.city) {
760
+ dispatch({
761
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_CITY,
762
+ payload: {
763
+ city: branch.city
764
+ }
765
+ });
766
+ }
767
+ if (branch.street2) {
768
+ dispatch({
769
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
770
+ payload: {
771
+ houseNumber: branch.street2
772
+ }
773
+ });
774
+ }
775
+ if (branch.vatNumber) {
776
+ dispatch({
777
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_VAT_NUMBER,
778
+ payload: {
779
+ vatNumber: branch.vatNumber
780
+ }
781
+ });
782
+ }
783
+ if (branch.kvkNumber) {
784
+ dispatch({
785
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_KVK_NUMBER,
786
+ payload: {
787
+ kvkNumber: branch.kvkNumber
788
+ }
789
+ });
790
+ }
791
+ if (branch.huisnummerToevoeging) {
792
+ dispatch({
793
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER_ADDITION,
794
+ payload: {
795
+ houseNumberAddition: branch.huisnummerToevoeging
796
+ }
797
+ });
798
+ }
799
+ if (branch.country && branch.country.entityId) {
800
+ dispatch({
801
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_COUNTRY_ID,
802
+ payload: {
803
+ countryId: branch.country.entityId
804
+ }
805
+ });
806
+ setRefreshKey(Date.now());
807
+ }
808
+ setCompanySearchTerm('');
809
+ setIsCompanyInputFocused(false);
810
+ }
811
+ }, branch.name))))), /*#__PURE__*/_react.default.createElement("h5", {
623
812
  className: (0, _helpers__.withStyle)('my-2')
624
813
  }, "Persoonlijke gegevens"), /*#__PURE__*/_react.default.createElement("div", {
625
814
  className: (0, _helpers__.withStyle)('col-12 col-md-6 mb-2')
@@ -756,140 +945,7 @@ const InternalAppointmentForm = _ref => {
756
945
  form: "appointment",
757
946
  label: "E-mailadres:",
758
947
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['email']
759
- }), /*#__PURE__*/_react.default.createElement("div", {
760
- className: (0, _helpers__.withStyle)('company-search-container position-relative mt-2 mb-2')
761
- }, /*#__PURE__*/_react.default.createElement(_TextInput.default, {
762
- placeholder: "Zoek leasemaatschappijen...",
763
- value: customer.companyName,
764
- name: "companyName",
765
- onChange: value => {
766
- // Update company name in state
767
- dispatch({
768
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_COMPANY_NAME,
769
- payload: {
770
- companyName: value
771
- }
772
- });
773
-
774
- // Also update search term if value is different
775
- if (value !== companySearchTerm) {
776
- console.log('value', value);
777
- setCompanySearchTerm(value);
778
- // Force focused state when typing
779
- setIsCompanyInputFocused(true);
780
- }
781
- },
782
- onFocus: () => {
783
- setIsCompanyInputFocused(true);
784
- },
785
- onBlur: () => {
786
- // Delay hiding the dropdown to allow click events to complete
787
- setTimeout(() => {
788
- setIsCompanyInputFocused(false);
789
- }, 300); // Increased delay for better chance of click completion
790
- },
791
- isRequired: false,
792
- form: "quotation",
793
- label: "Leasemaatschappij:",
794
- errorMessage: errors === null || errors === void 0 ? void 0 : errors['companyName']
795
- }), isCompanyInputFocused && companySearchTerm && companySearchTerm.length >= 3 && branchesByType && branchesByType.length > 0 && /*#__PURE__*/_react.default.createElement("div", {
796
- className: (0, _helpers__.withStyle)('dropdown-results position-absolute w-100 border rounded bg-white shadow'),
797
- style: {
798
- maxHeight: '200px',
799
- overflowY: 'auto',
800
- zIndex: 1050,
801
- top: '100%',
802
- left: 0,
803
- right: 0
804
- },
805
- onMouseDown: e => {
806
- e.preventDefault();
807
- }
808
- }, isLoadingBranchesByType && /*#__PURE__*/_react.default.createElement("div", {
809
- className: (0, _helpers__.withStyle)('p-2 text-center')
810
- }, /*#__PURE__*/_react.default.createElement("span", null, "Zoeken...")), branchesByType.map(branch => /*#__PURE__*/_react.default.createElement("div", {
811
- key: branch.entityId,
812
- className: (0, _helpers__.withStyle)('dropdown-item p-2 border-bottom'),
813
- style: {
814
- cursor: 'pointer'
815
- },
816
- onMouseDown: e => {
817
- e.preventDefault();
818
- dispatch({
819
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_COMPANY_NAME,
820
- payload: {
821
- companyName: branch.name
822
- }
823
- });
824
- if (branch.postalCode) {
825
- dispatch({
826
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
827
- payload: {
828
- zipCode: branch.postalCode
829
- }
830
- });
831
- }
832
- if (branch.street) {
833
- dispatch({
834
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_STREET_NAME,
835
- payload: {
836
- streetName: branch.street
837
- }
838
- });
839
- }
840
- if (branch.city) {
841
- dispatch({
842
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_CITY,
843
- payload: {
844
- city: branch.city
845
- }
846
- });
847
- }
848
- if (branch.street2) {
849
- dispatch({
850
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
851
- payload: {
852
- houseNumber: branch.street2
853
- }
854
- });
855
- }
856
- if (branch.vatNumber) {
857
- dispatch({
858
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_VAT_NUMBER,
859
- payload: {
860
- vatNumber: branch.vatNumber
861
- }
862
- });
863
- }
864
- if (branch.kvkNumber) {
865
- dispatch({
866
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_KVK_NUMBER,
867
- payload: {
868
- kvkNumber: branch.kvkNumber
869
- }
870
- });
871
- }
872
- if (branch.huisnummerToevoeging) {
873
- dispatch({
874
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER_ADDITION,
875
- payload: {
876
- houseNumberAddition: branch.huisnummerToevoeging
877
- }
878
- });
879
- }
880
- if (branch.country && branch.country.entityId) {
881
- dispatch({
882
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_COUNTRY_ID,
883
- payload: {
884
- countryId: branch.country.entityId
885
- }
886
- });
887
- setRefreshKey(Date.now());
888
- }
889
- setCompanySearchTerm('');
890
- setIsCompanyInputFocused(false);
891
- }
892
- }, branch.name)))), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
948
+ }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
893
949
  placeholder: "",
894
950
  value: customer.phoneNumber,
895
951
  name: "phoneNumber",
@@ -1133,12 +1189,18 @@ const InternalAppointmentForm = _ref => {
1133
1189
  placeholder: "",
1134
1190
  value: customer.zipCode,
1135
1191
  name: "zipCode",
1136
- onChange: value => dispatch({
1137
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
1138
- payload: {
1139
- zipCode: value
1192
+ onChange: value => {
1193
+ dispatch({
1194
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
1195
+ payload: {
1196
+ zipCode: value
1197
+ }
1198
+ });
1199
+ // Trigger address lookup if house number is also available
1200
+ if (customer.houseNumber) {
1201
+ handleAddressLookup(value, customer.houseNumber);
1140
1202
  }
1141
- }),
1203
+ },
1142
1204
  key: "zipCode-".concat(refreshKey),
1143
1205
  isRequired: true,
1144
1206
  label: "Postcode:",
@@ -1147,12 +1209,18 @@ const InternalAppointmentForm = _ref => {
1147
1209
  placeholder: "",
1148
1210
  value: customer.houseNumber,
1149
1211
  name: "houseNumber",
1150
- onChange: value => dispatch({
1151
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
1152
- payload: {
1153
- houseNumber: value
1212
+ onChange: value => {
1213
+ dispatch({
1214
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
1215
+ payload: {
1216
+ houseNumber: value
1217
+ }
1218
+ });
1219
+ // Trigger address lookup if postcode is also available
1220
+ if (customer.zipCode) {
1221
+ handleAddressLookup(customer.zipCode, value);
1154
1222
  }
1155
- }),
1223
+ },
1156
1224
  key: "houseNumber-".concat(refreshKey),
1157
1225
  isRequired: true,
1158
1226
  label: "Huisnummer:",
@@ -1172,7 +1240,7 @@ const InternalAppointmentForm = _ref => {
1172
1240
  label: "Huisnummer toevoeging:",
1173
1241
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['houseNumberAddition']
1174
1242
  }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
1175
- placeholder: "",
1243
+ placeholder: addressLookupLoading ? 'Adres wordt opgezocht...' : '',
1176
1244
  value: customer.streetName,
1177
1245
  name: "streetName",
1178
1246
  onChange: value => dispatch({
@@ -1183,10 +1251,10 @@ const InternalAppointmentForm = _ref => {
1183
1251
  }),
1184
1252
  key: "streetName-".concat(refreshKey),
1185
1253
  isRequired: true,
1186
- label: "Straat:",
1254
+ label: "Straat:".concat(addressLookupLoading ? ' (wordt opgezocht...)' : ''),
1187
1255
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['streetName']
1188
1256
  }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
1189
- placeholder: "",
1257
+ placeholder: addressLookupLoading ? 'Stad wordt opgezocht...' : '',
1190
1258
  value: customer.city,
1191
1259
  name: "city",
1192
1260
  onChange: value => dispatch({
@@ -1197,7 +1265,7 @@ const InternalAppointmentForm = _ref => {
1197
1265
  }),
1198
1266
  key: "city-".concat(refreshKey),
1199
1267
  isRequired: true,
1200
- label: "Stad:",
1268
+ label: "Stad:".concat(addressLookupLoading ? ' (wordt opgezocht...)' : ''),
1201
1269
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['city']
1202
1270
  }), /*#__PURE__*/_react.default.createElement(_DropdownInput.default, {
1203
1271
  key: "country-business-".concat((customer === null || customer === void 0 ? void 0 : customer.countryId) || 'default'),
@@ -1225,12 +1293,18 @@ const InternalAppointmentForm = _ref => {
1225
1293
  placeholder: "",
1226
1294
  value: customer.zipCode,
1227
1295
  name: "zipCode",
1228
- onChange: value => dispatch({
1229
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
1230
- payload: {
1231
- zipCode: value
1296
+ onChange: value => {
1297
+ dispatch({
1298
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
1299
+ payload: {
1300
+ zipCode: value
1301
+ }
1302
+ });
1303
+ // Trigger address lookup if house number is also available
1304
+ if (customer.houseNumber) {
1305
+ handleAddressLookup(value, customer.houseNumber);
1232
1306
  }
1233
- }),
1307
+ },
1234
1308
  key: "zipCode-".concat(refreshKey),
1235
1309
  isRequired: true,
1236
1310
  label: "Postcode:",
@@ -1239,12 +1313,18 @@ const InternalAppointmentForm = _ref => {
1239
1313
  placeholder: "",
1240
1314
  value: customer.houseNumber,
1241
1315
  name: "houseNumber",
1242
- onChange: value => dispatch({
1243
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
1244
- payload: {
1245
- houseNumber: value
1316
+ onChange: value => {
1317
+ dispatch({
1318
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
1319
+ payload: {
1320
+ houseNumber: value
1321
+ }
1322
+ });
1323
+ // Trigger address lookup if postcode is also available
1324
+ if (customer.zipCode) {
1325
+ handleAddressLookup(customer.zipCode, value);
1246
1326
  }
1247
- }),
1327
+ },
1248
1328
  key: "houseNumber-".concat(refreshKey),
1249
1329
  isRequired: true,
1250
1330
  label: "Huisnummer:",
@@ -1264,7 +1344,7 @@ const InternalAppointmentForm = _ref => {
1264
1344
  label: "Huisnummer toevoeging:",
1265
1345
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['houseNumberAddition']
1266
1346
  }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
1267
- placeholder: "",
1347
+ placeholder: addressLookupLoading ? 'Adres wordt opgezocht...' : '',
1268
1348
  value: customer.streetName,
1269
1349
  name: "streetName",
1270
1350
  onChange: value => dispatch({
@@ -1275,10 +1355,10 @@ const InternalAppointmentForm = _ref => {
1275
1355
  }),
1276
1356
  key: "streetName-".concat(refreshKey),
1277
1357
  isRequired: true,
1278
- label: "Straat:",
1358
+ label: "Straat:".concat(addressLookupLoading ? ' (wordt opgezocht...)' : ''),
1279
1359
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['streetName']
1280
1360
  }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
1281
- placeholder: "",
1361
+ placeholder: addressLookupLoading ? 'Stad wordt opgezocht...' : '',
1282
1362
  value: customer.city,
1283
1363
  name: "city",
1284
1364
  onChange: value => dispatch({
@@ -1289,7 +1369,7 @@ const InternalAppointmentForm = _ref => {
1289
1369
  }),
1290
1370
  key: "city-".concat(refreshKey),
1291
1371
  isRequired: true,
1292
- label: "Stad:",
1372
+ label: "Stad:".concat(addressLookupLoading ? ' (wordt opgezocht...)' : ''),
1293
1373
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['city']
1294
1374
  }), /*#__PURE__*/_react.default.createElement(_DropdownInput.default, {
1295
1375
  key: "country-lease-".concat((customer === null || customer === void 0 ? void 0 : customer.countryId) || 'default'),
@@ -1331,12 +1411,18 @@ const InternalAppointmentForm = _ref => {
1331
1411
  placeholder: "",
1332
1412
  value: customer.zipCode,
1333
1413
  name: "zipCode",
1334
- onChange: value => dispatch({
1335
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
1336
- payload: {
1337
- zipCode: value
1414
+ onChange: value => {
1415
+ dispatch({
1416
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_ZIP_CODE,
1417
+ payload: {
1418
+ zipCode: value
1419
+ }
1420
+ });
1421
+ // Trigger address lookup if house number is also available
1422
+ if (customer.houseNumber) {
1423
+ handleAddressLookup(value, customer.houseNumber);
1338
1424
  }
1339
- }),
1425
+ },
1340
1426
  key: "zipCode-".concat(refreshKey),
1341
1427
  isRequired: true,
1342
1428
  label: "Postcode:",
@@ -1345,12 +1431,18 @@ const InternalAppointmentForm = _ref => {
1345
1431
  placeholder: "",
1346
1432
  value: customer.houseNumber,
1347
1433
  name: "houseNumber",
1348
- onChange: value => dispatch({
1349
- type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
1350
- payload: {
1351
- houseNumber: value
1434
+ onChange: value => {
1435
+ dispatch({
1436
+ type: _OrderSessionContext.orderSessionActions.SET_CUSTOMER_HOUSE_NUMBER,
1437
+ payload: {
1438
+ houseNumber: value
1439
+ }
1440
+ });
1441
+ // Trigger address lookup if postcode is also available
1442
+ if (customer.zipCode) {
1443
+ handleAddressLookup(customer.zipCode, value);
1352
1444
  }
1353
- }),
1445
+ },
1354
1446
  key: "houseNumber-".concat(refreshKey),
1355
1447
  isRequired: true,
1356
1448
  label: "Huisnummer:",
@@ -1370,7 +1462,7 @@ const InternalAppointmentForm = _ref => {
1370
1462
  label: "Huisnummer toevoeging:",
1371
1463
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['houseNumberAddition']
1372
1464
  }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
1373
- placeholder: "",
1465
+ placeholder: addressLookupLoading ? 'Adres wordt opgezocht...' : '',
1374
1466
  value: customer.streetName,
1375
1467
  name: "streetName",
1376
1468
  onChange: value => dispatch({
@@ -1381,10 +1473,10 @@ const InternalAppointmentForm = _ref => {
1381
1473
  }),
1382
1474
  key: "streetName-".concat(refreshKey),
1383
1475
  isRequired: true,
1384
- label: "Straat:",
1476
+ label: "Straat:".concat(addressLookupLoading ? ' (wordt opgezocht...)' : ''),
1385
1477
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['streetName']
1386
1478
  }), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
1387
- placeholder: "",
1479
+ placeholder: addressLookupLoading ? 'Stad wordt opgezocht...' : '',
1388
1480
  value: customer.city,
1389
1481
  name: "city",
1390
1482
  onChange: value => dispatch({
@@ -1395,7 +1487,7 @@ const InternalAppointmentForm = _ref => {
1395
1487
  }),
1396
1488
  key: "city-".concat(refreshKey),
1397
1489
  isRequired: true,
1398
- label: "Stad:",
1490
+ label: "Stad:".concat(addressLookupLoading ? ' (wordt opgezocht...)' : ''),
1399
1491
  errorMessage: errors === null || errors === void 0 ? void 0 : errors['city']
1400
1492
  }), /*#__PURE__*/_react.default.createElement(_DropdownInput.default, {
1401
1493
  key: "country-personal-".concat((customer === null || customer === void 0 ? void 0 : customer.countryId) || 'default'),
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+
3
+ require("core-js/modules/es.parse-int.js");
4
+ require("core-js/modules/es.promise.js");
5
+ require("core-js/modules/es.regexp.exec.js");
6
+ require("core-js/modules/es.regexp.test.js");
7
+ require("core-js/modules/es.string.replace.js");
8
+ require("core-js/modules/web.dom-collections.iterator.js");
9
+ Object.defineProperty(exports, "__esModule", {
10
+ value: true
11
+ });
12
+ exports.default = void 0;
13
+ require("core-js/modules/es.parse-int.js");
14
+ require("core-js/modules/es.promise.js");
15
+ require("core-js/modules/es.regexp.exec.js");
16
+ require("core-js/modules/es.regexp.test.js");
17
+ require("core-js/modules/es.string.replace.js");
18
+ require("core-js/modules/web.dom-collections.iterator.js");
19
+ class AddressLookupService {
20
+ constructor() {
21
+ this.cache = new Map();
22
+ }
23
+
24
+ /**
25
+ * @description Validates Dutch postcode format
26
+ * @param {string} postcode - The postcode to validate
27
+ * @returns {boolean} - True if valid Dutch postcode format
28
+ */
29
+ isValidPostcode(postcode) {
30
+ if (!postcode || typeof postcode !== 'string') return false;
31
+ const cleanPostcode = postcode.replace(/\s/g, '').toUpperCase();
32
+ const dutchPostcodeRegex = /^[1-9][0-9]{3}[A-Z]{2}$/;
33
+ return dutchPostcodeRegex.test(cleanPostcode);
34
+ }
35
+
36
+ /**
37
+ * @description Validates house number
38
+ * @param {string|number} houseNumber - The house number to validate
39
+ * @returns {boolean} - True if valid house number
40
+ */
41
+ isValidHouseNumber(houseNumber) {
42
+ if (!houseNumber) return false;
43
+ const num = typeof houseNumber === 'string' ? parseInt(houseNumber, 10) : houseNumber;
44
+ return !isNaN(num) && num > 0 && num <= 99999;
45
+ }
46
+
47
+ /**
48
+ * @description Creates a cache key for the lookup
49
+ * @param {string} postcode - The postcode
50
+ * @param {string|number} houseNumber - The house number
51
+ * @returns {string} - Cache key
52
+ */
53
+ getCacheKey(postcode, houseNumber) {
54
+ const cleanPostcode = postcode.replace(/\s/g, '').toUpperCase();
55
+ return "".concat(cleanPostcode, "-").concat(houseNumber);
56
+ }
57
+
58
+ /**
59
+ * @description Lookup using PDOK BAG API (free Dutch government service)
60
+ * @param {string} postcode - The Dutch postcode
61
+ * @param {string|number} houseNumber - The house number
62
+ * @returns {Promise<{street: string, city: string} | null>} - Address information or null if not found
63
+ */
64
+ async lookupAddressPDOK(postcode, houseNumber) {
65
+ try {
66
+ if (!this.isValidPostcode(postcode) || !this.isValidHouseNumber(houseNumber)) {
67
+ return null;
68
+ }
69
+ const cacheKey = this.getCacheKey(postcode, houseNumber);
70
+ if (this.cache.has(cacheKey)) {
71
+ return this.cache.get(cacheKey);
72
+ }
73
+ const cleanPostcode = postcode.replace(/\s/g, '').toUpperCase();
74
+ const url = "https://api.pdok.nl/bzk/locatieserver/search/v3_1/suggest?q=".concat(cleanPostcode, " ").concat(houseNumber, "&fl=weergavenaam,straatnaam,woonplaatsnaam,postcode,huisnummer&rows=1");
75
+ const response = await fetch(url, {
76
+ method: 'GET',
77
+ headers: {
78
+ Accept: 'application/json'
79
+ }
80
+ });
81
+ if (!response.ok) {
82
+ console.warn('PDOK lookup failed:', response.status);
83
+ return null;
84
+ }
85
+ const data = await response.json();
86
+ let addressInfo = null;
87
+ if (data && data.response && data.response.docs && data.response.docs.length > 0) {
88
+ const doc = data.response.docs[0];
89
+ if (doc.postcode === cleanPostcode && String(doc.huisnummer) === String(houseNumber)) {
90
+ addressInfo = {
91
+ street: doc.straatnaam,
92
+ city: doc.woonplaatsnaam
93
+ };
94
+ }
95
+ }
96
+ this.cache.set(cacheKey, addressInfo);
97
+ return addressInfo;
98
+ } catch (error) {
99
+ console.error('PDOK address lookup error:', error);
100
+ return null;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * @description Mock lookup for development/demo (returns mock data for common postcodes)
106
+ * @param {string} postcode - The Dutch postcode
107
+ * @param {string|number} houseNumber - The house number
108
+ * @returns {Promise<{street: string, city: string} | null>} - Address information or null if not found
109
+ */
110
+ async lookupAddressMock(postcode, houseNumber) {
111
+ const cleanPostcode = postcode.replace(/\s/g, '').toUpperCase();
112
+ const mockData = {
113
+ '1012JS': {
114
+ street: 'Dam',
115
+ city: 'Amsterdam'
116
+ },
117
+ '2511CS': {
118
+ street: 'Binnenhof',
119
+ city: 'Den Haag'
120
+ },
121
+ '3011AD': {
122
+ street: 'Coolsingel',
123
+ city: 'Rotterdam'
124
+ },
125
+ '3512JE': {
126
+ street: 'Oudegracht',
127
+ city: 'Utrecht'
128
+ },
129
+ '9712CP': {
130
+ street: 'Grote Markt',
131
+ city: 'Groningen'
132
+ },
133
+ '5611AG': {
134
+ street: 'Stratumseind',
135
+ city: 'Eindhoven'
136
+ },
137
+ '6511LN': {
138
+ street: 'Grote Markt',
139
+ city: 'Nijmegen'
140
+ },
141
+ '4811CE': {
142
+ street: 'Grote Markt',
143
+ city: 'Breda'
144
+ }
145
+ };
146
+ await new Promise(resolve => setTimeout(resolve, 500));
147
+ const addressInfo = mockData[cleanPostcode] || null;
148
+ if (addressInfo) {
149
+ console.log("Mock address lookup for ".concat(cleanPostcode, ": ").concat(addressInfo.street, ", ").concat(addressInfo.city));
150
+ }
151
+ return addressInfo;
152
+ }
153
+
154
+ /**
155
+ * @description Main lookup method that tries PDOK API first, then fallback to mock data
156
+ * @param {string} postcode - The Dutch postcode
157
+ * @param {string|number} houseNumber - The house number
158
+ * @returns {Promise<{street: string, city: string} | null>} - Address information or null if not found
159
+ */
160
+ async lookup(postcode, houseNumber) {
161
+ if (!this.isValidPostcode(postcode) || !this.isValidHouseNumber(houseNumber)) {
162
+ return null;
163
+ }
164
+ const cacheKey = this.getCacheKey(postcode, houseNumber);
165
+ if (this.cache.has(cacheKey)) {
166
+ return this.cache.get(cacheKey);
167
+ }
168
+ let result = null;
169
+ try {
170
+ result = await this.lookupAddressPDOK(postcode, houseNumber);
171
+ if (result) {
172
+ return result;
173
+ }
174
+ } catch (error) {
175
+ console.warn('PDOK lookup failed, using mock data...');
176
+ }
177
+ try {
178
+ result = await this.lookupAddressMock(postcode, houseNumber);
179
+ } catch (error) {
180
+ console.warn('Mock lookup failed');
181
+ }
182
+ return result;
183
+ }
184
+
185
+ /**
186
+ * @description Clears the cache
187
+ */
188
+ clearCache() {
189
+ this.cache.clear();
190
+ }
191
+ }
192
+ var _default = exports.default = AddressLookupService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thm-p3-configurator",
3
- "version": "0.0.202",
3
+ "version": "0.0.204",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "author": "EnoRm.",