abmp-npm 1.6.0 → 1.6.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abmp-npm",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -32,6 +32,7 @@
32
32
  "@wix/essentials": "^0.1.28",
33
33
  "@wix/members": "^1.0.330",
34
34
  "@wix/site-location": "^1.31.0",
35
+ "@wix/site-storage": "^1.22.0",
35
36
  "@wix/site-window": "^1.44.0",
36
37
  "ngeohash": "^0.6.3",
37
38
  "phone": "^3.1.67",
@@ -2,6 +2,14 @@ const { location: wixLocation } = require('@wix/site-location');
2
2
  const { storage: wixStorage } = require('@wix/site-storage');
3
3
  const { window: wixWindow } = require('@wix/site-window');
4
4
 
5
+ const {
6
+ ADDRESS_STATUS_TYPES,
7
+ DEFAULT_BUSINESS_NAME_TEXT,
8
+ FREE_WEBSITE_TEXT_STATES,
9
+ LIGHTBOX_NAMES,
10
+ ABMP_MEMBERS_HOME_URL,
11
+ } = require('../public/consts');
12
+ const { handleOnCustomValidation, isNotValidUrl } = require('../public/Utils/formValidation');
5
13
  const { generateId } = require('../public/Utils/sharedUtils');
6
14
 
7
15
  const MAX_PHONES_COUNT = 10;
@@ -54,18 +62,11 @@ async function personalDetailsFormOnReady({
54
62
  saveRegistrationData,
55
63
  validateMemberToken,
56
64
  checkUrlUniqueness,
57
- ADDRESS_STATUS_TYPES,
58
- DEFAULT_BUSINESS_NAME_TEXT,
59
- FREE_WEBSITE_TEXT_STATES,
60
- LIGHTBOX_NAMES,
61
- ABMP_MEMBERS_HOME_URL,
62
- handleOnCustomValidation,
63
- isNotValidUrl,
64
65
  }) {
65
66
  let itemMemberObj = {};
66
67
  let originalMemberData = {};
67
68
  let selectedServices = [];
68
- let uploadedImages = {
69
+ const uploadedImages = {
69
70
  profileImage: '',
70
71
  logoImage: '',
71
72
  bannerImage: '',
@@ -73,7 +74,7 @@ async function personalDetailsFormOnReady({
73
74
 
74
75
  const FALLBACK_ADDRESS_STATUS = ADDRESS_STATUS_TYPES.STATE_CITY_ZIP;
75
76
 
76
- let formHasUnsavedChanges = {
77
+ const formHasUnsavedChanges = {
77
78
  [FORM_SECTION_HANDLER_MAP.PERSONAL.section]: false,
78
79
  [FORM_SECTION_HANDLER_MAP.BUSINESS_SERVICES.section]: false,
79
80
  [FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING.section]: false,
@@ -81,7 +82,7 @@ async function personalDetailsFormOnReady({
81
82
  [FORM_SECTION_HANDLER_MAP.WEBSITE_OPT_OUT.section]: false,
82
83
  };
83
84
 
84
- let slugValidationTimeout = {};
85
+ const slugValidationTimeout = {};
85
86
  let isSlugValid = true;
86
87
  let currentSlugValidationId = 0;
87
88
  let memberData, isValid, isStudent;
@@ -147,7 +148,7 @@ async function personalDetailsFormOnReady({
147
148
  originalMemberData = JSON.parse(JSON.stringify(memberData));
148
149
  // Initialize selectedServices based on memberData
149
150
  selectedServices = Array.isArray(itemMemberObj.areasOfPractices)
150
- ? itemMemberObj.areasOfPractices.map((label) => ({ _id: generateId(), label: String(label) }))
151
+ ? itemMemberObj.areasOfPractices.map(label => ({ _id: generateId(), label: String(label) }))
151
152
  : [];
152
153
 
153
154
  $w('#mainMultiStateBox').changeState(MAIN_STATE_BOX_STATES.FORM_STATE);
@@ -230,7 +231,7 @@ async function personalDetailsFormOnReady({
230
231
  }
231
232
  function initGallery() {
232
233
  $w('#galleryRepeater').onItemReady(handleGalleryItem);
233
- $w('#uploadGalleryImageButton').onChange(async (event) => {
234
+ $w('#uploadGalleryImageButton').onChange(async event => {
234
235
  const $item = $w.at(event.context);
235
236
  const uploadButton = $item('#uploadGalleryImageButton');
236
237
  if (uploadButton.value.length === 0) return;
@@ -241,7 +242,7 @@ async function personalDetailsFormOnReady({
241
242
  itemMemberObj.gallery = [];
242
243
  }
243
244
 
244
- uploadedFiles.forEach((file) => {
245
+ uploadedFiles.forEach(file => {
245
246
  itemMemberObj.gallery.unshift({ src: file.fileUrl });
246
247
  });
247
248
 
@@ -255,12 +256,12 @@ async function personalDetailsFormOnReady({
255
256
  console.error('Upload failed:', error);
256
257
  }
257
258
  });
258
- $w('#deleteImageButton').onClick(async (event) => {
259
+ $w('#deleteImageButton').onClick(async event => {
259
260
  const itemId = event.context.itemId;
260
- const itemData = $w('#galleryRepeater').data.find((item) => item._id === itemId);
261
+ const itemData = $w('#galleryRepeater').data.find(item => item._id === itemId);
261
262
  const result = await wixWindow.openLightbox(LIGHTBOX_NAMES.DELETE_CONFIRM);
262
263
  if (result && result.toDelete) {
263
- itemMemberObj.gallery = itemMemberObj.gallery.filter((img) => img.src !== itemData.image.src);
264
+ itemMemberObj.gallery = itemMemberObj.gallery.filter(img => img.src !== itemData.image.src);
264
265
  await saveGalleryToCMS();
265
266
  setGallery(); // Re-render
266
267
  }
@@ -275,8 +276,6 @@ async function personalDetailsFormOnReady({
275
276
 
276
277
  $w('#slugInput').value = itemMemberObj.url || '';
277
278
 
278
- isSlugValid = true;
279
-
280
279
  $w(SLUG_FLAGS.VALID).collapse();
281
280
  $w(SLUG_FLAGS.INVALID).collapse();
282
281
 
@@ -284,7 +283,7 @@ async function personalDetailsFormOnReady({
284
283
  $w('#profileLink').link = fullProfilePageLink;
285
284
  $w('#profileLink').target = '_blank';
286
285
  $w('#licenceNoText').text = (itemMemberObj.licenses || [])
287
- .map((val) => val.license)
286
+ .map(val => val.license)
288
287
  .filter(Boolean)
289
288
  .join(', ');
290
289
  const handleIsStudent = () => {
@@ -306,7 +305,7 @@ async function personalDetailsFormOnReady({
306
305
  '#optConfirmationBox',
307
306
  '#yesOptButton',
308
307
  '#cancelOptButton',
309
- (confirmed) => handleOptConfirmation(confirmed, '#optCheckbox', '#optConfirmationBox', 'optOut')
308
+ confirmed => handleOptConfirmation(confirmed, '#optCheckbox', '#optConfirmationBox', 'optOut')
310
309
  );
311
310
 
312
311
  setupOptOutCheckbox(
@@ -314,15 +313,27 @@ async function personalDetailsFormOnReady({
314
313
  '#optWebsiteConfirmationBox',
315
314
  '#yesOptWebsiteButton',
316
315
  '#cancelOptwebsiteButton',
317
- (confirmed) => handleOptConfirmation(confirmed, '#optWebsiteCheckbox', '#optWebsiteConfirmationBox', 'showWixUrl')
316
+ confirmed =>
317
+ handleOptConfirmation(
318
+ confirmed,
319
+ '#optWebsiteCheckbox',
320
+ '#optWebsiteConfirmationBox',
321
+ 'showWixUrl'
322
+ )
318
323
  );
319
324
  }
320
325
 
321
- function setupOptOutCheckbox(checkboxId, confirmationBoxId, confirmBtnId, cancelBtnId, confirmCallback) {
326
+ function setupOptOutCheckbox(
327
+ checkboxId,
328
+ confirmationBoxId,
329
+ confirmBtnId,
330
+ cancelBtnId,
331
+ confirmCallback
332
+ ) {
322
333
  const checkbox = $w(checkboxId);
323
334
  const box = $w(confirmationBoxId);
324
335
 
325
- checkbox.onChange((e) => {
336
+ checkbox.onChange(e => {
326
337
  if (!e.target.checked) {
327
338
  box.expand();
328
339
  checkbox.disable();
@@ -433,18 +444,18 @@ async function personalDetailsFormOnReady({
433
444
  { $elem: elements.$UrlInput, changeEvent: CHANGE_EVENTS.ON_INPUT },
434
445
  ],
435
446
  };
436
- Object.keys(formChangeEventBindings).forEach((section) => {
447
+ Object.keys(formChangeEventBindings).forEach(section => {
437
448
  formChangeEventBindings[section].forEach(({ $elem, changeEvent }) => {
438
449
  $elem[changeEvent](() => {
439
450
  const handlerMap = Object.values(FORM_SECTION_HANDLER_MAP).find(
440
- (handlerMap) => handlerMap.section === section
451
+ handlerMap => handlerMap.section === section
441
452
  );
442
453
  checkFormChanges(handlerMap);
443
454
  });
444
455
  });
445
456
  });
446
457
 
447
- $w('#slugInput').onInput((event) => {
458
+ $w('#slugInput').onInput(event => {
448
459
  $w('#savePersonalButton').disable();
449
460
  const slug = event.target.value;
450
461
 
@@ -500,7 +511,8 @@ async function personalDetailsFormOnReady({
500
511
  isSlugValid = true;
501
512
  if (formDataType === FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING.section) {
502
513
  isEmailValid = $w('#contactFormEmailInput').valid;
503
- isUrlValid = !isNotValidUrl($w('#UrlInput').value) && !isNotValidUrl($w('#schedulingLinkInput').value);
514
+ isUrlValid =
515
+ !isNotValidUrl($w('#UrlInput').value) && !isNotValidUrl($w('#schedulingLinkInput').value);
504
516
  }
505
517
  if (formDataType === FORM_SECTION_HANDLER_MAP.PERSONAL.section) {
506
518
  isNameValid = $w('#firstNameInput').valid && $w('#lastNameInput').valid;
@@ -587,7 +599,7 @@ async function personalDetailsFormOnReady({
587
599
  // Get memberships array
588
600
  const memberships = Array.isArray(itemMemberObj.memberships) ? itemMemberObj.memberships : [];
589
601
  // Find ABMP object
590
- const abmp = memberships.find((m) => m.association === 'ABMP');
602
+ const abmp = memberships.find(m => m.association === 'ABMP');
591
603
  // Set yearJoinedText
592
604
  if (abmp && abmp.membersince) {
593
605
  $w('#yearJoinedText').text = abmp.membersince;
@@ -607,7 +619,7 @@ async function personalDetailsFormOnReady({
607
619
  }
608
620
 
609
621
  if (Array.isArray(itemMemberObj.areasOfPractices)) {
610
- selectedServices = itemMemberObj.areasOfPractices.map((label) => ({
622
+ selectedServices = itemMemberObj.areasOfPractices.map(label => ({
611
623
  _id: generateId(),
612
624
  label: String(label),
613
625
  }));
@@ -628,7 +640,7 @@ async function personalDetailsFormOnReady({
628
640
  if ($w(uploadButton).value?.length > 0) {
629
641
  try {
630
642
  const uploadedFiles = await $w(uploadButton).uploadFiles();
631
- uploadedFiles.forEach((file) => {
643
+ uploadedFiles.forEach(file => {
632
644
  uploadedImages[imageKey] = file.fileUrl;
633
645
  updateUI(file);
634
646
  });
@@ -669,19 +681,19 @@ async function personalDetailsFormOnReady({
669
681
  }
670
682
 
671
683
  function setupImageUploadAndDeleteHandlers() {
672
- uploadImage('#uploadProfileButton', 'profileImage', (file) => {
684
+ uploadImage('#uploadProfileButton', 'profileImage', file => {
673
685
  $w('#profileImage').src = file.fileUrl;
674
686
  $w('#profileImageName').text = formatFileName(file.fileName);
675
687
  $w('#profileImageContainer').expand();
676
688
  });
677
689
 
678
- uploadImage('#uploadLogoButton', 'logoImage', (file) => {
690
+ uploadImage('#uploadLogoButton', 'logoImage', file => {
679
691
  $w('#logoImage').src = file.fileUrl;
680
692
  $w('#logoImageName').text = file.fileName;
681
693
  $w('#logoImageContainer').expand();
682
694
  });
683
695
 
684
- uploadImage('#uploadBannerButton', 'bannerImage', (file) => {
696
+ uploadImage('#uploadBannerButton', 'bannerImage', file => {
685
697
  $w('#bannerImage').src = file.fileUrl;
686
698
  $w('#bannerImageName').text = file.fileName;
687
699
  $w('#bannerImageContainer').expand();
@@ -777,7 +789,7 @@ async function personalDetailsFormOnReady({
777
789
  arrayRef.splice(
778
790
  0,
779
791
  arrayRef.length,
780
- ...arrayRef.filter((item) =>
792
+ ...arrayRef.filter(item =>
781
793
  typeof item === 'string' ? item !== textToRemove : item[matchField] !== textToRemove
782
794
  )
783
795
  );
@@ -790,7 +802,7 @@ async function personalDetailsFormOnReady({
790
802
  async function setInterestData() {
791
803
  const interestsData = await getInterestAll();
792
804
 
793
- $w('#removeServiceButton').onClick((event) => {
805
+ $w('#removeServiceButton').onClick(event => {
794
806
  handleItemDelete(event, '#serviceNameText', selectedServices, 'label', renderServices);
795
807
  });
796
808
 
@@ -801,7 +813,7 @@ async function personalDetailsFormOnReady({
801
813
  }));
802
814
 
803
815
  $w('#repeaterInterest').data = formattedData;
804
- $w('#repeaterInterest').onItemReady(($item, itemData, index) => {
816
+ $w('#repeaterInterest').onItemReady(($item, itemData, _index) => {
805
817
  $item('#interestText').text = itemData.value;
806
818
  });
807
819
  }
@@ -827,7 +839,7 @@ async function personalDetailsFormOnReady({
827
839
  // }, 150);
828
840
  // });
829
841
 
830
- intrestInput.onKeyPress((event) => {
842
+ intrestInput.onKeyPress(event => {
831
843
  debounce_fun();
832
844
 
833
845
  if (event.key === 'Enter') {
@@ -835,7 +847,9 @@ async function personalDetailsFormOnReady({
835
847
 
836
848
  if (
837
849
  typedValue &&
838
- !selectedServices.some((service) => service.label.toLowerCase() === typedValue.toLowerCase())
850
+ !selectedServices.some(
851
+ service => service.label.toLowerCase() === typedValue.toLowerCase()
852
+ )
839
853
  ) {
840
854
  selectedServices.unshift({
841
855
  _id: generateId(),
@@ -853,7 +867,7 @@ async function personalDetailsFormOnReady({
853
867
  $item('#interestText').text = itemData.value;
854
868
 
855
869
  $item('#intrestItem').onClick(() => {
856
- if (!selectedServices.some((service) => service.label === itemData.value)) {
870
+ if (!selectedServices.some(service => service.label === itemData.value)) {
857
871
  selectedServices.unshift({
858
872
  _id: generateId(),
859
873
  label: itemData.value,
@@ -887,7 +901,9 @@ async function personalDetailsFormOnReady({
887
901
  const memberId = wixStorage.local.getItem('memberId');
888
902
  const timestamp = new Date().toISOString();
889
903
 
890
- console.group(`User Data Change Log - ${saveType.toUpperCase()} - ${success ? 'SUCCESS' : 'FAILED'}`);
904
+ console.group(
905
+ `User Data Change Log - ${saveType.toUpperCase()} - ${success ? 'SUCCESS' : 'FAILED'}`
906
+ );
891
907
  console.log('Change Details:', {
892
908
  memberId,
893
909
  timestamp,
@@ -900,7 +916,7 @@ async function personalDetailsFormOnReady({
900
916
 
901
917
  // Calculate and log specific changes
902
918
  const changes = {};
903
- Object.keys(afterData).forEach((key) => {
919
+ Object.keys(afterData).forEach(key => {
904
920
  if (JSON.stringify(beforeData[key]) !== JSON.stringify(afterData[key])) {
905
921
  changes[key] = {
906
922
  before: beforeData[key],
@@ -942,7 +958,8 @@ async function personalDetailsFormOnReady({
942
958
 
943
959
  return {
944
960
  success: false,
945
- message: "It looks like something went wrong — the information wasn't saved. Please try again later.",
961
+ message:
962
+ "It looks like something went wrong — the information wasn't saved. Please try again later.",
946
963
  };
947
964
  }
948
965
  }
@@ -1024,8 +1041,8 @@ async function personalDetailsFormOnReady({
1024
1041
  function getBusinessAndServicesData() {
1025
1042
  const getCurrentTestimonials = () =>
1026
1043
  $w('#testimonialRepeater')
1027
- .data.filter((item) => item.isAdd === false)
1028
- .map((item) => item.text)
1044
+ .data.filter(item => item.isAdd === false)
1045
+ .map(item => item.text)
1029
1046
  .filter(Boolean) || itemMemberObj.testimonial;
1030
1047
 
1031
1048
  return {
@@ -1035,7 +1052,7 @@ async function personalDetailsFormOnReady({
1035
1052
  profileImage: uploadedImages.profileImage,
1036
1053
  logoImage: uploadedImages.logoImage,
1037
1054
  bannerImages: uploadedImages.bannerImage ? [uploadedImages.bannerImage] : [],
1038
- areasOfPractices: selectedServices.map((service) => service.label),
1055
+ areasOfPractices: selectedServices.map(service => service.label),
1039
1056
  aboutService: $w('#aboutInput').value,
1040
1057
  testimonial: getCurrentTestimonials(),
1041
1058
  };
@@ -1063,7 +1080,11 @@ async function personalDetailsFormOnReady({
1063
1080
  if (result.success) {
1064
1081
  if (personalChanges.url && personalChanges.url !== originalUrl) {
1065
1082
  const newProfileLink = `${wixLocation.baseUrl}/profile/${personalChanges.url}`;
1066
- console.log('🔗 Updating profile link:', { originalUrl, newUrl: personalChanges.url, newProfileLink });
1083
+ console.log('🔗 Updating profile link:', {
1084
+ originalUrl,
1085
+ newUrl: personalChanges.url,
1086
+ newProfileLink,
1087
+ });
1067
1088
  $w('#profileLink').text = newProfileLink;
1068
1089
  $w('#profileLink').link = newProfileLink;
1069
1090
 
@@ -1109,8 +1130,14 @@ async function personalDetailsFormOnReady({
1109
1130
  const addTestimonialButton = $w('#addTestimonialButton');
1110
1131
 
1111
1132
  addTestimonialButton.onClick(handleAddTestimonial);
1112
- $w('#deleteTestimonialButton').onClick((event) => {
1113
- handleItemDelete(event, '#testimonialText', itemMemberObj.testimonial, null, renderTestimonials);
1133
+ $w('#deleteTestimonialButton').onClick(event => {
1134
+ handleItemDelete(
1135
+ event,
1136
+ '#testimonialText',
1137
+ itemMemberObj.testimonial,
1138
+ null,
1139
+ renderTestimonials
1140
+ );
1114
1141
  });
1115
1142
 
1116
1143
  renderTestimonials();
@@ -1135,7 +1162,7 @@ async function personalDetailsFormOnReady({
1135
1162
  const addItem = { _id: 'add-item', text: '', isAdd: true };
1136
1163
  const testimonialData = [
1137
1164
  addItem,
1138
- ...testimonials.map((text) => ({ _id: generateId(), text, isAdd: false })),
1165
+ ...testimonials.map(text => ({ _id: generateId(), text, isAdd: false })),
1139
1166
  ];
1140
1167
 
1141
1168
  setupRepeater('#testimonialRepeater', testimonialData);
@@ -1202,7 +1229,7 @@ async function personalDetailsFormOnReady({
1202
1229
  });
1203
1230
 
1204
1231
  // toggle handlers
1205
- $w('#showUrlWixCheckbox').onChange((e) => {
1232
+ $w('#showUrlWixCheckbox').onChange(e => {
1206
1233
  if (e.target.checked) {
1207
1234
  $w('#showExsistingUrlCheckbox').checked = false;
1208
1235
  $w('#UrlInput').disable();
@@ -1210,7 +1237,7 @@ async function personalDetailsFormOnReady({
1210
1237
  }
1211
1238
  checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
1212
1239
  });
1213
- $w('#showExsistingUrlCheckbox').onChange((e) => {
1240
+ $w('#showExsistingUrlCheckbox').onChange(e => {
1214
1241
  if (e.target.checked) {
1215
1242
  $w('#showUrlWixCheckbox').checked = false;
1216
1243
  $w('#UrlInput').enable();
@@ -1239,7 +1266,9 @@ async function personalDetailsFormOnReady({
1239
1266
  const formatted = formatFullAddress(address);
1240
1267
 
1241
1268
  const hasValidCoordinates = Boolean(address.latitude && address.longitude);
1242
- const location = hasValidCoordinates ? { latitude: address.latitude, longitude: address.longitude } : null;
1269
+ const location = hasValidCoordinates
1270
+ ? { latitude: address.latitude, longitude: address.longitude }
1271
+ : null;
1243
1272
 
1244
1273
  return {
1245
1274
  formatted,
@@ -1283,14 +1312,16 @@ async function personalDetailsFormOnReady({
1283
1312
  state: addressInputValue.subdivision || '',
1284
1313
  postalcode: addressInputValue.postalCode || '',
1285
1314
  country: addressInputValue.country || 'US',
1286
- latitude: addressInputValue.location?.latitude || (existingAddress?.latitude || 0),
1287
- longitude: addressInputValue.location?.longitude || (existingAddress?.longitude || 0),
1315
+ latitude: addressInputValue.location?.latitude || existingAddress?.latitude || 0,
1316
+ longitude: addressInputValue.location?.longitude || existingAddress?.longitude || 0,
1288
1317
  addressStatus: existingAddress?.addressStatus || FALLBACK_ADDRESS_STATUS,
1289
1318
  };
1290
1319
  }
1291
1320
 
1292
1321
  function setupAddressRepeater() {
1293
- $w('#addressesList').onItemReady(($item, itemData, index) => handleAddressItem($item, itemData, index));
1322
+ $w('#addressesList').onItemReady(($item, itemData, _index) =>
1323
+ handleAddressItem($item, itemData, _index)
1324
+ );
1294
1325
  renderAddressesList();
1295
1326
 
1296
1327
  $w('#newAddressButton').onClick(addNewAddress);
@@ -1299,9 +1330,9 @@ async function personalDetailsFormOnReady({
1299
1330
  }
1300
1331
 
1301
1332
  function setupAddressRepeaterEventListeners() {
1302
- $w('#mainAddressCheckbox').onChange((event) => {
1333
+ $w('#mainAddressCheckbox').onChange(event => {
1303
1334
  const data = $w('#addressesList').data;
1304
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1335
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1305
1336
  const $item = $w.at(event.context);
1306
1337
 
1307
1338
  $w('#mainAddressCheckbox').checked = false;
@@ -1316,9 +1347,9 @@ async function personalDetailsFormOnReady({
1316
1347
  checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
1317
1348
  });
1318
1349
 
1319
- $w('#addressStatusOptions').onChange((event) => {
1350
+ $w('#addressStatusOptions').onChange(event => {
1320
1351
  const data = $w('#addressesList').data;
1321
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1352
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1322
1353
  const newStatus = event.target.value;
1323
1354
  const $item = $w.at(event.context);
1324
1355
  const isMain = $item('#mainAddressCheckbox').checked;
@@ -1332,32 +1363,32 @@ async function personalDetailsFormOnReady({
1332
1363
  checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
1333
1364
  });
1334
1365
 
1335
- $w('#addressItemEditBtn').onClick((event) => {
1366
+ $w('#addressItemEditBtn').onClick(event => {
1336
1367
  const data = $w('#addressesList').data;
1337
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1368
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1338
1369
  const $item = $w.at(event.context);
1339
1370
  $item('#addressItemStates').changeState(ADDRESS_STATES.EDIT);
1340
1371
  const addressInputValue = convertToAddressInputFormat(clickedItemData.address);
1341
1372
  $item('#addressEditInput').value = addressInputValue;
1342
1373
  });
1343
1374
 
1344
- $w('#addressItemRemoveBtn').onClick(async (event) => {
1375
+ $w('#addressItemRemoveBtn').onClick(async event => {
1345
1376
  const data = $w('#addressesList').data;
1346
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1377
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1347
1378
  const result = await wixWindow.openLightbox(LIGHTBOX_NAMES.DELETE_CONFIRM);
1348
1379
  if (result && result.toDelete) {
1349
1380
  removeAddress(clickedItemData._id);
1350
1381
  }
1351
1382
  });
1352
1383
 
1353
- $w('#addressEditInput').onChange((event) => {
1384
+ $w('#addressEditInput').onChange(event => {
1354
1385
  const $item = $w.at(event.context);
1355
1386
  validateAddressCompleteness($item);
1356
1387
  });
1357
1388
 
1358
- $w('#addressEditCancelBtn').onClick((event) => {
1389
+ $w('#addressEditCancelBtn').onClick(event => {
1359
1390
  const data = $w('#addressesList').data;
1360
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1391
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1361
1392
  const $item = $w.at(event.context);
1362
1393
  if (clickedItemData.isNewAddress) {
1363
1394
  removeNewAddressFromRepeater(clickedItemData._id);
@@ -1367,9 +1398,9 @@ async function personalDetailsFormOnReady({
1367
1398
  }
1368
1399
  });
1369
1400
 
1370
- $w('#addressEditSaveBtn').onClick((event) => {
1401
+ $w('#addressEditSaveBtn').onClick(event => {
1371
1402
  const data = $w('#addressesList').data;
1372
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1403
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1373
1404
  const $item = $w.at(event.context);
1374
1405
  saveAddressFromSingleInput($item, clickedItemData);
1375
1406
  });
@@ -1433,7 +1464,7 @@ async function personalDetailsFormOnReady({
1433
1464
  $item('#addressStatusOptions').value = addressStatus;
1434
1465
  }
1435
1466
 
1436
- function setupAddressEditState($item, itemData, index) {
1467
+ function setupAddressEditState($item, itemData, _index) {
1437
1468
  $item('#addressEditInput').enable();
1438
1469
 
1439
1470
  const addressInputValue = convertToAddressInputFormat(itemData.address);
@@ -1526,7 +1557,7 @@ async function personalDetailsFormOnReady({
1526
1557
 
1527
1558
  function removeNewAddressFromRepeater(addressId) {
1528
1559
  const currentData = $w('#addressesList').data || [];
1529
- const updatedData = currentData.filter((item) => item._id !== addressId);
1560
+ const updatedData = currentData.filter(item => item._id !== addressId);
1530
1561
  $w('#addressesList').data = updatedData;
1531
1562
  }
1532
1563
 
@@ -1568,7 +1599,7 @@ async function personalDetailsFormOnReady({
1568
1599
  : [];
1569
1600
 
1570
1601
  addressData = addresses.map((address, index) => {
1571
- const displayOption = displayOptions.find((opt) => opt.key === address.key);
1602
+ const displayOption = displayOptions.find(opt => opt.key === address.key);
1572
1603
  return {
1573
1604
  _id: address.key || `address_${index}`,
1574
1605
  address,
@@ -1601,11 +1632,11 @@ async function personalDetailsFormOnReady({
1601
1632
  itemMemberObj.addressDisplayOption = [];
1602
1633
  }
1603
1634
 
1604
- itemMemberObj.addressDisplayOption.forEach((option) => {
1635
+ itemMemberObj.addressDisplayOption.forEach(option => {
1605
1636
  option.isMain = false;
1606
1637
  });
1607
1638
 
1608
- const selectedOption = itemMemberObj.addressDisplayOption.find((opt) => opt.key === selectedId);
1639
+ const selectedOption = itemMemberObj.addressDisplayOption.find(opt => opt.key === selectedId);
1609
1640
 
1610
1641
  selectedOption.isMain = true;
1611
1642
  }
@@ -1613,7 +1644,7 @@ async function personalDetailsFormOnReady({
1613
1644
  function updateAddressStatus(addressId, newStatus) {
1614
1645
  const addresses = Array.isArray(itemMemberObj.addresses) ? itemMemberObj.addresses : [];
1615
1646
  const addressIndex = addresses.findIndex(
1616
- (addr) => (addr.key || `address_${addresses.indexOf(addr)}`) === addressId
1647
+ addr => (addr.key || `address_${addresses.indexOf(addr)}`) === addressId
1617
1648
  );
1618
1649
 
1619
1650
  if (addressIndex !== -1) {
@@ -1624,7 +1655,7 @@ async function personalDetailsFormOnReady({
1624
1655
  function updateAddress(addressId, newAddressValue) {
1625
1656
  const addresses = Array.isArray(itemMemberObj.addresses) ? itemMemberObj.addresses : [];
1626
1657
  const addressIndex = addresses.findIndex(
1627
- (addr) => (addr.key || `address_${addresses.indexOf(addr)}`) === addressId
1658
+ addr => (addr.key || `address_${addresses.indexOf(addr)}`) === addressId
1628
1659
  );
1629
1660
 
1630
1661
  if (addressIndex !== -1) {
@@ -1640,12 +1671,14 @@ async function personalDetailsFormOnReady({
1640
1671
  function removeAddress(addressId) {
1641
1672
  if (itemMemberObj.addresses) {
1642
1673
  itemMemberObj.addresses = itemMemberObj.addresses.filter(
1643
- (addr) => (addr.key || `address_${itemMemberObj.addresses.indexOf(addr)}`) !== addressId
1674
+ addr => (addr.key || `address_${itemMemberObj.addresses.indexOf(addr)}`) !== addressId
1644
1675
  );
1645
1676
  }
1646
1677
 
1647
1678
  if (itemMemberObj.addressDisplayOption) {
1648
- itemMemberObj.addressDisplayOption = itemMemberObj.addressDisplayOption.filter((opt) => opt.key !== addressId);
1679
+ itemMemberObj.addressDisplayOption = itemMemberObj.addressDisplayOption.filter(
1680
+ opt => opt.key !== addressId
1681
+ );
1649
1682
  }
1650
1683
 
1651
1684
  renderAddressesList();
@@ -1680,9 +1713,9 @@ async function personalDetailsFormOnReady({
1680
1713
  }
1681
1714
 
1682
1715
  function setupPhoneRepeaterEventListeners() {
1683
- $w('#phoneInput').onInput((event) => {
1716
+ $w('#phoneInput').onInput(event => {
1684
1717
  const data = $w('#phoneNumbersList').data;
1685
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1718
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1686
1719
  const phoneValue = event.target.value;
1687
1720
 
1688
1721
  updatePhoneNumber(clickedItemData._id, phoneValue);
@@ -1695,9 +1728,9 @@ async function personalDetailsFormOnReady({
1695
1728
  checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
1696
1729
  });
1697
1730
 
1698
- $w('#showPhoneCheckbox').onChange((event) => {
1731
+ $w('#showPhoneCheckbox').onChange(event => {
1699
1732
  const data = $w('#phoneNumbersList').data;
1700
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1733
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1701
1734
  const $item = $w.at(event.context);
1702
1735
 
1703
1736
  $w('#showPhoneCheckbox').checked = false;
@@ -1707,9 +1740,9 @@ async function personalDetailsFormOnReady({
1707
1740
  checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
1708
1741
  });
1709
1742
 
1710
- $w('#removePhoneBtn').onClick(async (event) => {
1743
+ $w('#removePhoneBtn').onClick(async event => {
1711
1744
  const data = $w('#phoneNumbersList').data;
1712
- const clickedItemData = data.find((item) => item._id === event.context.itemId);
1745
+ const clickedItemData = data.find(item => item._id === event.context.itemId);
1713
1746
  const result = await wixWindow.openLightbox(LIGHTBOX_NAMES.DELETE_CONFIRM);
1714
1747
  if (result && result.toDelete) {
1715
1748
  removePhone(clickedItemData._id);
@@ -1776,7 +1809,7 @@ async function personalDetailsFormOnReady({
1776
1809
 
1777
1810
  function updatePhoneNumber(phoneId, newPhoneNumber) {
1778
1811
  const currentData = $w('#phoneNumbersList').data || [];
1779
- const itemIndex = currentData.findIndex((item) => item._id === phoneId);
1812
+ const itemIndex = currentData.findIndex(item => item._id === phoneId);
1780
1813
 
1781
1814
  if (itemIndex !== -1) {
1782
1815
  currentData[itemIndex].phoneNumber = newPhoneNumber;
@@ -1789,8 +1822,8 @@ async function personalDetailsFormOnReady({
1789
1822
  function syncPhonesFromRepeater() {
1790
1823
  const phoneData = $w('#phoneNumbersList').data || [];
1791
1824
  itemMemberObj.phones = phoneData
1792
- .filter((item) => !item.isNewPhone && item.phoneNumber.trim())
1793
- .map((item) => item.phoneNumber);
1825
+ .filter(item => !item.isNewPhone && item.phoneNumber.trim())
1826
+ .map(item => item.phoneNumber);
1794
1827
  }
1795
1828
 
1796
1829
  function addNewPhoneToData(phoneId, phoneNumber) {
@@ -1805,21 +1838,21 @@ async function personalDetailsFormOnReady({
1805
1838
 
1806
1839
  function removePhone(phoneId) {
1807
1840
  const currentData = $w('#phoneNumbersList').data || [];
1808
- const phoneToRemove = currentData.find((item) => item._id === phoneId);
1841
+ const phoneToRemove = currentData.find(item => item._id === phoneId);
1809
1842
 
1810
1843
  if (phoneToRemove) {
1811
1844
  if (itemMemberObj.toShowPhone === phoneToRemove.phoneNumber) {
1812
1845
  itemMemberObj.toShowPhone = null;
1813
1846
  }
1814
1847
 
1815
- const updatedData = currentData.filter((item) => item._id !== phoneId);
1848
+ const updatedData = currentData.filter(item => item._id !== phoneId);
1816
1849
  renderPhonesList(updatedData);
1817
1850
  }
1818
1851
  }
1819
1852
 
1820
1853
  function updateShowPhoneSelection(phoneId, isVisible) {
1821
1854
  const currentData = $w('#phoneNumbersList').data || [];
1822
- const selectedItem = currentData.find((item) => item._id === phoneId);
1855
+ const selectedItem = currentData.find(item => item._id === phoneId);
1823
1856
 
1824
1857
  if (selectedItem && selectedItem.phoneNumber) {
1825
1858
  if (isVisible) {
@@ -1906,7 +1939,7 @@ async function personalDetailsFormOnReady({
1906
1939
  function buildGalleryData(gallery) {
1907
1940
  return [
1908
1941
  { _id: 'add-item', isAdd: true },
1909
- ...gallery.map((image) => ({
1942
+ ...gallery.map(image => ({
1910
1943
  _id: generateId(),
1911
1944
  image,
1912
1945
  isAdd: false,
@@ -1955,16 +1988,10 @@ async function personalDetailsFormOnReady({
1955
1988
  const container = $w('#containerRepeaterInterest');
1956
1989
  const repeater = $w('#repeaterInterest');
1957
1990
 
1958
- // if (!searchValue) {
1959
- // container.collapse();
1960
- // repeater.data = [];
1961
- // return [];
1962
- // }
1963
-
1964
1991
  const allInterests = await getInterestAll();
1965
1992
  const filtered = allInterests
1966
- .filter((val) => val.toLowerCase().includes(searchValue))
1967
- .map((val) => ({ _id: generateId(), value: val }));
1993
+ .filter(val => val.toLowerCase().includes(searchValue))
1994
+ .map(val => ({ _id: generateId(), value: val }));
1968
1995
 
1969
1996
  if (filtered.length > 0) {
1970
1997
  repeater.data = filtered;
@@ -1977,7 +2004,8 @@ async function personalDetailsFormOnReady({
1977
2004
  return filtered;
1978
2005
  }
1979
2006
 
1980
- const debounce_fun = _.debounce(async function () {
2007
+ // Declare debounce_fun - uses filterInterests above
2008
+ const debounce_fun = _.debounce(async () => {
1981
2009
  const searchValue = $w('#intrestInput').value.trim().toLowerCase();
1982
2010
  await filterInterests(searchValue);
1983
2011
  }, 250);
@@ -1986,4 +2014,3 @@ async function personalDetailsFormOnReady({
1986
2014
  module.exports = {
1987
2015
  personalDetailsFormOnReady,
1988
2016
  };
1989
-
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Handle custom validation for URL inputs
3
+ * @param {Object} element - The input element to validate
4
+ */
5
+ function handleOnCustomValidation(element) {
6
+ element.onCustomValidation((value, reject) => {
7
+ if (isNotValidUrl(value)) {
8
+ reject('Please enter a valid URL');
9
+ }
10
+ });
11
+ }
12
+
13
+ /**
14
+ * Check if URL is not valid using regex
15
+ * @param {string} url - The URL to validate
16
+ * @returns {boolean} - True if URL is invalid, false if valid
17
+ */
18
+ function isNotValidUrl(url) {
19
+ // Empty URLs are considered valid (optional field)
20
+ if (!url) return false;
21
+
22
+ // URL must start with protocol OR www - handles all TLDs including multi-level and query params
23
+ const urlRegex =
24
+ /^(https?:\/\/|www\.)([\da-z\.-]+)\.([a-z\.]{2,})([\/\w \.-]*)*(\?[&\w=.-]*)?(\#[&\w=.-]*)?\/?$/;
25
+
26
+ return !urlRegex.test(url);
27
+ }
28
+
29
+ module.exports = {
30
+ handleOnCustomValidation,
31
+ isNotValidUrl,
32
+ };
33
+
package/public/consts.js CHANGED
@@ -74,6 +74,23 @@ const MEMBERS_FIELDS = {
74
74
  showWebsite: 'showWebsite',
75
75
  addressDisplayOption: 'addressDisplayOption',
76
76
  };
77
+
78
+ const LIGHTBOX_NAMES = {
79
+ SAVE_ALERT: 'Save Alert',
80
+ LOGIN_ERROR_ALERT: 'loginError',
81
+ DELETE_CONFIRM: 'deleteConfirm',
82
+ SELECT_BANNER_IMAGES: 'Select Banner Images',
83
+ };
84
+
85
+ const ABMP_MEMBERS_HOME_URL = 'https://www.abmp.com/members';
86
+
87
+ const FREE_WEBSITE_TEXT_STATES = {
88
+ ENABLED: 'This is the default and will auto-populate with the information entered on this page.',
89
+ DISABLED: 'To deactivate, please opt in via Personal Details.',
90
+ };
91
+
92
+ const DEFAULT_BUSINESS_NAME_TEXT = 'Business name not provided';
93
+
77
94
  module.exports = {
78
95
  REGEX,
79
96
  COLLECTIONS,
@@ -82,4 +99,8 @@ module.exports = {
82
99
  DROPDOWN_OPTIONS,
83
100
  DEBOUNCE_DELAY,
84
101
  MEMBERS_FIELDS,
102
+ LIGHTBOX_NAMES,
103
+ ABMP_MEMBERS_HOME_URL,
104
+ FREE_WEBSITE_TEXT_STATES,
105
+ DEFAULT_BUSINESS_NAME_TEXT,
85
106
  };
package/public/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  module.exports = {
2
2
  ...require('./consts'),
3
3
  ...require('./messages'),
4
+ ...require('./Utils/sharedUtils'),
5
+ ...require('./Utils/formValidation'),
4
6
  };