abmp-npm 1.1.83 → 1.1.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/backend/consts.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const PAC_API_URL = 'https://members.abmp.com/eweb/api/Wix';
2
+ const BACKUP_API_URL = 'https://psdevteamenterpris.wixstudio.com/abmp-backup/_functions';
2
3
  const SSO_TOKEN_AUTH_API_URL = 'https://members.professionalassistcorp.com/';
3
4
 
4
5
  /**
@@ -40,4 +41,5 @@ module.exports = {
40
41
  COMPILED_FILTERS_FIELDS,
41
42
  MEMBERSHIPS_TYPES,
42
43
  SSO_TOKEN_AUTH_API_URL,
44
+ BACKUP_API_URL,
43
45
  };
@@ -84,7 +84,7 @@ const validateCoreMemberData = inputMemberData => {
84
84
  return true;
85
85
  };
86
86
 
87
- const containsNonEnglish = str => /[^a-zA-Z0-9]/.test(str); // if it contains any non-english characters, test1 is allowed, but any others are not
87
+ const containsNonEnglish = str => /[^a-zA-Z0-9-]/.test(str); // if it contains any non-english characters or invalid URL chars, test1 is allowed, hyphens are allowed
88
88
 
89
89
  /**
90
90
  * Creates a full name from first and last name components
@@ -0,0 +1,18 @@
1
+ const { ensureUniqueUrlsInBatch } = require('./daily-pull/bulk-process-methods');
2
+ const { wixData } = require('./elevated-modules');
3
+ const { bulkSaveMembers } = require('./members-data-methods');
4
+ const { queryAllItems } = require('./utils');
5
+
6
+ async function deduplicateURls(collectionName, duplicateUrlsList) {
7
+ const query = await wixData.query(collectionName).hasSome('url', duplicateUrlsList).limit(1000);
8
+ const membersWithSameUrl = await queryAllItems(query);
9
+
10
+ console.log({ membersWithSameUrl });
11
+ const membersWithUniqueUrls = await ensureUniqueUrlsInBatch(membersWithSameUrl);
12
+ console.log({ membersWithUniqueUrls });
13
+ const deduplicatedUrls = membersWithUniqueUrls.map(m => m.url);
14
+ console.log({ deduplicatedUrls });
15
+ return await bulkSaveMembers(membersWithUniqueUrls, collectionName);
16
+ }
17
+
18
+ module.exports = { deduplicateURls };
package/backend/index.js CHANGED
@@ -13,4 +13,5 @@ module.exports = {
13
13
  ...require('./login'),
14
14
  ...require('./data-hooks'),
15
15
  ...require('./http-functions'),
16
+ ...require('./dev-only-methods'),
16
17
  };
@@ -61,9 +61,10 @@ async function createContactAndMemberIfNew(memberData) {
61
61
 
62
62
  /** Performs bulk save operation for member data
63
63
  * @param { Array } memberDataList - Array of member data objects to save
64
+ * @param { string } [collectionName] - The collection name to save the members to (default: COLLECTIONS.MEMBERS_DATA)
64
65
  * @returns { Promise < Object >} - Bulk save operation result
65
66
  */
66
- async function bulkSaveMembers(memberDataList) {
67
+ async function bulkSaveMembers(memberDataList, collectionName = COLLECTIONS.MEMBERS_DATA) {
67
68
  if (!Array.isArray(memberDataList) || memberDataList.length === 0) {
68
69
  throw new Error('Invalid member data list provided for bulk save');
69
70
  }
@@ -71,9 +72,7 @@ async function bulkSaveMembers(memberDataList) {
71
72
  try {
72
73
  // bulkSave all with batches of 1000 items as this is the Velo limit for bulkSave
73
74
  const batches = chunkArray(memberDataList, 1000);
74
- return await Promise.all(
75
- batches.map(batch => wixData.bulkSave(COLLECTIONS.MEMBERS_DATA, batch))
76
- );
75
+ return await Promise.all(batches.map(batch => wixData.bulkSave(collectionName, batch)));
77
76
  } catch (error) {
78
77
  console.error('Error bulk saving members:', error);
79
78
  throw new Error(`Bulk save failed: ${error.message}`);
@@ -133,7 +132,9 @@ async function getMemberBySlug({
133
132
  }
134
133
  query = query.limit(1000);
135
134
  const searchResult = await searchAllItems(query);
136
- const membersList = searchResult.filter(item => item.url && item.url.includes(slug)); //replacement for contains
135
+ const membersList = searchResult.filter(
136
+ item => item.url && item.url.toLowerCase().includes(slug.toLowerCase())
137
+ ); //replacement for contains - case insensitive
137
138
  let matchingMembers = membersList.filter(
138
139
  item => item.url && item.url.toLowerCase() === slug.toLowerCase()
139
140
  );
@@ -270,23 +271,13 @@ async function urlExists(url, excludeMemberId) {
270
271
  if (!url) return false;
271
272
 
272
273
  try {
273
- let query = wixData
274
- .query(COLLECTIONS.MEMBERS_DATA)
275
- .contains('url', url)
276
- .ne('action', MEMBER_ACTIONS.DROP); //TODO: change it to wix search
277
-
278
- if (excludeMemberId) {
279
- query = query.ne('memberId', excludeMemberId);
280
- }
281
-
282
- const { items } = await query.find();
283
-
284
- // Case-insensitive comparison
285
- const matchingMembers = items.filter(
286
- item => item.url && item.url.toLowerCase() === url.toLowerCase()
287
- );
288
-
289
- return matchingMembers.length > 0;
274
+ const member = await getMemberBySlug({
275
+ slug: url,
276
+ excludeDropped: false,
277
+ excludeSearchedMember: true,
278
+ memberId: excludeMemberId,
279
+ });
280
+ return member !== null;
290
281
  } catch (error) {
291
282
  console.error('Error checking URL existence:', error);
292
283
  return false;
@@ -1,7 +1,7 @@
1
1
  const { getMainAddress } = require('../../public/Utils/sharedUtils');
2
2
  const { getMemberBySlug } = require('../members-data-methods');
3
3
  const {
4
- getAddressesByStatus,
4
+ getMoreAddressesToDisplay,
5
5
  formatDateToMonthYear,
6
6
  hasStudentMembership,
7
7
  isPAC_STAFF,
@@ -48,7 +48,10 @@ function transformMemberToProfileData(member, siteAssociation) {
48
48
  ?.map(val => val.license)
49
49
  .filter(Boolean)
50
50
  .join(', ');
51
- const processedAddresses = getAddressesByStatus(member.addresses, member.addressDisplayOption);
51
+ const moreAddressesToDisplay = getMoreAddressesToDisplay(
52
+ member.addresses,
53
+ member.addressDisplayOption
54
+ );
52
55
 
53
56
  const memberships = member.memberships || [];
54
57
  const siteAssociationMembership = memberships.find(m => m.association === siteAssociation);
@@ -67,7 +70,7 @@ function transformMemberToProfileData(member, siteAssociation) {
67
70
  mainAddress,
68
71
  testimonials: member.testimonial || [],
69
72
  licenceNo,
70
- processedAddresses,
73
+ moreAddressesToDisplay,
71
74
  memberSince:
72
75
  (member.showABMP &&
73
76
  siteAssociationMembership &&
@@ -89,7 +89,7 @@ const TASKS = {
89
89
  getIdentifier: () => 'SHOULD_NEVER_SKIP',
90
90
  process: updateSiteMapS3,
91
91
  shouldSkipCheck: () => false,
92
- estimatedDurationSec: 70,
92
+ estimatedDurationSec: 90,
93
93
  },
94
94
  [TASKS_NAMES.scheduleContactFormEmailMigration]: {
95
95
  name: TASKS_NAMES.scheduleContactFormEmailMigration,
package/backend/utils.js CHANGED
@@ -4,7 +4,7 @@ const { site } = require('@wix/urls');
4
4
  const { encode } = require('ngeohash');
5
5
 
6
6
  const { COLLECTIONS, ADDRESS_STATUS_TYPES } = require('../public/consts');
7
- const { formatAddress, generateId } = require('../public/Utils/sharedUtils');
7
+ const { formatAddress, generateId, findMainAddress } = require('../public/Utils/sharedUtils');
8
8
 
9
9
  const { CONFIG_KEYS, GEO_HASH_PRECISION, MEMBERSHIPS_TYPES } = require('./consts');
10
10
  const { wixData } = require('./elevated-modules');
@@ -91,16 +91,17 @@ function getAddressDisplayOptions(member) {
91
91
  }
92
92
  return displayOptions;
93
93
  }
94
- function getAddressesByStatus(addresses = [], addressDisplayOption = []) {
94
+ function getMoreAddressesToDisplay(addresses = [], addressDisplayOption = []) {
95
95
  const visible = addresses.filter(addr => addr.addressStatus !== ADDRESS_STATUS_TYPES.DONT_SHOW);
96
96
  if (visible.length < 2) {
97
97
  return [];
98
98
  }
99
- const opts = Array.isArray(addressDisplayOption) ? addressDisplayOption : [];
100
- const mainOpt = opts.find(o => o.isMain);
101
- const mainKey = mainOpt ? mainOpt.key : visible[0].key; // fallback to the first visible if none marked
102
- return visible
103
- .filter(addr => addr?.key !== mainKey)
99
+ const mainAddress = findMainAddress(addressDisplayOption, addresses);
100
+ const remainingAddressesToFormat = mainAddress
101
+ ? visible.filter(addr => addr?.key !== mainAddress.key)
102
+ : visible;
103
+
104
+ return remainingAddressesToFormat
104
105
  .map(addr => {
105
106
  const addressString = formatAddress(addr);
106
107
  return addressString ? { _id: generateId(), address: addressString } : null;
@@ -214,7 +215,7 @@ module.exports = {
214
215
  getSiteBaseUrl,
215
216
  encodeXml,
216
217
  formatDateOnly,
217
- getAddressesByStatus,
218
+ getMoreAddressesToDisplay,
218
219
  isPAC_STAFF,
219
220
  searchAllItems,
220
221
  };
@@ -0,0 +1,201 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const csv = require('csv-parser');
5
+
6
+ /**
7
+ * Finds duplicate URLs in a CSV file and generates a JSON report
8
+ * Usage: node scripts/find-duplicate-urls.js <path-to-csv-file>
9
+ */
10
+ function findDuplicateUrls(csvFilePath) {
11
+ // Validate command-line argument
12
+ if (!csvFilePath) {
13
+ console.error('Error: CSV file path is required');
14
+ console.error('Usage: node scripts/find-duplicate-urls.js <path-to-csv-file>');
15
+ process.exit(1);
16
+ }
17
+
18
+ // Validate file exists and is readable
19
+ if (!fs.existsSync(csvFilePath)) {
20
+ console.error(`Error: File not found: ${csvFilePath}`);
21
+ process.exit(1);
22
+ }
23
+
24
+ const urlMap = new Map(); // url -> [memberId1, memberId2, ...]
25
+ let totalMembers = 0;
26
+ let rowNumber = 0;
27
+ let headersValidated = false;
28
+ let headers = null;
29
+ let urlColumnName = null;
30
+ let memberIdColumnName = null;
31
+
32
+ return new Promise((resolve, reject) => {
33
+ fs.createReadStream(csvFilePath)
34
+ .pipe(csv())
35
+ .on('headers', receivedHeaders => {
36
+ headers = receivedHeaders;
37
+ // Validate required columns exist - normalize by removing quotes, trimming, and lowercasing
38
+ const normalizedHeaders = headers.map(h => {
39
+ let normalized = String(h).trim();
40
+ // Remove all quotes (single and double) from the string
41
+ normalized = normalized.replace(/["']/g, '');
42
+ return normalized.toLowerCase().trim();
43
+ });
44
+
45
+ // Find the actual column names for url and memberId
46
+ const urlIndex = normalizedHeaders.indexOf('url');
47
+ const memberIdIndex = normalizedHeaders.indexOf('memberid');
48
+
49
+ if (urlIndex === -1 || memberIdIndex === -1) {
50
+ console.error('Error: CSV must contain "url" and "memberId" columns (case-insensitive)');
51
+ console.error(`Found columns: ${headers.join(', ')}`);
52
+ console.error(`Normalized columns: ${normalizedHeaders.join(', ')}`);
53
+ process.exit(1);
54
+ }
55
+
56
+ // Store the actual column names (with original casing/quotes)
57
+ urlColumnName = headers[urlIndex];
58
+ memberIdColumnName = headers[memberIdIndex];
59
+ headersValidated = true;
60
+ })
61
+ .on('data', row => {
62
+ // Validate headers on first data row if headers event didn't fire
63
+ if (!headersValidated) {
64
+ headers = Object.keys(row);
65
+ // Normalize by removing quotes, trimming, and lowercasing
66
+ const normalizedHeaders = headers.map(h => {
67
+ let normalized = String(h).trim();
68
+ // Remove all quotes (single and double) from the string
69
+ normalized = normalized.replace(/["']/g, '');
70
+ return normalized.toLowerCase().trim();
71
+ });
72
+
73
+ const urlIndex = normalizedHeaders.indexOf('url');
74
+ const memberIdIndex = normalizedHeaders.indexOf('memberid');
75
+
76
+ if (urlIndex === -1 || memberIdIndex === -1) {
77
+ console.error(
78
+ 'Error: CSV must contain "url" and "memberId" columns (case-insensitive)'
79
+ );
80
+ console.error(`Found columns: ${headers.join(', ')}`);
81
+ console.error(`Normalized columns: ${normalizedHeaders.join(', ')}`);
82
+ process.exit(1);
83
+ }
84
+
85
+ // Store the actual column names
86
+ urlColumnName = headers[urlIndex];
87
+ memberIdColumnName = headers[memberIdIndex];
88
+ headersValidated = true;
89
+ }
90
+
91
+ rowNumber++;
92
+ totalMembers++;
93
+
94
+ // Get URL and memberId using the actual column names from headers
95
+ const url = row[urlColumnName];
96
+ const memberId = row[memberIdColumnName];
97
+
98
+ // Skip rows with missing URL or memberId
99
+ if (!url || !memberId) {
100
+ console.warn(
101
+ `Warning: Row ${rowNumber} skipped - missing url or memberId (url: ${url}, memberId: ${memberId})`
102
+ );
103
+ return;
104
+ }
105
+
106
+ const trimmedUrl = url.trim();
107
+ const trimmedMemberId = memberId.trim();
108
+
109
+ // Track URL occurrences
110
+ if (!urlMap.has(trimmedUrl)) {
111
+ urlMap.set(trimmedUrl, []);
112
+ }
113
+ urlMap.get(trimmedUrl).push(trimmedMemberId);
114
+ })
115
+ .on('error', error => {
116
+ console.error('Error reading CSV file:', error.message);
117
+ reject(error);
118
+ })
119
+ .on('end', () => {
120
+ if (!headersValidated) {
121
+ console.error('Error: Could not read CSV headers');
122
+ process.exit(1);
123
+ }
124
+
125
+ // Find duplicates (URLs with count > 1)
126
+ const duplicateUrls = [];
127
+ let totalDuplicates = 0;
128
+
129
+ for (const [url, memberIds] of urlMap.entries()) {
130
+ if (memberIds.length > 1) {
131
+ duplicateUrls.push({
132
+ url: url,
133
+ count: memberIds.length,
134
+ memberIds: memberIds,
135
+ });
136
+ totalDuplicates += memberIds.length;
137
+ }
138
+ }
139
+
140
+ // Sort by count (descending) then by URL (ascending)
141
+ duplicateUrls.sort((a, b) => {
142
+ if (b.count !== a.count) {
143
+ return b.count - a.count;
144
+ }
145
+ return a.url.localeCompare(b.url);
146
+ });
147
+
148
+ const totalUniqueUrls = urlMap.size;
149
+ const uniqueDuplicateUrls = duplicateUrls.length;
150
+
151
+ // Create a simple list of duplicated URLs (just the URL strings)
152
+ const duplicatedUrlsList = duplicateUrls.map(item => item.url);
153
+
154
+ // Generate report
155
+ const report = {
156
+ totalMembers: totalMembers,
157
+ totalUniqueUrls: totalUniqueUrls,
158
+ duplicateUrls: duplicateUrls,
159
+ duplicatedUrlsList: duplicatedUrlsList,
160
+ summary: {
161
+ totalDuplicates: totalDuplicates,
162
+ uniqueDuplicateUrls: uniqueDuplicateUrls,
163
+ },
164
+ };
165
+
166
+ // Generate output filename
167
+ const csvDir = path.dirname(csvFilePath);
168
+ const csvBasename = path.basename(csvFilePath, path.extname(csvFilePath));
169
+ const outputPath = path.join(csvDir, `${csvBasename}-duplicate-urls-report.json`);
170
+
171
+ // Write JSON report
172
+ fs.writeFileSync(outputPath, JSON.stringify(report, null, 2), 'utf8');
173
+
174
+ console.log('\n=== Duplicate URL Report ===');
175
+ console.log(`Total members processed: ${totalMembers}`);
176
+ console.log(`Total unique URLs: ${totalUniqueUrls}`);
177
+ console.log(`Unique URLs with duplicates: ${uniqueDuplicateUrls}`);
178
+ console.log(`Total duplicate entries: ${totalDuplicates}`);
179
+ console.log(`\nReport saved to: ${outputPath}`);
180
+ console.log(`\nTop 10 most duplicated URLs:`);
181
+ duplicateUrls.slice(0, 10).forEach((item, index) => {
182
+ console.log(
183
+ ` ${index + 1}. "${item.url}" - appears ${item.count} times (memberIds: ${item.memberIds.join(', ')})`
184
+ );
185
+ });
186
+
187
+ resolve(report);
188
+ });
189
+ });
190
+ }
191
+
192
+ // Run if executed directly
193
+ if (require.main === module) {
194
+ const csvFilePath = process.argv[2];
195
+ findDuplicateUrls(csvFilePath).catch(error => {
196
+ console.error('Fatal error:', error.message);
197
+ process.exit(1);
198
+ });
199
+ }
200
+
201
+ module.exports = { findDuplicateUrls };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abmp-npm",
3
- "version": "1.1.83",
3
+ "version": "1.1.85",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "check-cycles": "madge --circular .",
@@ -9,7 +9,8 @@
9
9
  "lint:fix": "eslint . --fix",
10
10
  "format": "prettier --write \"**/*.{js,json,md}\"",
11
11
  "format:check": "prettier --check \"**/*.{js,json,md}\"",
12
- "prepare": "husky"
12
+ "prepare": "husky",
13
+ "find-duplicates": "node dev-only-scripts/find-duplicate-urls.js"
13
14
  },
14
15
  "author": "",
15
16
  "license": "ISC",
@@ -30,7 +31,7 @@
30
31
  "dependencies": {
31
32
  "@wix/automations": "^1.0.261",
32
33
  "@wix/crm": "^1.0.1061",
33
- "@wix/data": "^1.0.303",
34
+ "@wix/data": "^1.0.349",
34
35
  "@wix/essentials": "^0.1.28",
35
36
  "@wix/identity": "^1.0.178",
36
37
  "@wix/media": "^1.0.213",
@@ -46,6 +47,7 @@
46
47
  "crypto": "^1.0.1",
47
48
  "jwt-js-decode": "^1.9.0",
48
49
  "lodash": "^4.17.21",
50
+ "csv-parser": "^3.0.0",
49
51
  "ngeohash": "^0.6.3",
50
52
  "phone": "^3.1.67",
51
53
  "psdev-task-manager": "1.1.7",
package/pages/Profile.js CHANGED
@@ -52,16 +52,16 @@ async function profileOnReady({ $w: _$w }) {
52
52
  profileData.mainAddress
53
53
  );
54
54
  } else {
55
- collapseElements(['#locationContainer', '#location1Container', '#locationContainer2']);
55
+ deleteElements(['#locationContainer', '#location1Container', '#locationContainer2']);
56
56
  }
57
57
 
58
58
  setupAdditionalAddresses();
59
59
  }
60
60
 
61
61
  function setupAdditionalAddresses() {
62
- _$w('#moreAdressesRepeater').data = profileData.processedAddresses;
62
+ _$w('#moreAdressesRepeater').data = profileData.moreAddressesToDisplay;
63
63
 
64
- if (profileData.processedAddresses.length > 0) {
64
+ if (profileData.moreAddressesToDisplay.length > 0) {
65
65
  _$w('#moreLocationButton').expand();
66
66
  _$w('#addressTitle').collapse();
67
67
  }
@@ -98,7 +98,7 @@ async function profileOnReady({ $w: _$w }) {
98
98
  if (profileData.memberSince) {
99
99
  _$w('#sinceYearText').text = profileData.memberSince;
100
100
  } else {
101
- _$w('#memberSinceBox').collapse();
101
+ _$w('#memberSinceBox').delete();
102
102
  }
103
103
  }
104
104
 
@@ -106,7 +106,7 @@ async function profileOnReady({ $w: _$w }) {
106
106
  if (profileData.shouldHaveStudentBadge) {
107
107
  _$w('#studentContainer, #studentContainerMobile').expand();
108
108
  } else {
109
- _$w('#studentContainer, #studentContainerMobile').collapse();
109
+ _$w('#studentContainer, #studentContainerMobile').delete();
110
110
  }
111
111
  }
112
112
 
@@ -114,7 +114,7 @@ async function profileOnReady({ $w: _$w }) {
114
114
  if (profileData.logoImage) {
115
115
  _$w('#logoImage').src = profileData.logoImage;
116
116
  } else {
117
- _$w('#logoImage').collapse();
117
+ _$w('#logoImage').delete();
118
118
  }
119
119
 
120
120
  if (profileData.profileImage) {
@@ -131,7 +131,7 @@ async function profileOnReady({ $w: _$w }) {
131
131
  profileData.fullName
132
132
  );
133
133
  } else {
134
- collapseElements(['#fullNameText', '#fullNameText2', '#fullNameTextFoter']);
134
+ deleteElements(['#fullNameText', '#fullNameText2', '#fullNameTextFoter']);
135
135
  }
136
136
  }
137
137
 
@@ -149,7 +149,7 @@ async function profileOnReady({ $w: _$w }) {
149
149
  wixWindow.openLightbox(LIGHTBOX_NAMES.CONTACT_US, profileData)
150
150
  );
151
151
  } else {
152
- _$w('#contactButton').collapse();
152
+ _$w('#contactButton').delete();
153
153
  }
154
154
  }
155
155
 
@@ -157,7 +157,7 @@ async function profileOnReady({ $w: _$w }) {
157
157
  if (profileData.bookingUrl) {
158
158
  _$w('#bookNowButton').link = profileData.bookingUrl;
159
159
  } else {
160
- _$w('#bookNowButton').collapse();
160
+ _$w('#bookNowButton').delete();
161
161
  }
162
162
  }
163
163
 
@@ -172,7 +172,7 @@ async function profileOnReady({ $w: _$w }) {
172
172
  _$w('#phoneText').html = getPhoneHTML(_$w('#phoneText'));
173
173
  _$w('#phoneText2').html = getPhoneHTML(_$w('#phoneText2'));
174
174
  } else {
175
- collapseElements(['#phoneContainer', '#phoneContainer2']);
175
+ deleteElements(['#phoneContainer', '#phoneContainer2']);
176
176
  }
177
177
  }
178
178
 
@@ -180,7 +180,7 @@ async function profileOnReady({ $w: _$w }) {
180
180
  if (profileData.licenceNo) {
181
181
  _$w('#licenceNoText').text = profileData.licenceNo;
182
182
  } else {
183
- _$w('#licensesContainer').collapse();
183
+ _$w('#licensesContainer').delete();
184
184
  }
185
185
  }
186
186
 
@@ -194,7 +194,7 @@ async function profileOnReady({ $w: _$w }) {
194
194
  if (profileData.aboutService) {
195
195
  _$w('#aboutYouText').html = profileData.aboutService;
196
196
  } else {
197
- _$w('#aboutSection').collapse();
197
+ _$w('#aboutSection').delete();
198
198
  }
199
199
  }
200
200
 
@@ -203,7 +203,7 @@ async function profileOnReady({ $w: _$w }) {
203
203
  _$w('#businessName').text = profileData.businessName;
204
204
  _$w('#businessName').expand();
205
205
  } else {
206
- _$w('#businessName').collapse();
206
+ _$w('#businessName').delete();
207
207
  }
208
208
  }
209
209
 
@@ -213,13 +213,13 @@ async function profileOnReady({ $w: _$w }) {
213
213
  if (areasText) {
214
214
  _$w('#areaOfPracticesText').text = areasText;
215
215
  } else {
216
- _$w('#areaOfPracticesText').collapse();
216
+ _$w('#areaOfPracticesText').delete();
217
217
  }
218
218
 
219
219
  if (Array.isArray(profileData.areasOfPractices) && profileData.areasOfPractices.length > 0) {
220
220
  populateRepeater(profileData.areasOfPractices, '#areaOfPracticesRepeater', '#practiceText');
221
221
  } else {
222
- _$w('#servicesSection').collapse();
222
+ _$w('#servicesSection').delete();
223
223
  }
224
224
  }
225
225
 
@@ -229,16 +229,16 @@ async function profileOnReady({ $w: _$w }) {
229
229
  }
230
230
 
231
231
  if (!profileData.gallery?.length) {
232
- _$w('#gallerySection').collapse();
232
+ _$w('#gallerySection').delete();
233
233
  } else {
234
234
  _$w('#gallery').items = profileData.gallery;
235
- _$w('#gallerySection').expand();
235
+ _$w('#gallerySection').restore();
236
236
  }
237
237
  }
238
238
 
239
239
  function bindTestimonialsData() {
240
240
  if (!profileData.testimonials?.length) {
241
- _$w('#testimonialsSection').collapse();
241
+ _$w('#testimonialsSection').delete();
242
242
  }
243
243
  }
244
244
 
@@ -267,7 +267,7 @@ async function profileOnReady({ $w: _$w }) {
267
267
  setupTestimonialsPagination(profileData.testimonials);
268
268
  _$w('#testimonialsSection').expand();
269
269
  } else {
270
- _$w('#testimonialsSection').collapse();
270
+ _$w('#testimonialsSection').delete();
271
271
  }
272
272
  }
273
273
 
@@ -283,9 +283,9 @@ async function profileOnReady({ $w: _$w }) {
283
283
  });
284
284
  }
285
285
 
286
- function collapseElements(elementIds) {
286
+ function deleteElements(elementIds) {
287
287
  elementIds.forEach(id => {
288
- _$w(id).collapse();
288
+ _$w(id).delete();
289
289
  });
290
290
  }
291
291
 
@@ -1106,6 +1106,7 @@ async function personalDetailsOnReady({
1106
1106
  });
1107
1107
  _$w('#profileLink').text = newProfileLink;
1108
1108
  _$w('#profileLink').link = newProfileLink;
1109
+ _$w('#urlWebsiteText').text = newProfileLink;
1109
1110
 
1110
1111
  _$w(SLUG_FLAGS.VALID).collapse();
1111
1112
  _$w(SLUG_FLAGS.INVALID).collapse();
@@ -1858,8 +1859,15 @@ async function personalDetailsOnReady({
1858
1859
  itemMemberObj.toShowPhone = null;
1859
1860
  }
1860
1861
 
1862
+ if (itemMemberObj.phones) {
1863
+ itemMemberObj.phones = itemMemberObj.phones.filter(
1864
+ phone => phone !== phoneToRemove.phoneNumber
1865
+ );
1866
+ }
1867
+
1861
1868
  const updatedData = currentData.filter(item => item._id !== phoneId);
1862
1869
  renderPhonesList(updatedData);
1870
+ checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
1863
1871
  }
1864
1872
  }
1865
1873