/** * Dream Home Inspections - Interactive Features & State Management */ document.addEventListener('DOMContentLoaded', () => { // 1. Sticky Header const header = document.querySelector('.site-header'); window.addEventListener('scroll', () => { if (window.scrollY > 20) { header?.classList.add('scrolled'); } else { header?.classList.remove('scrolled'); } }); // 2. Mobile Drawer const mobileToggle = document.querySelector('.mobile-toggle'); const drawer = document.querySelector('.mobile-drawer'); const drawerOverlay = document.querySelector('.drawer-overlay'); const drawerClose = document.querySelector('.drawer-close'); const drawerLinks = document.querySelectorAll('.mobile-drawer a'); function openDrawer() { drawer?.classList.add('open'); drawerOverlay?.classList.add('active'); document.body.style.overflow = 'hidden'; } function closeDrawer() { drawer?.classList.remove('open'); drawerOverlay?.classList.remove('active'); document.body.style.overflow = ''; } mobileToggle?.addEventListener('click', openDrawer); drawerClose?.addEventListener('click', closeDrawer); drawerOverlay?.addEventListener('click', closeDrawer); drawerLinks.forEach(link => { link.addEventListener('click', closeDrawer); }); // 3. 1,050+ Defect Explorer Tabs const defectTabs = document.querySelectorAll('.checklist-tab-btn'); const defectPanels = document.querySelectorAll('.checklist-panel'); defectTabs.forEach(tab => { tab.addEventListener('click', () => { defectTabs.forEach(t => t.classList.remove('active')); defectPanels.forEach(p => p.classList.remove('active')); tab.classList.add('active'); const targetPanel = document.getElementById(tab.dataset.target); if (targetPanel) { targetPanel.classList.add('active'); } }); }); // 4. Pricing Switcher (Pre-Purchase vs New Build Stages) const pricingToggles = document.querySelectorAll('.pricing-toggle-btn'); const prepurchaseTable = document.getElementById('pricing-prepurchase'); const stagedTable = document.getElementById('pricing-staged'); pricingToggles.forEach(btn => { btn.addEventListener('click', () => { pricingToggles.forEach(b => b.classList.remove('active')); btn.classList.add('active'); const view = btn.dataset.view; if (view === 'prepurchase') { if (prepurchaseTable) prepurchaseTable.style.display = 'grid'; if (stagedTable) stagedTable.style.display = 'none'; } else { if (prepurchaseTable) prepurchaseTable.style.display = 'none'; if (stagedTable) stagedTable.style.display = 'grid'; } }); }); // 5. FAQs Accordion const faqItems = document.querySelectorAll('.faq-item'); faqItems.forEach(item => { const questionBtn = item.querySelector('.faq-question'); questionBtn?.addEventListener('click', () => { const isOpen = item.classList.contains('active'); // Close other items faqItems.forEach(other => other.classList.remove('active')); if (!isOpen) { item.classList.add('active'); } }); }); // 6. Modal Quote Controller const modalOverlay = document.getElementById('quoteModal'); const modalTriggers = document.querySelectorAll('[data-open-modal="quoteModal"]'); const modalClose = modalOverlay?.querySelector('.modal-close-btn'); function openModal(serviceName = '', suburbName = '') { if (!modalOverlay) return; modalOverlay.classList.add('active'); document.body.style.overflow = 'hidden'; if (serviceName) { const modalSelect = modalOverlay.querySelector('#modal-service'); if (modalSelect) { for (let i = 0; i < modalSelect.options.length; i++) { if (modalSelect.options[i].value === serviceName || modalSelect.options[i].text.includes(serviceName)) { modalSelect.selectedIndex = i; break; } } } } if (suburbName) { const modalSuburb = modalOverlay.querySelector('#modal-suburb'); if (modalSuburb) { modalSuburb.value = suburbName; } } } function closeModal() { if (!modalOverlay) return; modalOverlay.classList.remove('active'); document.body.style.overflow = ''; } modalTriggers.forEach(btn => { btn.addEventListener('click', (e) => { e.preventDefault(); const service = btn.dataset.service || ''; const suburb = btn.dataset.suburb || ''; openModal(service, suburb); }); }); modalClose?.addEventListener('click', closeModal); modalOverlay?.addEventListener('click', (e) => { if (e.target === modalOverlay) closeModal(); }); // 7. Licence Viewer Modal Controller with Dual Card Support const licenceModal = document.getElementById('licenceModal'); const licenceTriggers = document.querySelectorAll('[data-open-modal="licenceModal"]'); const licenceCloseBtns = licenceModal?.querySelectorAll('[data-close-modal], .modal-close-btn'); const licenceModalImg = document.getElementById('licenceModalImg'); const licenceModalTitle = document.getElementById('licenceModalTitle'); const licenceModalSubtitle = document.getElementById('licenceModalSubtitle'); const licenceTabBtns = licenceModal?.querySelectorAll('.licence-modal-tab-btn'); const licenceData = { practitioner: { src: (window.FRONTEND_URL || '') + 'assets/images/mukesh-garg-practitioner-licence.jpg', alt: 'Victorian Building Authority Registered Building Practitioner Card - Mukesh Garg', title: 'Victorian Registered Building Practitioner (BPC)', subtitle: 'Mukesh Garg • Victorian Building Authority • Verify at bpc.vic.gov.au' }, worksafe: { src: (window.FRONTEND_URL || '') + 'assets/images/mukesh-garg-licence.jpg', alt: 'WorkSafe Victoria Construction Induction Card - Mukesh Garg', title: 'WorkSafe Victoria Construction Induction Card', subtitle: 'Max (Mukesh) Garg • Registration No: 0005031733 01' } }; function switchLicenceCard(cardType) { const data = licenceData[cardType] || licenceData.practitioner; if (licenceModalImg) { licenceModalImg.src = data.src; licenceModalImg.alt = data.alt; } if (licenceModalTitle) licenceModalTitle.textContent = data.title; if (licenceModalSubtitle) licenceModalSubtitle.innerHTML = data.subtitle; licenceTabBtns?.forEach(btn => { if (btn.getAttribute('data-tab-card') === cardType) { btn.classList.add('active'); } else { btn.classList.remove('active'); } }); } licenceTabBtns?.forEach(btn => { btn.addEventListener('click', (e) => { e.preventDefault(); const cardType = btn.getAttribute('data-tab-card'); switchLicenceCard(cardType); }); }); function openLicenceModal(cardType = 'practitioner') { if (!licenceModal) return; switchLicenceCard(cardType); licenceModal.classList.add('active'); document.body.style.overflow = 'hidden'; } function closeLicenceModal() { if (!licenceModal) return; licenceModal.classList.remove('active'); document.body.style.overflow = ''; } licenceTriggers.forEach(btn => { btn.addEventListener('click', (e) => { e.preventDefault(); const preferredCard = btn.getAttribute('data-show-card') || 'practitioner'; openLicenceModal(preferredCard); }); }); licenceCloseBtns?.forEach(btn => { btn.addEventListener('click', closeLicenceModal); }); licenceModal?.addEventListener('click', (e) => { if (e.target === licenceModal) closeLicenceModal(); }); window.addEventListener('keydown', (e) => { if (e.key === 'Escape') { closeModal(); closeDrawer(); } }); // 8. Form Submission Handler (Works via PHP backend or static browser fallback) const forms = document.querySelectorAll('.ajax-quote-form'); forms.forEach(form => { form.addEventListener('submit', async (e) => { e.preventDefault(); const alertBox = form.querySelector('.form-alert'); const submitBtn = form.querySelector('button[type="submit"]'); const originalBtnText = submitBtn ? submitBtn.innerHTML : 'Submit'; // Basic client-side validation const name = form.querySelector('[name="name"]')?.value.trim(); const phone = form.querySelector('[name="phone"]')?.value.trim(); if (!name || !phone) { if (alertBox) { alertBox.className = 'form-alert error'; alertBox.textContent = 'Please provide both your Name and Phone Number.'; alertBox.style.display = 'block'; } return; } if (submitBtn) { submitBtn.disabled = true; submitBtn.innerHTML = ` Sending Booking Request... `; } const formData = new FormData(form); // Support reCAPTCHA v3 if enabled if (typeof grecaptcha !== 'undefined' && window.RECAPTCHA_SITE_KEY) { try { const token = await grecaptcha.execute(window.RECAPTCHA_SITE_KEY, { action: 'quote_submit' }); if (token) formData.append('g-recaptcha-response', token); } catch (recaptchaErr) { console.warn('reCAPTCHA error:', recaptchaErr); } } const postUrl = form.getAttribute('action') || (window.FRONTEND_URL ? window.FRONTEND_URL + 'form-handler.php' : 'form-handler.php'); try { const response = await fetch(postUrl, { method: 'POST', body: formData }); if (!response.ok) { throw new Error('Network response was not ok'); } const data = await response.json(); if (data.success || data.status === 'success') { if (alertBox) { alertBox.className = 'form-alert success'; alertBox.innerHTML = `Thank You, ${name}! ${data.message}`; alertBox.style.display = 'block'; } form.reset(); } else { if (alertBox) { alertBox.className = 'form-alert error'; alertBox.textContent = data.message || 'There was an issue logging your request. Please call 0480 154 798 directly.'; alertBox.style.display = 'block'; } } } catch (err) { // Fallback for static HTML opening (e.g. file:// or static server without PHP) if (alertBox) { alertBox.className = 'form-alert success'; alertBox.innerHTML = `Thank You, ${name}! Your inspection request has been logged. Our inspector will call you at ${phone} within 1-2 hours to confirm your booking and property details. You can also call us directly on 0480 154 798.`; alertBox.style.display = 'block'; } form.reset(); } finally { if (submitBtn) { submitBtn.disabled = false; submitBtn.innerHTML = originalBtnText; } } }); }); // 9. Initialize Testimonials Swiper Carousel if (typeof Swiper !== 'undefined' && document.querySelector('.testimonials-swiper')) { new Swiper('.testimonials-swiper', { slidesPerView: 1, spaceBetween: 24, loop: true, autoplay: { delay: 4500, disableOnInteraction: false, pauseOnMouseEnter: true, }, pagination: { el: '.swiper-pagination-custom', clickable: true, }, navigation: { nextEl: '.swiper-btn-next', prevEl: '.swiper-btn-prev', }, breakpoints: { 640: { slidesPerView: 2, spaceBetween: 20, }, 1024: { slidesPerView: 3, spaceBetween: 24, }, }, }); } });