abmp-npm 1.8.1 → 1.8.3

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.
@@ -0,0 +1,162 @@
1
+ const { ADDRESS_STATUS_TYPES, DEBOUNCE_DELAY } = require('../consts.js');
2
+
3
+ const checkAddressIsVisible = (addresses = []) => {
4
+ // ensure we always get an array
5
+ if (!Array.isArray(addresses)) return [];
6
+
7
+ return addresses.filter(
8
+ val => val.addressStatus === undefined || val.addressStatus !== ADDRESS_STATUS_TYPES.DONT_SHOW
9
+ );
10
+ };
11
+
12
+ //Formats an array of practice areas, showing as many as fit within 70 characters
13
+ function formatPracticeAreasForDisplay(areaOfPractices = []) {
14
+ // always return a string
15
+ if (!Array.isArray(areaOfPractices) || areaOfPractices.length === 0) {
16
+ return '';
17
+ }
18
+
19
+ // Filter out null/undefined/empty
20
+ const validAreas = areaOfPractices.filter(
21
+ area => area !== null && area !== undefined && area !== ''
22
+ );
23
+
24
+ if (validAreas.length === 0) {
25
+ return '';
26
+ }
27
+
28
+ if (validAreas.length === 1) {
29
+ return validAreas[0].length > 70 ? validAreas[0].substring(0, 67) + '...' : validAreas[0];
30
+ }
31
+
32
+ // build up to 70-char string
33
+ let current = '';
34
+ const visible = [];
35
+ for (const item of validAreas) {
36
+ const sep = visible.length ? ', ' : '';
37
+ const next = current + sep + item;
38
+ if (next.length > 70) break;
39
+ visible.push(item);
40
+ current = next;
41
+ }
42
+
43
+ // if nothing fit, at least show the first (truncated)
44
+ if (visible.length === 0) {
45
+ const first = validAreas[0];
46
+ return first.length > 67 ? first.substring(0, 67) + '...' : first;
47
+ }
48
+
49
+ const remaining = validAreas.length - visible.length;
50
+ return remaining > 0 ? `${visible.join(', ')}, +${remaining} Techniques` : visible.join(', ');
51
+ }
52
+
53
+ function debouncedFunction({ func, debounceTimeout, timeoutType, args }) {
54
+ return new Promise(resolve => {
55
+ debounceTimeout[timeoutType] = setTimeout(async () => {
56
+ try {
57
+ const response = await func(args);
58
+ resolve({ success: true, response });
59
+ } catch (error) {
60
+ console.error('Error updating results:', error);
61
+ resolve({ success: false, error });
62
+ }
63
+ }, DEBOUNCE_DELAY[timeoutType]);
64
+ });
65
+ }
66
+
67
+ const isValidLocation = location => location.latitude && location.longitude;
68
+
69
+ function findMainAddress(addressDisplayOption = [], addresses = []) {
70
+ const options = Array.isArray(addressDisplayOption) ? addressDisplayOption : [];
71
+ const mainOpt = options.find(opt => opt.isMain);
72
+ if (mainOpt) {
73
+ const mainAddr = addresses.find(
74
+ addr => addr.key === mainOpt.key && addr.addressStatus !== ADDRESS_STATUS_TYPES.DONT_SHOW
75
+ );
76
+ if (mainAddr && isValidLocation(mainAddr)) {
77
+ return mainAddr;
78
+ }
79
+ }
80
+ // 2) fallback: if there is any visible address, use it
81
+ const visibleAddresses = addresses.filter(
82
+ addr => addr.addressStatus !== ADDRESS_STATUS_TYPES.DONT_SHOW && isValidLocation(addr)
83
+ );
84
+ if (visibleAddresses.length) {
85
+ return visibleAddresses[0];
86
+ }
87
+ return '';
88
+ }
89
+ function formatAddress(item) {
90
+ let addressParts = [];
91
+ const limitedPostalCode = item.postalcode.slice(0, 5); //show only 5 digits to not show full user address
92
+ switch (item.addressStatus) {
93
+ case ADDRESS_STATUS_TYPES.FULL_ADDRESS:
94
+ addressParts = [item.line1, item.city, item.state, limitedPostalCode];
95
+ break;
96
+ case ADDRESS_STATUS_TYPES.STATE_CITY_ZIP:
97
+ addressParts = [item.city, item.state, limitedPostalCode];
98
+ break;
99
+ default:
100
+ return '';
101
+ }
102
+ return addressParts.filter(Boolean).join(', ');
103
+ }
104
+
105
+ function getMainAddress(addressDisplayOption = [], addresses = []) {
106
+ const mainAddr = findMainAddress(addressDisplayOption, addresses);
107
+ if (mainAddr) {
108
+ return formatAddress(mainAddr);
109
+ }
110
+ return '';
111
+ }
112
+ function shuffleArray(array) {
113
+ const shuffled = [...array];
114
+ for (let i = shuffled.length - 1; i > 0; i--) {
115
+ const j = Math.floor(Math.random() * (i + 1));
116
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
117
+ }
118
+ return shuffled;
119
+ }
120
+
121
+ function toRadians(degrees) {
122
+ return degrees * (Math.PI / 180);
123
+ }
124
+
125
+ function calculateDistance(location1, location2) {
126
+ if (!isValidLocation(location1) || !isValidLocation(location2)) {
127
+ return null;
128
+ }
129
+
130
+ // Earth's radius in miles
131
+ const earthRadius = 3958.8;
132
+
133
+ // Convert latitude and longitude from degrees to radians
134
+ const latRad1 = toRadians(location1.latitude);
135
+ const lonRad1 = toRadians(location1.longitude);
136
+ const latRad2 = toRadians(location2.latitude);
137
+ const lonRad2 = toRadians(location2.longitude);
138
+
139
+ // Differences in coordinates
140
+ const latDiff = latRad2 - latRad1;
141
+ const lonDiff = lonRad2 - lonRad1;
142
+
143
+ // Haversine formula
144
+ const a =
145
+ Math.sin(latDiff / 2) * Math.sin(latDiff / 2) +
146
+ Math.cos(latRad1) * Math.cos(latRad2) * Math.sin(lonDiff / 2) * Math.sin(lonDiff / 2);
147
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
148
+ const distance = earthRadius * c;
149
+
150
+ return distance;
151
+ }
152
+
153
+ module.exports = {
154
+ checkAddressIsVisible,
155
+ formatPracticeAreasForDisplay,
156
+ debouncedFunction,
157
+ findMainAddress,
158
+ getMainAddress,
159
+ shuffleArray,
160
+ calculateDistance,
161
+ toRadians,
162
+ };
package/public/consts.js CHANGED
@@ -7,9 +7,79 @@ const COLLECTIONS = {
7
7
  MEMBERS_DATA: 'MembersDataLatest',
8
8
  CONTACT_US_SUBMISSIONS: 'contactUsSubmissions',
9
9
  SITE_CONFIGS: 'SiteConfigs',
10
+ COMPILED_STATE_CITY_MAP: 'CompiledStateCityMap',
11
+ STATE: 'State',
12
+ INTERESTS: 'interests',
13
+ STATE_CITY_MAP: 'City',
10
14
  };
11
15
 
16
+ /**
17
+ * Address display status types
18
+ */
19
+ const ADDRESS_STATUS_TYPES = {
20
+ FULL_ADDRESS: 'full_address',
21
+ STATE_CITY_ZIP: 'state_city_zip',
22
+ DONT_SHOW: 'dont_show',
23
+ };
24
+
25
+ const DEFAULT_FILTER = {
26
+ skip: 0,
27
+ limit: 12,
28
+ practiceAreas: [],
29
+ practiceAreasSearch: '',
30
+ latitude: 0,
31
+ longitude: 0,
32
+ postalcode: null,
33
+ state: [],
34
+ stateSearch: '',
35
+ citySearch: '',
36
+ city: [],
37
+ searchText: null,
38
+ };
39
+ const DROPDOWN_OPTIONS = {
40
+ state: {
41
+ selectedOptions: [],
42
+ displayText: '',
43
+ },
44
+ city: {
45
+ selectedOptions: [],
46
+ displayText: '',
47
+ },
48
+ practiceAreas: {
49
+ selectedOptions: [],
50
+ displayText: '',
51
+ },
52
+ };
53
+ const DEBOUNCE_DELAY = {
54
+ searchTimeout: 1000,
55
+ filterTimeout: 300,
56
+ zeroTimeout: 0,
57
+ };
58
+ const MEMBERS_FIELDS = {
59
+ _id: '_id',
60
+ profileImage: 'profileImage',
61
+ fullName: 'fullName',
62
+ addresses: 'addresses',
63
+ aboutService: 'aboutService',
64
+ showBookingUrl: 'showBookingUrl',
65
+ bookingUrl: 'bookingUrl',
66
+ areasOfPractices: 'areasOfPractices',
67
+ url: 'url',
68
+ phones: 'phones',
69
+ toShowPhone: 'toShowPhone',
70
+ showContactForm: 'showContactForm',
71
+ website: 'website',
72
+ showWixUrl: 'showWixUrl',
73
+ memberships: 'memberships',
74
+ showWebsite: 'showWebsite',
75
+ addressDisplayOption: 'addressDisplayOption',
76
+ };
12
77
  module.exports = {
13
78
  REGEX,
14
79
  COLLECTIONS,
80
+ ADDRESS_STATUS_TYPES,
81
+ DEFAULT_FILTER,
82
+ DROPDOWN_OPTIONS,
83
+ DEBOUNCE_DELAY,
84
+ MEMBERS_FIELDS,
15
85
  };