Add form mailer

This commit is contained in:
2025-07-14 08:54:43 +02:00
parent 361beedb38
commit d5ae939f03
6 changed files with 395 additions and 2 deletions

View File

@ -4633,3 +4633,73 @@ body.theme-ecommerce {
color: var(--secondary-color);
background: rgba(52, 152, 219, 0.15);
}
/* Notification System */
.notification {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
max-width: 400px;
transform: translateX(100%);
transition: transform 0.3s ease-in-out;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.notification.show {
transform: translateX(0);
}
.notification-content {
display: flex;
align-items: center;
padding: 16px 20px;
border-radius: 8px;
font-weight: 500;
}
.notification-success {
background: linear-gradient(135deg, #28a745, #20c997);
color: white;
}
.notification-error {
background: linear-gradient(135deg, #dc3545, #e74c3c);
color: white;
}
.notification-info {
background: linear-gradient(135deg, #17a2b8, #3498db);
color: white;
}
.notification-close {
background: none;
border: none;
color: inherit;
margin-left: auto;
padding: 0;
cursor: pointer;
opacity: 0.8;
transition: opacity 0.2s;
}
.notification-close:hover {
opacity: 1;
}
/* Contact form button states */
.contact-submit-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.contact-submit-btn .fa-spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

View File

@ -361,3 +361,105 @@ document.addEventListener('DOMContentLoaded', function() {
`;
document.head.appendChild(style);
});
// Contact Form Handling
document.addEventListener('DOMContentLoaded', function() {
const contactForm = document.querySelector('.contact-form');
const submitBtn = document.querySelector('.contact-submit-btn');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
// Get form data
const formData = {
firstName: document.getElementById('firstName').value,
lastName: document.getElementById('lastName').value,
email: document.getElementById('email').value,
phone: document.getElementById('phone').value,
company: document.getElementById('company').value,
service: document.getElementById('service').value,
budget: document.getElementById('budget').value,
message: document.getElementById('message').value
};
// Disable submit button and show loading state
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Sending...';
}
// Send form data
fetch('/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Show success message
showNotification(data.message, 'success');
// Reset form
contactForm.reset();
} else {
// Show error message
showNotification(data.message, 'error');
}
})
.catch(error => {
console.error('Error:', error);
showNotification('An error occurred. Please try again.', 'error');
})
.finally(() => {
// Re-enable submit button
if (submitBtn) {
submitBtn.disabled = false;
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Send Message';
}
});
});
}
});
// Notification system
function showNotification(message, type = 'info') {
// Remove existing notifications
const existingNotifications = document.querySelectorAll('.notification');
existingNotifications.forEach(notification => notification.remove());
// Create notification element
const notification = document.createElement('div');
notification.className = `notification notification-${type}`;
notification.innerHTML = `
<div class="notification-content">
<i class="fas ${type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-circle' : 'fa-info-circle'} me-2"></i>
<span>${message}</span>
<button class="notification-close" onclick="this.parentElement.parentElement.remove()">
<i class="fas fa-times"></i>
</button>
</div>
`;
// Add to page
document.body.appendChild(notification);
// Show notification
setTimeout(() => {
notification.classList.add('show');
}, 100);
// Auto-hide after 5 seconds (except for errors)
if (type !== 'error') {
setTimeout(() => {
notification.classList.remove('show');
setTimeout(() => {
if (notification.parentElement) {
notification.remove();
}
}, 300);
}, 5000);
}
}