-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathscript.js
More file actions
266 lines (228 loc) · 10.7 KB
/
script.js
File metadata and controls
266 lines (228 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
document.addEventListener('DOMContentLoaded', function() {
// Mobile menu toggle
const menuButton = document.getElementById('menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if (menuButton && mobileMenu) {
menuButton.addEventListener('click', function() {
mobileMenu.classList.toggle('hidden');
});
}
// Close mobile menu when clicking a nav link
const mobileNavLinks = mobileMenu ? mobileMenu.querySelectorAll('a') : [];
mobileNavLinks.forEach(link => {
link.addEventListener('click', function() {
mobileMenu.classList.add('hidden');
});
});
// FAQ accordion functionality
const faqToggles = document.querySelectorAll('.faq-toggle');
faqToggles.forEach(toggle => {
toggle.addEventListener('click', function() {
// Get the content element that follows this toggle
const content = this.nextElementSibling;
const icon = this.querySelector('i');
// Toggle visibility of content
content.classList.toggle('hidden');
// Rotate plus icon when expanded
icon.classList.toggle('active');
// Close other open FAQs
faqToggles.forEach(otherToggle => {
if (otherToggle !== toggle) {
const otherContent = otherToggle.nextElementSibling;
const otherIcon = otherToggle.querySelector('i');
if (!otherContent.classList.contains('hidden')) {
otherContent.classList.add('hidden');
otherIcon.classList.remove('active');
}
}
});
});
});
// Form validation and submission
const appointmentForm = document.getElementById('appointment-form');
const formSuccess = document.getElementById('form-success');
if (appointmentForm) {
appointmentForm.addEventListener('submit', function(event) {
// Validate the form before submission
if (!validateForm()) {
event.preventDefault();
return false;
}
// Add the +91 prefix to the phone number for submission
const phoneInput = document.getElementById('phone');
if (phoneInput) {
const formattedPhone = "+91" + phoneInput.value;
// Create a temporary hidden input for the formatted phone
const formattedPhoneInput = document.createElement('input');
formattedPhoneInput.type = 'hidden';
formattedPhoneInput.name = 'formatted_phone';
formattedPhoneInput.value = formattedPhone;
appointmentForm.appendChild(formattedPhoneInput);
}
// If using Formspree and the form is valid, handle submission
// This code handles the form submission without page reload
event.preventDefault();
const formData = new FormData(appointmentForm);
const formAction = appointmentForm.getAttribute('action');
// Add a hidden honeypot field for spam protection
const honeypot = document.createElement('input');
honeypot.type = 'text';
honeypot.name = '_gotcha';
honeypot.value = '';
honeypot.style.display = 'none';
appointmentForm.appendChild(honeypot);
fetch(formAction, {
method: 'POST',
body: formData,
headers: {
'Accept': 'application/json'
}
})
.then(response => {
if (response.ok) {
// Redirect to thank you page on successful submission
window.location.href = 'thank-you.html';
} else {
return response.json().then(data => {
throw new Error(data.error || 'Form submission failed');
});
}
})
.catch(error => {
console.error('Error:', error);
showFormError(error.message);
});
});
}
// Form validation function
function validateForm() {
let isValid = true;
const requiredFields = appointmentForm.querySelectorAll('[required]');
// Reset previous validation errors
const errorElements = appointmentForm.querySelectorAll('.error-message');
errorElements.forEach(el => el.remove());
// Check each required field
requiredFields.forEach(field => {
if (!field.value.trim()) {
const fieldName = field.previousElementSibling ? field.previousElementSibling.textContent.replace('*', '').trim() : 'This field';
displayError(field, `${fieldName} is required`);
isValid = false;
} else if (field.type === 'email' && !validateEmail(field.value)) {
displayError(field, 'Please enter a valid email address (e.g., name@example.com)');
isValid = false;
} else if (field.id === 'phone') {
if (field.value.length < 10) {
displayError(field, 'Phone number must be exactly 10 digits');
isValid = false;
} else if (!validatePhone(field.value)) {
displayError(field, 'Phone number should contain only digits (0-9)');
isValid = false;
}
} else if (field.id === 'service' && field.selectedIndex === 0) {
displayError(field, 'Please select a service');
isValid = false;
}
});
return isValid;
}
// Display error message below the field
function displayError(field, message) {
// Get the parent element - might be different for phone due to our custom layout
let parent = field.parentNode;
if (parent.classList.contains('flex')) {
parent = parent.parentNode; // For phone field, go one level up
}
const errorDiv = document.createElement('div');
errorDiv.className = 'error-message text-red-500 text-sm mt-1';
errorDiv.innerText = message;
parent.appendChild(errorDiv);
// Highlight the field with error
field.classList.add('border-red-500');
// For phone field, highlight the container too
if (field.id === 'phone' && field.parentNode.classList.contains('flex')) {
field.parentNode.classList.add('border-red-500');
}
// Remove error styling when user starts typing
field.addEventListener('input', function() {
this.classList.remove('border-red-500');
// For phone field, remove highlight from container too
if (this.id === 'phone' && this.parentNode.classList.contains('flex')) {
this.parentNode.classList.remove('border-red-500');
}
const parentElement = this.parentNode.classList.contains('flex') ?
this.parentNode.parentNode : this.parentNode;
const error = parentElement.querySelector('.error-message');
if (error) {
error.remove();
}
});
// Also remove error on dropdown change
if (field.tagName === 'SELECT') {
field.addEventListener('change', function() {
this.classList.remove('border-red-500');
const error = this.parentNode.querySelector('.error-message');
if (error) {
error.remove();
}
});
}
}
// Show success message
function showFormSuccess() {
if (formSuccess) {
formSuccess.classList.remove('hidden');
formSuccess.textContent = "Thank you for booking an appointment! We will contact you shortly to confirm the details.";
formSuccess.classList.add('bg-green-100', 'text-green-700');
// Scroll to success message
formSuccess.scrollIntoView({ behavior: 'smooth' });
// Hide success message after 5 seconds
setTimeout(() => {
formSuccess.classList.add('hidden');
}, 5000);
}
}
// Show error message for form submission
function showFormError(errorMessage) {
if (formSuccess) {
formSuccess.classList.remove('hidden', 'bg-green-100', 'text-green-700');
formSuccess.textContent = errorMessage || "There was a problem submitting your form. Please try again later.";
formSuccess.classList.add('bg-red-100', 'text-red-700');
// Scroll to error message
formSuccess.scrollIntoView({ behavior: 'smooth' });
// Hide error message after 5 seconds
setTimeout(() => {
formSuccess.classList.add('hidden');
}, 5000);
}
}
// Email validation
function validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
// Phone validation (10-digit Indian phone numbers)
function validatePhone(phone) {
const re = /^[0-9]{10}$/;
return re.test(String(phone));
}
// Set minimum date for appointment to today
const dateInput = document.getElementById('preferred_date');
if (dateInput) {
const today = new Date().toISOString().split('T')[0];
dateInput.setAttribute('min', today);
}
// Smooth scrolling for nav links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href');
const targetElement = document.querySelector(targetId);
if (targetElement) {
window.scrollTo({
top: targetElement.offsetTop - 80, // Adjust for fixed header
behavior: 'smooth'
});
}
});
});
});