/** * BotKonzept - Main JavaScript * ============================ * Handles all interactive functionality for the BotKonzept website */ // Configuration const CONFIG = { // API Endpoints - Update these for production WEBHOOK_URL: 'https://n8n.userman.de/webhook/botkonzept-registration', API_BASE_URL: 'https://api.botkonzept.de', // Validation MIN_NAME_LENGTH: 2, MAX_NAME_LENGTH: 50, // Animation SCROLL_OFFSET: 100, ANIMATION_DELAY: 100, }; // ============================================ // DOM Ready // ============================================ document.addEventListener('DOMContentLoaded', () => { initNavigation(); initMobileMenu(); initSmoothScroll(); initFAQ(); initRegistrationForm(); initScrollAnimations(); initTypingAnimation(); }); // ============================================ // Navigation // ============================================ function initNavigation() { const navbar = document.getElementById('navbar'); let lastScroll = 0; window.addEventListener('scroll', () => { const currentScroll = window.pageYOffset; // Add shadow on scroll if (currentScroll > 50) { navbar.style.boxShadow = '0 4px 6px -1px rgb(0 0 0 / 0.1)'; } else { navbar.style.boxShadow = 'none'; } // Hide/show navbar on scroll (optional) // if (currentScroll > lastScroll && currentScroll > 200) { // navbar.style.transform = 'translateY(-100%)'; // } else { // navbar.style.transform = 'translateY(0)'; // } lastScroll = currentScroll; }); } // ============================================ // Mobile Menu // ============================================ function initMobileMenu() { const mobileMenuBtn = document.getElementById('mobileMenuBtn'); const navLinks = document.getElementById('navLinks'); if (!mobileMenuBtn || !navLinks) return; mobileMenuBtn.addEventListener('click', () => { navLinks.classList.toggle('active'); // Toggle icon const icon = mobileMenuBtn.querySelector('i'); if (navLinks.classList.contains('active')) { icon.classList.remove('fa-bars'); icon.classList.add('fa-times'); } else { icon.classList.remove('fa-times'); icon.classList.add('fa-bars'); } }); // Close menu when clicking a link navLinks.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => { navLinks.classList.remove('active'); const icon = mobileMenuBtn.querySelector('i'); icon.classList.remove('fa-times'); icon.classList.add('fa-bars'); }); }); } // ============================================ // Smooth Scroll // ============================================ function initSmoothScroll() { document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); if (targetId === '#') return; const targetElement = document.querySelector(targetId); if (targetElement) { const navbarHeight = document.getElementById('navbar').offsetHeight; const targetPosition = targetElement.offsetTop - navbarHeight - 20; window.scrollTo({ top: targetPosition, behavior: 'smooth' }); } }); }); } // ============================================ // FAQ Accordion // ============================================ function initFAQ() { const faqItems = document.querySelectorAll('.faq-item'); faqItems.forEach(item => { const question = item.querySelector('.faq-question'); question.addEventListener('click', () => { // Close other items faqItems.forEach(otherItem => { if (otherItem !== item && otherItem.classList.contains('active')) { otherItem.classList.remove('active'); } }); // Toggle current item item.classList.toggle('active'); }); }); } // ============================================ // Registration Form // ============================================ function initRegistrationForm() { const form = document.getElementById('registerForm'); const submitBtn = document.getElementById('submitBtn'); const formSuccess = document.getElementById('formSuccess'); const formError = document.getElementById('formError'); if (!form) return; form.addEventListener('submit', async (e) => { e.preventDefault(); // Validate form if (!validateForm(form)) { return; } // Show loading state setLoadingState(submitBtn, true); // Collect form data const formData = { firstName: form.firstName.value.trim(), lastName: form.lastName.value.trim(), email: form.email.value.trim(), company: form.company.value.trim() || null, website: form.website.value.trim() || null, newsletter: form.newsletter.checked, timestamp: new Date().toISOString(), source: 'website', userAgent: navigator.userAgent, language: navigator.language, }; try { // Send registration request const response = await fetch(CONFIG.WEBHOOK_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formData), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); // Show success message form.style.display = 'none'; formSuccess.style.display = 'block'; // Track conversion (if analytics is set up) trackConversion('registration_complete', formData); } catch (error) { console.error('Registration error:', error); // Show error message form.style.display = 'none'; formError.style.display = 'block'; const errorMessage = document.getElementById('errorMessage'); if (errorMessage) { errorMessage.textContent = getErrorMessage(error); } } finally { setLoadingState(submitBtn, false); } }); } // Form validation function validateForm(form) { let isValid = true; // Clear previous errors form.querySelectorAll('.error').forEach(el => el.classList.remove('error')); form.querySelectorAll('.error-message').forEach(el => el.remove()); // Validate first name const firstName = form.firstName.value.trim(); if (firstName.length < CONFIG.MIN_NAME_LENGTH) { showFieldError(form.firstName, 'Bitte geben Sie Ihren Vornamen ein'); isValid = false; } // Validate last name const lastName = form.lastName.value.trim(); if (lastName.length < CONFIG.MIN_NAME_LENGTH) { showFieldError(form.lastName, 'Bitte geben Sie Ihren Nachnamen ein'); isValid = false; } // Validate email const email = form.email.value.trim(); if (!isValidEmail(email)) { showFieldError(form.email, 'Bitte geben Sie eine gültige E-Mail-Adresse ein'); isValid = false; } // Validate website (if provided) const website = form.website.value.trim(); if (website && !isValidURL(website)) { showFieldError(form.website, 'Bitte geben Sie eine gültige URL ein (z.B. https://beispiel.de)'); isValid = false; } // Validate privacy checkbox if (!form.privacy.checked) { showFieldError(form.privacy, 'Bitte akzeptieren Sie die Datenschutzerklärung'); isValid = false; } return isValid; } // Show field error function showFieldError(field, message) { field.classList.add('error'); field.style.borderColor = '#ef4444'; const errorDiv = document.createElement('div'); errorDiv.className = 'error-message'; errorDiv.style.color = '#ef4444'; errorDiv.style.fontSize = '0.75rem'; errorDiv.style.marginTop = '4px'; errorDiv.textContent = message; field.parentNode.appendChild(errorDiv); } // Email validation function isValidEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } // URL validation function isValidURL(url) { try { new URL(url); return true; } catch { return false; } } // Set loading state function setLoadingState(button, isLoading) { const btnText = button.querySelector('.btn-text'); const btnLoading = button.querySelector('.btn-loading'); if (isLoading) { button.disabled = true; if (btnText) btnText.style.display = 'none'; if (btnLoading) btnLoading.style.display = 'inline-flex'; } else { button.disabled = false; if (btnText) btnText.style.display = 'inline'; if (btnLoading) btnLoading.style.display = 'none'; } } // Get user-friendly error message function getErrorMessage(error) { if (error.message.includes('Failed to fetch')) { return 'Verbindungsfehler. Bitte überprüfen Sie Ihre Internetverbindung.'; } if (error.message.includes('500')) { return 'Serverfehler. Bitte versuchen Sie es später erneut.'; } if (error.message.includes('400')) { return 'Ungültige Eingabe. Bitte überprüfen Sie Ihre Daten.'; } return 'Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.'; } // Reset form function resetForm() { const form = document.getElementById('registerForm'); const formSuccess = document.getElementById('formSuccess'); const formError = document.getElementById('formError'); if (form) { form.reset(); form.style.display = 'flex'; } if (formSuccess) formSuccess.style.display = 'none'; if (formError) formError.style.display = 'none'; } // Make resetForm available globally window.resetForm = resetForm; // ============================================ // Scroll Animations // ============================================ function initScrollAnimations() { const animatedElements = document.querySelectorAll('.feature-card, .step, .pricing-card, .faq-item'); const observer = new IntersectionObserver((entries) => { entries.forEach((entry, index) => { if (entry.isIntersecting) { setTimeout(() => { entry.target.classList.add('visible'); entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; }, index * CONFIG.ANIMATION_DELAY); observer.unobserve(entry.target); } }); }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }); animatedElements.forEach(el => { el.style.opacity = '0'; el.style.transform = 'translateY(20px)'; el.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; observer.observe(el); }); } // ============================================ // Typing Animation (Chat Preview) // ============================================ function initTypingAnimation() { const typingMessage = document.querySelector('.message.typing'); if (!typingMessage) return; // Simulate typing response setTimeout(() => { typingMessage.innerHTML = '

Sie können Ihre Bestellung ganz einfach über unser Online-Formular aufgeben. Alternativ können Sie uns auch telefonisch unter 0800-123456 erreichen.

'; typingMessage.classList.remove('typing'); }, 3000); } // ============================================ // Analytics & Tracking // ============================================ function trackConversion(eventName, data = {}) { // Google Analytics 4 if (typeof gtag !== 'undefined') { gtag('event', eventName, { 'event_category': 'conversion', 'event_label': 'registration', ...data }); } // Facebook Pixel if (typeof fbq !== 'undefined') { fbq('track', 'Lead', data); } // Console log for debugging console.log('Conversion tracked:', eventName, data); } // ============================================ // Utility Functions // ============================================ // Debounce function function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Throttle function function throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // Format currency function formatCurrency(amount, currency = 'EUR') { return new Intl.NumberFormat('de-DE', { style: 'currency', currency: currency }).format(amount); } // Format date function formatDate(date) { return new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' }).format(new Date(date)); } // ============================================ // Export for testing // ============================================ if (typeof module !== 'undefined' && module.exports) { module.exports = { validateForm, isValidEmail, isValidURL, formatCurrency, formatDate }; }