abmp-npm 1.8.0 → 1.8.2

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/pages/Home.js ADDED
@@ -0,0 +1,763 @@
1
+ //home page code
2
+ const { location: wixLocation } = require('@wix/site-location');
3
+ const { window: wixWindow, rendering } = require('@wix/site-window');
4
+ const { withWarmUpData } = require('psdev-utils/frontend');
5
+
6
+ const { ADDRESS_STATUS_TYPES, DEFAULT_FILTER, DROPDOWN_OPTIONS } = require('../public/consts.js');
7
+ const { createHomepageUtils } = require('../public/Utils/homePage.js');
8
+ const {
9
+ getMainAddress,
10
+ formatPracticeAreasForDisplay,
11
+ checkAddressIsVisible,
12
+ } = require('../public/Utils/sharedUtils.js');
13
+
14
+ let filter = JSON.parse(JSON.stringify(DEFAULT_FILTER));
15
+ let dropDownOptions = JSON.parse(JSON.stringify(DROPDOWN_OPTIONS));
16
+ let stateCityMap;
17
+ let retryAttempts = 0;
18
+ const sidePanelFilterData = new Map();
19
+ const stateNameCodeMap = new Map();
20
+ let multiStateBoxSelector;
21
+ // Debounce variables
22
+ const debounceTimeout = {};
23
+ // Pagination variables
24
+ const pagination = {
25
+ pageSize: 12,
26
+ currentPage: 0,
27
+ };
28
+ let searchResults = [];
29
+ let isMobile = false;
30
+
31
+ const homePageOnReady = async ({
32
+ _$w,
33
+ getCompiledFiltersOptions,
34
+ getNonCompiledFiltersOptions,
35
+ filterProfiles,
36
+ }) => {
37
+ const {
38
+ getParamsMapping,
39
+ handlePagination,
40
+ getFiltersSelectors,
41
+ onChangeMultiCheckbox,
42
+ setDefaultCity,
43
+ setDefaultState,
44
+ setDefaultFilterOption,
45
+ prepareOptionsFunction,
46
+ getAndSetUserLocation,
47
+ setDefaultDropdownState,
48
+ toggleDropdownFunctionality,
49
+ showFiltersOnDesktop,
50
+ filterOptionsFunction,
51
+ parseAndValidateQueryParams,
52
+ updateUrlParams,
53
+ noSearchCriteria,
54
+ search,
55
+ } = createHomepageUtils(_$w, filterProfiles);
56
+ detectMobile();
57
+ initPageUI();
58
+ attachEventListeners();
59
+ await handleUrlParams();
60
+
61
+ async function detectMobile() {
62
+ try {
63
+ const formFactor = await wixWindow.formFactor();
64
+ isMobile = formFactor === 'Mobile';
65
+ } catch (error) {
66
+ isMobile = false;
67
+ console.log('Mobile detection error, assuming desktop:', error);
68
+ }
69
+ }
70
+
71
+ function initPageUI() {
72
+ multiStateBoxSelector = _$w('#resultsStateBox');
73
+ multiStateBoxSelector.changeState('loadingState');
74
+ _$w('#searchDesktop').expand();
75
+ _$w('#showingResult').expand();
76
+ showFiltersOnDesktop();
77
+ }
78
+
79
+ async function attachEventListeners() {
80
+ /**
81
+ * PAGINATION CODE
82
+ */
83
+ _$w('#previousPage').onClick(() => {
84
+ handlePagination({ delta: -1, pagination, searchResults, filter });
85
+ });
86
+
87
+ _$w('#nextPage').onClick(() => {
88
+ handlePagination({ delta: 1, pagination, searchResults, filter });
89
+ });
90
+
91
+ _$w(
92
+ '#pageButton1,#pageButton2,#pageButton3,#pageButton4,#pageButton5,#pageButton6,#pageButton7,#pageButton8,#pageButton9,#pageButton10,#pageButton11,#pageButton12,#pageButton13,#pageButton14,#pageButton15'
93
+ ).onClick(event => {
94
+ const label = event.target.label;
95
+ const pageNumber = Number(label) - 1;
96
+ if (pageNumber === pagination.currentPage) return;
97
+ handlePagination({
98
+ delta:
99
+ pageNumber > pagination.currentPage
100
+ ? pageNumber - pagination.currentPage
101
+ : (pagination.currentPage - pageNumber) * -1,
102
+ pagination,
103
+ searchResults,
104
+ filter,
105
+ });
106
+ });
107
+ _$w('#resetFilter').onClick(resetFilter);
108
+ _$w('#clearButton').onClick(resetFilter);
109
+
110
+ _$w('#searchDesktop').onInput(event => searchProfilesOnSearchText(event));
111
+ _$w('#searchTabletMobile').onInput(event => searchProfilesOnSearchText(event));
112
+ // Use onChange for the switch and onClick for the retry button
113
+ _$w('#nearBy').onChange(() => {
114
+ updateFiltersState();
115
+ if (isMobile) {
116
+ return;
117
+ }
118
+ nearByHandler();
119
+ });
120
+
121
+ _$w('#nearByRetryButton').onClick(() => {
122
+ nearByHandler();
123
+ });
124
+
125
+ // ZIP CODE FILTER
126
+ _$w('#zipcode').onInput(async event => {
127
+ const zipcode = event.target.value.trim();
128
+ zipcode === '' ? (filter.postalcode = null) : (filter.postalcode = zipcode);
129
+ updateFiltersState();
130
+
131
+ if (isMobile) {
132
+ return;
133
+ }
134
+
135
+ await updateResults('filterTimeout');
136
+ });
137
+
138
+ _$w('#filterButton').onClick(() => {
139
+ _$w('#filtersContainer').expand();
140
+ _$w('#filtersContainer').scrollTo();
141
+ });
142
+
143
+ _$w('#closeFiltersButton').onClick(() => _$w('#filtersContainer').collapse());
144
+ _$w('#applyButton').onClick(async () => {
145
+ _$w('#filtersContainer').collapse();
146
+
147
+ // Update URL params with current filter state before searching
148
+ updateFiltersState();
149
+ await updateUrlParams(filter, pagination);
150
+ await updateResults('zeroTimeout');
151
+ });
152
+
153
+ // Retry
154
+
155
+ _$w('#retryButton').onClick(async () => {
156
+ if (retryAttempts > 1) {
157
+ resetFilter();
158
+
159
+ return;
160
+ }
161
+
162
+ retryAttempts += 1;
163
+
164
+ await updateResults('zeroTimeout');
165
+ });
166
+
167
+ _$w('#clearSearch').onClick(async () => {
168
+ if (!filter.searchText || filter.searchText.length === 0) {
169
+ await resetFilter();
170
+
171
+ return;
172
+ }
173
+
174
+ filter.searchText = null;
175
+
176
+ _$w('#searchDesktop').value = undefined;
177
+ _$w('#searchTabletMobile').value = undefined;
178
+
179
+ await updateResults('zeroTimeout');
180
+ });
181
+ const baseUrl = await wixLocation.baseUrl();
182
+ _$w('#profileRepeater').onItemReady(($item, itemData) => {
183
+ // 1) safely default to arrays
184
+ const addresses = Array.isArray(itemData.addresses) ? itemData.addresses : [];
185
+ const areasOfPractices = Array.isArray(itemData.areasOfPractices)
186
+ ? itemData.areasOfPractices
187
+ : [];
188
+
189
+ // 2) Profile image
190
+ if (itemData.profileImage) {
191
+ $item('#profileImage').src = itemData.profileImage;
192
+ }
193
+
194
+ // 3) Website link
195
+ if (!itemData.showWixUrl && !itemData.showWebsite) {
196
+ $item('#website').collapse();
197
+ $item('#websiteContainer').collapse();
198
+ } else {
199
+ if (itemData.showWebsite) {
200
+ $item('#website').link = itemData.website;
201
+ } else {
202
+ $item('#website').link = `${baseUrl}/profile/${itemData.url}`;
203
+ }
204
+ $item('#website').target = '_blank';
205
+ }
206
+
207
+ // 4) Full name
208
+ $item('#fullName').text = itemData.fullName || '';
209
+
210
+ // 5) Location text
211
+ const mainAddress = getMainAddress(itemData.addressDisplayOption, addresses);
212
+ $item('#location').text = mainAddress || '';
213
+ const miles = itemData.distance ?? 0;
214
+ $item('#differenceInMiles').text = miles ? miles.toFixed(1) : '';
215
+ if (!miles) {
216
+ $item('#milesAwayText').text = '';
217
+ }
218
+
219
+ // 7) "Show maps" button enabled only if there's at least one visible address
220
+ const visible = checkAddressIsVisible(addresses);
221
+ if (visible.length && visible[0].addressStatus === ADDRESS_STATUS_TYPES.FULL_ADDRESS) {
222
+ $item('#showMaps').enable();
223
+ $item('#showMaps').show();
224
+ const { latitude, longitude } = visible[0];
225
+ $item('#showMaps').link = `https://maps.google.com/?q=${latitude},${longitude}`;
226
+ $item('#showMaps').target = '_blank';
227
+ } else {
228
+ $item('#showMaps').hide();
229
+ }
230
+
231
+ // 8) Phone / contact form
232
+ if (itemData.showContactForm) {
233
+ $item('#call').expand();
234
+ $item('#callContainer').expand();
235
+ $item('#call').onClick(() => wixWindow.openLightbox('Contact Us', itemData));
236
+ } else {
237
+ $item('#call').collapse();
238
+ $item('#callContainer').collapse();
239
+ }
240
+
241
+ // 9) "Book now" button
242
+ if (itemData.bookingUrl) {
243
+ $item('#bookNowButton').show();
244
+ $item('#bookNowButton').link = itemData.bookingUrl;
245
+ $item('#bookNowButton').target = '_blank';
246
+ } else {
247
+ $item('#bookNowButton').hide();
248
+ }
249
+
250
+ // 10) Area of practices text
251
+ const text = formatPracticeAreasForDisplay(areasOfPractices);
252
+ if (text) {
253
+ $item('#areaOfPracticesText').text = text;
254
+ } else {
255
+ $item('#areaOfPracticesText').collapse();
256
+ }
257
+
258
+ // 11) Hide separator if neither website nor call is shown
259
+ if ($item('#website').collapsed && $item('#call').collapsed) {
260
+ $item('#line').hide();
261
+ }
262
+ });
263
+ }
264
+
265
+ async function handleUrlParams() {
266
+ const { isDefaultStateParams, filter: newFilter } = await parseAndValidateQueryParams(
267
+ filter,
268
+ pagination
269
+ );
270
+ filter = newFilter;
271
+ await applyFilterToUI(isDefaultStateParams);
272
+ }
273
+
274
+ async function applyFilterToUI(isDefaultStateParams) {
275
+ const renderingEnv = await rendering.env();
276
+ const setFilterFromParams = async (isInitializeValue = true) => {
277
+ const params = await wixLocation.query();
278
+ console.log('params inside setFilterFromParams ', params);
279
+ const paramsMapping = getParamsMapping(filter, pagination);
280
+ for (const [param, { setValue, setUI }] of Object.entries(paramsMapping)) {
281
+ const value = params[param];
282
+ if (value !== undefined && value !== null && value !== '') {
283
+ try {
284
+ if (isInitializeValue) {
285
+ console.log('setting value ', value, ' for param ', param);
286
+ setValue({
287
+ value: String(value),
288
+ });
289
+ } else {
290
+ console.log('setting ui value ', value, ' for param ', param);
291
+ setUI &&
292
+ (await setUI({
293
+ value: String(value),
294
+ dropDownOptions,
295
+ stateNameCodeMap,
296
+ sidePanelFilterData,
297
+ stateCityMap,
298
+ }));
299
+ }
300
+ } catch (error) {
301
+ console.error(`Error setting parameter ${param}:`, error);
302
+ }
303
+ }
304
+ }
305
+ };
306
+ await setFilterFromParams(true);
307
+ if (isDefaultStateParams) {
308
+ console.log('default state set for nearby');
309
+ await Promise.all([fetchFilterData(), nearByHandler(true)]);
310
+ return;
311
+ }
312
+ console.log('not default state');
313
+ const searchPromise =
314
+ filter.searchText && filter.searchText.length > 0
315
+ ? () =>
316
+ search({
317
+ filter,
318
+ pagination,
319
+ debounceTimeout,
320
+ timeoutType: 'searchTimeout',
321
+ isSearchingNearby: _$w('#nearBy').checked,
322
+ }).then(result => {
323
+ searchResults = result;
324
+ })
325
+ : () => updateResults('filterTimeout', true);
326
+ console.log('filter ..', filter);
327
+ try {
328
+ await Promise.all([
329
+ fetchFilterData().then(() => setFilterFromParams(false)),
330
+ //TODO: remove this workaround to fix issue with SSR showing invalid results
331
+ renderingEnv === 'backend' ? Promise.resolve() : searchPromise(),
332
+ ]);
333
+ } catch (error) {
334
+ console.error('[applyFilterToUI] failed with error:', error);
335
+ multiStateBoxSelector.changeState('errorState');
336
+ }
337
+ }
338
+
339
+ /**
340
+ * UPDATE PROFILES BASED ON APPLIED/DEFAULT FILTER
341
+ */
342
+ async function updateResults(timeoutType, preservePagination = false) {
343
+ if (debounceTimeout[timeoutType]) {
344
+ clearTimeout(debounceTimeout[timeoutType]);
345
+ }
346
+ searchResults = await search({
347
+ filter,
348
+ pagination,
349
+ debounceTimeout,
350
+ timeoutType,
351
+ isSearchingNearby: _$w('#nearBy').checked,
352
+ preservePagination,
353
+ });
354
+ !preservePagination && (await updateUrlParams(filter, pagination));
355
+ return searchResults;
356
+ }
357
+
358
+ /**
359
+ * LEFT SIDE FILTER PANEL CODE
360
+ */
361
+
362
+ // RESET FILTER
363
+
364
+ async function resetFilter() {
365
+ _$w('#resetFilter').hide();
366
+ loadDefaultCheckBoxOptions('state');
367
+ loadDefaultCheckBoxOptions('practiceAreas');
368
+ loadDefaultCheckBoxOptions('city');
369
+ _$w('#searchDesktop').enable();
370
+ _$w('#searchTabletMobile').enable();
371
+ _$w('#zipcode').enable();
372
+ _$w('#stateTextInput').enable();
373
+ _$w('#searchDesktop').value = '';
374
+ _$w('#searchTabletMobile').value = '';
375
+ _$w('#zipcode').value = '';
376
+ _$w('#stateTextInput').value = '';
377
+ _$w('#nearBy').checked = false;
378
+
379
+ // Ensure city input is disabled on reset
380
+ _$w('#cityTextInput').disable();
381
+ filter = JSON.parse(JSON.stringify(DEFAULT_FILTER));
382
+ dropDownOptions = JSON.parse(JSON.stringify(DROPDOWN_OPTIONS));
383
+ await updateResults('zeroTimeout');
384
+ }
385
+
386
+ // SEARCH BAR FILTER
387
+ async function searchProfilesOnSearchText(event) {
388
+ const searchText = event.target.value.trim();
389
+ searchText === '' ? (filter.searchText = null) : (filter.searchText = searchText);
390
+ if (searchText.length === 0) {
391
+ filter[`stateSearch`] = '';
392
+ filter[`practiceAreasSearch`] = '';
393
+ await updateResults('zeroTimeout');
394
+ return;
395
+ }
396
+
397
+ const timeoutType = 'searchTimeout';
398
+ if (debounceTimeout[timeoutType]) {
399
+ clearTimeout(debounceTimeout[timeoutType]);
400
+ }
401
+ searchResults = await search({
402
+ filter,
403
+ pagination,
404
+ debounceTimeout,
405
+ timeoutType,
406
+ isSearchingNearby: _$w('#nearBy').checked,
407
+ });
408
+ await updateUrlParams(filter, pagination);
409
+ }
410
+ // NEAR BY FILTER
411
+ async function nearByHandler(preservePagination = false) {
412
+ const isSearchingNearby = _$w('#nearBy').checked;
413
+ const renderingEnv = await rendering.env();
414
+ // 1. Disable nearby input while processing
415
+ _$w('#nearBy').disable();
416
+
417
+ // 2. Enable/Disable other inputs first
418
+ updateFiltersState();
419
+
420
+ // 3. Do the query
421
+ const { success, filter: newFilter } = await getAndSetUserLocation(isSearchingNearby, filter);
422
+ filter = newFilter;
423
+ console.log('filter inside nearByHandler', filter);
424
+ if (!success) {
425
+ if (renderingEnv !== 'backend') {
426
+ //on Backend environment, geolocation API don't work, so makes no sense to change state for near by
427
+ multiStateBoxSelector.changeState('nearByState');
428
+ }
429
+ _$w('#nearBy').checked = false;
430
+ updateFiltersState();
431
+ // 4. Re-enable nearby input
432
+ _$w('#nearBy').enable();
433
+ return false;
434
+ }
435
+
436
+ // If location is not selected, change state to "resultsState"
437
+ if (!isSearchingNearby) {
438
+ if (await noSearchCriteria()) {
439
+ multiStateBoxSelector.changeState('noSearchCriteria');
440
+ // 4. Re-enable nearby input
441
+ _$w('#nearBy').enable();
442
+ return;
443
+ }
444
+ multiStateBoxSelector.changeState('resultsState');
445
+ }
446
+ await updateResults('zeroTimeout', preservePagination);
447
+
448
+ // 4. Re-enable nearby input when done
449
+ _$w('#nearBy').enable();
450
+ return true;
451
+ }
452
+
453
+ // STATE, CITY, AREA OF PRACTICES FILTER
454
+ // FETCH STATE/CITY/AREAS OF PRACTICE FROM BACKEND ONCE AND STORE IT
455
+
456
+ async function fetchFilterData() {
457
+ let completeStateList, areasOfPracticesList, stateCityMapList;
458
+ try {
459
+ const { COMPILED_STATE_LIST, COMPILED_AREAS_OF_PRACTICES, COMPILED_STATE_CITY_MAP } =
460
+ await withWarmUpData(
461
+ 'getCompiledFiltersOptions',
462
+ () => getCompiledFiltersOptions(),
463
+ console.log
464
+ );
465
+ completeStateList = COMPILED_STATE_LIST;
466
+ areasOfPracticesList = COMPILED_AREAS_OF_PRACTICES;
467
+ stateCityMapList = COMPILED_STATE_CITY_MAP;
468
+ } catch (error) {
469
+ console.error(
470
+ `Failed to get compiled filters list, falling back to non compiled version with error: ${error}`
471
+ );
472
+ const {
473
+ completeStateList: _completeStateList,
474
+ areasOfPracticesList: _areasOfPracticesList,
475
+ stateCityMapList: _stateCityMapList,
476
+ } = await withWarmUpData(
477
+ 'getNonCompiledFiltersOptions',
478
+ () => getNonCompiledFiltersOptions(),
479
+ console.log
480
+ );
481
+ completeStateList = _completeStateList;
482
+ areasOfPracticesList = _areasOfPracticesList;
483
+ stateCityMapList = _stateCityMapList;
484
+ }
485
+ await sidePanelFilterData.set('state', completeStateList);
486
+ multiSelectFilter('state');
487
+ sidePanelFilterData.set('practiceAreas', areasOfPracticesList);
488
+ multiSelectFilter('practiceAreas');
489
+ stateCityMap = new Map(Object.entries(stateCityMapList));
490
+ multiSelectFilter('city');
491
+ sidePanelFilterData
492
+ .get('state')
493
+ .forEach(state => stateNameCodeMap.set(state.value, state.label));
494
+
495
+ // Update filter states after data is loaded
496
+ updateFiltersState();
497
+ }
498
+
499
+ // CONSTRUCT DROPDOWN OPTIONS FOR STATE, CITY, AREA OF PRACTICES
500
+
501
+ // LOAD THE CONSTRUCTED OPTIONS TO RESPECTIVE DROPDOWNS
502
+
503
+ function loadDefaultCheckBoxOptions(filterName) {
504
+ setDefaultDropdownState(filterName, filter);
505
+ toggleDropdownFunctionality(filterName, true);
506
+ const options = prepareOptionsFunction({
507
+ filterName,
508
+ sidePanelFilterData,
509
+ stateCityMap,
510
+ filter,
511
+ });
512
+ _$w(`#${filterName}CheckBox`).options = options;
513
+
514
+ // Update filter states after loading options
515
+ updateFiltersState();
516
+ return options;
517
+ }
518
+
519
+ function updateFiltersState() {
520
+ const nearByChecked = _$w('#nearBy').checked;
521
+ const zipValue = _$w('#zipcode').value?.trim() || null;
522
+ const stateCount = _$w('#stateCheckBox').value?.length || 0;
523
+
524
+ // if nearBy → disable all and return immediately
525
+ if (nearByChecked) {
526
+ resetSearch('state');
527
+ resetSearch('city');
528
+ _$w('#zipcode').value = '';
529
+ _$w('#zipcode').disable();
530
+ _$w('#stateTextInput').disable();
531
+ _$w('#cityTextInput').disable();
532
+ return;
533
+ }
534
+
535
+ // if zip entered → state & city off, zip stays on
536
+ if (zipValue) {
537
+ resetSearch('state');
538
+ resetSearch('city');
539
+ _$w('#stateTextInput').disable();
540
+ _$w('#cityTextInput').disable();
541
+ _$w('#zipcode').enable();
542
+ zipValue === '' ? (filter.postalcode = null) : (filter.postalcode = zipValue);
543
+ return;
544
+ }
545
+
546
+ // default: zip + state + searchDesktop on
547
+ _$w('#zipcode').enable();
548
+ _$w('#stateTextInput').enable();
549
+ _$w('#searchDesktop').enable();
550
+
551
+ // only enable city if a state is selected
552
+ if (stateCount > 0) {
553
+ _$w('#cityTextInput').enable();
554
+ } else {
555
+ _$w('#cityTextInput').disable();
556
+ }
557
+ }
558
+
559
+ // Filters options based on search text
560
+
561
+ const filterOptions = (filterName, searchText) => {
562
+ const options = prepareOptionsFunction({
563
+ filterName,
564
+ sidePanelFilterData,
565
+ stateCityMap,
566
+ filter,
567
+ });
568
+ if (!searchText || searchText.trim() === '') {
569
+ return options;
570
+ }
571
+ return filterOptionsFunction(filterName, options, searchText.trim());
572
+ };
573
+ // DYNAMIC FUNCTION FOR INITIALIZING STATE, CITY, AREA OF PRACTICES FILTER
574
+ function multiSelectFilter(filterName) {
575
+ // Element selectors
576
+ const {
577
+ checkBoxContainerSelector,
578
+ searchTextInputSelector,
579
+ clearSearchButtonSelector,
580
+ toggleOptionListButtonSelector,
581
+ multiCheckBoxSelector,
582
+ } = getFiltersSelectors(filterName);
583
+
584
+ // Set up event handlers
585
+ // Clear search button handler
586
+
587
+ clearSearchButtonSelector.onClick(async () => {
588
+ searchTextInputSelector.value = undefined;
589
+ setDefaultState({
590
+ filterName,
591
+ withSelectedOptions: false,
592
+ filter,
593
+ dropDownOptions,
594
+ sidePanelFilterData,
595
+ stateCityMap,
596
+ });
597
+ if (filterName === 'state') {
598
+ setDefaultCity({
599
+ filter,
600
+ dropDownOptions,
601
+ sidePanelFilterData,
602
+ stateCityMap,
603
+ });
604
+ }
605
+ await handleFilterChanged(filterName);
606
+ });
607
+
608
+ // Toggle dropdown button handler
609
+ toggleOptionListButtonSelector.onClick(() => {
610
+ // If nearby is checked, don't allow any dropdown to open
611
+ if (_$w('#nearBy').checked && filterName !== 'practiceAreas') {
612
+ return;
613
+ }
614
+
615
+ if (filterName === 'city') {
616
+ // For city dropdown, ensure we have state selected and city data
617
+ if (filter.state.length === 0) {
618
+ return; // Don't expand if no state selected
619
+ }
620
+ // Ensure city data is loaded
621
+ const options = prepareOptionsFunction({
622
+ filterName,
623
+ sidePanelFilterData,
624
+ stateCityMap,
625
+ filter,
626
+ });
627
+ if (options.length === 0) {
628
+ return; // Don't expand if no city data
629
+ }
630
+ setDefaultFilterOption({
631
+ filterName,
632
+ withSelectedOptions: true,
633
+ dropDownOptions,
634
+ filter,
635
+ sidePanelFilterData,
636
+ stateCityMap,
637
+ });
638
+ checkBoxContainerSelector.collapsed
639
+ ? checkBoxContainerSelector.expand()
640
+ : checkBoxContainerSelector.collapse();
641
+ } else if (
642
+ filterName === 'practiceAreas' ||
643
+ (multiCheckBoxSelector.options.length > 0 &&
644
+ !_$w('#nearBy').checked &&
645
+ _$w('#zipcode').value?.trim() === '')
646
+ ) {
647
+ !searchTextInputSelector.value.length &&
648
+ setDefaultFilterOption({
649
+ filterName,
650
+ withSelectedOptions: true,
651
+ dropDownOptions,
652
+ filter,
653
+ sidePanelFilterData,
654
+ stateCityMap,
655
+ });
656
+ checkBoxContainerSelector.collapsed
657
+ ? checkBoxContainerSelector.expand()
658
+ : checkBoxContainerSelector.collapse();
659
+ }
660
+ });
661
+
662
+ // Search input handler
663
+
664
+ searchTextInputSelector.onClick(() => {
665
+ handleSearchTextInput(filterName, searchTextInputSelector.value);
666
+ });
667
+
668
+ searchTextInputSelector.onBlur(() => {
669
+ if (dropDownOptions[filterName].displayText) {
670
+ clearSearchButtonSelector.expand();
671
+ }
672
+ });
673
+
674
+ searchTextInputSelector.onInput(async event => {
675
+ handleSearchTextInput(filterName, event.target.value);
676
+ await handleFilterChanged(filterName, true);
677
+ });
678
+
679
+ // Checkbox selection handler
680
+
681
+ multiCheckBoxSelector.onChange(async event => {
682
+ await onChangeMultiCheckbox({
683
+ filterName,
684
+ selectedOptions: event.target.value,
685
+ dropDownOptions,
686
+ filter,
687
+ pagination,
688
+ sidePanelFilterData,
689
+ stateCityMap,
690
+ stateNameCodeMap,
691
+ isMobile,
692
+ });
693
+
694
+ await handleFilterChanged(filterName);
695
+ });
696
+
697
+ checkBoxContainerSelector.onMouseOut(() => checkBoxContainerSelector.collapse());
698
+
699
+ // Initialize with default options
700
+ loadDefaultCheckBoxOptions(filterName);
701
+ }
702
+ function handleSearchTextInput(filterName, input) {
703
+ const { checkBoxContainerSelector, clearSearchButtonSelector, multiCheckBoxSelector } =
704
+ getFiltersSelectors(filterName);
705
+ const tofilterOnValue = !input.includes('selected') ? input : '';
706
+ // Toggle clear button visibility
707
+ !input || input.length === 0
708
+ ? clearSearchButtonSelector.collapse()
709
+ : clearSearchButtonSelector.expand();
710
+
711
+ // Filter options based on input
712
+ const filteredOptions = filterOptions(filterName, tofilterOnValue);
713
+ multiCheckBoxSelector.options = filteredOptions;
714
+
715
+ // Toggle dropdown list visibility
716
+ if (checkBoxContainerSelector.collapsed) {
717
+ if (filteredOptions.length > 0) {
718
+ checkBoxContainerSelector.expand();
719
+ }
720
+ }
721
+ }
722
+ async function handleFilterChanged(filterName, isUserInput = false) {
723
+ try {
724
+ if (isMobile) {
725
+ return;
726
+ }
727
+
728
+ const { searchTextInputSelector } = getFiltersSelectors(filterName);
729
+ // Update results based on selection
730
+ filter[`${filterName}Search`] = isUserInput ? searchTextInputSelector.value : '';
731
+
732
+ if (filter.searchText && filter.searchText.length > 0) {
733
+ searchResults = await search({
734
+ filter,
735
+ pagination,
736
+ debounceTimeout,
737
+ timeoutType: 'searchTimeout',
738
+ isSearchingNearby: _$w('#nearBy').checked,
739
+ });
740
+ await updateUrlParams(filter, pagination);
741
+ } else {
742
+ await updateResults('filterTimeout');
743
+ }
744
+ } catch (error) {
745
+ console.error(`[handleFilterChanged]failed with error: ${error}`);
746
+ multiStateBoxSelector.changeState('errorState');
747
+ }
748
+ }
749
+
750
+ function resetSearch(filterName) {
751
+ const { searchTextInputSelector, clearSearchButtonSelector, multiCheckBoxSelector } =
752
+ getFiltersSelectors(filterName);
753
+ clearSearchButtonSelector.collapse();
754
+ multiCheckBoxSelector.options = [];
755
+ searchTextInputSelector.value = '';
756
+
757
+ filter[filterName] = [];
758
+ filter[`${filterName}Search`] = '';
759
+ }
760
+ };
761
+ module.exports = {
762
+ homePageOnReady,
763
+ };