Files
devbox-web/devbox-front/script.js
2025-06-09 15:18:16 +02:00

270 lines
8.7 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function() {
const emailForm = document.getElementById('emailForm');
const successMessage = document.getElementById('successMessage');
const API_BASE_URL = 'http://localhost:8080'; // Backend API URL
emailForm.addEventListener('submit', function(e) {
e.preventDefault();
const emailInput = document.getElementById('email');
const email = emailInput.value.trim();
// Basic email validation
if (!isValidEmail(email)) {
showError('Please enter a valid email address');
return;
}
// Submit email to backend
submitEmail(email);
});
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function submitEmail(email) {
// Show loading state
const submitBtn = document.querySelector('.submit-btn');
const originalText = submitBtn.textContent;
submitBtn.textContent = 'Joining...';
submitBtn.disabled = true;
submitBtn.classList.add('loading');
// Send to backend
fetch(`${API_BASE_URL}/api/subscribe`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
source: 'devbox-landing'
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Hide form and show success message
emailForm.style.display = 'none';
successMessage.classList.add('show');
console.log('DevBox waitlist email submitted:', email);
// Optional: Track the successful signup
trackEmailSignup(email);
} else {
// Show error message
showError(data.message || 'Email already subscribed or invalid.');
// Reset button
resetSubmitButton(submitBtn, originalText);
}
})
.catch((error) => {
console.error('Error:', error);
showError('Network error. Please check your connection and try again.');
// Reset button
resetSubmitButton(submitBtn, originalText);
});
}
function resetSubmitButton(submitBtn, originalText) {
submitBtn.textContent = originalText;
submitBtn.disabled = false;
submitBtn.classList.remove('loading');
}
function showError(message) {
// Remove existing error messages
const existingError = document.querySelector('.error-message');
if (existingError) {
existingError.remove();
}
// Create and show error message
const errorDiv = document.createElement('div');
errorDiv.className = 'error-message';
errorDiv.style.cssText = `
background: #ef4444;
color: white;
padding: 1rem 1.5rem;
border-radius: 8px;
margin-top: 1rem;
font-size: 0.9rem;
border: 1px solid #dc2626;
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
animation: slideDown 0.3s ease;
`;
errorDiv.textContent = message;
emailForm.appendChild(errorDiv);
// Remove error after 5 seconds
setTimeout(() => {
if (errorDiv.parentNode) {
errorDiv.style.animation = 'slideUp 0.3s ease';
setTimeout(() => {
errorDiv.remove();
}, 300);
}
}, 5000);
}
function trackEmailSignup(email) {
// Optional: Add analytics tracking here
// Example: Google Analytics, Mixpanel, etc.
console.log(`📧 Email signup tracked: ${email} at ${new Date().toISOString()}`);
// You could also send additional tracking data to your backend
// or third-party analytics services here
}
// Add smooth scrolling for any anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth'
});
}
});
});
// Add subtle animation to feature cards on scroll (Intersection Observer)
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe feature items for animation
document.querySelectorAll('.feature-item').forEach(item => {
// Set initial state
item.style.opacity = '0';
item.style.transform = 'translateY(20px)';
item.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
// Start observing
observer.observe(item);
});
// Add keyboard accessibility
document.addEventListener('keydown', function(e) {
// Close error messages with Escape key
if (e.key === 'Escape') {
const errorMessage = document.querySelector('.error-message');
if (errorMessage) {
errorMessage.remove();
}
}
});
// Form validation enhancements
const emailInput = document.getElementById('email');
emailInput.addEventListener('input', function() {
// Remove error styling when user starts typing
const errorMessage = document.querySelector('.error-message');
if (errorMessage) {
errorMessage.style.opacity = '0.5';
}
// Real-time validation feedback
if (this.value.length > 0) {
if (isValidEmail(this.value)) {
this.style.borderColor = '#10b981';
this.style.boxShadow = '0 0 0 1px rgba(16, 185, 129, 0.2)';
} else {
this.style.borderColor = '#ef4444';
this.style.boxShadow = '0 0 0 1px rgba(239, 68, 68, 0.2)';
}
} else {
// Reset to default styling
this.style.borderColor = '';
this.style.boxShadow = '';
}
});
// Add focus states for better accessibility
emailInput.addEventListener('focus', function() {
this.parentElement.style.boxShadow = '0 0 0 3px rgba(50, 108, 229, 0.1)';
});
emailInput.addEventListener('blur', function() {
this.parentElement.style.boxShadow = '';
// Reset border styling
this.style.borderColor = '';
this.style.boxShadow = '';
});
// Simple analytics: track page engagement
let startTime = Date.now();
let maxScroll = 0;
window.addEventListener('scroll', function() {
const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
maxScroll = Math.max(maxScroll, scrollPercent);
});
window.addEventListener('beforeunload', function() {
const timeOnPage = Math.round((Date.now() - startTime) / 1000);
console.log(`📊 Session stats: ${timeOnPage}s on page, ${Math.round(maxScroll)}% max scroll`);
// You could send this data to your analytics endpoint
// fetch('/api/analytics', { method: 'POST', body: JSON.stringify({ timeOnPage, maxScroll }) });
});
// Add some visual polish: animate elements on load
setTimeout(() => {
document.body.classList.add('loaded');
}, 100);
console.log('🚀 DevBox landing page initialized');
console.log(`📡 API endpoint: ${API_BASE_URL}`);
});
// Add CSS animations via JavaScript (if not in CSS file)
const style = document.createElement('style');
style.textContent = `
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideUp {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-10px);
}
}
body {
opacity: 0;
transition: opacity 0.3s ease;
}
body.loaded {
opacity: 1;
}
`;
document.head.appendChild(style);