PageSourceSearch

https://www.americaneagle.ae/blocks/account-address-book/account-address-book-util.js

js americaneagle.ae collected 2026-10-02 13:25:47 UTC 130,470 bytes, 3,080 lines download raw bytes

1import { decorateIcons } from '../../scripts/aem.js';
2import {
3  getConfigValue,
4  getMaxLengthByCountryCode,
5  getCountryIso,
6} from '../../scripts/configs.js';
7import {
8  sanitizeDOMSync,
9  createModalFromContent,
10  openModal,
11  closeModal,
12  showToastNotification,
13} from '../../scripts/utils.js';
14import {
15  createAddress, updateAddress, makePrimaryAddress, deleteAddress,
16  getDeliveryMatrixAddressStructure,
17  getAddressCitySegments,
18  getAddressAreas,
19  getAddressRegionSegments,
20} from '../../scripts/address/api.js';
21import fetchExternalDataShortcode from '../../scripts/address/shortcode-api.js';
22import { getCustomer } from '../../scripts/customer/api.js';
23import {
24  setErrorMessageForField,
25  validateForm,
26  validateInput,
27  validatePhone,
28  showErrorMessage,
29  customSelectbox,
30  validateCustomerEmail,
31  resetMessage,
32} from '../../scripts/forms.js';
33import { restrictSpecialCharacterText, getUserEmail } from '../../scripts/helpers/user-utils.js';
34import { dataLayerCustomerExistCheckoutErrors } from '../../scripts/analytics/google-data-layer.js';
35import '../../scripts/third-party/dompurify.js';
36import debounce from '../../scripts/helpers/debounce.js';
37import {
38  createShortCodeField,
39  createBuildingNumberField,
40  loadShortCodeMapModal,
41  allowSaveWhenApiDown,
42} from './shortCode.js';
43
44export const isShortCodeEnabled = await getConfigValue('shortcode-enabled') === 'true';
45export const isShortCodeMandatory = await getConfigValue('short-code-mandatory') === 'true';
46
47async function validateAndStoreShortcode(form, placeholders) {
48  const shortcodeInput = form.querySelector('#short_code');
49  if (!shortcodeInput) return true;
50  const entered = shortcodeInput.value?.trim()?.toUpperCase();
51
52  let result;
53  try {
54    result = await fetchExternalDataShortcode(entered);
55  } catch (e) {
56    // Network / JS failure → allow save
57    return allowSaveWhenApiDown(form, placeholders, e?.message);
58  }
59
60  const status = String(result?.status || '').toUpperCase();
61  const message = String(result?.message || '');
62  const details = result?.addressDetails || null;
63  // API AUTH / SERVER FAILURE → validation not possible
64  if (
65    status === 'FAILED'
66    && (
67      message.includes('401') || message.includes('403') || message.includes('404') || message.includes('500') || message.includes('503')
68    )
69  ) {
70    return allowSaveWhenApiDown(form, placeholders, message);
71  }
72  if (status !== 'SUCCESS' || !details) {
73    const errorBox = form.querySelector('.shortcode-error');
74    if (errorBox) {
75      const msg = placeholders?.invalidShortcodeData
76        || 'Invalid Short Address, please try again.';
77      errorBox.textContent = msg;
78      errorBox.classList.remove('hide');
79    }
80    shortcodeInput.classList.add('invalid');
81    return false;
82  }
83
84  const errorBox = form.querySelector('.shortcode-error');
85  if (errorBox) {
86    errorBox.textContent = '';
87    errorBox.classList.add('hide');
88  }
89  shortcodeInput.classList.remove('invalid');
90
91  const {
92    latitude, longitude, postalCode, additionalNumber,
93  } = details;
94  if (latitude) shortcodeInput.dataset.latitude = latitude;
95  if (longitude) shortcodeInput.dataset.longitude = longitude;
96  if (postalCode) shortcodeInput.dataset.postalCode = postalCode;
97  if (additionalNumber) shortcodeInput.dataset.additionalNumber = additionalNumber;
98
99  return true;
100}
101
102const countryRules = {
103  QA: {
104    required: ['street', 'area', 'address_building_segment', 'address_city_segment'],
105    notRequired: ['address'],
106  },
107  AE: {
108    required: ['address_building_segment', 'address_city_segment', 'area', 'street'],
109    notRequired: ['address_apartment_segment'],
110  },
111  KW: {
112    required: ['address_building_segment', 'address_block_segment', 'area', 'street', 'governate'],
113    notRequired: ['address_apartment_segment'],
114  },
115  SA: {
116    required: ['address_building_segment', 'area', 'street', 'address_city_segment'],
117    notRequired: ['address_apartment_segment', 'address_block_segment', 'secondary_number', 'longitude', 'latitude', 'postcode'],
118  },
119  EG: {
120    required: ['address_building_segment', 'address_region_segment', 'street', 'address_city_segment'],
121    notRequired: ['address_landmark_segment', 'postcode', 'address_floor_segment'],
122  },
123  JO: {
124    required: ['address_district_segment', 'address_city_segment', 'address_building_segment', 'street'],
125    notRequired: ['address_landmark_segment'],
126  },
127  BH: {
128    required: ['address_road_segment', 'address_building_segment', 'address_block_segment', 'address_district_segment', 'address_city_segment'],
129    notRequired: ['address_apartment_segment'],
130  },
131};
132if (isShortCodeEnabled) {
133  if (isShortCodeMandatory) {
134    countryRules.SA.required.push('short_code');
135  } else {
136    countryRules.SA.notRequired.push('short_code');
137  }
138}
139const countriesWithRegions = ['EG', 'JO', 'BH'];
140
141// adding toast notification
142export function addStatusMessage(message) {
143  showToastNotification(message);
144  window.scrollTo({
145    top: 0,
146    behavior: 'smooth',
147  });
148}
149
150export async function updateOptionData(form, options, type) {
151  const selectEle = form?.querySelector(type);
152  const selectItemsDiv = selectEle?.querySelector('.select-items');
153  if (selectItemsDiv) {
154    selectItemsDiv.innerHTML = '';
155    // Rebuild dropdown from options
156    Array.from(options?.items).forEach((option) => {
157      if (option?.location_id) {
158        const cityDiv = document.createElement('div');
159        cityDiv.setAttribute('data-value', option?.location_id);
160        cityDiv.textContent = option?.label;
161        selectItemsDiv.appendChild(cityDiv);
162      }
163    });
164  }
165}
166
167export const accountNoAddress = await getConfigValue('account-no-adddress-enabled');
168export const isAddAddressModalEnabled = await getConfigValue('add-address-modal-enabled');
169const dropdownLabelEnabled = await getConfigValue('dropdown-label-enabled');
170const disableInlineValidation = await getConfigValue('disable-inline-validation');
171function selectItemsTriggerModal(formElement) {
172  formElement.querySelectorAll('.select-items div').forEach((optionitem) => {
173    optionitem.addEventListener('click', function (e) {
174      e.stopPropagation();
175      const currentDropdown = this.closest('.custom-select');
176      const selected = currentDropdown.querySelector('.select-selected');
177      selected.textContent = this.textContent;
178      selected.dataset.value = this.dataset.value;
179      this.parentNode.classList.add('select-hide');
180      const parentInput = this.closest('div.input-field-wrapper.dropdown');
181      parentInput.querySelector('.error-message-container')?.classList.add('hide');
182      currentDropdown.querySelector('.select-search')?.classList.add('hide');
183    });
184  });
185}
186
187async function showDropdownModal(blockConfigs, modalType, placeholders, formElement, formDropdown) {
188  const modalId = `select-${modalType}-modal`;
189  let modalTitle;
190  let elementId;
191  let values;
192  const countryCode = await getConfigValue('country-code');
193  const hasDistrict = formElement.querySelector('#address_district_segment');
194  const hasRegion = formElement.querySelector('#address_region_segment');
195  const hasCity = formElement.querySelector('#address_city_segment');
196  if (modalType === 'city' && !hasDistrict && !hasRegion) {
197    modalTitle = placeholders.selectCity || 'Select City';
198    elementId = '#address_city_segment .select-selected';
199    values = await getAddressCitySegments(countryCode);
200  } else if (modalType === 'city' && hasDistrict) {
201    modalTitle = placeholders.selectCity || 'Select City';
202    elementId = '#address_city_segment .select-selected';
203    const districtValue = formElement.querySelector('.address_district_segment .select-selected')?.getAttribute('data-value') || formElement.querySelector('.address_district_segment .select-selected')?.getAttribute('data-initial-value');
204    values = await getAddressCitySegments(countryCode, districtValue);
205  } else if (modalType === 'city' && hasRegion) {
206    modalTitle = placeholders.selectCity || 'Select City';
207    elementId = '#address_city_segment .select-selected';
208    const regionValue = formElement.querySelector('.address_region_segment .select-selected')?.getAttribute('data-value') || formElement.querySelector('.address_regi
208on_segment .select-selected')?.getAttribute('data-initial-value');
209    values = await getAddressCitySegments(countryCode, regionValue);
210  } else if (modalType === 'area' && hasCity) {
211    modalTitle = placeholders.selectArea || 'Select Area';
212    elementId = '#area .select-selected';
213    const cityValue = formElement.querySelector('.address_city_segment .select-selected')?.getAttribute('data-value') || formElement.querySelector('.address_city_segment .select-selected')?.getAttribute('data-initial-value');
214    if (!cityValue) {
215      return;
216    }
217    values = await getAddressAreas(countryCode, cityValue);
218  } else if (modalType === 'area') {
219    modalTitle = placeholders.selectArea || 'Select Area';
220    elementId = '#area .select-selected';
221    const cityValue = formElement.querySelector('.address_city_segment .select-selected')?.getAttribute('data-value') || formElement.querySelector('.address_city_segment .select-selected')?.getAttribute('data-initial-value');
222    values = await getAddressAreas(countryCode, cityValue);
223  } else if (modalType === 'district') {
224    modalTitle = placeholders.selectDistrict || 'Select District';
225    elementId = '#address_district_segment .select-selected';
226    values = await getAddressRegionSegments(countryCode);
227  } else if (modalType === 'region') {
228    modalTitle = placeholders.selectRegion || 'Select Region';
229    elementId = '#address_region_segment .select-selected';
230    values = await getAddressRegionSegments(countryCode);
231  }
232  const modalContent = document.createElement('div');
233  modalContent.classList.add(`select-${modalType}-content`);
234  const itemList = document.createElement('ul');
235  itemList.innerHTML = `<li class="no-results hide">${placeholders.dropdownNoResultsFound || 'No Results Found'}</li>`;
236  values?.items.forEach((val) => {
237    const listItem = document.createElement('li');
238    listItem.id = val.location_id;
239    listItem.textContent = val.label;
240    itemList.appendChild(listItem);
241  });
242
243  /* searchbox created */
244  const searchContainerDiv = document.createElement('div');
245  const searchBarDiv = document.createElement('div');
246  searchBarDiv.setAttribute('data-filter-attr-name', 'searchBox');
247  searchBarDiv.setAttribute('data-filter-attr-value', 'searchBox');
248  searchBarDiv.classList.add('search-field');
249  const searchIcon = document.createElement('span');
250  searchIcon.classList.add('icon', 'search-icon');
251  const searchInput = document.createElement('input');
252  searchInput.type = 'text';
253  searchInput.classList.add('searchBox', 'search-input');
254  searchInput.placeholder = placeholders.addressDropdownSearchPlaceholder || 'Search';
255  searchBarDiv.appendChild(searchIcon);
256  searchBarDiv.appendChild(searchInput);
257  searchContainerDiv.appendChild(searchBarDiv);
258  searchContainerDiv.appendChild(itemList);
259
260  modalContent.innerHTML = searchContainerDiv.innerHTML;
261
262  const removeDropdownErrors = () => {
263    const inputWrapper = formDropdown?.parentElement?.parentElement;
264    inputWrapper?.classList?.remove('invalid');
265    inputWrapper?.querySelector('.error-message-container')?.classList.add('hide');
266  };
267
268  const toggleAreaField = () => {
269    const getCityElement = formElement.querySelector('#address_city_segment .select-selected');
270    const getAreaElement = formElement.querySelector('#area .select-selected');
271    const getPlaceholderSpan = getAreaElement.querySelector('span');
272    if (getPlaceholderSpan) {
273      getPlaceholderSpan.textContent = placeholders.selectArea || 'Select Area';
274    } else {
275      getAreaElement.textContent = blockConfigs['checkout-area-dropdown-placeholder'];
276    }
277    getAreaElement.setAttribute('data-value', '');
278    getAreaElement.setAttribute('data-initial-value', '');
279    if (getCityElement) {
280      getAreaElement.setAttribute('aria-disabled', 'false');
281    } else {
282      getAreaElement.setAttribute('aria-disabled', 'true');
283    }
284  };
285
286  const toggleCityField = () => {
287    const getDistrictElement = formElement.querySelector('#address_district_segment .select-selected');
288    const getRegionElement = formElement.querySelector('#address_region_segment .select-selected');
289    const getCityElement = formElement.querySelector('#address_city_segment .select-selected');
290    const getPlaceholderSpan = getCityElement.querySelector('span');
291    if (getPlaceholderSpan && !getDistrictElement && !getRegionElement) {
292      getPlaceholderSpan.textContent = placeholders.selectArea || 'Select Area';
293    } else if (getDistrictElement || getRegionElement) {
294      if (getPlaceholderSpan) {
295        getPlaceholderSpan.textContent = placeholders.selectCity || 'Select City';
296      } else {
297        getCityElement.textContent = placeholders.selectCity || 'Select City';
298      }
299    } else {
300      getCityElement.textContent = blockConfigs['checkout-city-dropdown-placeholder'];
301    }
302    getCityElement.setAttribute('data-value', '');
303    getCityElement.setAttribute('data-initial-value', '');
304    if (getDistrictElement || getRegionElement) {
305      getCityElement.setAttribute('aria-disabled', 'false');
306    } else {
307      getCityElement.setAttribute('aria-disabled', 'true');
308    }
309  };
310
311  modalContent.addEventListener('click', (e) => {
312    if (e.target.tagName === 'LI') {
313      const getElem = formElement.querySelector(elementId);
314      getElem.setAttribute('data-value', `${e.target.id}`);
315      if (dropdownLabelEnabled && getElem.querySelector('span')) {
316        getElem.querySelector('span').innerHTML = e.target.textContent;
317      } else {
318        getElem.innerHTML = e.target.textContent;
319      }
320      closeModal(modalId);
321      removeDropdownErrors();
322      if (modalType === 'city' && !hasDistrict && !hasRegion) {
323        toggleAreaField();
324      }
324 else if (modalType === 'district' || modalType === 'region') {
325        toggleCityField();
326      }
327    }
328  });
329  const listItems = modalContent.querySelectorAll('li');
330  const searchInputElem = modalContent.querySelector('.searchBox');
331  const noResultsOption = modalContent?.querySelector('.no-results');
332  searchInputElem.addEventListener('keyup', (e) => {
333    const filterText = e.target.value.toLowerCase(); // Get input and convert to lowercase
334    let anyVisible = false;
335    const filteredItems = Array.from(listItems)?.filter((item) => !item.classList.contains('no-results'));
336    filteredItems.forEach((item) => {
337      const itemText = item.textContent.toLowerCase(); // Convert list item text to lowercase
338      if (itemText.includes(filterText)) {
339        item.style.display = ''; // Show matching item
340        anyVisible = true;
341      } else {
342        item.style.display = 'none'; // Hide non-matching item
343      }
344    });
345
346    if (!anyVisible) {
347      noResultsOption.classList.remove('hide');
348    } else {
349      noResultsOption.classList.add('hide');
350    }
351  });
352
353  const arrowLeftIcon = blockConfigs?.flags?.arrowLeftIcon ? blockConfigs.flags.arrowLeftIcon : 'arrow-left-blue';
354  const closeIcon = blockConfigs?.flags?.closeIcon ? blockConfigs.flags.closeIcon : 'icon-close-blue';
355  await createModalFromContent(
356    modalId,
357    modalTitle,
358    modalContent,
359    [`${modalId}`],
360    arrowLeftIcon,
361    true,
362    closeIcon,
363  );
364  openModal(modalId);
365  const backButton = document.querySelector(`dialog.${modalId} .modal-header span`);
366  backButton.addEventListener('click', () => {
367    closeModal(modalId);
368  });
369}
370
371export async function wrapTwoDivsinWrapper(firstDiv, secondDiv, className) {
372  if (firstDiv.closest(`.${className}`)) {
373    return;
374  }
375  const WrapperDiv = document.createElement('div');
376  WrapperDiv.className = className; // Add a class to the wrapper div if needed
377
378  // Insert the wrapper div before the first div
379  firstDiv.parentNode.insertBefore(WrapperDiv, firstDiv);
380  // Move the two divs into the wrapper div
381  WrapperDiv.appendChild(firstDiv);
382  WrapperDiv.appendChild(secondDiv);
383}
384
385function customSelectboxModal(blockConfigs, placeholders, formElement) {
386  const searchInput = formElement.querySelector('.select-search');
387  const options = formElement?.querySelectorAll('.select-items div:not([disabled])');
388  const noResultsOption = formElement?.querySelector('.no-results');
389  searchInput?.addEventListener('keyup', function () {
390    const filter = this.value.toLowerCase();
391    let anyVisible = false;
392
393    options.forEach((option) => {
394      const text = option.textContent.toLowerCase();
395      if (text.includes(filter)) {
396        noResultsOption.classList.add('hide');
397        option.classList.remove('hide');
398        anyVisible = true;
399      } else {
400        option.classList.add('hide');
401      }
402    });
403
404    if (!anyVisible) {
405      noResultsOption.classList.remove('hide');
406    } else {
407      noResultsOption.classList.add('hide');
408    }
409  });
410
411  if (!formElement) return;
412  const hasDistrict = formElement.querySelector('#address_district_segment');
413  const hasRegion = formElement.querySelector('#address_region_segment');
414  formElement.querySelectorAll('.custom-select').forEach((item) => {
415    item.addEventListener('click', function () {
416      let modalOpened = false;
417      if (item.getAttribute('name') === 'address_city_segment' && !hasDistrict && !hasRegion) {
418        showDropdownModal(blockConfigs, 'city', placeholders, formElement, item);
419        modalOpened = true;
420      } else if (item.getAttribute('name') === 'address_city_segment' && hasDistrict && (item.querySelector('.select-selected').getAttribute('aria-disabled') === 'false' || item.querySelector('.select-selected').getAttribute('data-initial-value'))) {
421        item.querySelector('.select-items').innerHTML = '';
422        showDropdownModal(blockConfigs, 'city', placeholders, formElement, item);
423        modalOpened = true;
424      } else if (item.getAttribute('name') === 'address_city_segment' && hasRegion && (item.querySelector('.select-selected').getAttribute('aria-disabled') === 'false' || item.querySelector('.select-selected').getAttribute('data-initial-value'))) {
425        item.querySelector('.select-items').innerHTML = '';
426        showDropdownModal(blockConfigs, 'city', placeholders, formElement, item);
427        modalOpened = true;
428      } else if (item.getAttribute('name') === 'area') {
429        item.querySelector('.select-items').innerHTML = '';
430        showDropdownModal(blockConfigs, 'area', placeholders, formElement, item);
431        modalOpened = true;
432      } else if (item.getAttribute('name') === 'address_district_segment') {
433        showDropdownModal(blockConfigs, 'district', placeholders, formElement, item);
434        modalOpened = true;
435      }
435 else if (item.getAttribute('name') === 'address_region_segment') {
436        showDropdownModal(blockConfigs, 'region', placeholders, formElement, item);
437        modalOpened = true;
438      }
439      if (modalOpened) return;
440
441      formElement.querySelector('.select-search').classList.remove('hide');
442      // closeModal(addAddressModalId);
443      const currentItems = this.parentNode.querySelector('.select-items');
444      // Hide all other dropdowns
445      document.querySelectorAll('.select-items').forEach((selectItem) => {
446        if (selectItem !== currentItems) {
447          selectItem.classList.add('select-hide');
448        }
449        selectItem.addEventListener('click', () => {
450          formElement.querySelector('.select-search').classList.add('hide');
451        });
452      });
453      // Toggle the clicked dropdown
454      currentItems.classList.remove('select-hide');
455      currentItems.parentNode.querySelector('.select-search')?.classList.toggle('hide');
456    });
457  });
458
459  selectItemsTriggerModal(formElement);
460
461  document.addEventListener('click', (e) => {
462    if (!e.target.matches('.custom-select, .custom-select *')) {
463      formElement.querySelectorAll('.select-items').forEach((item) => {
464        item.classList.add('select-hide');
465      });
466      formElement.querySelector('.select-search').classList.add('hide');
467    }
468  });
469}
470
471// handleNoAddress
472export function handleNoAddress() {
473  const noAddress = document.querySelector('.account-no-address');
474  noAddress?.classList.add('hide');
475}
476
477// Handling address hovering effect
478export function handleAddressHover(addressWrapper) {
479  const cta = addressWrapper.querySelector('.make-primary-cta');
480  cta?.addEventListener('mouseover', () => {
481    const addressFirstRow = cta.closest('.address').querySelector('.address-data');
482    addressFirstRow?.classList.add('primary-address-data');
483  });
484  cta?.addEventListener('mouseout', () => {
485    const addressFirstRow = cta.closest('.address').querySelector('.address-data');
486    addressFirstRow?.classList.remove('primary-address-data');
487  });
488
489  const data = addressWrapper.querySelector('.address-data');
490  data?.addEventListener('mouseover', () => {
491    data.closest('.address').querySelector('.make-primary-cta')?.classList.add('hovered');
492  });
493  data?.addEventListener('mouseout', () => {
494    data.closest('.address').querySelector('.make-primary-cta')?.classList.remove('hovered');
495  });
496}
497
498// live search feature to a custom dropdown menu. As the user types in searchInput,
499// the function filters the dropdown options, displaying only those that match the search term
500// and showing a "No results" message if no matches are found
501function enableDropdownSearch(dropdown) {
502  if (!dropdown) return;
503  const searchInput = dropdown?.querySelector('.select-search');
504  const options = Array.from(dropdown?.querySelectorAll('.select-items div:not([disabled])'));
505  const noResultsOption = dropdown?.querySelector('.no-results');
506  const selectItemsContainer = dropdown.querySelector('.select-items');
507
508  options.sort((a, b) => a.textContent.localeCompare(b.textContent));
509  selectItemsContainer.innerHTML = '';
510  options.forEach((option) => { option.setAttribute('tabindex', 0); selectItemsContainer.appendChild(option); });
511
512  searchInput.addEventListener('keyup', function () {
513    const filter = this.value.toLowerCase();
514    let anyVisible = false;
515
516    options.forEach((option) => {
517      const text = option.textContent.toLowerCase();
518      if (text.includes(filter)) {
519        option.classList.remove('hide');
520        anyVisible = true;
521      } else {
522        option.classList.add('hide');
523      }
524    });
525
526    if (!anyVisible) {
527      noResultsOption.classList.remove('hide');
528    } else {
529      noResultsOption.classList.add('hide');
530    }
531  });
532}
533
534async function updateArea(countryCode, cityValue, form, placeholders) {
535  const areas = await getAddressAreas(countryCode, cityValue);
536  const areaField = form.querySelector('#area');
537  const areaSelect = areaField.querySelector('.select-selected');
538  const areaItems = areaField.querySelector('.select-items');
539  const initialAreaValue = areaSelect?.getAttribute('data-initial-value');
540  areaItems.innerHTML = `<div data-value="" class="no-results hide">${placeholders.dropdownNoResultsFound || 'No Results Found'}</div>`;
541  let selectedAreaLabel;
542
543  areas.items?.forEach((area) => {
544    if (area.location_id === Number(initialAreaValue)) {
545      selectedAreaLabel = area.label;
546    }
547    const option = document.createElement('div');
548    option.setAttribute('data-value', area.location_id);
549    option.textContent = area.label;
550    areaItems.appendChild(option);
551  });
552  areaField.querySelector('.select-items > div[disabled]')?.remove();
553  enableDropdownSearch(areaField);
554  // Reset the dropdown state
555  if (dropdownLabelEnabled && areaSelect.querySelector('span')) {
556    areaSelect.querySelector('span').textContent = selectedAreaLabel || placeholders.selectArea || 'Select Area';
557  } else {
558    areaSelect.innerHTML = selectedAreaLabel || placeholders.selectArea || 'Select Area';
559  }
560  areaSelect.dataset.value = initialAreaValue;
561
562  if (!selectedAreaLabel) {
563    areaSelect.setAttribute('data-initial-value', '');
564    areaSelect.dataset.value = '';
565  }
566
567  // Clean up any existing event listeners
568  const clonedAreaSelect = areaSelect.cloneNode(true);
569  areaField.replaceChild(clonedAreaSelect, areaSelect);
570
571  // Reinitialize the custom select box
572  customSelectbox(form.querySelector('.input-field-wrapper.dropdown.area'));
573}
574
575function updateCity(regionValue, form, placeholders, cities, resetDefaultValue) {
576  const cityField = form.querySelector('#address_city_segment');
577  const citySelect = cityField.querySelector('.select-selected');
578  if (resetDefaultValue) citySelect.setAttribute('data-initial-value', '');
579  const cityItems = cityField.querySelector('.select-items');
580  const initialCityValue = citySelect?.getAttribute('data-initial-value');
581  cityItems.innerHTML = '';
582  let selectedCityLabel;
583
584  const regionSpecificCities = cities?.items?.filter((city) => city.parent_id === +regionValue);
585  if (regionSpecificCities?.length) {
586    regionSpecificCities.forEach((city) => {
587      if (city.location_id === Number(initialCityValue)) {
588        selectedCityLabel = city.label;
589      }
590      const option = document.createElement('div');
591      option.setAttribute('data-value', city.location_id);
592      option.textContent = city.label;
593      cityItems.appendChild(option);
594    });
595  } else {
596    cityItems.innerHTML = `<div data-value="" class="no-results">${placeholders.dropdownNoResultsFound || 'No Results Found'}</div>`;
597  }
598
599  cityField.querySelector('.select-items > div[disabled]')?.remove();
600  enableDropdownSearch(cityField);
601
602  // Reset the dropdown state
603  citySelect.textContent = selectedCityLabel || placeholders.selectCity || 'Select City';
604  citySelect.dataset.value = initialCityValue;
605
606  // Clean up any existing event listeners
607  const clonedCitySelect = citySelect.cloneNode(true);
608  cityField.replaceChild(clonedCitySelect, citySelect);
609
610  // Reinitialize the custom select box
611  customSelectbox(form.querySelector('.input-field-wrapper.dropdown.address_city_segment'));
612}
613
614// Hide the 'new-address-container' element by adding the 'hide' class
615export function hideNewAddressCta() {
616  const newAddressContainer = document.querySelector('.new-address-container');
617  newAddressContainer?.classList.add('hide');
618}
619
620// populating city in address form
621async function populateCity(form, citySegments, countryCode, placeholders) {
622  const cityField = form.querySelector('#address_city_segment');
623  const initialCityValue = cityField?.querySelector('.select-selected')?.getAttribute('data-initial-value');
624  let selectedCityLabel;
625  if (citySegments && citySegments?.items?.length > 0) {
626    await updateOptionData(form, citySegments, '#address_city_segment');
627  }
628  if (cityField && citySegments) {
629    citySegments.items?.forEach((segment) => {
630      if (segment.location_id === Number(initialCityValue)) {
631        selectedCityLabel = segment.label;
632      }
633    });
634    cityField.querySelector('.select-items > div[disabled]')?.remove();
635  }
636  if (selectedCityLabel) {
637    const getElem = cityField.querySelector('.select-selected');
638    if (dropdownLabelEnabled && getElem.querySelector('span')) {
639      getElem.querySelector('span').textContent = selectedCityLabel;
640    } else {
641      getElem.innerHTML = selectedCityLabel;
642    }
643  }
644
645  if (cityField) {
646    enableDropdownSearch(cityField);
647    cityField.value = initialCityValue;
648    cityField.querySelectorAll('.select-items div').forEach((item) => {
649      ['click', 'keydown'].map((e) => item.addEventListener(e, async (event) => {
650        await updateArea(countryCode, event.target.getAttribute('data-value'), form, placeholders);
651      }));
652    });
653  }
654  if (initialCityValue) {
655    await updateArea(countryCode, cityField.value, form, placeholders);
656  } else {
657    customSelectbox(form.querySelector('.input-field-wrapper.dropdown.area'));
658  }
659}
660
661// populating city in address form
662async function populateRegions(form, regionSegments, countryCode, placeholders) {
663  const cities = await getAddressCitySegments(countryCode);
664  const regionIdSelector = (countryCode === 'JO' || countryCode === 'BH') ? '#address_district_segment' : '#address_region_segment';
665  const regionClassSelector = (countryCode === 'JO' || countryCode === 'BH') ? '.input-field-wrapper.dropdown.address_district_segment' : '.input-field-wrapper.dropdown.address_region_segment';
666  if (regionSegments && regionSegments?.items?.length > 0) {
667    await updateOptionData(form, regionSegments, regionIdSelector);
668  }
669  const regionField = form.querySelector(regionIdSelector);
670  const initialRegionValue = regionField?.querySelector('.select-selected')?.getAttribute('data-initial-value');
671
672  const regionItems = regionField.querySelector('.select-items');
673  regionItems.innerHTML = `<div data-value="" class="no-results hide">${placeholders.dropdownNoResultsFound || 'No Results Found'}</div>`;
674
675  let selectedCityLabel;
676  if (regionField && regionSegments) {
677    regionSegments.items?.forEach((segment) => {
678      if (segment.location_id === Number(initialRegionValue)) {
679        selectedCityLabel = segment.label;
680      }
681
682      const option = document.createElement('div');
683      option.setAttribute('data-value', segment.location_id);
684      option.textContent = segment.label;
685      regionItems.appendChild(option);
686    });
687    regionField.querySelector('.select-items > div[disabled]')?.remove();
688  }
689  if (selectedCityLabel) {
690    regionField.querySelector('.select-selected').textContent = selectedCityLabel;
691  }
692  if (regionField) {
693    enableDropdownSearch(regionField);
694    regionField.value = initialRegionValue;
695    regionField.querySelectorAll('.select-items div').forEach((item) => {
696      item.addEventListener('click', async (event) => {
697        await updateCity(event.target.getAttribute('data-value'), form, placeholders, cities, true);
698      });
699    });
700  }
701  setTimeout(() => {
702    updateCity(regionField.value, form, placeholders, cities, false);
703  });
704  customSelectbox(form.querySelector(regionClassSelector));
705}
706
707// to set country code
708function setCountryCode(form, countryCode) {
709  const countryId = form.querySelector('#country_id');
710  if (countryId) {
711    countryId.value = countryCode;
712    countryId.disabled = true;
713  }
714}
715
716// Function to handle country code visibility based on phone number input
717function updateCountryCodeVisibility(inputElement, force = true) {
718  const addressModalClosest = inputElement?.closest('.add-address-modal, .edit-ad
718dress-modal, .checkout-form');
719  const countryCodeLabel = addressModalClosest?.querySelector('.countrycode');
720  if (countryCodeLabel) {
721    const isNumeric = /^\d*$/.test(inputElement.value.trim()) && inputElement.value.trim();
722    if (force) {
723      countryCodeLabel.classList.toggle('hidden', !isNumeric);
724    } else {
725      countryCodeLabel.classList.toggle('hidden', false);
726    }
727  }
728}
729
730// Handle initial visibility when the modal or form is opened
731function handleInitialCheck() {
732  const telephone = document.querySelector('#telephone');
733  if (telephone) {
734    updateCountryCodeVisibility(telephone);
735  }
736}
737
738const hasTransition = await getConfigValue('phone-input-has-transition') === 'true';
739
740/**
741 * Validates and cleans telephone number before sending to API
742 * - Strips country prefix if present
743 * - Enforces maxlength based on country code
744 * - Returns cleaned number (without prefix) ready for API submission
745 *
746 * @param {string} telephoneValue - The telephone value from input
747 * @param {string} countryPrefix - Country prefix (e.g., '+965')
748 * @param {number} maxLength - Maximum allowed length for phone number
749 * @returns {string} - Cleaned telephone number without prefix, trimmed to maxLength
750 */
751function validateAndCleanTelephone(telephoneValue, countryPrefix, maxLength) {
752  if (!telephoneValue) return '';
753
754  let cleaned = telephoneValue.toString().trim();
755
756  // Remove all occurrences of country prefix from the beginning
757  if (countryPrefix) {
758    cleaned = cleaned.replace(new RegExp(`^\\${countryPrefix}+`), '');
759  }
760
761  // Remove any leading + sign that might remain
762  cleaned = cleaned.replace(/^\+/, '');
763
764  // Enforce maxlength - take only the last maxLength digits
765  // This handles cases where user bypassed maxlength attribute
766  if (maxLength && cleaned.length > maxLength) {
767    cleaned = cleaned.slice(-maxLength);
768  }
769
770  return cleaned;
771}
772
773// to set telephone input
774function createTelephoneInput(
775  countryCode,
776  maxLength,
777  countryPrefix,
778  fieldDiv,
779  name,
780  label,
781  isRequired,
782  value,
783) {
784  const pattern = '[0-9]*';
785  fieldDiv.classList.add('phonevalidation');
786  if (hasTransition) {
787    fieldDiv.classList.add('notransistion');
788  }
789  fieldDiv.innerHTML = `
790  <div class="input-wrapper input-field input-phone-prefix">
791    <label for="countrycode" class="countrycode ${hasTransition ? 'hidden' : ''}">${countryPrefix}</label>
792    <input type="tel" id="${name}" name="${name}" data-phone-prefix="${countryPrefix}" aria-label="${label}" placeholder=" " value="${value}" ${isRequired ? 'required' : ''} pattern='${pattern}' maxlength='${maxLength}' />
793     <label for="${name}" class="input-label">${label}</label>
794    </div>`;
795
796  // Handle initial visibility on focus (when editing existing numbers)
797  document.addEventListener('focus', (event) => {
798    if (event.target && event.target.id === 'telephone') {
799      updateCountryCodeVisibility(event.target, false);
800    }
801  }, true);
802
803  // Handle initial visibility on focus (when editing existing numbers)
804  document.addEventListener('focusout', (event) => {
805    if (event.target && event.target.id === 'telephone') {
806      updateCountryCodeVisibility(event.target);
807    }
808  }, true);
809
810  handleInitialCheck();
811}
812
813function getSelectedLabel(countryCode, field) {
814  return field.attribute.options?.find(
815    (option) => option.value === countryCode,
816  )?.label || countryCode;
817}
818
819function getSelectedValue(countryCode, field) {
820  return field.attribute.options?.find(
821    (option) => option.value === countryCode,
822  )?.value || countryCode;
823}
824
825// eslint-disable-next-line max-len
826function handleCheckoutFormStructure(formStructure, isLoggedIn, countryCode, placeholders, showAddressFormEmailForLoggedInUsers) {
827  // Helper function to add a field after a specific attribute code
828  const addFieldAfterAttributeCode = (attributeCode, newField, offset) => {
829    const fieldIndex = formStructure.findIndex(
830      (field) => field.attribute.attribute_code === attributeCode,
831    );
832    if (fieldIndex !== -1) {
833      formStructure.splice(fieldIndex + offset, 0, newField);
834    }
835  };
836
837  // Find the telephone field and add the email field after it
838  const telephoneFieldIndex = formStructure.findIndex((field) => field.attribute.attribute_code === 'telephone');
839  // eslint-disable-next-line max-len
840  if (telephoneFieldIndex !== -1 && (!isLoggedIn || (isLoggedIn && showAddressFormEmailForLoggedInUsers))) {
841    const emailField = JSON.parse(JSON.stringify(formStructure[telephoneFieldIndex]));
842    emailField.attribute.attribute_code = 'email';
843    emailField.attribute.store_label = placeholders.email || 'Email';
844    emailField.attribute.frontend_input = 'text';
845    emailField.attribute.required = true;
846
847    addFieldAfterAttributeCode('telephone', emailField, countryCode === 'KW' ? -1 : 0);
848  }
849}
850
851function restructureForm(form, config) {
852  if (!config?.checkoutV1) {
853    form.querySelector('.input-field-wrapper label[for="email"]')?.closest('.input-field-wrapper')?.classList?.add('emailValidation');
854    const phoneDiv = form.querySelector('.input-field-wrapper.phonevalidation');
855    const emailDiv = form.querySelector('.input-field-wrapper.emailValidation');
856    const city = form.querySelector('.input-field-wrapper.dropdown.address_city_segment');
857    const area = form.querySelector('.input-field-wrapper.dropdown.area');
858    const district = form.querySelector('.input-field-wrapper.dropdown.address_district_segment');
859    const region = form.querySelector('.input-field-wrapper.dropdown.address_region_segment');
860    wrapTwoDivsinWrapper(phoneDiv, emailDiv, 'form__phone-email-wrapper');
861    if (city && area) {
862      wrapTwoDivsinWrapper(city, area, 'form__city-area-wrapper');
863    } else if (district && city) {
864      wrapTwoDivsinWrapper(district, city, 'form__district-city-wrapper');
865    } else if (region && city) {
866      wrapTwoDivsinWrapper(region, city, 'form__region-city-wrapper');
867    }
868  }
869}
870
871// to show address form
872export async function showAddressForm(
873  blockConfigs,
874  $parent,
875  placeholders,
876  addressObj,
877  newCustomer = false,
878  isCheckoutPage = false,
879  isLoggedIn = false,
880  config = {},
881  updateOnlyTelephone = false,
882  infoMessage = '',
883  isTopup = false,
884  showAddressFormEmailForLoggedInUsers = false,
885) {
886  if (isCheckoutPage) {
887    window.dispatchEvent(new CustomEvent('react:addressFormLoading'));
888  }
889  const countryCode = await getConfigValue('country-code');
890  const addressesContainer = document.querySelector('.addresses-container');
891
892  /*
893  Filtering landmark and address_apartment_segment for EG for now from UI.
894  Once it's handled on backend, this code needs to be removed.
895  OLD CODE : const formStructure = await getDeliveryMatrixAddressStructure(countryCode);
896  */
897  const formStructureAll = await getDeliveryMatrixAddressStructure(countryCode);
898  const excludedAttributes = ['landmark', 'address_apartment_segment'];
899  const filteredFormStructure = formStructureAll.filter(
900    (item) => !(item?.country_id === 'EG' && excludedAttributes.includes(item?.attribute?.attribute_code)),
901  );
902  const formStructure = [...filteredFormStructure];
903
904  const isUpdate = Object.keys(addressObj).length > 0;
905  const block = $parent.closest('.account-address-book');
906  const maxLength = await getMaxLengthByCountryCode(countryCode);
907  const countryPrefix = `+${await getCountryIso(countryCode)}`;
908  const showArea = countryCode === 'KW';
909
910  const form = document.createElement('form');
911  let cityDefaultLabel = placeholders.selectCity || 'Select City';
912  let areaDefaultLabel = placeholders.selectArea || 'Select Area';
913
914  const firstnameField = formStructure?.find((d) => d?.attribute?.attribute_code === 'firstname');
915  if (firstnameField) {
916    firstnameField.sort_order = '0';
917  }
918  formStructure.sort((a, b) => {
919    if (Number(a.sort_order) < Number(b.sort_order)) return -1;
920    if (Number(a.sort_order) > Number(b.sort_order)) return 1;
921    return 0;
922  });
923
924  if (isCheckoutPage) {
925    // eslint-disable-next-line max-len
926    handleCheckoutFormStructure(formStructure, isLoggedIn, countryCode, placeholders, showAddressFormEmailForLoggedInUsers);
927  }
928
929  const checkoutRequiredFields = ['address_building_segment', 'address_block_segment', 'address_district_segment', 'address_city_segment'];
930  const customerData = await getCustomer();
931  const savedEmail = await getUserEmail('guest-checkout-email');
932  formStructure
933    .filter((field) => field.visible === '1' && field.attribute.attribute_code !== 'lastname')
934    .forEach((field) => {
935      if (['firstname', 'lastname', 'telephone'].includes(field.attribute.attribute_code)) {
936        field.attribute.required = true;
937      }
938      const rules = countryRules[field.country_id];
939      if (rules) {
940        if (rules.required.includes(field.attribute.attribute_code)) {
941          field.attribute.required = true;
942        } else if (rules.notRequired.includes(field.attribute.attribute_code)) {
943          field.attribute.required = false;
944        }
945      }
946      const fieldDiv = document.createElement('div');
947      fieldDiv.classList.add('input-field-wrapper');
948      let isDisabled = false;
949      if (isCheckoutPage && updateOnlyTelephone && field.attribute.attribute_code !== 'telephone') {
950        fieldDiv.classList.add('address-form-field-disabled');
951        isDisabled = true;
952      }
953      const checkoutGuestEmail = !isTopup ? (savedEmail ?? '') : '';
954      const guestUserEmail = addressObj?.[field.attribute.attribute_code] || checkoutGuestEmail;
955      if ((isLoggedIn || (guestUserEmail && !isTopup)) && field.attribute.attribute_code === 'email') isDisabled = true;
956      const validations = ['tabindex="0"'];
957      const isRequiedInCheckout = isCheckoutPage
958        ? checkoutRequiredFields.includes(field.attribute.attribute_code) : false;
959      if (field.attribute.required || isRequiedInCheckout) {
960        validations.push('required');
961      }
962
963      field.attribute.validation_rules?.forEach((rule) => {
964        if (rule.name === 'min_text_length') {
965          validations.push(`minlength="${rule.value}"`);
966        } else if (rule.name === 'max_text_length') {
967          validations.push(`maxlength="${rule.value}"`);
968        }
969      });
970
971      if (field.attribute.attribute_code === 'telephone') {
972        createTelephoneInput(countryCode, maxLength, countryPrefix, fieldDiv, field.attribute.attribute_code, field.attribute.store_label, field.attribute.required, addressObj?.[field.attribute.attribute_code] ? addressObj[field.attribute.attribute_code].replace(countryPrefix, '') : '', isCheckoutPage, updateOnlyTelephone, infoMessage);
973      } else if (field.attribute.attribute_code === 'short_code') {
974        // Show ONLY if config enabled AND market is SA
975        if (!isShortCodeEnabled || countryCode !== 'SA') {
976          return;
977        }
978        const value = addressObj?.custom_attributes?.find(
979          (a) => a.attribute_code === 'short_code',
980        )?.value || addressObj?.short_code || '';
981
982        if (field.attribute.required) {
983          validations.push('required');
984        }
985
986        createShortCodeField({
987          fieldDiv,
988          storeLabel: placeholders.shortCodeLabel || 'Short Address (Eg. RRRD2929)',
989          value,
990          validations,
991          placeholders,
992          blockConfigs,
993        });
994
995        form.appendChild(fieldDiv);
996        return;
997      } else if (field.attribute.attribute_code === 'address_building_segment' && isShortCodeEnabled && countryCode === 'SA') {
998        // Show ONLY if config enabled AND market is SA
999        const value = addressObj?.custom_attributes?.find(
1000          (a) => a.attribute_code === 'address_building_segment',
1001        )?.value || addressObj?.address_building_segment || '';
1002
1003        if (field.attribute.required) {
1004          validations.push('required');
1005        }
1006        createBuildingNumberField({
1007          fieldDiv,
1008          storeLabel: field.attribute.store_label || 'Building Number (Eg. 1234)',
1009          value,
1010          validations,
1011          placeholders,
1012          blockConfigs,
1013        });
1014
1015        form.appendChild(fieldDiv);
1016        return;
1017      } else if (field.attribute.frontend_input === 'text') {
1018        let textInputValue;
1019        if (field.attribute.attribute_code === 'email') {
1020          const email = customerData?.email || '';
1021          textInputValue = isLoggedIn ? email : guestUserEmail;
1022        } else {
1023          textInputValue = addressObj?.[field.attribute.attribute_code];
1024        }
1025        let label = field.attribute.store_label;
1026        let attributeCode = field.attribute.attribute_code;
1027        if (field.attribute.attribute_code === 'firstname') {
1028          textInputValue = textInputValue ? `${textInputValue} ${addressObj?.lastname ?? ''}` : '';
1029          label = placeholders.fullname || 'Full Name';
1030          attributeCode = 'fullName';
1031        }
1032        fieldDiv.innerHTML = `
1033          <div class="input-wrapper input-field">
1034            <input type="text" id="${attributeCode}" name="${attributeCode}" aria-label="${label}"
1035            placeholder=" " 
1036            ${isDisabled ? 'disabled' : ''}
1037            value="${sanitizeDOMSync(textInputValue || '')}" 
1038            ${field.attribute.attribute_code === 'firstname' ? 'pattern="^\\p{L}+(?:\\s\\p{L}+)+\\s?$"' : ''}
1039            ${field.attribute.attribute_code === 'email' ? 'pattern="^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"' : ''}
1040            ${validations.join(' ')}>
1041            <label for="${attributeCode}">${label}</label>
1042          </div>
1043      `;
1044      } else if (field.attribute.frontend_input === 'select') {
1045        const defaultLabelContent = field.attribute?.attribute_code === 'country_id'
1046          ? getSelectedLabel(countryCode, field)
1047          : `${field.attribute.store_label}`;
1048        const defaultLabelContentValue = field.attribute?.attribute_code === 'country_id'
1049          ? getSelectedValue(countryCode, field)
1050          : `${field.attribute.store_label}`;
1051        if (field.attribute?.attribute_code === 'city') {
1052          cityDefaultLabel = defaultLabelContent;
1053        } else if (field.attribute?.attribute_code === 'area') {
1054          areaDefaultLabel = defaultLabelContent;
1055        }
1056        const classesToAdd = ['dropdown', 'notransistion', field.attribute.attribute_code];
1057
1058        if (isCheckoutPage && field.attribute.attribute_code === 'country_id') {
1059          classesToAdd.push('hidden');
1060        }
1061        fieldDiv.classList.add(...classesToAdd);
1062        fieldDiv.innerHTML = `
1063        <div class="input-wrapper input-field">
1064          <div class="custom-select" id="${field.attribute.attribute_code}" name="${field.attribute.attribute_code}" aria-label="${field.attribute.store_label}" ${validations.join(' ')}>
1065            <div class="select-selected ${field.attribute.attribute_code === 'country_id' ? ' disabled' : ''} ${isDisabled ? ' disable' : ''}" data-value="${field.attribute.attribute_code === 'country_id' ? defaultLabelContentValue : ''}">${defaultLabelContent}</div>
1066            <input type="text" class="select-search hide ${isCheckoutPage && 'hideSearch'}" placeholder="${isCheckoutPage && field.attribute.attribute_code !== 'country_id' ? defaultLabelContent : ''}">
1067            <div class="select-items select-hide">
1068              <div data-value="" class="no-results ${field.attribute.attribute_code === 'area' && !showArea ? '' : 'hide'}">${placeholders.dropdownNoResultsFound || 'No Results Found'}</div>
1069              ${field.attribute.attribute_code === 'area' && !showArea ? '' : field.attribute.options?.filter((option) => option.label !== 'Select an option')
1070    .map((option) => `<div data-value="${option.value}" ${addressObj?.[field.attribute.attribute_code] === option.value ? 'selected' : ''}>${option.label}</div>`)
1071    .join('')}
1072            </div>
1073          </div>
1074        </div>
1075      `;
1076
1077        field.attribute.options?.map((option) => `<div data-value="${option.value}">${option.label}</div>`);
1078      } else if (field.attribute.frontend_input === 'multiline') {
1079        const rows = field.attribute.multiline_count ? `rows="${field.attribute.multiline_count}"` : '';
1080        fieldDiv.innerHTML = `
1081          <div class="input-field-wrapper">
1082            <div class="input-wrapper input-field">
1083              <textarea id="${field.attribute.attribute_code}" name="${field.attribute.attribute_code}" aria-label="${field.attribute.store_label}" placeholder=" " ${validations.join(' ')} ${rows}  ${isDisabled ? 'disabled' : ''}>${sanitizeDOMSync(addressObj?.[field.attribute.attribute_code] || '')}</textarea>
1084              <label for="${field.attribute.attribute_code}">${field.attribute.store_label}</label>
1085            </div>
1086          </div>
1087        `;
1088      }
1089
1090      const customAttributeFields = ['area', 'address_region_segment', 'address_building_segment',
1091        'address_apartment_segment', 'address_city_segment', 'address_block_segment',
1092        'address', 'address_floor_segment', 'address_landmark_segment', 'address_district_segment', 'address_road_segment', 'short_code', 'secondary_number', 'latitude', 'longitude',
1093      ];
1094      if (customAttributeFields.indexOf(field.attribute.attribute_code) !== -1) {
1095        let value = addressObj.custom_attributes?.find((attr) => attr.attribute_code === field.attribute.attribute_code)?.value || '';
1096        if (field?.attribute?.required === true && field?.attribute?.frontend_input === 'select') {
1097          value = (field?.attribute?.options.some((option) => String(option.value) === value) === true) ? value : '';
1098        }
1099
1100        const inputField = fieldDiv.querySelector('input, .select-selected, textarea');
1101        inputField.value = value;
1102        inputField.setAttribute('data-initial-value', value);
1103      }
1104      form.appendChild(fieldDiv);
1105    });
1106  let submitButtonLabel = placeholders.addAddress || 'Add Address';
1107  if (isUpdate || isCheckoutPage) {
1108    submitButtonLabel = placeholders.save || 'Save';
1109  }
1110
1111  const addressFormButtons = isCheckoutPage
1112    ? `<div class="address-form-button-wrapper">
1113        <button type="submit" class="address-submit-button address-form-button" aria-label="${submitButtonLabel}"><span>${submitButtonLabel}</span></button>
1114      </div>`
1115    : `<div class="address-form-button-wrapper">
1116        <button type="submit" class="address-submit-button address-form-button" aria-label="${submitButtonLabel}"><span>${submitButtonLabel}</span></button>
1117        <button type="button" class="address-cancel-button secondary address-form-button" aria-label="${placeholders.cancel || 'Cancel'}">${placeholders.cancel || 'Cancel'}</button>
1118      </div>`;
1119
1120  form.insertAdjacentHTML('beforeend', addressFormButtons);
1121
1122  form.noValidate = true;
1123  setCountryCode(form, countryCode);
1124
1125  if (countriesWithRegions.includes(countryCode)) {
1126    const regionSegments = await getAddressRegionSegments(countryCode);
1127    await populateRegions(form, regionSegments, countryCode, placeholders);
1128  } else {
1129    const citySegments = await getAddressCitySegments(countryCode);
1130    await populateCity(form, citySegments, countryCode, placeholders);
1131  }
1132
1133  if (showArea) {
1134    await updateArea(countryCode, '', form, placeholders);
1135  }
1136
1137  // TODO - Use Block-Config(Developer authorable) instead of config(Author authorable).
1138  if (disableInlineValidation === 'false') {
1139    form.querySelectorAll('input, .custom-select, textarea').forEach((input) => {
1140      setErrorMessageForField(input, placeholders);
1141      input.addEventListener('input', () => {
1142        validateInput(input);
1143      });
1144    });
1145  } else {
1146    form.querySelectorAll('input, .custom-select, textarea').forEach((input) => {
1147      setErrorMessageForField(input, placeholders);
1148      input.addEventListener('input', () => {
1149        debounce(() => {
1150          resetMessage(input);
1151          const isFormValid = validateForm(form, placeholders, isCheckoutPage);
1152          form.querySelector('button').disabled = !isFormValid;
1153        }, 300)();
1154      });
1155
1156      input.addEventListener('blur', async () => {
1157        if (input.type === 'tel') {
1158          const phoneValue = input.value;
1159          const isValidPhoneNumber = await validatePhone(phoneValue, countryCode);
1160          if (!isValidPhoneNumber) {
1161            let phoneNumberErrorMessage = placeholders.invalidMobileNumber || `The number provided ${input.value} is not a valid mobile number.`;
1162            phoneNumberErrorMessage = phoneNumberErrorMessage.replace('{{mobile}}', input.value);
1163            showErrorMessage(input, phoneNumberErrorMessage);
1164            form.querySelector('button').disabled = true;
1165            return;
1166          }
1167        }
1168        if (!validateInput(input)) {
1169          form.querySelector('button').disabled = true;
1170        }
1171      });
1172    });
1173  }
1174
1175  form.querySelectorAll('.custom-select').forEach((dropdown) => {
1176    setErrorMessageForField(dropdown, placeholders);
1177    dropdown.addEventListener('keydown', (event) => {
1178      if (event.key === 'Enter') {
1179        const selectBox = dropdown.querySelector('.select-selected');
1180        if (selectBox) {
1181          selectBox.click();
1182        }
1183      }
1184    });
1185    dropdown.addEventListener('blur', (event) => {
1186      event.stopPropagation();
1187      if (dropdown.contains(event.relatedTarget)) {
1188        return;
1189      }
1190      const mainBox = event.target.closest('.custom-select');
1191      const selectionBox = mainBox.querySelector('.select-selected');
1192      if (!selectionBox.getAttribute('data-initial-value') && !selectionBox.getAttribute('data-value')) {
1193        const dropdownLabel = dropdown.getAttribute('aria-label');
1194        let errorMessage = placeholders.addAddressSelectError || `Please select ${dropdownLabel}`;
1195        errorMessage = errorMessage.replace('{{label}}', dropdownLabel);
1196        showErrorMessage(mainBox, errorMessage);
1197      } else {
1198        resetMessage(mainBox);
1199      }
1200    });
1201    const dropDownOptions = dropdown.querySelectorAll('.select-items');
1202    dropDownOptions.forEach((option) => {
1203      option.addEventListener('click', () => {
1204        option.closest('.input-field-wrapper')?.classList.remove('invalid');
1205        const isFormValid = validateForm(form, placeholders, isCheckoutPage);
1206        form.querySelector('button').disabled = !isFormValid;
1207      });
1208    });
1209  });
1210
1211  const phoneInput = form.querySelector('#telephone');
1212  phoneInput.addEventListener('input', async (event) => {
1213    event.target.value = event.target.value.replace(/[^0-9]/g, '');
1214    if (event.target.value.length > phoneInput.maxLength) {
1215      const isValidPhoneNumber = await validatePhone(
1216        phoneInput.value,
1217        countryCode,
1218      );
1219      let phoneErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
1220      phoneErrorMessage = phoneErrorMessage.replace('{{mobile}}', phoneInput.value);
1221
1222      if (!isValidPhoneNumber) {
1223        showErrorMessage(phoneInput, phoneErrorMessage);
1224      }
1225    }
1226  });
1227
1228  const addressCancelButton = form.querySelector('.address-cancel-button');
1229  addressCancelButton?.addEventListener('click', () => {
1230    if (newCustomer) {
1231      $parent?.firstChild?.querySelectorAll('input, textarea').forEach((input) => {
1232        input.value = '';
1233      });
1234      document.querySelector('.dropdown.address_city_segment .select-selected').textContent = cityDefaultLabel;
1235      document.querySelector('.dropdown.area .select-selected').textContent = areaDefaultLabel;
1236    } else {
1237      $parent?.classList.add('hide');
1238    }
1239    window.scrollTo(0, 0);
1240  });
1241
1242  const addressSubmitButton = form.querySelector('.address-submit-button');
1243  form.addEventListener('submit', async (event) => {
1244    event.preventDefault();
1245    const phoneValue = phoneInput.value;
1246    let isValidPhoneNumber = false;
1247    let phoneNumLengthError = false;
1248    const phoneValidationPromise = validatePhone(phoneValue, countryCode)
1249      .then((result) => {
1250        isValidPhoneNumber = result;
1251      })
1252      .catch(() => {
1253        phoneNumLengthError = true;
1254      });
1255
1256    const isFormValid = validateForm(form, placeholders, isCheckoutPage);
1257    form.querySelector('button').disabled = !isFormValid;
1258    await phoneValidationPromise;
1259    if (!isValidPhoneNumber || phoneNumLengthError) {
1260      let phoneNumberErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
1261      phoneNumberErrorMessage = phoneNumberErrorMessage.replace('{{mobile}}', phoneInput.value);
1262      showErrorMessage(phoneInput, phoneNumberErrorMessage);
1263    }
1264    if (!isValidPhoneNumber || phoneNumLengthError || !isFormValid) {
1265      return;
1266    }
1267
1268    addressSubmitButton.classList.add('loader');
1269
1270    if (isShortCodeMandatory) {
1271      const isShortcodeValid = await validateAndStoreShortcode(form, placeholders);
1272      if (!isShortcodeValid) {
1273        addressSubmitButton.classList.remove('loader');
1274        return;
1275      }
1276    }
1277
1278    if (isCheckoutPage && !isLoggedIn) {
1279      const emailInput = form.querySelector('#email');
1280      const responseData = await validateCustomerEmail(emailInput.value);
1281      if (responseData?.customerExists) {
1282        const emailErrorMessage = placeholders.emailExist || 'You already have an account. Please log in.';
1283        showErrorMessage(emailInput, emailErrorMessage, true);
1284        dataLayerCustomerExistCheckoutErrors();
1285        addressSubmitButton.classList.remove('loader');
1286        return;
1287      }
1288      emailInput.classList.remove('error');
1289    }
1290
1291    const address = {};
1292    const baseCustomAttributeNames = [
1293      'address_city_segment',
1294      ...(countryCode === 'EG' ? ['address_region_segment'] : ['area']),
1295      'address_building_segment',
1296      'address_apartment_segment',
1297      ...(countryCode === 'EG' || countryCode === 'JO' ? ['address_floor_segment'] : []),
1298      ...(countryCode === 'EG' || countryCode === 'JO' ? ['address_landmark_segment'] : []),
1299      ...(countryCode === 'JO' || countryCode === 'BH' ? ['address_district_segment'] : []),
1300      ...(countryCode === 'BH' ? ['address_road_segment', 'address_block_segment'] : []),
1301      'address',
1302      'short_code',
1303      'longitude',
1304      'latitude',
1305      'secondary_number',
1306    ];
1307
1308    if (showArea) {
1309      baseCustomAttributeNames.push('address_block_segment');
1310    }
1311
1312    // ---- ADD LAT/LNG ONLY FOR SA + SHORTCODE ENABLED ----
1313    if (countryCode === 'SA' && isShortCodeEnabled === true) {
1314      const scInput = form.querySelector('#short_code');
1315      const hasValidShortcodeData = scInput && scInput.dataset?.latitude
1316      && scInput.dataset?.longitude;
1317
1318      if (hasValidShortcodeData) {
1319        address.custom_attributes = address.custom_attributes || [];
1320        address.custom_attributes.push(
1321          {
1322            attribute_code: 'latitude',
1323            value: scInput.dataset.latitude,
1324          },
1325          {
1326            attribute_code: 'longitude',
1327            value: scInput.dataset.longitude,
1328          },
1329        );
1330        if (scInput.dataset?.additionalNumber) {
1331          address.custom_attributes.push({
1332            attribute_code: 'secondary_number',
1333            value: scInput.dataset.additionalNumber,
1334          });
1335        }
1336        // SA-only postcode override
1337        if (scInput.dataset?.postalCode) {
1338          address.postcode = scInput.dataset.postalCode;
1339        }
1340      }
1341    }
1342
1343    const customAttributeNames = new Set(baseCustomAttributeNames);
1344    const inputs = form.querySelectorAll('input, .custom-select, textarea');
1345
1346    inputs.forEach((input) => {
1347      const name = input?.getAttribute('name');
1348      if (!name) return;
1349
1350      let key = name;
1351      let value = sanitizeDOMSync(input.value?.trim() || '');
1352
1353      switch (name) {
1354        case 'country_id':
1355          key = 'country_code';
1356          break;
1357
1358        case 'address_city_segment':
1359        case 'address_district_segment':
1360        case 'address_region_segment':
1361        case 'area': {
1362          const selected = input.querySelector('.select-selected');
1363          const dataValue = selected?.getAttribute('data-value') || '';
1364          const dataInitialValue = selected?.getAttribute('data-initial-value') || '';
1365          value = input.classList.contains('custom-select')
1366            ? dataValue || dataInitialValue
1367            : value;
1368
1369          if (name === 'address_city_segment') {
1370            address.city = isCheckoutPage ? (dataValue || dataInitialValue || '-') : (dataValue || '-');
1371          } else if (name === 'address_region_segment') {
1372            address.region = isCheckoutPage ? (dataValue || dataInitialValue || '-') : (dataValue || '-');
1373          }
1374          break;
1375        }
1376
1377        case 'fullName': {
1378          const [firstName = '', ...rest] = value.split(/\s+/);
1379          address.firstname = firstName;
1380          address.lastname = rest.join(' ');
1381          return;
1382        }
1383
1384        case 'telephone': {
1385          // Validate and clean telephone: strip prefix, enforce maxlength
1386          // This handles cases where user bypassed maxlength via dev tools or browser issues
1387          const cleanedTelephone = validateAndCleanTelephone(value, countryPrefix, maxLength);
1388          // Add prefix back for API (API expects full number with prefix)
1389          address.telephone = cleanedTelephone ? `${countryPrefix}${cleanedTelephone}` : '';
1390          return;
1391        }
1392
1393        default:
1394          break;
1395      }
1396
1397      if (customAttributeNames.has(name)) {
1398        address.custom_attributes = address.custom_attributes || [];
1399        address.custom_attributes.push({
1400          attribute_code: key,
1401          value,
1402        });
1403      } else if (!(isCheckoutPage && isLoggedIn && key === 'email')) {
1404        address[key] = value;
1405      }
1406    });
1407
1408    // Due to out of the box validations for commerce we have to
1409    // send City attribute explicitly, It is not required at alshaya
1410    if (countryCode === 'KW') address.city = 'city';
1411
1412    // Sending null at region due to magento mapping
1413    if (countryCode === 'EG') address.region = null;
1414
1415    if (countryCode === 'BH') address.street = [null];
1416
1417    let res = null;
1418    let message;
1419
1420    if (isUpdate && !isCheckoutPage) {
1421      res = await updateAddress(addressObj.id, address);
1422      if (res?.success) {
1423        message = placeholders.addressUpdated || 'Address is updated successfully.';
1424      }
1425    } else if (isCheckoutPage) {
1426      if (isLoggedIn && !isTopup) {
1427        delete address.address;
1428        if (isUpdate) {
1429          const response = await updateAddress(addressObj.id
1430          || addressObj?.customer_address_id, address, config);
1431          address.id = response?.data?.commerce_updateCustomerAddress?.id;
1432          address.street = response?.data?.commerce_updateCustomerAddress?.street
1433            ?? address?.street;
1434        } else {
1435          const response = await createAddress(address, config);
1436          address.id = response?.data?.commerce_createCustomerAddress?.id;
1437          address.street = response?.data?.commerce_createCustomerAddress?.street
1438            ?? address?.street;
1439        }
1440      }
1441      window.dispatchEvent(new CustomEvent('react:addressFormSubmitted', { detail: { address, isUpdate } }));
1442    } else {
1443      res = await createAddress(address);
1444      if (res?.success) {
1445        message = placeholders.addressAdded || 'Address is added successfully.';
1446      }
1447    }
1448    if (res?.success) {
1449      block.dispatchEvent(new CustomEvent('address-updated'));
1450      addressesContainer.classList.remove('hide');
1451      $parent.classList.add('hide');
1452      document.querySelector('.new-address-container').classList.remove('hide');
1453      addStatusMessage(message);
1454    }
1455  });
1456
1457  decorateIcons(form);
1458  if (!isCheckoutPage) {
1459    customSelectbox(form.querySelector('.input-field-wrapper.dropdown.country_id'));
1460  }
1461  if (countryCode !== 'EG') customSelectbox(form.querySelector('.input-field-wrapper.dropdown.address_city_segment'));
1462  $parent.innerHTML = '';
1463  if (isCheckoutPage && !config?.checkoutV1) {
1464    const formDiv = document.createElement('div');
1465    formDiv.append(form);
1466    formDiv.classList.add('address-form', 'checkout-form');
1467    $parent.appendChild(formDiv);
1468  } else {
1469    $parent.appendChild(form);
1470  }
1471  if (isCheckoutPage) {
1472    window.dispatchEvent(new CustomEvent('react:addressFormLoaded'));
1473    if (isUpdate) validateForm(form, placeholders, isCheckoutPage);
1474  }
1475  $parent.classList.remove('hide');
1476
1477  const showAreaModal = await getConfigValue('addressbook-show-area-modal') === 'true';
1478  if (isCheckoutPage && showAreaModal) {
1479    const formElement = document.querySelector('.dialog__overlay form');
1480    if (formElement) {
1481      blockConfigs['checkout-area-dropdown-placeholder'] = areaDefaultLabel;
1482      blockConfigs['checkout-city-dropdown-placeholder'] = cityDefaultLabel;
1483      customSelectboxModal(blockConfigs, placeholders, formElement);
1484    }
1485  }
1486
1487  handleInitialCheck();
1488
1489  if (isCheckoutPage) {
1490    restructureForm(form, config);
1491  }
1492  // Load Short Code Map modal if enabled
1493  if (blockConfigs?.flags?.enableShortCodeMap === true) {
1494    loadShortCodeMapModal(placeholders, 'checkout-home-delivery');
1495  }
1496}
1497
1498// to shoe address form for new customer
1499function handleNewCustomer(blockConfigs, placeholders, addressesContainer) {
1500  const addressForm = document.querySelector('.address-form');
1501  showAddressForm(blockConfigs, addressForm, placeholders, {}, true);
1502  addressesContainer.classList.add('hide');
1503  hideNewAddressCta();
1504}
1505
1506async function showDeleteAddressModal(addressId, placeholders, addressesContainer) {
1507  const deleteTitle = placeholders.deleteAddressModalTitle || 'Delete Address';
1508  const deleteContent = document.createElement('div');
1509  deleteContent.classList.add('delete-content');
1510
1511  deleteContent.innerHTML = `<span class="delete-title">${placeholders.deleteAddressModalTitle || 'Delete Address'}</span>
1512    <span class="delete-message">${placeholders.deleteAddressModalMessage || 'You have selected to delete this address, are you sure?'}</span>
1513    <div class="delete-buttons">
1514      <button class="delete-cancel secondary" aria-label="${placeholders.deleteAddressCancel || 'No'}">${placeholders.deleteAddressCancel || 'No'}</button>
1515      <button class="delete-confirm" aria-label="${placeholders.deleteAddressConfirm || 'Yes'}">${placeholders.deleteAddressConfirm || 'Yes'}</button>
1516    </div>`;
1517  await createModalFromContent('delete-address-modal', deleteTitle, deleteContent.outerHTML, ['delete-address-modal'], 'trash', false, 'icon-close-black');
1518
1519  document.querySelector('.delete-address-modal .delete-cancel').addEventListener('click', () => {
1520    closeModal('delete-address-modal');
1521  });
1522
1523  document.querySelector('.delete-address-modal .delete-confirm').addEventListener('click', async () => {
1524    closeModal('delete-address-modal');
1525    const res = await deleteAddress(addressId);
1526    if (res?.success) {
1527      const message = placeholders.addressDeleted || 'Address is deleted successfully.';
1528      addStatusMessage(message);
1529      const block = addressesContainer.closest('.account-address-book');
1530      block?.dispatchEvent(new CustomEvent('address-updated'));
1531    }
1532  });
1533  openModal('delete-address-modal');
1534}
1535
1536export const displayAddressList = async function (
1537  blockConfigs,
1538  addressForm,
1539  addressesContainer,
1540  placeholders,
1541) {
1542  addressesContainer.innerHTML = '';
1543  const countryCode = await getConfigValue('country-code');
1544  const customerPromise = getCustomer(false);
1545  const citySegmentsPromise = getAddressCitySegments(countryCode);
1546  const regionSegmentsPromise = getAddressRegionSegments(countryCode);
1547  const areasPromise = getAddressAreas(countryCode);
1548  const formStructurePromise = getDeliveryMatrixAddressStructure(countryCode);
1549
1550  const [customer, citySegments, regionSegments, areas,
1551    formStructure] = await Promise.all([customerPromise,
1552    citySegmentsPromise,
1553    regionSegmentsPromise,
1554    areasPromise,
1555    formStructurePromise,
1556  ]);
1557
1558  const country = formStructure
1559    .find((field) => field.visible === '1' && field?.attribute?.attribute_code === 'country_id')
1560    ?.attribute?.options?.find((option) => option.value === countryCode)?.label;
1561  if (customer?.addresses?.length < 1) {
1562    handleNewCustomer(blockConfigs, placeholders, addressesContainer);
1563    return;
1564  }
1565  customer?.addresses.sort((a, b) => (b.default_billing === true) - (a.default_billing === true));
1566  customer?.addresses?.forEach((address) => {
1567    const addressWrapper = document.createElement('div');
1568    addressWrapper.classList.add('address-wrapper');
1569
1570    const addressDiv = document.createElement('div');
1571    addressDiv.classList.add('address');
1572
1573    const editAddressHtml = `<div class="edit-address-cta-wrapper">
1574     <a href="#" class="edit-address-cta" aria-label="${placeholders.edit || 'Edit'}"><span>${placeholders.edit || 'Edit'}</span></a>
1575    </div>`;
1576
1577    const city = citySegments.items?.find(
1578      (item) => item.location_id
1579        === Number(
1580          address.custom_attributes?.find(
1581            (attr) => attr.attribute_code === 'address_city_segment',
1582          )?.value,
1583        ),
1584    )?.label;
1585
1586    const area = areas.items?.find(
1587      (item) => item.location_id
1588        === Number(
1589          address.custom_attributes?.find(
1590            (attr) => attr.attribute_code === 'area',
1591          )?.value,
1592        ),
1593    )?.label;
1594
1595    const region = regionSegments.items?.find(
1596      (item) => item.location_id
1597        === Number(
1598          address.custom_attributes?.find(
1599            (attr) =>
1599 attr.attribute_code === 'address_region_segment',
1600          )?.value,
1601        ),
1602    )?.label;
1603
1604    const buildingName = sanitizeDOMSync(
1605      address.custom_attributes?.find(
1606        (attr) => attr.attribute_code === 'address_building_segment',
1607      )?.value,
1608    );
1609    const apartment = sanitizeDOMSync(
1610      address.custom_attributes?.find(
1611        (attr) => attr.attribute_code === 'address_apartment_segment',
1612      )?.value,
1613    );
1614
1615    const shortcode = sanitizeDOMSync(
1616      address.custom_attributes?.find(
1617        (attr) => attr.attribute_code === 'short_code',
1618      )?.value,
1619    );
1620
1621    const shortcodeSpan = country ? `<span>${shortcode}</span>` : '';
1622    const countrySpan = country ? `<span>${country}</span>` : '';
1623    const citySpan = city ? `<span>${city}</span>` : '';
1624    const areaSpan = area ? `<span>${area}</span>` : '';
1625    const regionSpan = region ? `<span>${region}</span>` : '';
1626    const buildingSpan = buildingName ? `<span>${buildingName}</span>` : '';
1627    const apartmentSpan = apartment ? `<span>${apartment}</span>` : '';
1628
1629    const addressContent = `
1630      <div class="address-data ${address.default_billing || customer.addresses.length === 1 ? 'primary-address-data' : ''}">
1631        <div class="address-userinfo">
1632          <div class="address-section col-1 deliveryTo">
1633            <p class="label"><span>${placeholders.deliveryTo || 'Delivery To'}</span></p>
1634            <p class="address-value"><span>${address.firstname} ${address.lastname}</span></p>
1635          </div>
1636          <div class="address-section col-1 contact-number">
1637            <p class="label"><span>${placeholders.contactNumber || 'Contact Number'}</span></p>
1638            <p class="address-value"><span>${address.telephone}</span></p>
1639          </div>
1640        </div>
1641        <div class="address-section address-line">
1642          <p class="label"><span>${placeholders.deliveryAddress || 'Delivery Address'}</span></p>
1643          <p class="address-value">
1644          ${shortcodeSpan}
1645          ${countrySpan}
1646          ${citySpan}${areaSpan}${regionSpan}
1647          <span>${sanitizeDOMSync(address.street)}</span>${sanitizeDOMSync(buildingSpan)}${sanitizeDOMSync(apartmentSpan)}
1648          </p>
1649        </div>
1650      </div>
1651      ${
1652  address.default_billing
1653    ? `
1654        <div class="address-section cta-container primary-address-cta-container">
1655          <div class="primary-address-cta-wrapper">
1656          <span class="icon icon-radio-active"></span>
1657          <span>${placeholders.primaryAddress || 'Primary Address'}</span>
1658          </div>
1659          ${editAddressHtml}
1660        </div>`
1661    : `
1662        <div class="address-section cta-container address-cta-container">
1663          <div class="make-primary-cta-wrapper">
1664          <span class="icon icon-radio-active hovericon"></span>
1665          <span class="icon icon-radio-icon"></span>
1666          <a class="make-primary-cta" aria-label="${placeholders.makePrimary || 'Make Primary'}"><span>${placeholders.makePrimary || 'Make Primary'}</span></a>
1667          </div>
1668          ${editAddressHtml}
1669        <div class="delete-address-cta-wrapper">
1670          <a href="#" class="delete-address-cta" aria-label="${placeholders.delete || 'Delete'}"><span>${placeholders.delete || 'Delete'}</span></a>
1671        </div>`
1672}`;
1673
1674    addressDiv.innerHTML = addressContent;
1675    addressWrapper.appendChild(addressDiv);
1676    decorateIcons(addressWrapper);
1677
1678    const editButton = addressWrapper.querySelector('.edit-address-cta');
1679    if (editButton) {
1680      editButton.addEventListener('click', async () => {
1681        editButton.classList.add('loader');
1682        await showAddressForm(blockConfigs, addressForm, placeholders, address);
1683        editButton.classList.remove('loader');
1684      });
1685    }
1686
1687    const deleteButton = addressWrapper.querySelector('.delete-address-cta');
1688    deleteButton?.addEventListener('click', async () => {
1689      await showDeleteAddressModal(address.id, placeholders, addressesContainer);
1690    });
1691
1692    const makePrimaryButton = addressWrapper.querySelector(
1693      '.make-primary-cta-wrapper',
1694    );
1695    makePrimaryButton?.addEventListener('click', async () => {
1696      const res = await makePrimaryAddress(address.id);
1697      if (res?.success) {
1698        const message = placeholders.primaryAddressUpdated
1699          || 'Primary address is updated successfully.';
1700        addStatusMessage(message, placeholders);
1701        const block = addressWrapper.closest('.account-address-book');
1702        block?.dispatchEvent(new CustomEvent('address-updated'));
1703      }
1704    });
1705    handleAddressHover(addressWrapper);
1706    addressesContainer.appendChild(addressWrapper);
1707    const addressSubmitButton = document.querySelector(
1708      '.address-submit-button',
1709    );
1710    addressSubmitButton?.classList.remove('hide');
1711  });
1712};
1713
1714function phoneValidation(phoneInput, countryCode, formElement, placeholders) {
1715  phoneInput.addEventListener('blur', async (event) => {
1716    event.target.value = event.target.value.replace(/[^0-9]/g, '');
1717    const isValidPhoneNumber = await validatePhone(
1718      phoneInput.value,
1719      countryCode,
1720    );
1721    let phoneErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
1722    phoneErrorMessage = phoneErrorMessage.replace('{{mobile}}', phoneInput.value);
1723    if (!isValidPhoneNumber) {
1724      showErrorMessage(phoneInput, phoneErrorMessage);
1725      formElement.querySelector('button').disabled = true;
1726    }
1727  });
1728
1729  phoneInput.addEventListener('input', debounce(() => {
1730    resetMessage(phoneInput);
1731    formElement.querySelector('button').disabled = false;
1732  }), 300);
1733
1734  phoneInput.addEventListener('input', (event) => {
1735    event.target.value = event.target.value.replace(/[^0-9]/g, '');
1736  });
1737}
1738
1739// to show address form
1740export async function showAddressFormModal(
1741  blockConfigs,
1742  formId,
1743  $parent,
1744  placeholders,
1745  addressObj,
1746  newCustomer = false,
1747  isCheckoutPage = false,
1748  isLoggedIn = false,
1749  config = {},
1750  updateOnlyTelephone = false,
1751  infoMessage = '',
1752  isTopup = false,
1753  showAddressFormEmailForLoggedInUsers = false,
1754) {
1755  if (isCheckoutPage) {
1756    window.dispatchEvent(new CustomEvent('react:addressFormLoading'));
1757  }
1758  const countryCode = await getConfigValue('country-code');
1759  const addressesContainer = document.querySelector('.addresses-container');
1760
1761  // Update form structure for EG market.
1762  const disableLandmark = blockConfigs?.flags?.disableLandmark;
1763  let formStructure = await getDeliveryMatrixAddressStructure(countryCode);
1764  if (disableLandmark === true) {
1765    const excludedAttributes = ['landmark', 'address_apartment_segment'];
1766    const filteredFormStructure = formStructure.filter(
1767      (item) => !(item?.country_id === 'EG' && excludedAttributes.includes(item?.attribute?.attribute_code)),
1768    );
1769    formStructure = [...filteredFormStructure];
1770  }
1771
1772  const citySegments = await getAddressCitySegments(countryCode);
1773  const isUpdate = Object.keys(addressObj).length > 0;
1774  const block = $parent.closest('.account-address-book');
1775  const maxLength = await getMaxLengthByCountryCode(countryCode);
1776  const countryPrefix = `+${await getCountryIso(countryCode)}`;
1777  const showArea = countryCode === 'KW';
1778  const form = document.createElement('form');
1779  let cityDefaultLabel = placeholders.selectCity || 'Select City';
1780  let areaDefaultLabel = placeholders.selectArea || 'Select Area';
1781  // Retrieve the email from session storage
1782  const customerData = await getCustomer();
1783  const email = customerData?.email || '';
1784  // Variable to track if the email field has been added
1785  let emailFieldAdded = false;
1786
1787  if (isCheckoutPage) {
1788    // eslint-disable-next-line max-len
1789    handleCheckoutFormStructure(formStructure, isLoggedIn, countryCode, placeholders, showAddressFormEmailForLoggedInUsers);
1790  }
1791
1792  const checkoutRequiredFields = ['address', 'address_building_segment'];
1793  const firstnameField = formStructure?.find((d) => d?.attribute?.attribute_code === 'firstname');
1794  if (firstnameField) {
1795    firstnameField.sort_order = '0';
1796  }
1797  formStructure.sort((a, b) => {
1798    if (Number(a.sort_order) < Number(b.sort_order)) return -1;
1799    if (Number(a.sort_order) > Number(b.sort_order)) return 1;
1800    return 0;
1801  });
1802
1803  formStructure
1804    .filter((field) => field.visible === '1' && field.attribute.attribute_code !== 'lastname')
1805    .forEach(async (field) => {
1806      if (['firstname', 'lastname', 'telephone'].includes(field.attribute.attribute_code)) {
1807        field.attribute.required = true;
1808      }
1809      const rules = countryRules[field.country_id];
1810      if (rules) {
1811        if (rules.required.includes(field.attribute.attribute_code)) {
1812          field.attribute.required = true;
1813        } else if (rules.notRequired.includes(field.attribute.attribute_code)) {
1814          field.attribute.required = false;
1815        }
1816      }
1817      const fieldDiv = document.createElement('div');
1818      fieldDiv.classList.add('input-field-wrapper');
1819      let isDisabled = false;
1820      if (isCheckoutPage && updateOnlyTelephone && field.attribute.attribute_code !== 'telephone') {
1821        fieldDiv.classList.add('address-form-field-disabled');
1822        isDisabled = true;
1823      }
1824      const validations = ['tabindex="0"'];
1825
1826      const isRequiedInCheckout = isCheckoutPage
1827        ? checkoutRequiredFields.includes(field.attribute.attribute_code) : false;
1828      if (field.attribute.required || isRequiedInCheckout) {
1829        validations.push('required');
1830      }
1831
1832      field.attribute.validation_rules?.forEach((rule) => {
1833        if (rule.name === 'min_text_length') {
1834          validations.push(`minlength="${rule.value}"`);
1835        } else if (rule.name === 'max_text_length') {
1836          validations.push(`maxlength="${rule.value}"`);
1837        }
1838      });
1839
1840      if (field.attribute.attribute_code === 'telephone') {
1841        createTelephoneInput(countryCode, maxLength, countryPrefix, fieldDiv, field.attribute.attribute_code, field.attribute.store_label, field.attribute.required, addressObj?.[field.attribute.attribute_code] ? addressObj[field.attribute.attribute_code].replace(countryPrefix, '') : '', isCheckoutPage, updateOnlyTelep
1841hone, infoMessage);
1842      } else if (field.attribute.attribute_code === 'short_code') {
1843        // Show ONLY if config enabled AND market is SA
1844        if (!isShortCodeEnabled || countryCode !== 'SA') {
1845          return;
1846        }
1847
1848        const value = addressObj?.custom_attributes?.find(
1849          (a) => a.attribute_code === 'short_code',
1850        )?.value || addressObj?.short_code || '';
1851
1852        if (field.attribute.required) {
1853          validations.push('required');
1854        }
1855
1856        createShortCodeField({
1857          fieldDiv,
1858          storeLabel: placeholders.shortCodeLabel || 'Short Address (Eg. RRRD2929)',
1859          value,
1860          validations,
1861          placeholders,
1862          blockConfigs,
1863        });
1864
1865        form.appendChild(fieldDiv);
1866        return;
1867      } else if (field.attribute.attribute_code === 'address_building_segment' && isShortCodeEnabled && countryCode === 'SA') {
1868        // Show ONLY if config enabled AND market is SA
1869        const value = addressObj?.custom_attributes?.find(
1870          (a) => a.attribute_code === 'address_building_segment',
1871        )?.value || addressObj?.address_building_segment || '';
1872
1873        if (field.attribute.required) {
1874          validations.push('required');
1875        }
1876        createBuildingNumberField({
1877          fieldDiv,
1878          storeLabel: field.attribute.store_label || 'Building Number (Eg. 1234)',
1879          value,
1880          validations,
1881          placeholders,
1882          blockConfigs,
1883        });
1884
1885        form.appendChild(fieldDiv);
1886        return;
1887      } else if (field.attribute.frontend_input === 'text') {
1888        let textInputValue = addressObj?.[field.attribute.attribute_code];
1889        let label = field.attribute.store_label;
1890        let attributeCode = field.attribute.attribute_code;
1891        if (field.attribute.attribute_code === 'firstname') {
1892          textInputValue = textInputValue ? `${textInputValue} ${addressObj?.lastname ?? ''}` : '';
1893          label = placeholders.fullname || 'Full Name';
1894          attributeCode = 'fullName';
1895        }
1896        fieldDiv.innerHTML = `
1897          <div class="input-field-wrapper">
1898            <div class="input-wrapper input-field">
1899              <input type="text" id="${attributeCode}" name="${attributeCode}" aria-label="${label}" 
1900              placeholder=" "
1901              ${isDisabled ? 'disabled' : ''}
1902              value="${textInputValue || ''}" 
1903              ${field.attribute.attribute_code === 'firstname' ? 'pattern="^\\p{L}+(?:\\s\\p{L}+)+\\s?$"' : ''}
1904              ${field.attribute.attribute_code === 'email' ? 'pattern="^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"' : ''}
1905              ${validations.join(' ')}>
1906              <label for="${attributeCode}">${label}</label>
1907            </div>
1908          </div>
1909        `;
1910      } else if (field.attribute.frontend_input === 'select') {
1911        const defaultLabelContent = field.attribute?.attribute_code === 'country_id'
1912          ? getSelectedLabel(countryCode, field)
1913          : `${field.attribute.store_label}`;
1914        const defaultLabelContentValue = field.attribute?.attribute_code === 'country_id'
1915          ? getSelectedValue(countryCode, field)
1916          : `${field.attribute.store_label}`;
1917
1918        if (field.attribute?.attribute_code === 'city') {
1919          cityDefaultLabel = defaultLabelContent;
1920        } else if (field.attribute?.attribute_code === 'area') {
1921          areaDefaultLabel = defaultLabelContent;
1922        }
1923        const classesToAdd = ['dropdown', 'notransistion', field.attribute.attribute_code];
1924
1925        if (isCheckoutPage && field.attribute.attribute_code === 'country_id') {
1926          classesToAdd.push('hidden');
1927        }
1928        fieldDiv.classList.add(...classesToAdd);
1929        fieldDiv.innerHTML = `
1930          <div class="input-wrapper input-field">
1931            <div class="custom-select" id="${field.attribute.attribute_code}" name="${field.attribute.attribute_code}" aria-label="${field.attribute.store_label}" ${validations.join(' ')} required>
1932              <div class="select-selected${field.attribute.attribute_code === 'country_id' || isDisabled ? ' disabled' : ''}" data-value="${field.attribute.attribute_code === 'country_id' ? defaultLabelContentValue : ''}">
1933              <label for="${field.attribute.store_label}">${field.attribute.store_label}</label>
1934              <span for="${field.attribute.store_label}">${placeholders.select || 'Select'} ${field.attribute.store_label}</span>
1935              </div>
1936              <input type="text" class="select-search hide" placeholder="${isCheckoutPage && field.attribute.attribute_code !== 'country_id' ? defaultLabelContent : ''}" />
1937              <div class="select-items select-hide">
1938                <div data-value="" class="no-results ${field.attribute.attribute_code === 'area' && showArea ? '' : 'hide'}">${placeholders.dropdownNoResultsFound || 'No Results Found'}</div>
1939                ${field.attribute.attribute_code === 'area' && showArea ? '' : field.attribute.options?.filter((option) => option.label !== 'Select an option')
1940    .map((option) => `<div data-value="${option.value}" ${addressObj?.[field.attribute.attribute_code] === option.value ? 'selected' : ''}>${option.label}</div>`)
1941    .join('')}
1942              </div>
1943            </div>
1944          </div>
1945        `;
1946
1947        field.attribute.options?.map((option) => `<div data-value="${option.value}">${option.label}</div>`);
1948      } else if (field.attribute.frontend_input === 'multiline') {
1949        const rows = field.attribute.multiline_count ? `rows="${field.attribute.multiline_count}"` : '';
1950        fieldDiv.innerHTML = `
1951            <div class="input-field-wrapper">
1952              <div class="input-wrapper input-field">
1953                <textarea id="${field.attribute.attribute_code}" name="${field.attribute.attribute_code}" aria-label="${field.attribute.store_label}" placeholder=" " ${validations.join(' ')} ${rows}  ${isDisabled ? 'disabled' : ''}>${addressObj?.[field.attribute.attribute_code] || ''}</textarea>
1954                <label for="${field.attribute.attribute_code}">${field.attribute.store_label}</label>
1955              </div>
1956            </div>
1957          `;
1958      }
1959
1960      // Check if the current field is the telephone field
1961      if (field.attribute.attribute_code === 'country_id' && !emailFieldAdded) {
1962        // Create email field to add after the telephone field
1963        const emailFieldDiv = document.createElement('div');
1964        emailFieldDiv.classList.add('input-field-wrapper', 'emailValidation', 'notransistion');
1965        emailFieldDiv.innerHTML = `
1966              <div class="input-wrapper input-field email-field">
1967                <label for="email" class="input-label">${placeholders.emailAddressLabel || 'Email Address'}</label>
1968                <input type="email" class="email" id="email" name="email" aria-label="${placeholders.emailAddressLabel || 'Email Address'}"
1969                  placeholder=" "
1970                  value="${email}" disabled>
1971              </div>
1972            `;
1973
1974        // Append the email field right after the telephone field
1975        form.appendChild(emailFieldDiv);
1976
1977        // Set the flag to true so the email field is only added once
1978        emailFieldAdded = true;
1979      }
1980
1981      const validAttributeCodes = [
1982        'area',
1983        'address_building_segment',
1984        'address_apartment_segment',
1985        'address_city_segment',
1986        'address',
1987        'address_district_segment',
1988        'address_landmark_segment',
1989        'address_region_segment',
1990        'address_floor_segment',
1991        'address_block_segment',
1992        'address_road_segment',
1993        'short_code',
1994        'latitude',
1995        'longitude',
1996        'secondary_number',
1997      ];
1998      if (validAttributeCodes.includes(field.attribute.attribute_code)) {
1999        const value = addressObj.custom_attributes?.find((attr) => attr.attribute_code === field.attribute.attribute_code)?.value || '';
2000        const inputField = fieldDiv.querySelector('input, .select-selected, textarea');
2001        inputField.setAttribute('value', value);
2002        inputField.setAttribute('data-initial-value', value);
2003        inputField.setAttribute('data-value', value);
2004      }
2005
2006      if (blockConfigs?.decorations?.addressFormElement) {
2007        if (formId === 'edit-address-modal') {
2008          const attributeCode = field.attribute.attribute_code;
2009          const label = field.attribute.store_label;
2010          blockConfigs.decorations.addressFormElement(fieldDiv, attributeCode, label);
2011        }
2012      }
2013      form.appendChild(fieldDiv);
2014    });
2015
2016  const addressFormButtons = `<div class="address-form-button-wrapper">
2017          <button type="submit" class="address-submit-button address-form-button" aria-label="${placeholders.save || 'Save'}"><span>${placeholders.save || 'Save'}</span></button>
2018       </div>`;
2019
2020  form.insertAdjacentHTML('beforeend', addressFormButtons);
2021
2022  form.noValidate = true;
2023  setCountryCode(form, countryCode);
2024  if (countriesWithRegions.includes(countryCode)) {
2025    const regionSegments = await getAddressRegionSegments(countryCode);
2026    await populateRegions(form, regionSegments, countryCode, placeholders);
2027  } else {
2028    await populateCity(form, citySegments, countryCode, placeholders);
2029  }
2030
2031  if (showArea) {
2032    await updateArea(countryCode, '', form, placeholders);
2033  }
2034
2035  form.querySelectorAll('input, .custom-select, textarea').forEach((input) => {
2036    setErrorMessageForField(input, placeholders);
2037    input.addEventListener('input', () => {
2038      validateInput(input);
2039    });
2040  });
2041
2042  const phoneInput = form.querySelector('#telephone');
2043  phoneInput.addEventListener('input', async (event) => {
2044    event.target.value = event.target.value.replace(/[^0-9]/g, '');
2045    if (event.target.value.length > phoneInput.maxLength) {
2046      const isValidPhoneNumber = await validatePhone(
2047        phoneInput.value,
2048        countryCode,
2049      );
2050      let phoneErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
2051      phoneErrorMessage = phoneErrorMessage.replace('{{mobile}}', phoneInput.value);
2052
2053      if (!isValidPhoneNumber) {
2054        showErrorMessage(phoneInput, phoneErrorMessage);
2055      }
2056    }
2057  });
2058
2059  const addressCancelButton = form.querySelector('.address-cancel-button');
2060  addressCancelButton?.addEventListener('click', () => {
2061    if (newCustomer) {
2062      $parent?.firstChild?.querySelectorAll('input, textarea').forEach((input) => {
2063        input.value = '';
2064      });
2065      document.querySelector('.dropdown.address_city_segment .select-selected').textContent = cityDefaultLabel;
2066      document.querySelector('.dropdown.area .select-selected').textContent = areaDefaultLabel;
2067    } else {
2068      $parent?.classList.add('hide');
2069    }
2070    window.scrollTo(0, 0);
2071  });
2072
2073  const addressSubmitButton = form.querySelector('.address-submit-button');
2074  form.addEventListener('submit', async (event) => {
2075    event.preventDefault();
2076    if (!validateForm(form, placeholders, isCheckoutPage)) {
2077      return;
2078    }
2079    const phoneValue = phoneInput.value;
2080    const isValidPhoneNumber = await validatePhone(phoneValue, countryCode);
2081    if (!isValidPhoneNumber) {
2082      let phoneNumberErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
2083      phoneNumberErrorMessage = phoneNumberErrorMessage.replace('{{mobile}}', phoneInput.value);
2084      showErrorMessage(phoneInput, phoneNumberErrorMessage);
2085      return;
2086    }
2087
2088    addressSubmitButton.classList.add('loader');
2089
2090    if (isCheckoutPage && !isLoggedIn) {
2091      const emailInput = form.querySelector('#email');
2092      const responseData = await validateCustomerEmail(emailInput.value);
2093      if (responseData?.customerExists) {
2094        const emailErrorMessage = placeholders.emailExist || 'You already have an account. Please log in.';
2095        showErrorMessage(emailInput, emailErrorMessage, true);
2096        dataLayerCustomerExistCheckoutErrors();
2097        addressSubmitButton.classList.remove('loader');
2098        return;
2099      }
2100      emailInput.classList.remove('error');
2101    }
2102
2103    const address = {};
2104    const customAttributeNames = new Set([
2105      'address_city_segment',
2106      'area',
2107      'address_building_segment',
2108      'address_apartment_segment',
2109      'address',
2110      'short_code',
2111      'secondary_number',
2112      'longitude',
2113      'latitude',
2114    ]);
2115    const inputs = form.querySelectorAll('input, .custom-select, textarea');
2116
2117    inputs.forEach((input) => {
2118      const name = input?.getAttribute('name');
2119      if (!name) return;
2120
2121      let key = name;
2122      let value = input.value?.trim() || '';
2123
2124      switch (name) {
2125        case 'country_id':
2126          key = 'country_code';
2127          break;
2128
2129        case 'address_city_segment':
2130        case 'area': {
2131          const selected = input.querySelector('.select-selected');
2132          const dataValue = selected?.getAttribute('data-value') || '';
2133          const dataInitialValue = selected?.getAttribute('data-initial-value') || '';
2134          value = input.classList.contains('custom-select')
2135            ? dataValue || dataInitialValue
2136            : value;
2137
2138          if (name === 'address_city_segment') {
2139            address.city = isCheckoutPage ? (dataValue || dataInitialValue || '-') : (dataValue || '-');
2140          }
2141          break;
2142        }
2143
2144        case 'fullName': {
2145          const [firstName = '', ...rest] = value.split(/\s+/);
2146          address.firstname = firstName;
2147          address.lastname = rest.join(' ');
2148          return;
2149        }
2150
2151        case 'telephone': {
2152          // Validate and clean telephone: strip prefix, enforce maxlength
2153          // This handles cases where user bypassed maxlength via dev tools or browser issues
2154          const cleanedTelephoneModal = validateAndCleanTelephone(value, countryPrefix, maxLength);
2155          // Add prefix back for API (API expects full number with prefix)
2156          address.telephone = cleanedTelephoneModal ? `${countryPrefix}${cleanedTelephoneModal}` : '';
2157          return;
2158        }
2159        default:
2160          break;
2161      }
2162
2163      if (customAttributeNames.has(name)) {
2164        address.custom_attributes = address.custom_attributes || [];
2165        address.custom_attributes.push({
2166          attribute_code: key,
2167          value,
2168        });
2169      } else {
2170        address[key] = value;
2171      }
2172    });
2173
2174    let res = null;
2175    let message;
2176    if (isUpdate && !isCheckoutPage) {
2177      res = await updateAddress(addressObj.id, address);
2178      if (res?.success) {
2179        message = placeholders.addressUpdated || 'Address is updated successfully.';
2180      }
2181    } else if (isCheckoutPage) {
2182      if (isLoggedIn && !isTopup) {
2183        delete address.address;
2184        if (isUpdate) {
2185          const response = await updateAddress(addressObj.id, address, config);
2186          address.id = response?.data?.commerce_updateCustomerAddress?.id;
2187          address.street = response?.data?.commerce_updateCustomerAddress?.street;
2188        } else {
2189          const response = await createAddress(address, config);
2190          address.id = response?.data?.commerce_createCustomerAddress?.id;
2191          address.street = response?.data?.commerce_createCustomerAddress?.street;
2192        }
2193      }
2194      window.dispatchEvent(new CustomEvent('react:addressFormSubmitted', { detail: { address, isUpdate } }));
2195    } else {
2196      res = await createAddress(address);
2197      if (res?.success) {
2198        message = placeholders.addressAdded || 'Address is added successfully.';
2199      }
2200    }
2201    if (res?.success) {
2202      block.dispatchEvent(new CustomEvent('address-updated'));
2203      addressesContainer.classList.remove('hide');
2204      $parent.classList.add('hide');
2205      document.querySelector('.new-address-container').classList.remove('hide');
2206      addStatusMessage(message);
2207    }
2208  });
2209
2210  decorateIcons(form);
2211  if (!isCheckoutPage) {
2212    customSelectbox(form.querySelector('.input-field-wrapper.dropdown.country_id'));
2213  }
2214  customSelectbox(form.querySelector('.input-field-wrapper.dropdown.address_city_segment'));
2215  $parent.innerHTML = '';
2216  $parent.appendChild(form);
2217  if (isCheckoutPage) {
2218    window.dispatchEvent(new CustomEvent('react:addressFormLoaded'));
2219  }
2220  if (countryCode === 'EG') {
2221    form.querySelector('#address_floor_segment').closest('form > .input-field-wrapper')?.remove();
2222  }
2223  // Load Short Code Map modal if enabled
2224  if (blockConfigs?.flags?.enableShortCodeMap === true) {
2225    loadShortCodeMapModal(placeholders, formId);
2226  }
2227  // $parent.classList.remove('hide');
2228  return $parent;
2229}
2230
2231// EDIT ADDRESS form in modal
2232export async function showEditAddressModal(
2233  blockConfigs,
2234  addressForm,
2235  placeholders,
2236  addressObj,
2237  citySegments,
2238  isCheckoutPage = false,
2239  isLoggedIn = false,
2240  config = {},
2241  isTopup = false,
2242  // newCustomer = false,
2243  // updateOnlyTelephone = false,
2244  // infoMessage = ''
2245) {
2246  const editAddressModalId = 'edit-address-modal';
2247  const editAddressTitle = placeholders.editAddressModalTitle || 'Edit Address';
2248  const editAddressContent = document.createElement('div');
2249  editAddressContent.classList.add('edit-address-content');
2250  try {
2251    const formContent = await showAddressFormModal(
2252      blockConfigs,
2253      editAddressModalId,
2254      addressForm,
2255      placeholders,
2256      addressObj,
2257    );
2258    editAddressContent.appendChild(formContent);
2259  } catch (error) {
2260    console.error('Error rendering address form:', error);
2261  }
2262  const closeIcon = blockConfigs?.flags?.closeIcon ? blockConfigs.flags.closeIcon : 'icon-close-blue';
2263  await createModalFromContent(
2264    editAddressModalId,
2265    editAddressTitle,
2266    editAddressContent.outerHTML,
2267    ['edit-address-modal'],
2268    null,
2269    false,
2270    closeIcon,
2271  );
2272  openModal(editAddressModalId);
2273  // Attach the submit event listener after modal is open and content is loaded
2274
2275  const formElement = document.querySelector('.edit-address-content .address-form form');
2276  const phoneInput = formElement.querySelector('#telephone');
2277  const countryCode = await getConfigValue('country-code');
2278  const countryPrefix = `+${await getCountryIso(countryCode)}`;
2279  const maxLength = await getMaxLengthByCountryCode(countryCode);
2280  let isUpdate = '';
2281  if (addressObj) {
2282    isUpdate = Object.keys(addressObj)?.length > 0;
2283  }
2284
2285  if (phoneInput) {
2286    const addressModalClosest = phoneInput?.closest('.add-address-modal, .edit-address-modal, .checkout-form');
2287    const countryCodeLabel = addressModalClosest?.querySelector('.countrycode');
2288    if (countryCodeLabel) {
2289      const isNumeric = /^\d*$/.test(phoneInput.value.trim()) && phoneInput.value.trim();
2290      countryCodeLabel.classList.toggle('hidden', !isNumeric);
2291    }
2292  }
2293
2294  const addressSubmitButton = formElement.querySelector('.address-submit-button');
2295  const addressesContainer = document.querySelector('.addresses-container');
2296  const updateSubmitButtonState = () => {
2297    const isFormValid = formElement.checkValidity(); // Check overall form validity
2298    const isPhoneValid = phoneInput.value.length >= phoneInput.minLength
2299      && phoneInput.value.length <= phoneInput.maxLength;
2300      // Check if City and Area dropdowns have valid selections
2301    const cityDropdown = formElement.querySelector('#address_city_segment .select-selected');
2302    const isCityValid = cityDropdown && cityDropdown.getAttribute('data-value') !== '';
2303    const areaDropdown = formElement.querySelector('.area .select-selected');
2304    const isAreaValid = areaDropdown && areaDropdown.getAttribute('data-value') !== '';
2305    const districtDropdown = formElement.querySelector('#address_district_segment .select-selected');
2306    const isDistrictValid = districtDropdown && districtDropdown.getAttribute('data-value') !== '';
2307    const regionDropdown = formElement.querySelector('#address_region_segment .select-selected');
2308    const isRegionValid = regionDropdown && regionDropdown.getAttribute('data-value') !== '';
2309    // Disable submit button if form is invalid or if city/area are not selected
2310    addressSubmitButton.disabled = !(
2311      isFormValid && isPhoneValid && isCityValid
2312      && (isAreaValid || isDistrictValid || isRegionValid));
2313  };
2314  phoneValidation(phoneInput, countryCode, formElement, placeholders);
2315
2316  if (formElement) {
2317    // samriddhi submit
2318    formElement.addEventListener('submit', async (event) => {
2319      event.preventDefault();
2320      if (!validateForm(formElement, placeholders, isCheckoutPage)) {
2321        return;
2322      }
2323      const phoneValue = phoneInput.value;
2324      const isValidPhoneNumber = await validatePhone(phoneValue, countryCode);
2325      if (!isValidPhoneNumber) {
2326        let phoneNumberErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
2327        phoneNumberErrorMessage = phoneNumberErrorMessage.replace('{{mobile}}', phoneInput.value);
2328        showErrorMessage(phoneInput, phoneNumberErrorMessage);
2329        return;
2330      }
2331
2332      addressSubmitButton.classList.add('loader');
2333
2334      const isShortcodeValid = await validateAndStoreShortcode(formElement, placeholders);
2335      if (!isShortcodeValid) {
2336        addressSubmitButton.classList.remove('loader');
2337        return;
2338      }
2339      if (isCheckoutPage && !isLoggedIn) {
2340        const emailInput = formElement.querySelector('#email');
2341        const responseData = await validateCustomerEmail(emailInput.value);
2342        if (responseData?.customerExists) {
2343          const emailErrorMessage = placeholders.emailExist || 'You already have an account. Please log in.';
2344          showErrorMessage(emailInput, emailErrorMessage, true);
2345          dataLayerCustomerExistCheckoutErrors();
2346          addressSubmitButton.classList.remove('loader');
2347          return;
2348        }
2349        emailInput.classList.remove('error');
2350      }
2351
2352      const address = {};
2353      const customAttributeNames = new Set([
2354        'address_city_segment',
2355        'area',
2356        'address_building_segment',
2357        'address_apartment_segment',
2358        'address',
2359        'address_district_segment',
2360        'address_landmark_segment',
2361        'address_region_segment',
2362        'address_floor_segment',
2363        'address_block_segment',
2364        'address_road_segment',
2365        'short_code',
2366        'secondary_number',
2367        'longitude',
2368        'latitude',
2369      ]);
2370      const inputs = formElement.querySelectorAll('input, .custom-select, textarea');
2371
2372      inputs.forEach((input) => {
2373        const name = input?.getAttribute('name');
2374        if (!name) return;
2375
2376        let key = name;
2377        let value = input.value?.trim() || '';
2378        switch (name) {
2379          case 'country_id': {
2380            key = 'country_code';
2381            break;
2382          }
2383
2384          case 'address_city_segment':
2385          case 'address_district_segment':
2386          case 'address_region_segment':
2387          case 'area': {
2388            const selected = input.querySelector('.select-selected');
2389            const dataValue = selected?.getAttribute('data-value') || '';
2390            const dataInitialValue = selected?.getAttribute('data-initial-value') || '';
2391            value = input.classList.contains('custom-select')
2392              ? dataValue || dataInitialValue
2393              : value;
2394
2395            if (name === 'address_city_segment' || name === 'address_district_segment' || name === 'address_region_segment') {
2396              address.city = isCheckoutPage ? (dataValue || dataInitialValue || '-') : (dataValue || '-');
2397            }
2398            break;
2399          }
2400
2401          case 'fullName': {
2402            const [firstName = '', ...rest] = value.split(/\s+/);
2403            address.firstname = firstName;
2404            address.lastname = rest.join(' ');
2405            return;
2406          }
2407
2408          case 'telephone': {
2409            // Validate and clean telephone: strip prefix, enforce maxlength
2410            // This handles cases where user bypassed maxlength via dev tools or browser issues
2411            const cleanedTelephoneEdit = validateAndCleanTelephone(value, countryPrefix, maxLength);
2412            // Add prefix back for API (API expects full number with prefix)
2413            address.telephone = cleanedTelephoneEdit ? `${countryPrefix}${cleanedTelephoneEdit}` : '';
2414            return;
2415          }
2416          default:
2417            break;
2418        }
2419
2420        if (customAttributeNames.has(name)) {
2421          address.custom_attributes = address.custom_attributes || [];
2422          address.custom_attributes.push({
2423            attribute_code: key,
2424            value,
2425          });
2426        } else if (key !== 'email') {
2427          address[key] = value;
2428        }
2429      });
2430
2431      let res = null;
2432      let message;
2433      if (isUpdate && !isCheckoutPage) {
2434        res = await updateAddress(addressObj.id, address);
2435        if (res?.success) {
2436          message = placeholders.addressUpdated || 'Address is updated successfully.';
2437          closeModal('edit-address-modal');
2438        }
2439      } else if (isCheckoutPage) {
2440        if (isLoggedIn && !isTopup) {
2441          delete address.address;
2442          if (isUpdate) {
2443            const response = await updateAddress(addressObj.id, address, config);
2444            address.id = response?.data?.commerce_updateCustomerAddress?.id;
2445            address.street = response?.data?.commerce_updateCustomerAddress?.street;
2446          } else {
2447            const response = await createAddress(address, config);
2448            address.id = response?.data?.commerce_createCustomerAddress?.id;
2449            address.street = response?.data?.commerce_createCustomerAddress?.street;
2450          }
2451        }
2452        window.dispatchEvent(new CustomEvent('react:addressFormSubmitted', { detail: { address, isUpdate } }));
2453      } else {
2454        res = await createAddress(address);
2455        if (res?.success) {
2456          message = placeholders.addressAdded || 'Address is added successfully.';
2457          closeModal('edit-address-modal');
2458        }
2459      }
2460      if (res?.success) {
2461        window.dispatchEvent(new CustomEvent('address-updated'));
2462        closeModal('edit-address-modal');
2463        addressesContainer.classList.remove('hide');
2464        // $parent.classList.add('hide');
2465        document.querySelector('.new-address-container').classList.remove('hide');
2466        addStatusMessage(message);
2467      }
2468    });
2469  }
2470
2471  // TODO - Use Block-Config(Developer authorable) instead of config(Author authorable).
2472  if (disableInlineValidation === 'false') {
2473    formElement.querySelectorAll('input, .custom-select, textarea').forEach((input) => {
2474      input.addEventListener('input', () => {
2475        validateInput(input);
2476        updateSubmitButtonState();
2477      });
2478      input.addEventListener('blur', () => {
2479        updateSubmitButtonState();
2480      });
2481    });
2482  } else {
2483    formElement.querySelectorAll('input, .custom-select, textarea').forEach((input) => {
2484      if (input.type === 'tel') {
2485        return;
2486      }
2487      input.addEventListener('input', () => {
2488        debounce(() => {
2489          resetMessage(input);
2490          formElement.querySelector('button').disabled = false;
2491        }, 300)();
2492      });
2493
2494      input.addEventListener('blur', () => {
2495        if (!validateInput(input)) {
2496          formElement.querySelector('button').disabled = true;
2497        }
2498      });
2499    });
2500  }
2501  // Enable/disable Area field based on City selection
2502  const cityDropdown = formElement.querySelector('#address_city_segment .select-selected');
2503  const areaDropdown = formElement.querySelector('#area .select-selected');
2504  const districtDropdown = formElement.querySelector('#address_district_segment .select-selected');
2505  const regionDropdown = formElement.querySelector('#address_region_segment .select-selected');
2506  const inputFieldWrapper = formElement.querySelector('.input-field-wrapper.dropdown');
2507  const areaValid = () => {
2508    const areaOptionsContainer = formElement.querySelector('#area .select-items');
2509    areaOptionsContainer.addEventListener('click', (e) => {
2510      e.stopPropagation();
2511      areaDropdown.textContent = e.target.textContent;
2512      areaDropdown.setAttribute('data-value', e.target.getAttribute('data-value'));
2513      if (areaDropdown.getAttribute('data-value') !== '') {
2514        const inputFieldWrapperArea = formElement.querySelector('.input-field-wrapper.area');
2515        inputFieldWrapperArea.classList.remove('invalid');
2516        areaOptionsContainer.classList.add('select-hide');
2517      }
2518    });
2519  };
2520
2521  const cityValid = () => {
2522    const cityOptionsContainer = formElement.querySelector('#address_city_segment .select-items');
2523    cityOptionsContainer.addEventListener('click', (e) => {
2524      e.stopPropagation();
2525      cityDropdown.textContent = e.target.textContent;
2526      cityDropdown.setAttribute('data-value', e.target.getAttribute('data-value'));
2527      if (cityDropdown.getAttribute('data-value') !== '') {
2528        const inputFieldWrapperCity = formElement.querySelector('.input-field-wrapper.address_city_segment');
2529        inputFieldWrapperCity.classList.remove('invalid');
2530      }
2531    });
2532  };
2533
2534  const toggleAreaField = () => {
2535    if (districtDropdown) {
2536      const isDistrictSelected = districtDropdown.getAttribute('data-value') !== '';
2537      if (isDistrictSelected) {
2538        cityDropdown.setAttribute('aria-disabled', 'false');
2539      } else {
2540        cityDropdown.setAttribute('aria-disabled', 'true');
2541      }
2542    } else if (regionDropdown) {
2543      const isRegionSelected = regionDropdown.getAttribute('data-value') !== '';
2544      if (isRegionSelected) {
2545        cityDropdown.setAttribute('aria-disabled', 'false');
2546      } else {
2547        cityDropdown.setAttribute('aria-disabled', 'true');
2548      }
2549    } else if (cityDropdown) {
2550      const isCitySelected = cityDropdown.getAttribute('data-value') !== '';
2551      if (isCitySelected) {
2552        areaDropdown.setAttribute('aria-disabled', 'false');
2553      } else {
2554        areaDropdown.setAttribute('aria-disabled', 'true');
2555      }
2556    }
2557  };
2558
2559  if (districtDropdown) {
2560    // Function to update District selection and toggle City field state
2561    formElement.querySelectorAll('#address_district_segment .select-items div').forEach((districtOption) => {
2562      districtOption.addEventListener('click', () => {
2563        // Update district selection text and data-value
2564        districtDropdown.textContent = districtOption.textContent;
2565        districtDropdown.setAttribute('data-value', districtOption.getAttribute('data-value'));
2566        // Check if both city and area have values to remove the invalid class
2567        if (districtDropdown.getAttribute('data-value') !== '') {
2568          inputFieldWrapper.classList.remove('invalid');
2569        }
2570        toggleAreaField();
2571      });
2572    });
2573  } else if (regionDropdown) {
2574    // Function to update District selection and toggle City field state
2575    formElement.querySelectorAll('#address_region_segment .select-items div').forEach((regionOption) => {
2576      regionOption.addEventListener('click', () => {
2577        // Update region selection text and data-value
2578        regionDropdown.textContent = regionOption.textContent;
2579        regionDropdown.setAttribute('data-value', regionOption.getAttribute('data-value'));
2580        // Check if both region and city have values to remove the invalid class
2581        if (regionDropdown.getAttribute('data-value') !== '') {
2582          inputFieldWrapper.classList.remove('invalid');
2583        }
2584        toggleAreaField();
2585      });
2586    });
2587  } else {
2588    // Function to update city selection and toggle Area field state
2589    formElement.querySelectorAll('#address_city_segment .select-items div').forEach((cityOption) => {
2590      cityOption.addEventListener('click', () => {
2591        // Update city selection text and data-value
2592        cityDropdown.textContent = cityOption.textContent;
2593        cityDropdown.setAttribute('data-value', cityOption.getAttribute('data-value'));
2594        // Check if both city and area have values to remove the invalid class
2595        if (cityDropdown.getAttribute('data-value') !== '') {
2596          inputFieldWrapper.classList.remove('invalid');
2597        }
2598        toggleAreaField();
2599      });
2600    });
2601  }
2602
2603  // Trigger function on city selection
2604  // cityDropdown.addEventListener('click', toggleAreaField);
2605  if (districtDropdown || regionDropdown) {
2606    cityDropdown.addEventListener('click', cityValid);
2607    toggleAreaField();
2608    cityValid();
2609  } else {
2610    areaDropdown.addEventListener('click', areaValid);
2611    toggleAreaField();
2612    areaValid();
2613  }
2614  formElement.noValidate = true;
2615  setCountryCode(formElement, countryCode);
2616  if (countriesWithRegions.includes(countryCode)) {
2617    const regionSegments = await getAddressRegionSegments(countryCode);
2618    await populateRegions(formElement, regionSegments, countryCode, placeholders);
2619  } else {
2620    await populateCity(formElement, citySegments, countryCode, placeholders);
2621  }
2622  customSelectboxModal(blockConfigs, placeholders, formElement);
2623  const phoneDiv = document.querySelector('.edit-address-content .address-form form .input-field-wrapper.phonevalidation');
2624  const emailDiv = document.querySelector('.edit-address-content .address-form form .input-field-wrapper.emailValidation');
2625  const city = document.querySelector('.edit-address-content .address-form form .input-field-wrapper.dropdown.address_city_segment');
2626  const area = document.querySelector('.edit-address-content .address-form form .input-field-wrapper.dropdown.area');
2627  const district = document.querySelector('.edit-address-modal .address-form form .input-field-wrapper.dropdown.address_district_segment');
2628  const region = document.querySelector('.edit-address-modal .address-form form .input-field-wrapper.dropdown.address_region_segment');
2629  wrapTwoDivsinWrapper(phoneDiv, emailDiv, 'form__phone-email-wrapper');
2630  if (districtDropdown) {
2631    wrapTwoDivsinWrapper(district, city, 'form__district-city-wrapper');
2632  } else if (regionDropdown) {
2633    wrapTwoDivsinWrapper(region, city, 'form__region-city-wrapper');
2634  } else if (cityDropdown) {
2635    wrapTwoDivsinWrapper(city, area, 'form__city-area-wrapper');
2636  }
2637}
2638
2639// ADD ADDRESS form in modal
2640export async function showAddAddressModal(
2641  blockConfigs,
2642  placeholders,
2643  citySegments,
2644  addressObj = {},
2645  config = {},
2646  isCheckoutPage = false,
2647  isLoggedIn = false,
2648  isTopup = false,
2649  // newCustomer = false,
2650  // updateOnlyTelephone = false,
2651  // infoMessage = ''
2652) {
2653  const addAddressModalId = 'add-address-modal';
2654  const addAddressTitle = placeholders.addAddress || 'Add Address';
2655  const addAddressContent = document.createElement('div');
2656  addAddressContent.classList.add('add-address-content');
2657  const addressForm = document.createElement('div');
2658  addressForm.classList.add('address-form');
2659  try {
2660    const formContent = await showAddressFormModal(
2661      blockConfigs,
2662      addAddressModalId,
2663      addressForm,
2664      placeholders,
2665      {},
2666    );
2667    addAddressContent.innerHTML = formContent;
2668  } catch (error) {
2669    console.error('Error rendering address form:', error);
2670  }
2671  const closeIcon = blockConfigs?.flags?.closeIcon ? blockConfigs.flags.closeIcon : 'icon-close-blue';
2672  await createModalFromContent(
2673    addAddressModalId,
2674    addAddressTitle,
2675    addressForm.outerHTML,
2676    ['add-address-modal'],
2677    null,
2678    false,
2679    closeIcon,
2680  );
2681  openModal(addAddressModalId);
2682  // Attach the submit event listener after modal is open and content is loaded
2683  const formElement = document.querySelector(`#${addAddressModalId} .address-form form`);
2684  document.addEventListener('input', ({ target }) => {
2685    restrictSpecialCharacterText(target);
2686  });
2687
2688  const phoneInput = formElement.querySelector('#telephone');
2689  const countryCode = await getConfigValue('country-code');
2690  const countryPrefix = `+${await getCountryIso(countryCode)}`;
2691  const maxLength = await getMaxLengthByCountryCode(countryCode);
2692  const isUpdate = Object.keys(addressObj).length > 0;
2693
2694  const addressSubmitButton = formElement.querySelector('.address-submit-button');
2695  const addressesContainer = document.querySelector('.addresses-container');
2696  const updateSubmitButtonState = () => {
2697    const isFormValid = formElement.checkValidity(); // Check overall form validity
2698    const isPhoneValid = phoneInput.value.length >= phoneInput.minLength
2699      && phoneInput.value.length <= phoneInput.maxLength;
2700      // Check if City and Area dropdowns have valid selections
2701    const cityDropdown = formElement.querySelector('#address_city_segment .select-selected');
2702    const isCityValid = cityDropdown && cityDropdown.getAttribute('data-value') !== '';
2703    const areaDropdown = formElement.querySelector('.area .select-selected');
2704    const isAreaValid = areaDropdown && areaDropdown.getAttribute('data-value') !== '';
2705    const districtDropdown = formElement.querySelector('#address_district_segment .select-selected');
2706    const isDistrictValid = districtDropdown && districtDropdown.getAttribute('data-value') !== '';
2707    const regionDropdown = formElement.querySelector('#address_regi
2707on_segment .select-selected');
2708    const isRegionValid = regionDropdown && regionDropdown.getAttribute('data-value') !== '';
2709    // Disable submit button if form is invalid or if city/area are not selected
2710    addressSubmitButton.disabled = !(
2711      isFormValid && isPhoneValid && isCityValid
2712      && (isAreaValid || isDistrictValid || isRegionValid));
2713  };
2714  phoneValidation(phoneInput, countryCode, formElement, placeholders);
2715
2716  if (formElement) {
2717    // samriddhi submit
2718    formElement.addEventListener('submit', async (event) => {
2719      event.preventDefault();
2720      updateSubmitButtonState();
2721      if (!validateForm(formElement, placeholders, isCheckoutPage)) {
2722        return;
2723      }
2724      const phoneValue = phoneInput.value;
2725      const isValidPhoneNumber = await validatePhone(phoneValue, countryCode);
2726      if (!isValidPhoneNumber) {
2727        let phoneNumberErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`;
2728        phoneNumberErrorMessage = phoneNumberErrorMessage.replace('{{mobile}}', phoneInput.value);
2729        showErrorMessage(phoneInput, phoneNumberErrorMessage);
2730        return;
2731      }
2732
2733      addressSubmitButton.classList.add('loader');
2734
2735      if (isShortCodeMandatory) {
2736        const isShortcodeValid = await validateAndStoreShortcode(formElement, placeholders);
2737        if (!isShortcodeValid) {
2738          addressSubmitButton.classList.remove('loader');
2739          return;
2740        }
2741      }
2742
2743      if (isCheckoutPage && !isLoggedIn) {
2744        const emailInput = formElement.querySelector('#email');
2745        const responseData = await validateCustomerEmail(emailInput.value);
2746        if (responseData?.customerExists) {
2747          const emailErrorMessage = placeholders.emailExist || 'You already have an account. Please log in.';
2748          showErrorMessage(emailInput, emailErrorMessage, true);
2749          dataLayerCustomerExistCheckoutErrors();
2750          addressSubmitButton.classList.remove('loader');
2751          return;
2752        }
2753        emailInput.classList.remove('error');
2754      }
2755
2756      const address = {};
2757      const customAttributeNames = new Set([
2758        'address_city_segment',
2759        'area',
2760        'address_building_segment',
2761        'address_apartment_segment',
2762        'address',
2763        'address_district_segment',
2764        'address_floor_segment',
2765        'address_landmark_segment',
2766        'address_region_segment',
2767        'address_block_segment',
2768        'address_road_segment',
2769        'short_code',
2770        'secondary_number',
2771        'longitude',
2772        'latitude',
2773      ]);
2774      const inputs = formElement.querySelectorAll('input, .custom-select, textarea');
2775
2776      inputs.forEach((input) => {
2777        const name = input?.getAttribute('name');
2778        if (!name) return;
2779
2780        let key = name;
2781        let value = input.value?.trim() || '';
2782        switch (name) {
2783          case 'country_id': {
2784            key = 'country_code';
2785            break;
2786          }
2787
2788          case 'address_city_segment':
2789          case 'address_district_segment':
2790          case 'address_region_segment':
2791          case 'area': {
2792            const selected = input.querySelector('.select-selected');
2793            const dataValue = selected?.getAttribute('data-value') || '';
2794            const dataInitialValue = selected?.getAttribute('data-initial-value') || '';
2795            value = input.classList.contains('custom-select')
2796              ? dataValue || dataInitialValue
2797              : value;
2798
2799            if (name === 'address_city_segment' || name === 'address_district_segment' || name === 'address_region_segment') {
2800              address.city = isCheckoutPage ? (dataValue || dataInitialValue || '-') : (dataValue || '-');
2801            }
2802            break;
2803          }
2804
2805          case 'fullName': {
2806            const [firstName = '', ...rest] = value.split(/\s+/);
2807            address.firstname = firstName;
2808            address.lastname = rest.join(' ');
2809            return;
2810          }
2811
2812          case 'telephone': {
2813            // Validate and clean telephone: strip prefix, enforce maxlength
2814            // This handles cases where user bypassed maxlength via dev tools or browser issues
2815            const cleanedTelephoneAdd = validateAndCleanTelephone(value, countryPrefix, maxLength);
2816            // Add prefix back for API (API expects full number with prefix)
2817            address.telephone = cleanedTelephoneAdd ? `${countryPrefix}${cleanedTelephoneAdd}` : '';
2818            return;
2819          }
2820          default:
2821            break;
2822        }
2823
2824        if (customAttributeNames.has(name)) {
2825          address.custom_attributes = address.custom_attributes || [];
2826          address.custom_attributes.push({
2827            attribute_code: key,
2828            value,
2829          });
2830        } else if (key !== 'email') {
2831          address[key] = value;
2832        }
2833        const noAddress = document.querySelector('.account-no-address');
2834        if (!noAddress.classList.contains('hide')) {
2835          noAddress.classList.add('hide');
2836        }
2837      });
2838
2839      // Due to out of the box validations for commerce we have to
2840      // send City attribute explicitly, It is not required at alshaya
2841      if (countryCode === 'KW') address.city = 'city';
2842
2843      // Sending null at region due to magento mapping
2844      if (countryCode === 'EG') address.region = null;
2845
2846      if (countryCode === 'BH') address.street = [null];
2847
2848      let res = null;
2849      let message;
2850      if (isUpdate && !isCheckoutPage) {
2851        res = await updateAddress(addressObj.id, address);
2852        if (res?.success) {
2853          message = placeholders.addressUpdated || 'Address is updated successfully.';
2854          closeModal('add-address-modal');
2855        }
2856      } else if (isCheckoutPage) {
2857        if (isLoggedIn && !isTopup) {
2858          delete address.address;
2859          if (isUpdate) {
2860            const response = await updateAddress(addressObj.id, address, config);
2861            address.id = response?.data?.commerce_updateCustomerAddress?.id;
2862            address.street = response?.data?.commerce_updateCustomerAddress?.street;
2863          } else {
2864            const response = await createAddress(address, config);
2865            address.id = response?.data?.commerce_createCustomerAddress?.id;
2866            address.street = response?.data?.commerce_createCustomerAddress?.street;
2867          }
2868        }
2869        window.dispatchEvent(new CustomEvent('react:addressFormSubmitted', { detail: { address, isUpdate } }));
2870      } else {
2871        const customer = await getCustomer(false);
2872        if (customer.addresses.length === 0) {
2873          address.default_billing = true;
2874          address.default_shipping = true;
2875        }
2876        res = await createAddress(address);
2877        if (res?.success) {
2878          message = placeholders.addressAdded || 'Address is added successfully.';
2879          closeModal('add-address-modal');
2880        }
2881      }
2882      if (res?.success) {
2883        window.dispatchEvent(new CustomEvent('address-updated'));
2884        closeModal('add-address-modal');
2885        addressesContainer.classList.remove('hide');
2886        // $parent.classList.add('hide');
2887        document.querySelector('.new-address-container').classList.remove('hide');
2888        addStatusMessage(message);
2889      }
2890    });
2891  }
2892
2893  // TODO - Use Block-Config(Developer authorable) instead of config(Author authorable).
2894  if (disableInlineValidation === 'false') {
2895    formElement.querySelectorAll('input, .custom-select, textarea').forEach((input) => {
2896      input.addEventListener('input', () => {
2897        validateInput(input);
2898        updateSubmitButtonState();
2899      });
2900      input.addEventListener('blur', () => {
2901        updateSubmitButtonState();
2902      });
2903    });
2904  } else {
2905    formElement.querySelectorAll('input, textarea').forEach((input) => {
2906      if (input.type === 'tel') {
2907        return;
2908      }
2909      input.addEventListener('input', () => {
2910        debounce(() => {
2911          resetMessage(input);
2912          formElement.querySelector('button').disabled = false;
2913        }, 300)();
2914      });
2915
2916      input.addEventListener('blur', () => {
2917        if (!validateInput(input)) {
2918          formElement.querySelector('button').disabled = true;
2919        }
2920      });
2921
2922      formElement.querySelectorAll('.custom-select').forEach((dropdown) => {
2923        dropdown.addEventListener('click', (event) => {
2924          event.stopPropagation();
2925          if (dropdown.contains(event.relatedTarget)) {
2926            return;
2927          }
2928          formElement.querySelector('button').disabled = false;
2929          const mainBox = event.target.closest('.custom-select');
2930          const selectionBox = mainBox.querySelector('.select-selected');
2931          if (!selectionBox.getAttribute('data-initial-value') && !selectionBox.getAttribute('data-value')) {
2932            const dropdownLabel = dropdown.getAttribute('aria-label');
2933            let errorMessage = placeholders.addAddressSelectError || `Please select ${dropdownLabel}`;
2934            errorMessage = errorMessage.replace('{{label}}', dropdownLabel);
2935            showErrorMessage(mainBox, errorMessage);
2936          }
2937        });
2938      });
2939    });
2940  }
2941  // Enable/disable Area field based on City selection
2942  const cityDropdown = formElement.querySelector('#address_city_segment .select-selected');
2943  const areaDropdown = formElement.querySelector('#area .select-selected');
2944  const districtDropdown = formElement.querySelector('#address_district_segment .select-selected');
2945  const regionDropdown = formElement.querySelector('#address_region_segment .select-selected');
2946  const inputFieldWrapper = formElement.querySelector('.input-field-wrapper.dropdown');
2947  const areaValid = () => {
2948    const areaOptionsContainer = formElement.querySelector('#area .select-items');
2949    areaOptionsContainer.addEventListener('click', (e) => {
2950      e.stopPropagation();
2951      areaDropdown.textContent = e.target.textContent;
2952      areaDropdown.setAttribute('data-value', e.target.getAttribute('data-value'));
2953      if (areaDropdown.getAttribute('data-value') !== '') {
2954        const inputFieldWrapperArea = formElement.querySelector('.input-field-wrapper.area');
2955        inputFieldWrapperArea.classList.remove('invalid');
2956      }
2957    });
2958  };
2959
2960  const cityValid = () => {
2961    const cityOptionsContainer = formElement.querySelector('#address_city_segment .select-items');
2962    cityOptionsContainer.addEventListener('click', (e) => {
2963      e.stopPropagation();
2964      cityDropdown.textContent = e.target.textContent;
2965      cityDropdown.setAttribute('data-value', e.target.getAttribute('data-value'));
2966      if (cityDropdown.getAttribute('data-value') !== '') {
2967        const inputFieldWrapperCity = formElement.querySelector('.input-field-wrapper.address_city_segment');
2968        inputFieldWrapperCity.classList.remove('invalid');
2969      }
2970    });
2971  };
2972
2973  const toggleAreaField = () => {
2974    if (districtDropdown) {
2975      const isDistrictSelected = districtDropdown.getAttribute('data-value') !== '';
2976      if (isDistrictSelected) {
2977        cityDropdown.setAttribute('aria-disabled', 'false');
2978      } else {
2979        cityDropdown.setAttribute('aria-disabled', 'true');
2980      }
2981    } else if (regionDropdown) {
2982      const isRegionSelected = regionDropdown.getAttribute('data-value') !== '';
2983      if (isRegionSelected) {
2984        cityDropdown.setAttribute('aria-disabled', 'false');
2985      } else {
2986        cityDropdown.setAttribute('aria-disabled', 'true');
2987      }
2988    } else if (cityDropdown) {
2989      const isCitySelected = cityDropdown.getAttribute('data-value') !== '';
2990      if (isCitySelected) {
2991        areaDropdown.setAttribute('aria-disabled', 'false');
2992      } else {
2993        areaDropdown.setAttribute('aria-disabled', 'true');
2994      }
2995    }
2996  };
2997
2998  if (districtDropdown) {
2999    // Function to update District selection and toggle City field state
3000    formElement.querySelectorAll('#address_district_segment .select-items div').forEach((districtOption) => {
3001      districtOption.addEventListener('click', () => {
3002        // Update district selection text and data-value
3003        districtDropdown.textContent = districtOption.textContent;
3004        districtDropdown.setAttribute('data-value', districtOption.getAttribute('data-value'));
3005        // Check if both city and area have values to remove the invalid class
3006        if (districtDropdown.getAttribute('data-value') !== '') {
3007          inputFieldWrapper.classList.remove('invalid');
3008        }
3009        toggleAreaField();
3010      });
3011    });
3012  } else if (regionDropdown) {
3013    // Function to update Region selection and toggle City field state
3014    formElement.querySelectorAll('#address_region_segment .select-items div').forEach((regionOption) => {
3015      regionOption.addEventListener('click', () => {
3016      // Update region selection text and data-value
3017        regionDropdown.textContent = regionOption.textContent;
3018        regionDropdown.setAttribute('data-value', regionOption.getAttribute('data-value'));
3019        // Check if both region and city have values to remove the invalid class
3020        if (regionDropdown.getAttribute('data-value') !== '') {
3021          inputFieldWrapper.classList.remove('invalid');
3022        }
3023        toggleAreaField();
3024      });
3025    });
3026  } else {
3027    // Function to update city selection and toggle Area field state
3028    formElement.querySelectorAll('#address_city_segment .select-items div').forEach((cityOption) => {
3029      cityOption.addEventListener('click', () => {
3030        // Update city selection text and data-value
3031        cityDropdown.textContent = cityOption.textContent;
3032        cityDropdown.setAttribute('data-value', cityOption.getAttribute('data-value'));
3033        // Check if both city and area have values to remove the invalid class
3034        if (cityDropdown.getAttribute('data-value') !== '') {
3035          inputFieldWrapper.classList.remove('invalid');
3036        }
3037        toggleAreaField();
3038      });
3039    });
3040  }
3041
3042  // Trigger function on city selection
3043  // cityDropdown.addEventListener('click', toggleAreaField);
3044  if (districtDropdown || regionDropdown) {
3045    cityDropdown.addEventListener('click', cityValid);
3046    toggleAreaField();
3047    cityValid();
3048  } else {
3049    areaDropdown.addEventListener('click', areaValid);
3050    toggleAreaField();
3051    areaValid();
3052  }
3053  formElement.noValidate = true;
3054  setCountryCode(formElement, countryCode);
3055  await populateCity(formElement, citySegments, countryCode, placeholders);
3056  customSelectboxModal(blockConfigs, placeholders, formElement);
3057  const phoneDiv = document.querySelector('.add-address-modal .address-form form .input-field-wrapper.phonevalidation');
3058  const emailDiv = document.querySelector('.add-address-modal .address-form form .input-field-wrapper.emailValidation');
3059  const city = document.querySelector('.add-address-modal .address-form form .input-field-wrapper.dropdown.address_city_segment');
3060  const area = document.querySelector('.add-address-modal .address-form form .input-field-wrapper.dropdown.area');
3061  const district = document.querySelector('.add-address-modal .address-form form .input-field-wrapper.dropdown.address_district_segment');
3062  const region = document.querySelector('.add-address-modal .address-form form .input-field-wrapper.dropdown.address_region_segment');
3063
3064  wrapTwoDivsinWrapper(phoneDiv, emailDiv, 'form__phone-email-wrapper');
3065  if (districtDropdown) {
3066    wrapTwoDivsinWrapper(district, city, 'form__district-city-wrapper');
3067  } else if (regionDropdown) {
3068    wrapTwoDivsinWrapper(region, city, 'form__region-city-wrapper');
3069  } else if (cityDropdown) {
3070    wrapTwoDivsinWrapper(city, area, 'form__city-area-wrapper');
3071  }
3072
3073  const addAddressModal = document.querySelector('.add-address-modal');
3074  if (addAddressModal) {
3075    const countryCodeLabel = addAddressModal.querySelector('.countrycode');
3076    if (countryCodeLabel) {
3077      countryCodeLabel.classList.add('hidden');
3078    }
3079  }
3080}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.