updated form
This commit is contained in:
70
NETLIFY-FORMS-SETUP.md
Normal file
70
NETLIFY-FORMS-SETUP.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# Netlify Forms Setup Guide
|
||||||
|
|
||||||
|
This document explains how the contact form has been configured to work with Netlify's built-in form handling service.
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
1. **Form Component Modifications**
|
||||||
|
- Added `data-netlify="true"` attribute to enable Netlify Forms
|
||||||
|
- Added `name="contact"` attribute to identify the form
|
||||||
|
- Added a honeypot field with `data-netlify-honeypot="bot-field"` to prevent spam
|
||||||
|
- Added a hidden input with the form name for Netlify to process the form correctly
|
||||||
|
|
||||||
|
2. **Form Handling Script Updates**
|
||||||
|
- Removed CSRF token generation and validation (not needed with Netlify Forms)
|
||||||
|
- Updated form submission to use Netlify's form handling endpoint
|
||||||
|
- Simplified error handling and success messaging
|
||||||
|
|
||||||
|
3. **Netlify Configuration**
|
||||||
|
- Updated `netlify.toml` to explicitly enable form processing
|
||||||
|
|
||||||
|
## Configuring Form Notifications in Netlify
|
||||||
|
|
||||||
|
After deploying your site, follow these steps to set up email notifications for form submissions:
|
||||||
|
|
||||||
|
1. **Access Form Settings**
|
||||||
|
- Log in to your Netlify dashboard
|
||||||
|
- Select your site
|
||||||
|
- Go to **Site settings** > **Forms**
|
||||||
|
|
||||||
|
2. **Verify Form Detection**
|
||||||
|
- You should see your "contact" form listed
|
||||||
|
- If not, check your deployment logs for any issues
|
||||||
|
|
||||||
|
3. **Set Up Form Notifications**
|
||||||
|
- Click on your form name
|
||||||
|
- Go to the **Outgoing notifications** tab
|
||||||
|
- Click **Add notification** and select **Email notification**
|
||||||
|
- Configure the email address where you want to receive form submissions
|
||||||
|
- Customize the subject line and other settings as needed
|
||||||
|
|
||||||
|
4. **Test the Form**
|
||||||
|
- Visit your live site
|
||||||
|
- Submit a test message through the contact form
|
||||||
|
- Verify you receive the notification email
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If your form isn't working properly:
|
||||||
|
|
||||||
|
1. **Check Form Detection**
|
||||||
|
- Ensure your form was detected during deployment
|
||||||
|
- Look for "Processing forms from HTML" in your deploy logs
|
||||||
|
|
||||||
|
2. **Verify Form Markup**
|
||||||
|
- Ensure the form has `data-netlify="true"`
|
||||||
|
- Confirm the hidden input field has `name="form-name"` with the correct form name
|
||||||
|
|
||||||
|
3. **Check for JavaScript Errors**
|
||||||
|
- Open your browser's developer console
|
||||||
|
- Look for any errors during form submission
|
||||||
|
|
||||||
|
4. **Review Spam Filtering**
|
||||||
|
- Check if submissions are being marked as spam
|
||||||
|
- Adjust spam filtering settings in Netlify if needed
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Netlify Forms Documentation](https://docs.netlify.com/forms/setup/)
|
||||||
|
- [Form Notifications](https://docs.netlify.com/forms/notifications/)
|
||||||
|
- [Spam Filtering](https://docs.netlify.com/forms/spam-filters/)
|
10
netlify.toml
10
netlify.toml
@@ -1,9 +1,19 @@
|
|||||||
[build]
|
[build]
|
||||||
publish = "dist"
|
publish = "dist"
|
||||||
command = "npm run build"
|
command = "npm run build"
|
||||||
|
|
||||||
[build.processing.html]
|
[build.processing.html]
|
||||||
pretty_urls = false
|
pretty_urls = false
|
||||||
|
|
||||||
[[headers]]
|
[[headers]]
|
||||||
for = "/_astro/*"
|
for = "/_astro/*"
|
||||||
[headers.values]
|
[headers.values]
|
||||||
Cache-Control = "public, max-age=31536000, immutable"
|
Cache-Control = "public, max-age=31536000, immutable"
|
||||||
|
|
||||||
|
# Netlify Form handling
|
||||||
|
[build.processing]
|
||||||
|
skip_processing = false
|
||||||
|
|
||||||
|
[build.processing.forms]
|
||||||
|
# Enable Netlify Forms processing
|
||||||
|
enabled = true
|
||||||
|
@@ -463,39 +463,12 @@ import { UI } from 'astrowind:config';
|
|||||||
setupContactForm();
|
setupContactForm();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch CSRF token from the server
|
// Netlify form handling setup
|
||||||
async function fetchCsrfToken() {
|
|
||||||
console.log('Fetching CSRF token');
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/contact?csrf=true');
|
|
||||||
console.log('CSRF response status:', response.status);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error('CSRF request failed:', response.statusText);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
console.log('CSRF token received:', data.csrfToken ? 'yes' : 'no');
|
|
||||||
return data.csrfToken;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching CSRF token:', error);
|
|
||||||
console.error('Error details:', error.message);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setupContactForm() {
|
async function setupContactForm() {
|
||||||
const contactForm = document.getElementById('contact-form');
|
const contactForm = document.getElementById('contact-form');
|
||||||
if (!contactForm) return;
|
if (!contactForm) return;
|
||||||
|
|
||||||
// Get CSRF token and set it in the form
|
|
||||||
const csrfTokenInput = contactForm.querySelector('#csrf_token');
|
|
||||||
if (csrfTokenInput) {
|
|
||||||
const token = await fetchCsrfToken();
|
|
||||||
csrfTokenInput.value = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form validation and submission
|
// Form validation and submission
|
||||||
contactForm.addEventListener('submit', async function(e) {
|
contactForm.addEventListener('submit', async function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -530,81 +503,24 @@ import { UI } from 'astrowind:config';
|
|||||||
// Add timestamp to help prevent duplicate submissions
|
// Add timestamp to help prevent duplicate submissions
|
||||||
formData.append('timestamp', Date.now().toString());
|
formData.append('timestamp', Date.now().toString());
|
||||||
|
|
||||||
console.log('Sending form data to /api/contact');
|
// Submit the form to Netlify
|
||||||
const response = await fetch('/api/contact', {
|
console.log('Submitting form to Netlify');
|
||||||
|
const response = await fetch('/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
headers: {
|
body: new URLSearchParams(formData).toString()
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Response status:', response.status);
|
console.log('Response status:', response.status);
|
||||||
const result = await response.json();
|
|
||||||
console.log('Response data:', result);
|
|
||||||
|
|
||||||
if (result.success) {
|
if (response.ok) {
|
||||||
console.log('Form submission successful');
|
console.log('Form submission successful');
|
||||||
// Show success message
|
// Show success message
|
||||||
document.getElementById('form-success').classList.remove('hidden');
|
document.getElementById('form-success').classList.remove('hidden');
|
||||||
contactForm.reset();
|
contactForm.reset();
|
||||||
|
|
||||||
// Get a new CSRF token for next submission
|
|
||||||
console.log('Getting new CSRF token');
|
|
||||||
const newToken = await fetchCsrfToken();
|
|
||||||
console.log('New CSRF token:', newToken ? 'received' : 'not received');
|
|
||||||
if (csrfTokenInput) {
|
|
||||||
csrfTokenInput.value = newToken;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Form submission failed:', result);
|
console.log('Form submission failed');
|
||||||
// Show specific error messages instead of generic form error
|
document.getElementById('form-error').classList.remove('hidden');
|
||||||
if (result.errors) {
|
|
||||||
console.log('Form errors:', result.errors);
|
|
||||||
|
|
||||||
// Only show the generic error if there are no field-specific errors
|
|
||||||
// or if there's a server error not related to a specific field
|
|
||||||
const hasFieldErrors = Object.keys(result.errors).some(field =>
|
|
||||||
['name', 'email', 'message', 'disclaimer', 'csrf'].includes(field)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasFieldErrors) {
|
|
||||||
document.getElementById('form-error').classList.remove('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display field-specific errors
|
|
||||||
Object.keys(result.errors).forEach(field => {
|
|
||||||
const inputElement = contactForm.querySelector(`[name="${field}"]`);
|
|
||||||
if (inputElement) {
|
|
||||||
const feedbackElement = inputElement.closest('div').querySelector('.invalid-feedback');
|
|
||||||
if (feedbackElement) {
|
|
||||||
feedbackElement.textContent = result.errors[field];
|
|
||||||
feedbackElement.classList.remove('hidden');
|
|
||||||
inputElement.classList.add('border-red-500');
|
|
||||||
|
|
||||||
// Special handling for checkbox
|
|
||||||
if (field === 'disclaimer') {
|
|
||||||
const checkboxContainer = inputElement.closest('.flex.items-start');
|
|
||||||
if (checkboxContainer) {
|
|
||||||
checkboxContainer.classList.add('checkbox-error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// If no specific errors, show the generic error
|
|
||||||
document.getElementById('form-error').classList.remove('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
// If CSRF token is invalid, get a new one
|
|
||||||
if (result.errors && result.errors.csrf) {
|
|
||||||
console.log('CSRF token invalid, getting new token');
|
|
||||||
const newToken = await fetchCsrfToken();
|
|
||||||
if (csrfTokenInput) {
|
|
||||||
csrfTokenInput.value = newToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error submitting form:', error);
|
console.error('Error submitting form:', error);
|
||||||
|
@@ -15,7 +15,7 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form id="contact-form" action="/api/contact" method="POST" class="needs-validation" novalidate>
|
<form id="contact-form" name="contact" method="POST" class="needs-validation" data-netlify="true" data-netlify-honeypot="bot-field" novalidate>
|
||||||
|
|
||||||
<!-- Form status messages -->
|
<!-- Form status messages -->
|
||||||
<div id="form-success" class="hidden mb-6 p-4 bg-green-100 border border-green-200 text-green-700 rounded-lg">
|
<div id="form-success" class="hidden mb-6 p-4 bg-green-100 border border-green-200 text-green-700 rounded-lg">
|
||||||
@@ -26,8 +26,13 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
|
|||||||
There was an error sending your message. Please check all fields and try again.
|
There was an error sending your message. Please check all fields and try again.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- CSRF Token - Will be populated via JavaScript -->
|
<!-- Netlify form name -->
|
||||||
<input type="hidden" name="csrf_token" id="csrf_token" value="" />
|
<input type="hidden" name="form-name" value="contact" />
|
||||||
|
|
||||||
|
<!-- Honeypot field to prevent spam -->
|
||||||
|
<p class="hidden">
|
||||||
|
<label>Don't fill this out if you're human: <input name="bot-field" /></label>
|
||||||
|
</p>
|
||||||
{
|
{
|
||||||
inputs &&
|
inputs &&
|
||||||
inputs.map(
|
inputs.map(
|
||||||
|
Reference in New Issue
Block a user