abmp-npm 2.0.76 → 2.0.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/package.json +8 -1
  2. package/pages/Home.js +27 -55
  3. package/pages/index.js +0 -1
  4. package/public/Utils/personalDetailsUtils.js +5 -1
  5. package/public/Utils/sharedUtils.js +32 -0
  6. package/public/consts.js +0 -1
  7. package/.claude/worktrees/fix-save-button-disable/.husky/pre-commit +0 -19
  8. package/.claude/worktrees/fix-save-button-disable/.prettierignore +0 -7
  9. package/.claude/worktrees/fix-save-button-disable/.prettierrc.json +0 -16
  10. package/.claude/worktrees/fix-save-button-disable/README.md +0 -1
  11. package/.claude/worktrees/fix-save-button-disable/backend/README-member-contact-flows.md +0 -136
  12. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/daily-pull-execution-check.test.js +0 -124
  13. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/ensure-unique-urls-in-batch.test.js +0 -129
  14. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/login-email-sync.test.js +0 -49
  15. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/transient-retry-and-bulk-lookup.test.js +0 -129
  16. package/.claude/worktrees/fix-save-button-disable/backend/__tests__/url-uniqueness.test.js +0 -194
  17. package/.claude/worktrees/fix-save-button-disable/backend/automations-methods.js +0 -13
  18. package/.claude/worktrees/fix-save-button-disable/backend/cms-data-methods.js +0 -251
  19. package/.claude/worktrees/fix-save-button-disable/backend/consts.js +0 -58
  20. package/.claude/worktrees/fix-save-button-disable/backend/contacts-methods.js +0 -67
  21. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/bulk-process-methods.js +0 -222
  22. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/consts.js +0 -39
  23. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/index.js +0 -5
  24. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/process-member-methods.js +0 -213
  25. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/schedule-methods.js +0 -41
  26. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/sync-to-cms-methods.js +0 -161
  27. package/.claude/worktrees/fix-save-button-disable/backend/daily-pull/utils.js +0 -151
  28. package/.claude/worktrees/fix-save-button-disable/backend/data-hooks.js +0 -29
  29. package/.claude/worktrees/fix-save-button-disable/backend/dev-only-methods.js +0 -58
  30. package/.claude/worktrees/fix-save-button-disable/backend/elevated-modules.js +0 -18
  31. package/.claude/worktrees/fix-save-button-disable/backend/forms-methods.js +0 -52
  32. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/httpFunctions.js +0 -86
  33. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/index.js +0 -3
  34. package/.claude/worktrees/fix-save-button-disable/backend/http-functions/interests.js +0 -35
  35. package/.claude/worktrees/fix-save-button-disable/backend/index.js +0 -19
  36. package/.claude/worktrees/fix-save-button-disable/backend/jobs.js +0 -158
  37. package/.claude/worktrees/fix-save-button-disable/backend/login/generate-member-session-token.js +0 -27
  38. package/.claude/worktrees/fix-save-button-disable/backend/login/index.js +0 -8
  39. package/.claude/worktrees/fix-save-button-disable/backend/login/qa-login-methods.js +0 -54
  40. package/.claude/worktrees/fix-save-button-disable/backend/login/sso-methods.js +0 -159
  41. package/.claude/worktrees/fix-save-button-disable/backend/member-contact-orchestration.js +0 -111
  42. package/.claude/worktrees/fix-save-button-disable/backend/members-area-methods.js +0 -88
  43. package/.claude/worktrees/fix-save-button-disable/backend/members-data-methods.js +0 -789
  44. package/.claude/worktrees/fix-save-button-disable/backend/pac-api-methods.js +0 -54
  45. package/.claude/worktrees/fix-save-button-disable/backend/routers/index.js +0 -3
  46. package/.claude/worktrees/fix-save-button-disable/backend/routers/methods.js +0 -191
  47. package/.claude/worktrees/fix-save-button-disable/backend/routers/utils.js +0 -128
  48. package/.claude/worktrees/fix-save-button-disable/backend/search-filters-methods.js +0 -124
  49. package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-primary-methods.js +0 -256
  50. package/.claude/worktrees/fix-save-button-disable/backend/tasks/address-visibility-methods.js +0 -160
  51. package/.claude/worktrees/fix-save-button-disable/backend/tasks/consts.js +0 -34
  52. package/.claude/worktrees/fix-save-button-disable/backend/tasks/daily-pull-check-methods.js +0 -78
  53. package/.claude/worktrees/fix-save-button-disable/backend/tasks/email-normalize-methods.js +0 -134
  54. package/.claude/worktrees/fix-save-button-disable/backend/tasks/index.js +0 -10
  55. package/.claude/worktrees/fix-save-button-disable/backend/tasks/migration-methods.js +0 -46
  56. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-configs.js +0 -251
  57. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-helpers-methods.js +0 -433
  58. package/.claude/worktrees/fix-save-button-disable/backend/tasks/tasks-process-methods.js +0 -606
  59. package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-migration-methods.js +0 -378
  60. package/.claude/worktrees/fix-save-button-disable/backend/tasks/url-space-fix-methods.js +0 -174
  61. package/.claude/worktrees/fix-save-button-disable/backend/utils.js +0 -277
  62. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/extract-duplicate-url-groups.js +0 -201
  63. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-ids.js +0 -159
  64. package/.claude/worktrees/fix-save-button-disable/dev-only-scripts/find-duplicate-urls.js +0 -201
  65. package/.claude/worktrees/fix-save-button-disable/eslint.config.js +0 -120
  66. package/.claude/worktrees/fix-save-button-disable/index.js +0 -5
  67. package/.claude/worktrees/fix-save-button-disable/package-lock.json +0 -12160
  68. package/.claude/worktrees/fix-save-button-disable/package.json +0 -60
  69. package/.claude/worktrees/fix-save-button-disable/pages/ContactUs.js +0 -129
  70. package/.claude/worktrees/fix-save-button-disable/pages/Home.js +0 -779
  71. package/.claude/worktrees/fix-save-button-disable/pages/LearnMore.js +0 -27
  72. package/.claude/worktrees/fix-save-button-disable/pages/LoadingPage.js +0 -29
  73. package/.claude/worktrees/fix-save-button-disable/pages/Profile.js +0 -354
  74. package/.claude/worktrees/fix-save-button-disable/pages/QAPage.js +0 -39
  75. package/.claude/worktrees/fix-save-button-disable/pages/SaveAlerts.js +0 -13
  76. package/.claude/worktrees/fix-save-button-disable/pages/SelectBannerImages.js +0 -46
  77. package/.claude/worktrees/fix-save-button-disable/pages/deleteConfirm.js +0 -19
  78. package/.claude/worktrees/fix-save-button-disable/pages/index.js +0 -12
  79. package/.claude/worktrees/fix-save-button-disable/pages/personalDetails.js +0 -2486
  80. package/.claude/worktrees/fix-save-button-disable/public/Utils/homePage.js +0 -798
  81. package/.claude/worktrees/fix-save-button-disable/public/Utils/personalDetailsUtils.js +0 -25
  82. package/.claude/worktrees/fix-save-button-disable/public/Utils/sharedUtils.js +0 -235
  83. package/.claude/worktrees/fix-save-button-disable/public/consts.js +0 -113
  84. package/.claude/worktrees/fix-save-button-disable/public/index.js +0 -5
  85. package/.claude/worktrees/fix-save-button-disable/public/messages.js +0 -16
  86. package/.claude/worktrees/fix-save-button-disable/public/sso-auth-methods.js +0 -43
  87. package/.husky/pre-commit +0 -19
  88. package/.prettierignore +0 -7
  89. package/.prettierrc.json +0 -16
  90. package/backend/__tests__/daily-pull-execution-check.test.js +0 -124
  91. package/backend/__tests__/ensure-unique-urls-in-batch.test.js +0 -129
  92. package/backend/__tests__/login-email-sync.test.js +0 -49
  93. package/backend/__tests__/transient-retry-and-bulk-lookup.test.js +0 -129
  94. package/backend/__tests__/url-uniqueness.test.js +0 -194
  95. package/dev-only-scripts/extract-duplicate-url-groups.js +0 -201
  96. package/dev-only-scripts/find-duplicate-ids.js +0 -159
  97. package/dev-only-scripts/find-duplicate-urls.js +0 -201
  98. package/eslint.config.js +0 -120
  99. package/pages/contactForLocation.js +0 -28
@@ -1,798 +0,0 @@
1
- const { location: wixLocation, queryParams: wixQueryParams } = require('@wix/site-location');
2
- const { window: wixWindow, rendering } = require('@wix/site-window');
3
-
4
- const { DEFAULT_FILTER } = require('../consts.js');
5
-
6
- const { debouncedFunction } = require('./sharedUtils.js');
7
-
8
- function isValidGeolocation(lat, lng) {
9
- return Number.isFinite(lat) && Number.isFinite(lng) && (lat !== 0 || lng !== 0);
10
- }
11
-
12
- function applyGeolocationToFilter(filter, lat, lng, isSearchingNearby) {
13
- return {
14
- ...filter,
15
- postalcode: isSearchingNearby ? null : filter.postalcode,
16
- state: isSearchingNearby ? [] : filter.state,
17
- city: isSearchingNearby ? [] : filter.city,
18
- stateSearch: isSearchingNearby ? '' : filter.stateSearch,
19
- citySearch: isSearchingNearby ? '' : filter.citySearch,
20
- latitude: lat,
21
- longitude: lng,
22
- };
23
- }
24
-
25
- const GEOLOCATION_TIMEOUT_MS = 10000;
26
-
27
- function getCurrentGeolocationWithTimeout(timeoutMs = GEOLOCATION_TIMEOUT_MS) {
28
- return new Promise((resolve, reject) => {
29
- const timer = setTimeout(() => {
30
- reject(new Error(`Geolocation timed out after ${timeoutMs}ms`));
31
- }, timeoutMs);
32
- wixWindow
33
- .getCurrentGeolocation()
34
- .then(location => {
35
- clearTimeout(timer);
36
- resolve(location);
37
- })
38
- .catch(error => {
39
- clearTimeout(timer);
40
- reject(error);
41
- });
42
- });
43
- }
44
-
45
- const createHomepageUtils = (_$w, filterProfiles) => {
46
- const getFiltersSelectors = filterName => ({
47
- checkBoxContainerSelector: _$w(`#${filterName}CheckBoxContainer`),
48
- searchTextInputSelector: _$w(`#${filterName}TextInput`),
49
- clearSearchButtonSelector: _$w(`#${filterName}ClearButton`),
50
- toggleOptionListButtonSelector: _$w(`#${filterName}ToggleButton`),
51
- multiCheckBoxSelector: _$w(`#${filterName}CheckBox`),
52
- });
53
-
54
- const getParamsMapping = (filter, pagination) => ({
55
- page: {
56
- getValue: () => pagination.currentPage + 1,
57
- setValue: ({ value }) => {
58
- pagination.currentPage = parseInt(value) - 1;
59
- },
60
- },
61
- searchText: {
62
- getValue: () => filter.searchText,
63
- setValue: ({ value }) => {
64
- filter.searchText = value;
65
- _$w('#searchDesktop,#searchTabletMobile').value = value;
66
- },
67
- },
68
- state: {
69
- getValue: () => (filter.state?.length ? filter.state.join(',') : null),
70
- setValue: ({ value }) => {
71
- const states = value.split(',');
72
- filter['state'] = states;
73
- },
74
- setUI: async ({
75
- value,
76
- dropDownOptions,
77
- stateNameCodeMap,
78
- sidePanelFilterData,
79
- stateCityMap,
80
- }) => {
81
- const states = value.split(',');
82
- await onChangeMultiCheckbox({
83
- filterName: 'state',
84
- selectedOptions: states,
85
- dropDownOptions,
86
- filter,
87
- pagination,
88
- stateNameCodeMap,
89
- sidePanelFilterData,
90
- stateCityMap,
91
- });
92
- },
93
- },
94
- city: {
95
- getValue: () => (filter.city?.length ? filter.city.join(',') : null),
96
- setValue: ({ value }) => {
97
- const cities = value.split(',');
98
- filter['city'] = cities;
99
- },
100
- setUI: async ({
101
- value,
102
- dropDownOptions,
103
- stateNameCodeMap,
104
- sidePanelFilterData,
105
- stateCityMap,
106
- }) => {
107
- const cities = value.split(',');
108
- await onChangeMultiCheckbox({
109
- filterName: 'city',
110
- selectedOptions: cities,
111
- dropDownOptions,
112
- filter,
113
- pagination,
114
- stateNameCodeMap,
115
- sidePanelFilterData,
116
- stateCityMap,
117
- });
118
- },
119
- },
120
- practiceAreas: {
121
- getValue: () => (filter.practiceAreas?.length ? filter.practiceAreas.join(',') : null),
122
- setValue: ({ value }) => {
123
- const practices = value.split(',');
124
- filter['practiceAreas'] = practices;
125
- },
126
- setUI: async ({
127
- value,
128
- dropDownOptions,
129
- stateNameCodeMap,
130
- sidePanelFilterData,
131
- stateCityMap,
132
- }) => {
133
- const practices = value.split(',');
134
- await onChangeMultiCheckbox({
135
- filterName: 'practiceAreas',
136
- selectedOptions: practices,
137
- dropDownOptions,
138
- filter,
139
- pagination,
140
- stateNameCodeMap,
141
- sidePanelFilterData,
142
- stateCityMap,
143
- });
144
- },
145
- },
146
- zip: {
147
- getValue: () => filter.postalcode,
148
- setValue: ({ value }) => {
149
- filter.postalcode = value;
150
- _$w('#zipcode').value = value;
151
- },
152
- },
153
- nearby: {
154
- getValue: () => (_$w('#nearBy').checked ? 'true' : 'false'),
155
- setValue: ({ value }) => (_$w('#nearBy').checked = value === 'true'),
156
- },
157
- });
158
- async function handlePagination({ delta, pagination, searchResults, filter }) {
159
- const newPage = pagination.currentPage + delta;
160
- const maxPage = pagination.totalPages ? pagination.totalPages - 1 : 0;
161
- if (newPage < 0 || newPage > maxPage) return;
162
-
163
- newPage === 0 ? _$w('#previousPage').disable() : _$w('#previousPage').enable();
164
- newPage === maxPage ? _$w('#nextPage').disable() : _$w('#nextPage').enable();
165
- pagination.currentPage = newPage;
166
-
167
- paginateSearchResults(searchResults, pagination);
168
- await updateUrlParams(filter, pagination);
169
-
170
- _$w('#resultsStateBox').scrollTo();
171
- }
172
-
173
- async function onChangeMultiCheckbox({
174
- filterName,
175
- selectedOptions,
176
- dropDownOptions,
177
- filter,
178
- pagination,
179
- stateNameCodeMap,
180
- sidePanelFilterData,
181
- stateCityMap,
182
- isMobile = false,
183
- }) {
184
- const { searchTextInputSelector, clearSearchButtonSelector } = getFiltersSelectors(filterName);
185
- dropDownOptions[filterName].selectedOptions = selectedOptions;
186
-
187
- // Update display text based on selection
188
- dropDownOptions[filterName].displayText = displayTextValue({
189
- type: filterName,
190
- selectedOptions,
191
- totalLength: selectedOptions.length,
192
- stateNameCodeMap,
193
- });
194
-
195
- // Update searchTextInput to show selection summary
196
- searchTextInputSelector.value = dropDownOptions[filterName].displayText;
197
- filter[`${filterName}Search`] = '';
198
- // Show/hide clear button based on selection
199
- if (selectedOptions.length > 0) {
200
- clearSearchButtonSelector.expand();
201
- } else {
202
- clearSearchButtonSelector.collapse();
203
- }
204
-
205
- // Update filter object with selected values
206
- filter[filterName] = selectedOptions;
207
- filter.skip = 0;
208
-
209
- // Enable/disable city dropdown based on state selection
210
- if (filterName === 'state') {
211
- // update city selections based on state selection
212
- const { multiCheckBoxSelector, searchTextInputSelector: citySearchTextInputSelector } =
213
- getFiltersSelectors('city');
214
-
215
- const citySelectedOptions = multiCheckBoxSelector.selectedIndices;
216
- if (citySelectedOptions && citySelectedOptions.length > 0) {
217
- // get all city options for the selected state
218
- const options = prepareOptionsFunction({
219
- filterName: 'city',
220
- sidePanelFilterData,
221
- stateCityMap,
222
- filter,
223
- });
224
- // filter out options that are not in the selected state
225
- const filteredOptions =
226
- multiCheckBoxSelector.selectedIndices.filter(index =>
227
- options.some(o => o.value == multiCheckBoxSelector.options[index].value)
228
- ) || [];
229
- const filteredOptionsTexts = filteredOptions.map(
230
- index => multiCheckBoxSelector.options[index].label
231
- );
232
- // update city dropdown with filtered options
233
- if (filteredOptions.length > 0) {
234
- multiCheckBoxSelector.selectedIndices = filteredOptions;
235
- citySearchTextInputSelector.value = displayTextValue({
236
- type: 'city',
237
- selectedOptions: filteredOptionsTexts,
238
- totalLength: filteredOptionsTexts.length,
239
- stateNameCodeMap,
240
- });
241
- } else {
242
- // if no city options are selected, set default city
243
- setDefaultCity({
244
- filter,
245
- dropDownOptions,
246
- sidePanelFilterData,
247
- stateCityMap,
248
- });
249
- }
250
- }
251
-
252
- if (selectedOptions && selectedOptions.length > 0 && !_$w('#nearBy').checked) {
253
- _$w('#cityTextInput').enable();
254
- } else {
255
- _$w('#cityTextInput').disable();
256
- setDefaultCity({
257
- filter,
258
- dropDownOptions,
259
- sidePanelFilterData,
260
- stateCityMap,
261
- });
262
- }
263
- }
264
-
265
- if (!isMobile) {
266
- await updateUrlParams(filter, pagination);
267
- }
268
- }
269
-
270
- function displayTextValue({ type, selectedOptions, totalLength, stateNameCodeMap }) {
271
- if (totalLength === 0) {
272
- return '';
273
- }
274
- let displayText = '';
275
- if (type === 'state') {
276
- displayText =
277
- totalLength === 1 ? stateNameCodeMap.get(selectedOptions[0]) : `${totalLength} selected`;
278
- } else {
279
- displayText = totalLength === 1 ? selectedOptions[0] : `${totalLength} selected`;
280
- }
281
- return displayText;
282
- }
283
-
284
- function setDefaultCity({ filter, dropDownOptions, sidePanelFilterData, stateCityMap }) {
285
- _$w('#cityTextInput').value = '';
286
- _$w('#cityTextInput').disable();
287
- setDefaultState({
288
- filterName: 'city',
289
- withSelectedOptions: false,
290
- filter,
291
- dropDownOptions,
292
- sidePanelFilterData,
293
- stateCityMap,
294
- });
295
- }
296
-
297
- function setDefaultState({
298
- filterName,
299
- withSelectedOptions,
300
- filter,
301
- dropDownOptions,
302
- sidePanelFilterData,
303
- stateCityMap,
304
- }) {
305
- const { checkBoxContainerSelector, clearSearchButtonSelector } =
306
- getFiltersSelectors(filterName);
307
- setDefaultFilterOption({
308
- filterName,
309
- withSelectedOptions,
310
- dropDownOptions,
311
- filter,
312
- sidePanelFilterData,
313
- stateCityMap,
314
- });
315
- if (!withSelectedOptions) {
316
- filter[filterName] = [];
317
- }
318
- filter[`${filterName}Search`] = '';
319
- clearSearchButtonSelector.collapse();
320
- checkBoxContainerSelector.collapse();
321
- }
322
-
323
- function setDefaultFilterOption({
324
- filterName,
325
- withSelectedOptions = false,
326
- dropDownOptions,
327
- filter,
328
- sidePanelFilterData,
329
- stateCityMap,
330
- }) {
331
- const { multiCheckBoxSelector } = getFiltersSelectors(filterName);
332
- multiCheckBoxSelector.options = prepareOptionsFunction({
333
- filterName,
334
- sidePanelFilterData,
335
- stateCityMap,
336
- filter,
337
- });
338
- if (withSelectedOptions) {
339
- multiCheckBoxSelector.value = dropDownOptions[filterName].selectedOptions;
340
- } else {
341
- multiCheckBoxSelector.value = [];
342
- dropDownOptions[filterName].selectedOptions = [];
343
- dropDownOptions[filterName].displayText = undefined;
344
- filter[filterName] = [];
345
- }
346
- }
347
-
348
- function prepareOptionsFunction({ filterName, sidePanelFilterData, stateCityMap, filter }) {
349
- let options = [];
350
-
351
- if (filterName === 'state' || filterName === 'practiceAreas') {
352
- options =
353
- sidePanelFilterData.has(filterName) && sidePanelFilterData.get(filterName).length > 0
354
- ? sidePanelFilterData.get(filterName)
355
- : [];
356
-
357
- options.sort((a, b) => a.label.localeCompare(b.label));
358
- return options;
359
- }
360
-
361
- if (filterName === 'city' && filter.state.length > 0) {
362
- filter.state.forEach(state => {
363
- const cityArr = stateCityMap.get(state);
364
- if (!cityArr || cityArr.length === 0) return;
365
- cityArr.forEach(city => options.push({ label: city, value: city }));
366
- });
367
-
368
- // Sort cities alphabetically
369
- options.sort((a, b) => a.label.localeCompare(b.label));
370
- }
371
-
372
- return options;
373
- }
374
-
375
- function handleNumberOfResults(pagination, totalCount) {
376
- const startResult = pagination.currentPage * pagination.pageSize + 1;
377
- const endResult = Math.min((pagination.currentPage + 1) * pagination.pageSize, totalCount);
378
- _$w('#numberOfResults').text = `Showing ${startResult} - ${endResult} of ${totalCount} results`;
379
- }
380
-
381
- /**
382
- * TOGGLES BETWEEN FILTERS BASED ON THE SCREEN SIZE
383
- */
384
-
385
- function showFiltersOnDesktop() {
386
- wixWindow
387
- .getBoundingRect()
388
- .then(windowRect => {
389
- if (windowRect.window.width > 1300) {
390
- // Expand the container if the screen is wider than 1300px
391
- _$w('#filtersContainer').expand();
392
- } else {
393
- // Collapse the container if the screen is 1300px or less
394
- _$w('#filtersContainer').collapse();
395
- }
396
- })
397
- .catch(err => {
398
- console.error('Error getting window dimensions:', err);
399
- });
400
- }
401
- async function getAndSetUserLocation(isSearchingNearby, filter) {
402
- const { latitude: existingLat, longitude: existingLng } = filter;
403
- if (isValidGeolocation(existingLat, existingLng)) {
404
- return {
405
- success: true,
406
- filter: applyGeolocationToFilter(filter, existingLat, existingLng, isSearchingNearby),
407
- };
408
- }
409
-
410
- try {
411
- const location = await getCurrentGeolocationWithTimeout();
412
-
413
- console.log('location inside getAndSetUserLocation', location);
414
- const userLat = location.coords?.latitude ?? 0;
415
- const userLong = location.coords?.longitude ?? 0;
416
- return {
417
- success: true,
418
- filter: applyGeolocationToFilter(filter, userLat, userLong, isSearchingNearby),
419
- };
420
- } catch (error) {
421
- console.warn('Failed to get user location in getAndSetUserLocation', error);
422
- return { success: false, filter };
423
- }
424
- }
425
- function setDefaultDropdownState(filterName, filter) {
426
- filter[filterName] = [];
427
-
428
- // Hide clear search button ("x")
429
-
430
- const clearSearchButtonSelector = _$w(`#${filterName}ClearButton`);
431
-
432
- clearSearchButtonSelector.collapse();
433
-
434
- // Clear the text present on text input bar
435
-
436
- const searchTextInputSelector = _$w(`#${filterName}TextInput`);
437
-
438
- searchTextInputSelector.value = undefined;
439
-
440
- // Make dropdown options and selected as empty
441
-
442
- const multiCheckBoxSelector = _$w(`#${filterName}CheckBox`);
443
-
444
- multiCheckBoxSelector.options = [];
445
-
446
- multiCheckBoxSelector.value = [];
447
-
448
- // If dropdown drawer is open close it
449
-
450
- const checkBoxContainerSelector = _$w(`#${filterName}CheckBoxContainer`);
451
-
452
- checkBoxContainerSelector.collapse();
453
- }
454
-
455
- function toggleDropdownFunctionality(filterName, enable) {
456
- // If disable then hide clear search button ("x")
457
-
458
- const clearSearchButtonSelector = _$w(`#${filterName}ClearButton`);
459
-
460
- !enable && clearSearchButtonSelector.collapse();
461
-
462
- enable && clearSearchButtonSelector.enable();
463
-
464
- // Toggle functionality based on the enable flag
465
-
466
- const searchTextInputSelector = _$w(`#${filterName}TextInput`);
467
-
468
- enable ? searchTextInputSelector.enable() : searchTextInputSelector.disable();
469
-
470
- // Toggle functionality of dropdown options based on the enable flag
471
-
472
- const multiCheckBoxSelector = _$w(`#${filterName}CheckBox`);
473
-
474
- enable ? multiCheckBoxSelector.enable() : multiCheckBoxSelector.disable();
475
-
476
- // If disable close dropdown drawer
477
-
478
- const checkBoxContainerSelector = _$w(`#${filterName}CheckBoxContainer`);
479
-
480
- !enable && checkBoxContainerSelector.collapse();
481
- }
482
-
483
- function updatePaginationUI(pagination) {
484
- const { currentPage, totalPages } = pagination;
485
- const noOfPages = totalPages <= 10 ? totalPages : 10;
486
- for (let i = 0; i < 10; i++) {
487
- const pageNumber = i + 1;
488
- const currentPageButtonIterator = _$w(`#pageButton${pageNumber}`);
489
- if (i < noOfPages) {
490
- currentPageButtonIterator.expand();
491
- currentPageButtonIterator.label = `${pageNumber}`;
492
-
493
- // Style the current page button
494
- if (pageNumber === currentPage + 1) {
495
- currentPageButtonIterator.disable();
496
- } else {
497
- currentPageButtonIterator.enable();
498
- }
499
- } else {
500
- currentPageButtonIterator.collapse();
501
- }
502
- }
503
- if (totalPages === 0 || totalPages === 1) {
504
- _$w('#previousPage').disable();
505
- _$w('#nextPage').disable();
506
- return;
507
- }
508
- if (currentPage === 0) {
509
- _$w('#previousPage').disable();
510
- } else {
511
- _$w('#previousPage').enable();
512
- }
513
- if (currentPage >= totalPages - 1) {
514
- _$w('#nextPage').disable();
515
- } else {
516
- _$w('#nextPage').enable();
517
- }
518
- }
519
- function paginateSearchResults(searchResults, pagination) {
520
- updatePaginationUI(pagination);
521
- handleNumberOfResults(pagination, searchResults.length);
522
- const currentPageData = searchResults.slice(
523
- pagination.currentPage * pagination.pageSize,
524
- (pagination.currentPage + 1) * pagination.pageSize
525
- );
526
- _$w('#profileRepeater').data = currentPageData;
527
- }
528
-
529
- // BASED ON DROPDOWN SEARCH TEXT FILTER DROPDOWN OPTIONS
530
-
531
- function filterOptionsFunction(filterName, cachedOptions, searchText) {
532
- return cachedOptions.filter(
533
- option =>
534
- option.label.toLowerCase().includes(searchText.toLowerCase()) ||
535
- (filterName === 'state' && option.value.includes(searchText))
536
- );
537
- }
538
- async function parseAndValidateQueryParams(filter, pagination) {
539
- const params = await wixLocation.query();
540
- const paramsMapping = getParamsMapping(filter, pagination);
541
- const {
542
- siteRevision: _siteRevision,
543
- branchId: _branchId,
544
- ssrOnly: _ssrOnly,
545
- ...withoutPreviewParams
546
- } = params || {};
547
- const isSearchingNearby = params.nearby === 'true';
548
- const isNoParams = !withoutPreviewParams || Object.keys(withoutPreviewParams).length === 0;
549
- const { success, filter: newFilter } = await getAndSetUserLocation(isSearchingNearby, filter);
550
-
551
- // Auto-enable nearby if GPS permission granted on fresh page load
552
- if (
553
- isNoParams &&
554
- success &&
555
- newFilter.latitude !== 0 &&
556
- newFilter.longitude !== 0 &&
557
- !isSearchingNearby
558
- ) {
559
- await wixQueryParams.add({ nearby: 'true', page: '1' });
560
- return { isDefaultStateParams: true, filter: newFilter };
561
- }
562
-
563
- if (isNoParams) {
564
- // search({
565
- // filter,
566
- // pagination,
567
- // debounceTimeout: 0,
568
- // timeoutType: 'search',
569
- // isSearchingNearby: false,
570
- // });
571
- // Don't search yet - let the caller decide what to do
572
- // The search will be handled in applyFilterToUI
573
- return { isDefaultStateParams: true, filter: newFilter };
574
- }
575
- let autoAdjustFilters = false;
576
- const validatePageValue = value => {
577
- if (!value || isNaN(Number(value)) || Number(value) < 1 || Number(value) > 10) {
578
- return { valid: false, value: '1' };
579
- } else {
580
- return { valid: true, value: value.toString() };
581
- }
582
- };
583
- const pageValidationResult = validatePageValue(params.page);
584
- if (!pageValidationResult.valid) {
585
- paramsMapping.page.setValue({ value: pageValidationResult.value });
586
- autoAdjustFilters = true;
587
- }
588
- if (isSearchingNearby) {
589
- //if nearby is true only city,state,zip should be reset, others should be preserved and taken from query params
590
- const paramsToPreserve = ['practiceAreas', 'searchText', 'page'];
591
- paramsToPreserve.forEach(paramName => {
592
- if (params[paramName]) {
593
- let value = params[paramName];
594
- if (paramName === 'page') {
595
- value = pageValidationResult.value;
596
- }
597
- paramsMapping[paramName].setValue({ value });
598
- }
599
- });
600
- paramsMapping.nearby.setValue({ value: 'true' });
601
- autoAdjustFilters = true;
602
- }
603
- if (autoAdjustFilters) {
604
- await updateUrlParams(filter, pagination);
605
- }
606
- const isNearbyFilter =
607
- (Object.keys(withoutPreviewParams).length === 2 &&
608
- withoutPreviewParams.nearby &&
609
- withoutPreviewParams.page) ||
610
- (Object.keys(withoutPreviewParams).length === 1 && withoutPreviewParams.nearby);
611
- const isDefaultStateParams = isNoParams || isNearbyFilter;
612
- return { isDefaultStateParams, filter: newFilter };
613
- }
614
-
615
- async function updateUrlQuery(filters, defaultFilters) {
616
- const queryParams = {};
617
-
618
- for (const key in filters) {
619
- const val = filters[key];
620
- const defaultVal = defaultFilters[key];
621
-
622
- // Only include non-default values in URL
623
- if (JSON.stringify(val) !== JSON.stringify(defaultVal)) {
624
- queryParams[key] = Array.isArray(val) ? JSON.stringify(val) : val;
625
- }
626
- }
627
-
628
- await wixQueryParams.add(queryParams);
629
- }
630
-
631
- async function updateUrlParams(filter, pagination) {
632
- const paramsMapping = getParamsMapping(filter, pagination);
633
- // Get current query parameters
634
- const currentParams = await wixLocation.query();
635
- // Remove all existing parameters that we manage
636
- Object.keys(paramsMapping).forEach(async param => {
637
- if (currentParams[param]) {
638
- await wixQueryParams.remove([param]);
639
- }
640
- });
641
-
642
- // Add new parameters only if they have values
643
- let addedParams = 0;
644
- Object.entries(paramsMapping).forEach(async ([param, { getValue }]) => {
645
- const value = getValue();
646
- if (param !== 'page') {
647
- if (value !== null && value !== undefined && value !== '') {
648
- addedParams++;
649
- await wixQueryParams.add({ [param]: value.toString() });
650
- }
651
- }
652
- });
653
- if (addedParams === 1) {
654
- // Only add page URL parameter, if nearby is true when there's exactly one filter
655
- if (paramsMapping.nearby.getValue() === 'true') {
656
- await wixQueryParams.add({
657
- page: paramsMapping.page.getValue().toString(),
658
- });
659
- }
660
- } else if (addedParams > 1) {
661
- // Always add page when there are multiple filters
662
- await wixQueryParams.add({
663
- page: paramsMapping.page.getValue().toString(),
664
- });
665
- }
666
- }
667
-
668
- async function noSearchCriteria() {
669
- const params = await wixLocation.query();
670
- const {
671
- siteRevision: _siteRevision,
672
- branchId: _branchId,
673
- ...withoutPreviewParams
674
- } = params || {};
675
- const isNoParams = !withoutPreviewParams || Object.keys(withoutPreviewParams).length === 0;
676
-
677
- // Also consider it as no search criteria if only nearby=false exists
678
- const onlyNearbyFalse =
679
- Object.keys(withoutPreviewParams).length === 1 && withoutPreviewParams.nearby === 'false';
680
-
681
- return isNoParams || onlyNearbyFalse;
682
- }
683
-
684
- /**
685
- * UPDATE PROFILES BASED ON APPLIED/DEFAULT FILTER
686
- */
687
- async function search({
688
- filter,
689
- pagination,
690
- debounceTimeout,
691
- timeoutType,
692
- isSearchingNearby,
693
- preservePagination = false,
694
- }) {
695
- const multiStateBoxSelector = _$w('#resultsStateBox');
696
- const renderingEnv = await rendering.env();
697
- const initSearchResultsUI = () => {
698
- JSON.stringify(filter) === JSON.stringify(DEFAULT_FILTER)
699
- ? _$w('#resetFilter').hide()
700
- : _$w('#resetFilter').show();
701
- _$w('#showingResult').hide();
702
- multiStateBoxSelector.changeState('loadingState');
703
- _$w('#showingResult').hide();
704
- _$w('#profileRepeater').data = [];
705
- console.log({ filter });
706
- };
707
- const runSearchAndUpdateUI = async (filter, isSearchingNearby) => {
708
- if (!isSearchingNearby) {
709
- if (
710
- JSON.stringify({
711
- ...filter,
712
- latitude: 0,
713
- longitude: 0,
714
- }) === JSON.stringify(DEFAULT_FILTER)
715
- ) {
716
- multiStateBoxSelector.changeState('noSearchCriteria');
717
- return [];
718
- }
719
- }
720
- const nonDebouncedFilterProfiles = async () => {
721
- try {
722
- const result = await filterProfiles({ filter, isSearchingNearby });
723
- return { success: true, response: result };
724
- } catch (error) {
725
- return { success: false, error };
726
- }
727
- };
728
- //Don't run setTimeout on SSR
729
- const funcPromise =
730
- renderingEnv === 'backend'
731
- ? () => nonDebouncedFilterProfiles()
732
- : () =>
733
- debouncedFunction({
734
- func: filterProfiles,
735
- debounceTimeout,
736
- timeoutType,
737
- args: { filter, isSearchingNearby },
738
- });
739
- const { success, response, error } = await funcPromise();
740
- if (!success) {
741
- _$w('#numberOfResults').text = '';
742
- console.error('[search] failed with error:', error);
743
- multiStateBoxSelector.changeState('errorState');
744
- return [];
745
- }
746
- const totalCount = response.items.length;
747
- if (!totalCount) {
748
- _$w('#numberOfResults').text = 'Showing 0 results';
749
- _$w('#noResultsMessage').text = `${
750
- filter.searchText && filter.searchText.length > 0
751
- ? `'${filter.searchText}' did not match any search. Please try again.`
752
- : 'No results found for the selected filters. Please adjust your filters and try again'
753
- }`;
754
- multiStateBoxSelector.changeState('noResultsState');
755
- return [];
756
- }
757
- console.log({ response });
758
- handleNumberOfResults(pagination, totalCount);
759
- _$w('#showingResult').show();
760
-
761
- if (!preservePagination || pagination.currentPage >= pagination.totalPages) {
762
- pagination.currentPage = 0;
763
- }
764
- pagination.totalPages = Math.ceil(totalCount / pagination.pageSize);
765
- paginateSearchResults(response.items, pagination);
766
- multiStateBoxSelector.changeState('resultsState');
767
- return response.items;
768
- };
769
- initSearchResultsUI();
770
- return await runSearchAndUpdateUI(filter, isSearchingNearby);
771
- }
772
-
773
- return {
774
- getFiltersSelectors,
775
- getParamsMapping,
776
- handlePagination,
777
- onChangeMultiCheckbox,
778
- setDefaultCity,
779
- setDefaultState,
780
- setDefaultFilterOption,
781
- prepareOptionsFunction,
782
- handleNumberOfResults,
783
- getAndSetUserLocation,
784
- setDefaultDropdownState,
785
- toggleDropdownFunctionality,
786
- paginateSearchResults,
787
- showFiltersOnDesktop,
788
- filterOptionsFunction,
789
- parseAndValidateQueryParams,
790
- updateUrlQuery,
791
- updateUrlParams,
792
- noSearchCriteria,
793
- search,
794
- };
795
- };
796
- module.exports = {
797
- createHomepageUtils,
798
- };