abmp-npm 1.7.2 → 1.8.0
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/.husky/pre-commit +22 -0
- package/.prettierignore +7 -0
- package/.prettierrc.json +16 -0
- package/backend/automations-methods.js +13 -0
- package/backend/consts.js +9 -48
- package/backend/elevated-modules.js +16 -0
- package/backend/forms-methods.js +52 -0
- package/backend/index.js +2 -5
- package/backend/members-area-methods.js +36 -0
- package/backend/members-data-methods.js +55 -0
- package/backend/utils.js +30 -130
- package/eslint.config.js +113 -0
- package/index.js +1 -1
- package/package.json +28 -3
- package/pages/ContactUs.js +129 -0
- package/pages/Profile.js +351 -0
- package/pages/index.js +4 -0
- package/public/consts.js +15 -0
- package/public/index.js +5 -0
- package/public/messages.js +16 -0
- package/public/utils.js +58 -0
- package/backend/updateMemberData.js +0 -210
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const { lightbox } = require('@wix/site-window');
|
|
2
|
+
const { phone } = require('phone');
|
|
3
|
+
|
|
4
|
+
const { VALIDATION_MESSAGES, REGEX } = require('../public');
|
|
5
|
+
|
|
6
|
+
async function contactUsOnReady({ $w: _$w, contactSubmission }) {
|
|
7
|
+
_$w('#submitButton').disable();
|
|
8
|
+
const receivedData = await lightbox.getContext();
|
|
9
|
+
const formFieldsSelectors = ['#firstName', '#lastName', '#email', '#phone', '#message'];
|
|
10
|
+
const inputOnCustomValidation = ({ value, reject, message, pattern }) => {
|
|
11
|
+
const isValid = typeof value === 'string' && pattern.test(value.trim());
|
|
12
|
+
if (!isValid) reject(message);
|
|
13
|
+
};
|
|
14
|
+
async function validateAllFields() {
|
|
15
|
+
let allValid = true;
|
|
16
|
+
for (const selector of formFieldsSelectors) {
|
|
17
|
+
const isValid = await _$w(selector).valid;
|
|
18
|
+
_$w(selector).updateValidityIndication();
|
|
19
|
+
if (!isValid) {
|
|
20
|
+
allValid = false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return allValid;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function resetForm() {
|
|
27
|
+
formFieldsSelectors.forEach(selector => {
|
|
28
|
+
const field = _$w(selector);
|
|
29
|
+
if (field && field.reset) {
|
|
30
|
+
field.reset();
|
|
31
|
+
} else {
|
|
32
|
+
field.value = '';
|
|
33
|
+
}
|
|
34
|
+
if (field && field.resetValidityIndication) {
|
|
35
|
+
field.resetValidityIndication();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function setAlertMessage(message) {
|
|
41
|
+
const $message = _$w('#successMessage');
|
|
42
|
+
$message.text = message;
|
|
43
|
+
$message.expand();
|
|
44
|
+
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
$message.collapse();
|
|
47
|
+
}, 8000);
|
|
48
|
+
}
|
|
49
|
+
// First Name
|
|
50
|
+
_$w('#firstName').onCustomValidation((value, reject) => {
|
|
51
|
+
inputOnCustomValidation({
|
|
52
|
+
value,
|
|
53
|
+
reject,
|
|
54
|
+
message: VALIDATION_MESSAGES.CONTACT_US.FIRST_NAME,
|
|
55
|
+
pattern: REGEX.NAME,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
// Last Name
|
|
59
|
+
_$w('#lastName').onCustomValidation((value, reject) => {
|
|
60
|
+
inputOnCustomValidation({
|
|
61
|
+
value,
|
|
62
|
+
reject,
|
|
63
|
+
message: VALIDATION_MESSAGES.CONTACT_US.LAST_NAME,
|
|
64
|
+
pattern: REGEX.NAME,
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
// Message
|
|
68
|
+
_$w('#message').onCustomValidation((value, reject) => {
|
|
69
|
+
inputOnCustomValidation({
|
|
70
|
+
value,
|
|
71
|
+
reject,
|
|
72
|
+
message: VALIDATION_MESSAGES.CONTACT_US.MESSAGE,
|
|
73
|
+
pattern: REGEX.MESSAGE,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Email validation uses native input validation
|
|
78
|
+
// No custom validation needed as email input has built-in validation
|
|
79
|
+
|
|
80
|
+
// Phone (US format)
|
|
81
|
+
_$w('#phone').onCustomValidation((value, reject) => {
|
|
82
|
+
const { isValid } = phone(value, { country: 'US' });
|
|
83
|
+
if (!isValid) {
|
|
84
|
+
reject(VALIDATION_MESSAGES.CONTACT_US.PHONE);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
_$w('#captchaInput').onVerified(async () => {
|
|
88
|
+
const allValid = await validateAllFields();
|
|
89
|
+
if (allValid) {
|
|
90
|
+
_$w('#submitButton').enable();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
_$w('#submitButton').disable();
|
|
94
|
+
setAlertMessage(VALIDATION_MESSAGES.CONTACT_US.CAPTCHA);
|
|
95
|
+
_$w('#captchaInput').reset();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
_$w('#captchaInput').onTimeout(() => {
|
|
99
|
+
_$w('#submitButton').disable();
|
|
100
|
+
});
|
|
101
|
+
_$w('#submitButton').onClick(async () => {
|
|
102
|
+
const allValid = await validateAllFields();
|
|
103
|
+
if (!allValid) {
|
|
104
|
+
setAlertMessage(VALIDATION_MESSAGES.CONTACT_US.INVALID_FIELDS);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const formData = {
|
|
110
|
+
firstName: _$w('#firstName').value,
|
|
111
|
+
lastName: _$w('#lastName').value,
|
|
112
|
+
email: _$w('#email').value,
|
|
113
|
+
phone: _$w('#phone').value,
|
|
114
|
+
message: _$w('#message').value,
|
|
115
|
+
};
|
|
116
|
+
await contactSubmission(formData, receivedData._id);
|
|
117
|
+
await resetForm();
|
|
118
|
+
|
|
119
|
+
setAlertMessage(VALIDATION_MESSAGES.CONTACT_US.SUBMISSION_SUCCESS);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error('Submission failed:', error);
|
|
122
|
+
setAlertMessage(VALIDATION_MESSAGES.CONTACT_US.SUBMISSION_FAILED);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = {
|
|
128
|
+
contactUsOnReady,
|
|
129
|
+
};
|
package/pages/Profile.js
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
const TESTIMONIALS_PER_PAGE_CONFIG = {
|
|
2
|
+
DESKTOP: 4,
|
|
3
|
+
TABLET: 2,
|
|
4
|
+
MOBILE: 1,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const BREAKPOINTS = {
|
|
8
|
+
DESKTOP: 1301,
|
|
9
|
+
TABLET: 750,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
async function profileOnReady({
|
|
13
|
+
$w: _$w,
|
|
14
|
+
profileData,
|
|
15
|
+
openLightbox,
|
|
16
|
+
getBoundingRect,
|
|
17
|
+
wixLocation,
|
|
18
|
+
generateId,
|
|
19
|
+
prepareText,
|
|
20
|
+
}) {
|
|
21
|
+
let testimonialsPerPage = TESTIMONIALS_PER_PAGE_CONFIG.TABLET;
|
|
22
|
+
let currentTestimonialPage = 0;
|
|
23
|
+
|
|
24
|
+
console.log('profileData', profileData);
|
|
25
|
+
|
|
26
|
+
if (!profileData) {
|
|
27
|
+
wixLocation.to(`${wixLocation.baseUrl}/404`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
initializePage();
|
|
32
|
+
|
|
33
|
+
function initializePage() {
|
|
34
|
+
bindProfileData();
|
|
35
|
+
setupAddressToggle();
|
|
36
|
+
setupResponsiveTestimonials();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Profile data binding
|
|
40
|
+
function bindProfileData() {
|
|
41
|
+
bindAddressData();
|
|
42
|
+
bindMemberInfo();
|
|
43
|
+
bindContactInfo();
|
|
44
|
+
bindBusinessInfo();
|
|
45
|
+
bindGalleryData();
|
|
46
|
+
bindTestimonialsData();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function bindAddressData() {
|
|
50
|
+
if (profileData.mainAddress) {
|
|
51
|
+
setTextForElements(
|
|
52
|
+
['#LocationText', '#LocationText2', '#LocationText3'],
|
|
53
|
+
profileData.mainAddress
|
|
54
|
+
);
|
|
55
|
+
} else {
|
|
56
|
+
collapseElements(['#locationContainer', '#location1Container', '#locationContainer2']);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setupAdditionalAddresses();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function setupAdditionalAddresses() {
|
|
63
|
+
_$w('#moreAdressesRepeater').data = profileData.processedAddresses;
|
|
64
|
+
|
|
65
|
+
if (profileData.processedAddresses.length > 0) {
|
|
66
|
+
_$w('#moreLocationButton').expand();
|
|
67
|
+
_$w('#addressTitle').collapse();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_$w('#moreAdressesRepeater').onItemReady(($item, itemData) => {
|
|
71
|
+
console.log('Item Data:', itemData);
|
|
72
|
+
$item('#adressText').text = itemData.address || '';
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function setupAddressToggle() {
|
|
77
|
+
toggleContainer('#moreLocationButton', '#addressContainer');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function toggleContainer(buttonId, containerId) {
|
|
81
|
+
const $button = _$w(buttonId);
|
|
82
|
+
const $container = _$w(containerId);
|
|
83
|
+
|
|
84
|
+
$button.onClick(() => {
|
|
85
|
+
const isCollapsed = $container.collapsed;
|
|
86
|
+
$container[isCollapsed ? 'expand' : 'collapse']();
|
|
87
|
+
$button.label = isCollapsed ? 'Less Locations -' : 'More Locations +';
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function bindMemberInfo() {
|
|
92
|
+
bindMemberSince();
|
|
93
|
+
bindStudentBadge();
|
|
94
|
+
bindProfileImages();
|
|
95
|
+
bindFullName();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function bindMemberSince() {
|
|
99
|
+
if (profileData.memberSince) {
|
|
100
|
+
_$w('#sinceYearText').text = profileData.memberSince;
|
|
101
|
+
} else {
|
|
102
|
+
_$w('#memberSinceBox').collapse();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function bindStudentBadge() {
|
|
107
|
+
if (profileData.shouldHaveStudentBadge) {
|
|
108
|
+
_$w('#studentContainer, #studentContainerMobile').expand();
|
|
109
|
+
} else {
|
|
110
|
+
_$w('#studentContainer, #studentContainerMobile').collapse();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function bindProfileImages() {
|
|
115
|
+
if (profileData.logoImage) {
|
|
116
|
+
_$w('#logoImage').src = profileData.logoImage;
|
|
117
|
+
} else {
|
|
118
|
+
_$w('#logoImage').collapse();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (profileData.profileImage) {
|
|
122
|
+
_$w('#profileImage').src = profileData.profileImage;
|
|
123
|
+
} else {
|
|
124
|
+
_$w('#profileImage').src =
|
|
125
|
+
'https://static.wixstatic.com/media/1d7134_e052e9b1d0a543d0980650e16dd6d374~mv2.jpg';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function bindFullName() {
|
|
130
|
+
if (profileData.fullName) {
|
|
131
|
+
setTextForElements(
|
|
132
|
+
['#fullNameText', '#fullNameText2', '#fullNameTextFoter'],
|
|
133
|
+
profileData.fullName
|
|
134
|
+
);
|
|
135
|
+
} else {
|
|
136
|
+
collapseElements(['#fullNameText', '#fullNameText2', '#fullNameTextFoter']);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Contact information binding
|
|
141
|
+
function bindContactInfo() {
|
|
142
|
+
bindContactForm();
|
|
143
|
+
bindBookingUrl();
|
|
144
|
+
bindPhoneNumber();
|
|
145
|
+
bindLicenseNumber();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function bindContactForm() {
|
|
149
|
+
if (profileData.showContactForm) {
|
|
150
|
+
_$w('#contactButton').onClick(() => openLightbox('Contact Us', profileData));
|
|
151
|
+
} else {
|
|
152
|
+
_$w('#contactButton').collapse();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function bindBookingUrl() {
|
|
157
|
+
if (profileData.bookingUrl) {
|
|
158
|
+
_$w('#bookNowButton').link = profileData.bookingUrl;
|
|
159
|
+
} else {
|
|
160
|
+
_$w('#bookNowButton').collapse();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function bindPhoneNumber() {
|
|
165
|
+
if (profileData.phone) {
|
|
166
|
+
const formattedPhoneNumber = profileData.phone.replace(/[^\d+]/g, '');
|
|
167
|
+
const getPhoneHTML = ($phoneSelector) =>
|
|
168
|
+
$phoneSelector.html.replace(
|
|
169
|
+
$phoneSelector.text,
|
|
170
|
+
`<a href="${`tel:${formattedPhoneNumber}`}">${profileData.phone}</a>`
|
|
171
|
+
);
|
|
172
|
+
_$w('#phoneText').html = getPhoneHTML(_$w('#phoneText'));
|
|
173
|
+
_$w('#phoneText2').html = getPhoneHTML(_$w('#phoneText2'));
|
|
174
|
+
} else {
|
|
175
|
+
collapseElements(['#phoneContainer', '#phoneContainer2']);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function bindLicenseNumber() {
|
|
180
|
+
if (profileData.licenceNo) {
|
|
181
|
+
_$w('#licenceNoText').text = profileData.licenceNo;
|
|
182
|
+
} else {
|
|
183
|
+
_$w('#licensesContainer').collapse();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function bindBusinessInfo() {
|
|
188
|
+
bindAboutService();
|
|
189
|
+
bindBusinessName();
|
|
190
|
+
bindAreasOfPractice();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function bindAboutService() {
|
|
194
|
+
if (profileData.aboutService) {
|
|
195
|
+
_$w('#aboutYouText').html = profileData.aboutService;
|
|
196
|
+
} else {
|
|
197
|
+
_$w('#aboutSection').collapse();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function bindBusinessName() {
|
|
202
|
+
if (profileData.businessName) {
|
|
203
|
+
_$w('#businessName').text = profileData.businessName;
|
|
204
|
+
_$w('#businessName').expand();
|
|
205
|
+
} else {
|
|
206
|
+
_$w('#businessName').collapse();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function bindAreasOfPractice() {
|
|
211
|
+
const areasText = prepareText(profileData.areasOfPractices);
|
|
212
|
+
|
|
213
|
+
if (areasText) {
|
|
214
|
+
_$w('#areaOfPracticesText').text = areasText;
|
|
215
|
+
} else {
|
|
216
|
+
_$w('#areaOfPracticesText').collapse();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (Array.isArray(profileData.areasOfPractices) && profileData.areasOfPractices.length > 0) {
|
|
220
|
+
populateRepeater(profileData.areasOfPractices, '#areaOfPracticesRepeater', '#practiceText');
|
|
221
|
+
} else {
|
|
222
|
+
_$w('#servicesSection').collapse();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function bindGalleryData() {
|
|
227
|
+
if (profileData.bannerImages && profileData.bannerImages.length > 0) {
|
|
228
|
+
_$w('#bannerImage').src = profileData.bannerImages[0];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (!profileData.gallery?.length) {
|
|
232
|
+
_$w('#gallerySection').collapse();
|
|
233
|
+
} else {
|
|
234
|
+
_$w('#gallery').items = profileData.gallery;
|
|
235
|
+
_$w('#gallerySection').expand();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function bindTestimonialsData() {
|
|
240
|
+
if (!profileData.testimonials?.length) {
|
|
241
|
+
_$w('#testimonialsSection').collapse();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Responsive testimonials setup
|
|
246
|
+
async function setupResponsiveTestimonials() {
|
|
247
|
+
const { window } = await getBoundingRect();
|
|
248
|
+
testimonialsPerPage = getTestimonialsPerPage(window.width);
|
|
249
|
+
|
|
250
|
+
// Monitor window resize
|
|
251
|
+
setInterval(async () => {
|
|
252
|
+
const { window: win } = await getBoundingRect();
|
|
253
|
+
const newTestimonialsPerPage = getTestimonialsPerPage(win.width);
|
|
254
|
+
|
|
255
|
+
if (newTestimonialsPerPage !== testimonialsPerPage) {
|
|
256
|
+
testimonialsPerPage = newTestimonialsPerPage;
|
|
257
|
+
currentTestimonialPage = 0;
|
|
258
|
+
displayTestimonialsPage(profileData.testimonials);
|
|
259
|
+
}
|
|
260
|
+
}, 500);
|
|
261
|
+
|
|
262
|
+
setupTestimonialsIfAvailable();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function setupTestimonialsIfAvailable() {
|
|
266
|
+
if (profileData.testimonials.length > 0) {
|
|
267
|
+
setupTestimonialsPagination(profileData.testimonials);
|
|
268
|
+
_$w('#testimonialsSection').expand();
|
|
269
|
+
} else {
|
|
270
|
+
_$w('#testimonialsSection').collapse();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function getTestimonialsPerPage(width) {
|
|
275
|
+
if (width >= BREAKPOINTS.DESKTOP) return TESTIMONIALS_PER_PAGE_CONFIG.DESKTOP;
|
|
276
|
+
if (width >= BREAKPOINTS.TABLET) return TESTIMONIALS_PER_PAGE_CONFIG.TABLET;
|
|
277
|
+
return TESTIMONIALS_PER_PAGE_CONFIG.MOBILE;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function setTextForElements(elementIds, text) {
|
|
281
|
+
elementIds.forEach((id) => {
|
|
282
|
+
_$w(id).text = text;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function collapseElements(elementIds) {
|
|
287
|
+
elementIds.forEach((id) => {
|
|
288
|
+
_$w(id).collapse();
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function populateRepeater(data, repeaterId, textElementId) {
|
|
293
|
+
const repeaterData = data.map((item) => ({
|
|
294
|
+
_id: generateId(),
|
|
295
|
+
text: item.trim(),
|
|
296
|
+
}));
|
|
297
|
+
_$w(repeaterId).data = repeaterData;
|
|
298
|
+
_$w(repeaterId).onItemReady(($item, itemData) => {
|
|
299
|
+
$item(textElementId).text = itemData.text;
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Testimonials pagination
|
|
304
|
+
function setupTestimonialsPagination(allTestimonials) {
|
|
305
|
+
currentTestimonialPage = 0;
|
|
306
|
+
|
|
307
|
+
_$w('#prevTestimonialBtn').onClick(() => {
|
|
308
|
+
if (currentTestimonialPage > 0) {
|
|
309
|
+
currentTestimonialPage--;
|
|
310
|
+
displayTestimonialsPage(allTestimonials);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
_$w('#nextTestimonialBtn').onClick(() => {
|
|
315
|
+
const maxPage = Math.floor((allTestimonials.length - 1) / testimonialsPerPage);
|
|
316
|
+
if (currentTestimonialPage < maxPage) {
|
|
317
|
+
currentTestimonialPage++;
|
|
318
|
+
displayTestimonialsPage(allTestimonials);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
displayTestimonialsPage(allTestimonials);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function displayTestimonialsPage(allTestimonials) {
|
|
326
|
+
const start = currentTestimonialPage * testimonialsPerPage;
|
|
327
|
+
const end = start + testimonialsPerPage;
|
|
328
|
+
const currentBatch = allTestimonials.slice(start, end);
|
|
329
|
+
|
|
330
|
+
populateRepeater(currentBatch, '#testimonialsrepeater', '#testimonialText');
|
|
331
|
+
updateTestimonialNavigation(end, allTestimonials.length);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function updateTestimonialNavigation(end, totalLength) {
|
|
335
|
+
_$w('#prevTestimonialBtn').hide();
|
|
336
|
+
_$w('#nextTestimonialBtn').hide();
|
|
337
|
+
|
|
338
|
+
if (currentTestimonialPage > 0) {
|
|
339
|
+
_$w('#prevTestimonialBtn').show();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (end < totalLength) {
|
|
343
|
+
_$w('#nextTestimonialBtn').show();
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
module.exports = {
|
|
349
|
+
profileOnReady,
|
|
350
|
+
};
|
|
351
|
+
|
package/pages/index.js
ADDED
package/public/consts.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const REGEX = {
|
|
2
|
+
NAME: /^[a-zA-Z\s'-]{2,}$/,
|
|
3
|
+
MESSAGE: /^[A-Za-z0-9\s.,!?'"-]{2,}$/,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
const COLLECTIONS = {
|
|
7
|
+
MEMBERS_DATA: 'MembersDataLatest',
|
|
8
|
+
CONTACT_US_SUBMISSIONS: 'contactUsSubmissions',
|
|
9
|
+
SITE_CONFIGS: 'SiteConfigs',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
REGEX,
|
|
14
|
+
COLLECTIONS,
|
|
15
|
+
};
|
package/public/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const VALIDATION_MESSAGES = {
|
|
2
|
+
CONTACT_US: {
|
|
3
|
+
FIRST_NAME: 'Please enter a valid first name.',
|
|
4
|
+
LAST_NAME: 'Please enter a valid last name.',
|
|
5
|
+
MESSAGE: 'Please enter a valid message.',
|
|
6
|
+
PHONE: 'Please enter a valid US phone number.',
|
|
7
|
+
CAPTCHA: 'Please fix the highlighted fields before captcha verification.',
|
|
8
|
+
INVALID_FIELDS: 'Please fix the highlighted fields before submitting.',
|
|
9
|
+
SUBMISSION_FAILED: 'An error occurred. Please try again.',
|
|
10
|
+
SUBMISSION_SUCCESS: 'Contact submitted successfully',
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
VALIDATION_MESSAGES,
|
|
16
|
+
};
|
package/public/utils.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a unique ID
|
|
3
|
+
* @returns {string} Unique identifier
|
|
4
|
+
*/
|
|
5
|
+
function generateId() {
|
|
6
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Formats an array of practice areas, showing as many as fit within 70 characters
|
|
11
|
+
* @param {Array} areaOfPractices - Array of practice area strings
|
|
12
|
+
* @returns {string} Formatted string of practice areas
|
|
13
|
+
*/
|
|
14
|
+
function prepareText(areaOfPractices = []) {
|
|
15
|
+
// always return a string
|
|
16
|
+
if (!Array.isArray(areaOfPractices) || areaOfPractices.length === 0) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Filter out null/undefined/empty
|
|
21
|
+
const validAreas = areaOfPractices.filter(
|
|
22
|
+
(area) => area !== null && area !== undefined && area !== ''
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
if (validAreas.length === 0) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (validAreas.length === 1) {
|
|
30
|
+
return validAreas[0].length > 70 ? validAreas[0].substring(0, 67) + '...' : validAreas[0];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// build up to 70-char string
|
|
34
|
+
let current = '';
|
|
35
|
+
const visible = [];
|
|
36
|
+
for (const item of validAreas) {
|
|
37
|
+
const sep = visible.length ? ', ' : '';
|
|
38
|
+
const next = current + sep + item;
|
|
39
|
+
if (next.length > 70) break;
|
|
40
|
+
visible.push(item);
|
|
41
|
+
current = next;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// if nothing fit, at least show the first (truncated)
|
|
45
|
+
if (visible.length === 0) {
|
|
46
|
+
const first = validAreas[0];
|
|
47
|
+
return first.length > 67 ? first.substring(0, 67) + '...' : first;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const remaining = validAreas.length - visible.length;
|
|
51
|
+
return remaining > 0 ? `${visible.join(', ')}, +${remaining} Techniques` : visible.join(', ');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
generateId,
|
|
56
|
+
prepareText,
|
|
57
|
+
};
|
|
58
|
+
|