Remove Netlify form handling logic from BasicScripts.astro and update Form.astro to set action attribute for contact form submission to the new API endpoint.
This commit is contained in:
@@ -453,188 +453,4 @@ import { UI } from 'astrowind:config';
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Contact Form Handling -->
|
<!-- Contact Form Handling -->
|
||||||
<script is:inline>
|
<!-- Netlify form handling setup removed -->
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
setupContactForm();
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('astro:after-swap', () => {
|
|
||||||
setupContactForm();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Netlify form handling setup
|
|
||||||
|
|
||||||
async function setupContactForm() {
|
|
||||||
const contactForm = document.getElementById('contact-form');
|
|
||||||
if (!contactForm) return;
|
|
||||||
|
|
||||||
// Form validation and submission
|
|
||||||
contactForm.addEventListener('submit', async function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// Reset previous error messages
|
|
||||||
resetFormErrors();
|
|
||||||
|
|
||||||
// Client-side validation
|
|
||||||
if (!validateForm(contactForm)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show loading state
|
|
||||||
const submitButton = contactForm.querySelector('button[type="submit"]');
|
|
||||||
const originalButtonText = submitButton.innerHTML;
|
|
||||||
submitButton.disabled = true;
|
|
||||||
submitButton.innerHTML = 'Sending...';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const formData = new FormData(contactForm);
|
|
||||||
|
|
||||||
// Add timestamp to help prevent duplicate submissions
|
|
||||||
formData.append('timestamp', Date.now().toString());
|
|
||||||
|
|
||||||
// Submit the form to Netlify
|
|
||||||
const response = await fetch('/', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
body: new URLSearchParams(formData).toString(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
// Show success message
|
|
||||||
document.getElementById('form-success').classList.remove('hidden');
|
|
||||||
contactForm.reset();
|
|
||||||
} else {
|
|
||||||
document.getElementById('form-error').classList.remove('hidden');
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
document.getElementById('form-error').classList.remove('hidden');
|
|
||||||
} finally {
|
|
||||||
// Restore button state
|
|
||||||
submitButton.disabled = false;
|
|
||||||
submitButton.innerHTML = originalButtonText;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add input validation on blur
|
|
||||||
contactForm.querySelectorAll('input, textarea').forEach((input) => {
|
|
||||||
input.addEventListener('blur', function () {
|
|
||||||
validateInput(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addEventListener('input', function () {
|
|
||||||
// Remove error styling when user starts typing
|
|
||||||
this.classList.remove('border-red-500');
|
|
||||||
const feedbackElement = this.closest('div').querySelector('.invalid-feedback');
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.classList.add('hidden');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateForm(form) {
|
|
||||||
let isValid = true;
|
|
||||||
|
|
||||||
// Validate all inputs
|
|
||||||
form.querySelectorAll('input, textarea').forEach((input) => {
|
|
||||||
if (!validateInput(input)) {
|
|
||||||
isValid = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateInput(input) {
|
|
||||||
if (!input.required) return true;
|
|
||||||
|
|
||||||
let isValid = true;
|
|
||||||
const feedbackElement = input.closest('div').querySelector('.invalid-feedback');
|
|
||||||
|
|
||||||
// Reset previous error
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.classList.add('hidden');
|
|
||||||
}
|
|
||||||
input.classList.remove('border-red-500');
|
|
||||||
|
|
||||||
// Checkbox validation (special case for disclaimer)
|
|
||||||
if (input.type === 'checkbox') {
|
|
||||||
if (input.required && !input.checked) {
|
|
||||||
isValid = false;
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.textContent = 'Please check the required consent box before submitting';
|
|
||||||
feedbackElement.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
input.classList.add('border-red-500');
|
|
||||||
// Add red border to the checkbox container for better visibility
|
|
||||||
const checkboxContainer = input.closest('.flex.items-start');
|
|
||||||
if (checkboxContainer) {
|
|
||||||
checkboxContainer.classList.add('checkbox-error');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Remove error styling when checkbox is checked
|
|
||||||
const checkboxContainer = input.closest('.flex.items-start');
|
|
||||||
if (checkboxContainer) {
|
|
||||||
checkboxContainer.classList.remove('checkbox-error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if empty
|
|
||||||
if (input.required && !input.value.trim()) {
|
|
||||||
isValid = false;
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.textContent = 'This field is required';
|
|
||||||
feedbackElement.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
input.classList.add('border-red-500');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Email validation
|
|
||||||
if (input.type === 'email' && input.value.trim()) {
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(input.value.trim())) {
|
|
||||||
isValid = false;
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.textContent = 'Please enter a valid email address';
|
|
||||||
feedbackElement.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
input.classList.add('border-red-500');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Textarea minimum length
|
|
||||||
if (input.tagName === 'TEXTAREA' && input.value.trim().length < 10) {
|
|
||||||
isValid = false;
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.textContent = 'Please enter at least 10 characters';
|
|
||||||
feedbackElement.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
input.classList.add('border-red-500');
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetFormErrors() {
|
|
||||||
// Hide all error messages
|
|
||||||
document.querySelectorAll('.invalid-feedback').forEach((el) => {
|
|
||||||
el.classList.add('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove error styling
|
|
||||||
document.querySelectorAll('input, textarea').forEach((input) => {
|
|
||||||
input.classList.remove('border-red-500');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove checkbox container error styling
|
|
||||||
document.querySelectorAll('.flex.items-start').forEach((container) => {
|
|
||||||
container.classList.remove('checkbox-error');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hide form-level messages
|
|
||||||
document.getElementById('form-success')?.classList.add('hidden');
|
|
||||||
document.getElementById('form-error')?.classList.add('hidden');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
@@ -19,6 +19,7 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
|
|||||||
id="contact-form"
|
id="contact-form"
|
||||||
name="contact"
|
name="contact"
|
||||||
method="POST"
|
method="POST"
|
||||||
|
action="/api/contact"
|
||||||
class="needs-validation"
|
class="needs-validation"
|
||||||
novalidate
|
novalidate
|
||||||
>
|
>
|
||||||
|
Reference in New Issue
Block a user