// Suds & Bubbles Laundromat - Main JavaScript // Theme Management const themeManager = { init() { const savedTheme = localStorage.getItem('theme') || 'light'; this.setTheme(savedTheme); // Listen for theme toggle from web components document.addEventListener('theme-change', (e) => { this.setTheme(e.detail.theme); }); }, setTheme(theme) { const html = document.documentElement; if (theme === 'dark') { html.classList.add('dark'); } else { html.classList.remove('dark'); } localStorage.setItem('theme', theme); }, toggle() { const isDark = document.documentElement.classList.contains('dark'); this.setTheme(isDark ? 'light' : 'dark'); } }; // Testimonials Data const testimonials = [ { name: "Sarah Johnson", role: "Busy Mom", image: "http://static.photos/people/200x200/1", rating: 5, text: "Suds & Bubbles has been a lifesaver! With three kids, I never have time for laundry. Their pickup and delivery service is incredible." }, { name: "Michael Chen", role: "Software Engineer", image: "http://static.photos/people/200x200/2", rating: 5, text: "The app makes it so easy to track my orders. I love getting notifications when my clothes are ready. Highly recommend!" }, { name: "Emily Rodriguez", role: "Restaurant Owner", image: "http://static.photos/people/200x200/3", rating: 5, text: "We use their commercial service for our restaurant linens. Always pristine, always on time. Best laundry service in the city!" } ]; // Render Testimonials function renderTestimonials() { const container = document.getElementById('testimonials'); if (!container) return; container.innerHTML = testimonials.map(t => `
${Array(t.rating).fill('').join('')}

${t.text}

${t.name}
${t.name}
${t.role}
`).join(''); // Re-initialize feather icons for new content if (typeof feather !== 'undefined') { feather.replace(); } } // Order Tracking Simulation const orderTracker = { statuses: [ { id: 'received', label: 'Order Received', icon: 'inbox', time: '9:00 AM' }, { id: 'picked', label: 'Picked Up', icon: 'truck', time: '10:30 AM' }, { id: 'processing', label: 'In Progress', icon: 'loader', time: '2:00 PM' }, { id: 'ready', label: 'Ready for Delivery', icon: 'package', time: '5:00 PM' }, { id: 'delivered', label: 'Delivered', icon: 'check-circle', time: '6:30 PM' } ], simulateProgress(orderId) { const container = document.getElementById('tracking-timeline'); if (!container) return; let currentStep = 0; const updateTimeline = () => { const progress = (currentStep / (this.statuses.length - 1)) * 100; container.innerHTML = `
${this.statuses.map((status, index) => `
${status.label}
${index <= currentStep ? status.time : 'Pending'}
`).join('')}
`; if (typeof feather !== 'undefined') { feather.replace(); } if (currentStep < this.statuses.length - 1) { currentStep++; setTimeout(updateTimeline, 2000); } }; updateTimeline(); } }; // Service Pricing Data const services = { washFold: { name: 'Wash & Fold', basePrice: 1.50, unit: 'lb', options: [ { name: 'Regular', price: 1.50 }, { name: 'Eco-Friendly', price: 2.00 }, { name: 'Hypoallergenic', price: 2.50 } ] }, dryCleaning: { name: 'Dry Cleaning', items: [ { name: 'Shirt/Blouse', price: 5.99 }, { name: 'Pants/Skirt', price: 7.99 }, { name: 'Suit (2pc)', price: 14.99 }, { name: 'Dress', price: 12.99 }, { name: 'Coat/Jacket', price: 15.99 } ] }, homeItems: { name: 'Home Items', items: [ { name: 'Bedding Set', price: 25.99 }, { name: 'Comforter', price: 35.99 }, { name: 'Curtains (per panel)', price: 15.99 }, { name: 'Rug (small)', price: 29.99 }, { name: 'Rug (large)', price: 49.99 } ] } }; // Calculate Order Total function calculateTotal(items) { return items.reduce((sum, item) => sum + (item.price * item.quantity), 0); } // Format Currency function formatCurrency(amount) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); } // Toast Notification function showToast(message, type = 'success') { const toast = document.createElement('div'); toast.className = `fixed bottom-4 right-4 px-6 py-3 rounded-xl shadow-lg transform translate-y-full transition-transform duration-300 z-50 ${type === 'success' ? 'bg-green-500' : 'bg-red-500'} text-white`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => toast.classList.remove('translate-y-full'), 100); setTimeout(() => { toast.classList.add('translate-y-full'); setTimeout(() => toast.remove(), 300); }, 3000); } // Form Validation function validateForm(form) { const required = form.querySelectorAll('[required]'); let valid = true; required.forEach(field => { if (!field.value.trim()) { field.classList.add('border-red-500'); valid = false; } else { field.classList.remove('border-red-500'); } }); return valid; } // Initialize on DOM Ready document.addEventListener('DOMContentLoaded', () => { themeManager.init(); renderTestimonials(); // Initialize feather icons if (typeof feather !== 'undefined') { feather.replace(); } // Handle tracking form const trackForm = document.getElementById('track-form'); if (trackForm) { trackForm.addEventListener('submit', (e) => { e.preventDefault(); const orderId = document.getElementById('order-id').value; if (orderId) { orderTracker.simulateProgress(orderId); } }); } // Handle order form const orderForm = document.getElementById('order-form'); if (orderForm) { orderForm.addEventListener('submit', (e) => { e.preventDefault(); if (validateForm(orderForm)) { showToast('Order placed successfully! Order #LB' + Date.now().toString().slice(-6)); orderForm.reset(); } else { showToast('Please fill in all required fields', 'error'); } }); } // Service item quantity controls document.querySelectorAll('.qty-btn').forEach(btn => { btn.addEventListener('click', (e) => { const input = e.target.closest('.qty-control').querySelector('input'); const action = e.target.dataset.action; let value = parseInt(input.value) || 0; if (action === 'inc') value++; if (action === 'dec' && value > 0) value--; input.value = value; updateOrderSummary(); }); }); }); // Update Order Summary (for order page) function updateOrderSummary() { const summary = document.getElementById('order-summary'); if (!summary) return; const items = []; document.querySelectorAll('.service-item').forEach(item => { const qty = parseInt(item.querySelector('input').value) || 0; if (qty > 0) { const price = parseFloat(item.dataset.price); const name = item.dataset.name; items.push({ name, price, quantity: qty }); } }); const subtotal = calculateTotal(items); const tax = subtotal * 0.08; const total = subtotal + tax; summary.innerHTML = `
${items.map(i => `
${i.name} x${i.quantity} ${formatCurrency(i.price * i.quantity)}
`).join('')}
Subtotal ${formatCurrency(subtotal)}
Tax (8%) ${formatCurrency(tax)}
Total ${formatCurrency(total)}
`; } // Export for use in other scripts window.SudsBubbles = { themeManager, orderTracker, services, calculateTotal, formatCurrency, showToast, validateForm };