/**
* 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,
},
},
});
}
});