Naxawoo Plumbing

Your Cart

Service Unit Price Qty Total Actions

Subtotal: CAD $0.00

naxawoo.top

Confirm your order

We’ll contact you to schedule the service and confirm details.

Support: +1 647-284-3915

Order placed

Thank you! Your order has been received. We’ll reach out shortly.

'; } try { document.getElementById('site-footer').innerHTML = await loadPartial('footer.html'); } catch(e){ document.getElementById('site-footer').innerHTML = ''; } try { const modals = await loadPartial('modals.html'); const w=document.createElement('div'); w.innerHTML=modals; document.body.appendChild(w); } catch(e){} initUI(); initCart(); })(); function initUI(){ document.querySelectorAll('[data-modal-target]').forEach(b=>b.addEventListener('click', ()=>document.querySelector(b.getAttribute('data-modal-target'))?.showModal())); document.body.addEventListener('click', (e)=>{ if(e.target.matches('[data-modal-close]')) e.target.closest('dialog')?.close(); }); const savedTheme=localStorage.getItem('theme')||'light'; document.documentElement.classList.toggle('dark', savedTheme==='dark'); syncThemeIcon(); document.getElementById('theme-toggle').addEventListener('click', toggleTheme); const cookieKey='cookie-consent'; const cb=document.getElementById('cookie-banner'); if(!localStorage.getItem(cookieKey)){ cb.classList.remove('hidden'); } document.getElementById('cookie-accept').addEventListener('click', ()=>{ localStorage.setItem(cookieKey,'accepted'); cb.classList.add('hidden'); }); document.getElementById('cookie-decline').addEventListener('click', ()=>{ localStorage.setItem(cookieKey,'declined'); cb.classList.add('hidden'); }); // Close dialog when clicking outside the form document.querySelectorAll('dialog').forEach(d=>{ d.addEventListener('click', (e)=>{ const rect = d.getBoundingClientRect(); if(!(e.clientX>=rect.left && e.clientX<=rect.right && e.clientY>=rect.top && e.clientY<=rect.bottom)){ d.close(); }}); }); const email = document.getElementById('email'); const postal = document.getElementById('postal'); email?.addEventListener('input', ()=>{ document.getElementById('emailError').classList.toggle('hidden', email.checkValidity()); }); postal?.addEventListener('input', ()=>{ document.getElementById('postalError').classList.toggle('hidden', postal.checkValidity()); }); } function toggleTheme(){ const isDark = document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', isDark?'dark':'light'); syncThemeIcon(); } function syncThemeIcon(){ const isDark = document.documentElement.classList.contains('dark'); const sun=document.getElementById('icon-sun'); const moon=document.getElementById('icon-moon'); if(isDark){ sun.classList.remove('hidden'); moon.classList.add('hidden'); } else { moon.classList.remove('hidden'); sun.classList.add('hidden'); } } let DATA = [], CART = {}, subtotalNum = 0, holdInterval = null; async function initCart(){ const bodyEl = document.getElementById('cart-body'); if(!window.__cartHandlerBound){ bodyEl.addEventListener('click', onCartAction); window.__cartHandlerBound = true; } try { DATA = await (await fetch('catalog.json')).json(); } catch(e){ const empty = document.getElementById('cart-empty'); const wrap = document.getElementById('cart-wrap'); empty.textContent = 'Unable to load catalog. Please try again later.'; empty.classList.remove('hidden'); wrap.classList.add('hidden'); console.error(e); return; } CART = JSON.parse(localStorage.getItem('cart')||'{}'); renderCart(); document.getElementById('checkout').addEventListener('click', onCheckout); document.getElementById('clear-cart').addEventListener('click', ()=>{ CART={}; persist(); }); initHoldTimer(); setupCheckoutForm(); } function currency(n){ return `CAD $${(n||0).toFixed(2)}`; } function renderCart(){ const ids = Object.keys(CART); const empty = document.getElementById('cart-empty'); const wrap = document.getElementById('cart-wrap'); const body = document.getElementById('cart-body'); body.innerHTML=''; if (!ids.length){ empty.classList.remove('hidden'); wrap.classList.add('hidden'); updateHoldUI(true); return; } empty.classList.add('hidden'); wrap.classList.remove('hidden'); let subtotal=0; ids.forEach(id=>{ const item = DATA.find(x=>String(x.id)===String(id)); if(!item) return; const qty = Math.max(1, Number(CART[id]||1)); const unit = Number(item.priceCAD||0); const rowTotal = unit * qty; subtotal += rowTotal; const tr=document.createElement('tr'); tr.className = 'odd:bg-white even:bg-gray-50 dark:odd:bg-gray-900 dark:even:bg-gray-800'; tr.innerHTML = `
${item.name||'Service'} ID: ${item.id}
${currency(unit)}
${qty}
${currency(rowTotal)} `; body.appendChild(tr); }); subtotalNum = subtotal; document.getElementById('cart-sum').textContent = `Subtotal: ${currency(subtotal)}`; updateCheckoutState(); updateHoldUI(false); } function onCartAction(e){ const btn = e.target.closest('button'); if(!btn) return; const inc=btn.getAttribute('data-inc'); const dec=btn.getAttribute('data-dec'); const del=btn.getAttribute('data-del'); if (inc){ CART[inc]=(CART[inc]||1)+1; persist(); } if (dec){ CART[dec]=Math.max(1,(CART[dec]||1)-1); persist(); } if (del){ delete CART[del]; persist(); } } function persist(){ localStorage.setItem('cart', JSON.stringify(CART)); renderCart(); } function onCheckout(){ const ids = Object.keys(CART||{}); if(!ids.length) return; document.getElementById('checkout-modal').showModal(); } function setupCheckoutForm(){ const form = document.getElementById('checkout-form'); form.addEventListener('submit', (e)=>{ if(!form.checkValidity()){ e.preventDefault(); form.reportValidity(); document.getElementById('emailError').classList.toggle('hidden', document.getElementById('email').checkValidity()); document.getElementById('postalError').classList.toggle('hidden', document.getElementById('postal').checkValidity()); return; } e.preventDefault(); const items = Object.keys(CART).map(id=>{ const item = DATA.find(x=>String(x.id)===String(id)); if(!item) return null; const qty = Math.max(1, Number(CART[id]||1)); const unit = Number(item.priceCAD||0); return { id: item.id, name: item.name, unitPrice: unit, qty, total: unit*qty }; }).filter(Boolean); const orderNo = 'NXW-' + Math.random().toString(36).slice(2,6).toUpperCase() + '-' + Date.now().toString().slice(-4); document.getElementById('orderNo').value = orderNo; document.getElementById('subtotalField').value = subtotalNum.toFixed(2); document.getElementById('cartPayload').value = JSON.stringify({ currency: 'CAD', subtotal: subtotalNum, items }); document.getElementById('checkout-modal').close(); document.getElementById('success-orderNo').textContent = orderNo; document.getElementById('order-success').showModal(); CART = {}; persist(); sessionStorage.removeItem('cartHoldUntil'); }); } function updateCheckoutState(){ const checkoutBtn = document.getElementById('checkout'); const hasItems = Object.keys(CART).length>0; checkoutBtn.disabled = !hasItems; checkoutBtn.classList.toggle('opacity-60', !hasItems); checkoutBtn.classList.toggle('cursor-not-allowed', !hasItems); } function initHoldTimer(){ const holdEl = document.getElementById('hold-pill'); const timeEl = document.getElementById('hold-time'); const key = 'cartHoldUntil'; if(!Object.keys(CART).length){ holdEl.hidden = true; if(holdInterval) clearInterval(holdInterval); return; } let until = Number(sessionStorage.getItem(key)||0); if(!until || until