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);