header, .header, #header, footer, .footer, #footer { display: none !important; } body, html { margin:0 !important; padding:0 !important; } #main, #content, .container, .main, .wrapper { margin-top:0 !important; padding-top:0 !important; } @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600&family=DM+Mono:wght@400;500&display=swap'); :root { --bg: #0e1117; --surface: #161b25; --surface2: #1c2333; --border: #2a3347; --border2: #3a4a66; --accent: #0685a0; --accent-dim:#0585A0; --accent-glow: rgba(0,194,224,0.15); --text: #e5eaf4; --text-dim: #8a9bbf; --text-muted: #99E7FC; --red: #ff5c5c; --success: #0685a0; } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'DM Sans', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; padding: 40px 20px 60px; background-image: radial-gradient(ellipse 80% 50% at 50% -10%, rgba(0,194,224,0.07) 0%, transparent 60%); } .container { background: var(--surface); border: 1px solid var(--border); padding: 40px 36px; max-width: 860px; margin: auto; border-radius: 14px; box-shadow: 0 0 0 1px rgba(0,194,224,0.06), 0 24px 60px rgba(0,0,0,0.5); } /* Header */ .portal-header { text-align: center; margin-bottom: 38px; padding-bottom: 28px; border-bottom: 1px solid var(--border); } .portal-header .logo-row { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 6px; } .logo-icon { width: 36px; height: 36px; background: var(--accent); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; } h1 { font-size: 1.7rem; font-weight: 600; letter-spacing: -0.02em; color: var(--text); } .portal-header p { color: var(--text-dim); font-size: 0.88rem; margin-top: 4px; } /* Section headings */ h2 { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin: 32px 0 16px; display: flex; align-items: center; gap: 10px; } h2::after { content: ''; flex: 1; height: 1px; background: var(--border); } /* Labels & Inputs */ label { display: block; font-size: 0.82rem; font-weight: 500; color: var(--text-dim); margin-bottom: 5px; } label span.required { color: var(--red); margin-left: 2px; } input, textarea, select { width: 100%; padding: 10px 14px; margin-bottom: 16px; background: var(--surface2); border: 1px solid var(--border); border-radius: 7px; color: var(--text); font-family: 'DM Sans', sans-serif; font-size: 0.9rem; outline: none; transition: border-color 0.2s, box-shadow 0.2s; -webkit-appearance: none; } input::placeholder, textarea::placeholder { color: var(--text-muted); } input:focus, textarea:focus, select:focus { border-color: var(--accent-dim); box-shadow: 0 0 0 3px var(--accent-glow); } select { cursor: pointer; } select option { background: var(--surface2); } textarea { resize: vertical; min-height: 80px; } /* Password wrapper */ .password-wrapper { position: relative; display: flex; align-items: center; } .password-wrapper input { flex: 1; padding-right: 40px; margin-bottom: 16px; } .password-wrapper .toggle-password { position: absolute; right: 12px; cursor: pointer; font-size: 16px; color: var(--text-muted); user-select: none; transition: color 0.2s; } .password-wrapper .toggle-password:hover { color: var(--accent); } /* Device box */ .device-box { border: 1px solid var(--border); padding: 22px 22px 16px; margin-top: 16px; border-radius: 10px; background: var(--surface2); position: relative; } .device-box h3 { font-size: 0.85rem; font-weight: 600; color: var(--accent); margin-bottom: 18px; letter-spacing: 0.04em; text-transform: uppercase; } /* Buttons */ button { font-family: 'DM Sans', sans-serif; cursor: pointer; transition: all 0.2s; } .add-btn { background: transparent; color: var(--accent); border: 1px solid var(--accent-dim); border-radius: 7px; padding: 9px 20px; font-size: 0.88rem; font-weight: 500; display: inline-flex; align-items: center; gap: 7px; } .add-btn:hover { background: var(--accent-glow); border-color: var(--accent); } .submit-btn { width: 100%; background: var(--accent); color: #0a1520; border: none; border-radius: 8px; padding: 13px; font-size: 0.95rem; font-weight: 600; letter-spacing: 0.02em; margin-top: 10px; box-shadow: 0 0 20px rgba(0,194,224,0.25); } .submit-btn:hover { background: #00d8f8; box-shadow: 0 0 28px rgba(0,194,224,0.4); transform: translateY(-1px); } .submit-btn:active { transform: translateY(0); } .remove-btn { position: absolute; top: 14px; right: 14px; background: transparent; color: var(--text-muted); border: 1px solid var(--border); border-radius: 5px; padding: 3px 9px; font-size: 0.75rem; font-weight: 500; } .remove-btn:hover { background: rgba(255,92,92,0.12); color: var(--red); border-color: var(--red); } .advanced-btn { background: transparent; color: var(--text-muted); border: 1px solid var(--border); border-radius: 5px; padding: 6px 12px; font-size: 0.8rem; margin-top: 2px; margin-bottom: 4px; } .advanced-btn:hover { color: var(--accent); border-color: var(--accent-dim); } input.invalid { border-color: var(--red); } input.invalid:focus { box-shadow: 0 0 0 3px rgba(255,92,92,0.15); } .field-error { font-size: 0.76rem; color: var(--red); margin: -10px 0 10px; display: none; } .field-error.visible { display: block; } .field-hint { font-size: 0.76rem; color: var(--text-muted); margin: -10px 0 10px; display: block; } /* Password security note */ .password-security-note { font-size: 0.75rem; color: var(--text-muted); margin: -8px 0 12px; display: flex; align-items: center; gap: 5px; } .password-security-note::before { content: '🔒'; font-size: 0.7rem; } /* Submit button spinner */ .submit-btn { display: flex; align-items: center; justify-content: center; gap: 10px; } .btn-spinner { display: none; width: 16px; height: 16px; border: 2px solid rgba(10,21,32,0.3); border-top-color: #0a1520; border-radius: 50%; animation: spin 0.7s linear infinite; flex-shrink: 0; } .submit-btn.loading .btn-spinner { display: block; } .submit-btn.loading .btn-text { opacity: 0.8; } .submit-btn:disabled { opacity: 0.75; cursor: not-allowed; } /* Autocomplete */ .autocomplete-wrapper { position: relative; } .autocomplete-items { border: 1px solid var(--border); border-top: none; z-index: 99; position: absolute; background: var(--surface2); max-height: 200px; overflow-y: auto; width: 100%; border-radius: 0 0 7px 7px; box-shadow: 0 8px 24px rgba(0,0,0,0.4); } .autocomplete-item { padding: 10px 14px; cursor: pointer; font-size: 0.85rem; color: var(--text-dim); border-bottom: 1px solid var(--border); } .autocomplete-item:last-child { border-bottom: none; } .autocomplete-item:hover { background: var(--accent-glow); color: var(--text); } /* Terms */ .terms { background: var(--surface2); border: 1px solid var(--border); border-left: 3px solid var(--accent-dim); border-radius: 7px; padding: 16px 18px; margin: 28px 0 16px; } .terms p { font-size: 0.8rem; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 10px; } .terms ul { padding-left: 18px; } .terms ul li { font-size: 0.83rem; color: var(--text); line-height: 1.6; margin-bottom: 5px; } /* Checkbox */ .centered { text-align: center; margin-top: 8px; } .checkbox-inline { display: inline-flex; align-items: center; cursor: pointer; gap: 8px; font-size: 0.88rem; color: var(--text-dim); } .checkbox-inline input[type="checkbox"] { appearance: none; -webkit-appearance: none; width: 18px; height: 18px; margin: 0; border: 2px solid var(--border2); border-radius: 4px; background: var(--surface2); cursor: pointer; position: relative; transition: all 0.15s; flex-shrink: 0; } .checkbox-inline input[type="checkbox"]:checked { background: #22c55e; border-color: #22c55e; } .checkbox-inline input[type="checkbox"]:checked::after { content: ''; position: absolute; left: 50%; top: 50%; width: 5px; height: 9px; border: 2px solid white; border-top: none; border-left: none; transform: translate(-50%, -60%) rotate(45deg); } .checkbox-inline input[type="checkbox"]:focus { outline: none; box-shadow: 0 0 0 3px rgba(34,197,94,0.2); } /* Modal */ #thankyouModal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); backdrop-filter: blur(4px); z-index: 1000; } #thankyouContent { background: var(--surface); border: 1px solid var(--accent-dim); color: var(--text); padding: 40px 36px; border-radius: 14px; width: 90%; max-width: 420px; margin: 15% auto; text-align: center; box-shadow: 0 0 40px rgba(0,194,224,0.2); } #thankyouContent h2 { font-size: 1.3rem; color: var(--accent); justify-content: center; margin-bottom: 10px; letter-spacing: 0; text-transform: none; } #thankyouContent h2::after { display: none; } #thankyouContent p { color: var(--text-dim); font-size: 0.9rem; } @keyframes spin { to { transform: rotate(360deg); } } .spinner { width: 48px; height: 48px; border: 4px solid rgba(0,194,224,0.2); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; margin: 0 auto 20px; } ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-track { background: var(--surface); } ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; } ul li { color: #F2F5E8 !important; } } 🖥️ Computer Help NZ Self Service Portal — Submit a repair or service request Customer Information First Name * Last Name * Phone Number * Please enter a valid NZ phone number (e.g. 021 123 4567 or 03 123 4567) NZ mobile: 02x xxx xxxx | Landline: 0x xxx xxxx Email Address * Physical Address * Device Information + Add Another Device Terms & Conditions Assessment Fees: All new assessments are charged at $125, payable upfront. Work will not commence until payment is received, unless otherwise agreed. Repair Guarantee: Repairs are guaranteed for 3 months unless otherwise specified. Payment Terms: Payment for completed jobs is expected on device pickup. CHNZ reserves the right to retain devices related to unpaid invoices. I agree to the Terms & Conditions * Submit Job ✅ Request Submitted! Refreshing the form… // ───────────────────────────────────────────── // EMAILJS CONFIGURATION // ───────────────────────────────────────────── const EMAILJS_PUBLIC_KEY = "bQfZTldDnhO4RLpKH"; const EMAILJS_SERVICE_ID = "service_46fjhff"; const EMAILJS_TEMPLATE_ID = "template_bqpqwdr"; // ───────────────────────────────────────────── emailjs.init({ publicKey: EMAILJS_PUBLIC_KEY }); let deviceCount = 0; // ── NZ Phone Validation ───────────────────────── const phoneInput = document.getElementById('phoneInput'); const phoneError = document.getElementById('phoneError'); const NZ_PHONE_RE = /^(\+?64|0)(2\d{7,9}|[3-9]\d{7})$/; function validatePhone() { const val = phoneInput.value.replace(/[\s\-()+]/g, ''); const valid = NZ_PHONE_RE.test(val); const hasInput = phoneInput.value.length > 0; phoneInput.classList.toggle('invalid', !valid && hasInput); phoneError.classList.toggle('visible', !valid && hasInput); return valid; } phoneInput.addEventListener('blur', validatePhone); phoneInput.addEventListener('input', () => { if (phoneInput.classList.contains('invalid')) validatePhone(); }); // ── Add Device ────────────────────────────────── function addDevice() { deviceCount++; const div = document.createElement("div"); div.classList.add("device-box"); div.innerHTML = ` Remove Device ${deviceCount} Brand * Device Type * Charger? * Select Yes or No Yes No Password * 👁 Password is transmitted securely and deleted once your job is complete Issue Description * Show Advanced Options ▼ Model Number Serial Number `; document.getElementById("devices").appendChild(div); const toggle = div.querySelector(".toggle-password"); const input = div.querySelector("input[type='password']"); toggle.addEventListener("click", () => { input.type = input.type === "password" ? "text" : "password"; toggle.textContent = input.type === "password" ? "👁" : "🙈"; }); } // ── Remove Device ─────────────────────────────── function removeDevice(btn) { btn.parentElement.remove(); const boxes = document.querySelectorAll(".device-box"); deviceCount = boxes.length; boxes.forEach((box, i) => { box.querySelector("h3").textContent = `Device ${i+1}`; box.querySelectorAll("input, select, textarea").forEach(input => { input.name = (input.name || '').replace(/Device \d+/, `Device ${i+1}`); }); }); } // ── Toggle Advanced ───────────────────────────── function toggleAdvanced(btn) { const hiddenDiv = btn.nextElementSibling; if (hiddenDiv.style.display === "none" || hiddenDiv.style.display === "") { hiddenDiv.style.display = "block"; btn.textContent = "Hide Advanced Options ▲"; } else { hiddenDiv.style.display = "none"; btn.textContent = "Show Advanced Options ▼"; } } // ── Init ──────────────────────────────────────── window.addEventListener('DOMContentLoaded', () => { document.getElementById('serviceForm').reset(); document.getElementById('devices').innerHTML = ''; deviceCount = 0; addDevice(); }); // ── Submit ────────────────────────────────────── document.getElementById('serviceForm').addEventListener('submit', async function(e) { e.preventDefault(); if (!validatePhone()) { phoneInput.focus(); return; } const submitBtn = document.querySelector('.submit-btn'); submitBtn.disabled = true; submitBtn.classList.add('loading'); const firstName = document.querySelector('input[name="First Name"]').value; const lastName = document.querySelector('input[name="Last Name"]').value; const customerEmail = document.querySelector('input[name="Email Address"]').value; const subject = `[UNCHECKED] Self Service - ${firstName} ${lastName}`; // ── Build HTML email body ────────────────────── const tdLabel = `style="padding:8px 12px;background:#1a2235;color:#8a9bbf;font-size:13px;font-weight:600;width:160px;border:1px solid #2a3347;white-space:nowrap;"`; const tdValue = `style="padding:8px 12px;background:#0e1117;color:#e4eaf4;font-size:13px;border:1px solid #2a3347;"`; const tableStyle = `style="width:100%;border-collapse:collapse;margin-bottom:24px;font-family:Arial,sans-serif;"`; const headingStyle = `style="font-family:Arial,sans-serif;font-size:13px;font-weight:700;color:#00c2e0;text-transform:uppercase;letter-spacing:0.1em;padding:10px 12px;background:#0d1829;border:1px solid #2a3347;border-bottom:2px solid #00c2e0;"`; function row(label, value) { return `${label}${value || '—'}`; } function sectionTable(heading, rows) { return ` ${heading} ${rows} `; } const customerRows = sectionTable('Customer Information', row('First Name', firstName) + row('Last Name', lastName) + row('Email', customerEmail) + row('Phone Number', document.querySelector('input[name="Phone Number"]').value) + row('Physical Address', document.querySelector('input[name="Physical Address"]').value) ); let deviceRows = ''; document.querySelectorAll(".device-box").forEach((d, i) => { deviceRows += sectionTable(`Device ${i+1}`, row('Brand', d.querySelector(`input[name^="Device ${i+1} Brand"]`)?.value) + row('Type', d.querySelector(`input[name^="Device ${i+1} Type"]`)?.value) + row('Charger', d.querySelector(`select[name^="Device ${i+1} Charger"]`)?.value) + row('Password', d.querySelector(`input[name^="Device ${i+1} Password"]`)?.value) + row('Issue', d.querySelector(`textarea[name^="Device ${i+1} Issue"]`)?.value) + row('Model Number', d.querySelector(`input[name^="Device ${i+1} Model Number"]`)?.value) + row('Serial Number', d.querySelector(`input[name^="Device ${i+1} Serial Number"]`)?.value) ); }); const htmlMessage = ` New ticket submitted via CHNZ Self Service Portal — please create or attach to a customer account. ${customerRows} ${deviceRows} `; try { await emailjs.send(EMAILJS_SERVICE_ID, EMAILJS_TEMPLATE_ID, { title: subject, message: htmlMessage, to_email: 'support@chnz.co.nz', reply_to: customerEmail, customer_email: customerEmail }); document.getElementById('thankyouModal').style.display = 'block'; setTimeout(() => { window.location.href = 'https://www.chnz.co.nz/bookin'; // Or use window.location.replace(...) if you don't want the current page in browser history }, 3000); } catch (err) { console.error('EmailJS error:', err); alert('Failed to send. Please try again.\n\nError: ' + (err.text || err)); submitBtn.disabled = false; submitBtn.classList.remove('loading'); } }); // ── Address Autocomplete (debounced Nominatim) ── const addressInput = document.getElementById("PhysicalAddress"); const suggestionBox = document.getElementById("addressAutocomplete"); let addrDebounce = null; addressInput.addEventListener("input", function() { clearTimeout(addrDebounce); const query = this.value; suggestionBox.innerHTML = ""; if (query.length < 3) return; addrDebounce = setTimeout(() => { fetch(`https://nominatim.openstreetmap.org/search?format=json&addressdetails=1&limit=6&countrycodes=nz&q=${encodeURIComponent(query)}`) .then(res => res.json()) .then(data => { suggestionBox.innerHTML = ""; data.forEach(place => { const div = document.createElement("div"); div.classList.add("autocomplete-item"); div.textContent = place.display_name; div.addEventListener("mousedown", function(e) { e.preventDefault(); addressInput.value = this.textContent; suggestionBox.innerHTML = ""; }); suggestionBox.appendChild(div); }); }) .catch(() => { suggestionBox.innerHTML = ""; }); }, 300); }); document.addEventListener("click", function(e) { if (!suggestionBox.contains(e.target) && e.target !== addressInput) { suggestionBox.innerHTML = ""; } });