/* ════════════════════════════════════════════════════════════════ QIP Diagnostic Imaging Accreditation Registration qip-diagnostic-imaging-registration.js Stripe integration mirrors AGPAL / ADA / SPAP pattern exactly: 1. waitForToken / dataversePost / fetchLeadRef / spinner 2. diaSubmit: validates page 7, then createAllRecords() Lead → Contact → PaymentEvidence → redirect to /agpal-stripe-checkout 3. Stripe return handled by shared /agpal-stripe-return — no changes. Lead subject = page title: "QIP Diagnostic Imaging Registration – {practiceName}" Content Snippets required: dia/cc-surcharge-rate 0.01927 dia/gst-rate 0.10 agpal/contact-type-id GUID (shared) stripe/flow-url Power Automate checkout flow (shared) stripe/flow-url-verify Power Automate verify flow (shared) sessionStorage keys (distinct from AGPAL/ADA/SPAP): dia_registration_lead_id dia_registration_lead_ref dia_registration_evidence_id dia_payment_in_progress ════════════════════════════════════════════════════════════════ */ (function () { 'use strict'; /* ── Config ──────────────────────────────────────── */ var TOTAL_PAGES = 7; var LABELS = { 1: 'Contact', 2: 'Details', 3: 'Practice', 4: 'Address', 5: 'Modalities', 6: 'Standards', 7: 'Submit' }; var FEE_MATRIX = { entry: { single: 590, '2-3': 975, '4-6': 1155, '7-9': 1635 }, full: { single: 1765, '2-3': 2925, '4-6': 3470, '7-9': 4900 } }; var PC = window.portalContext || {}; var config = { ccSurchargeRate: parseFloat(PC.diaCCSurchargeRate) || 0.01927, gstRate: parseFloat(PC.diaGSTRate) || 0.10, contactTypeId: PC.contactTypeId || '' }; var state = { currentPage: 1, sigCtx: null, sigDrawing: false, isBusy: false, leadId: null, leadRef: null, paymentEvidenceId: null, leadIdKey: 'dia_registration_lead_id', leadRefKey: 'dia_registration_lead_ref', evidenceIdKey: 'dia_registration_evidence_id', paymentInProgressKey: 'dia_payment_in_progress' }; /* ════════════════════════════════════════════════════════════ SPINNER ════════════════════════════════════════════════════════════ */ function injectSpinner() { if (document.getElementById('dia-spinner-overlay')) return; var style = document.createElement('style'); style.textContent = '@keyframes dia-spin{to{transform:rotate(360deg)}}' + '#dia-spinner-overlay{display:none;position:fixed;inset:0;background:rgba(26,58,74,0.65);' + 'z-index:99999;align-items:center;justify-content:center;flex-direction:column;gap:18px;}'; document.head.appendChild(style); var overlay = document.createElement('div'); overlay.id = 'dia-spinner-overlay'; overlay.setAttribute('aria-live', 'assertive'); overlay.innerHTML = '
' + '
Please wait\u2026
'; document.body.appendChild(overlay); } function setBusy(busy, msg) { state.isBusy = busy; var overlay = document.getElementById('dia-spinner-overlay'); var msgEl = document.getElementById('dia-spinner-msg'); if (overlay) overlay.style.display = busy ? 'flex' : 'none'; if (msgEl && msg) msgEl.textContent = msg; if (msgEl && !busy) msgEl.textContent = 'Please wait\u2026'; document.querySelectorAll('button').forEach(function (btn) { if (busy) { btn.setAttribute('data-was-disabled', btn.disabled ? '1' : '0'); btn.disabled = true; } else { btn.disabled = btn.getAttribute('data-was-disabled') === '1'; } }); } /* ════════════════════════════════════════════════════════════ CSRF TOKEN ════════════════════════════════════════════════════════════ */ function waitForToken() { return new Promise(function (resolve, reject) { var pc = window.portalContext || {}; var cached = pc.csrfToken || pc.requestVerificationToken; if (cached && cached.length > 20) { resolve(cached); return; } var domEl = document.querySelector('input[name="__RequestVerificationToken"]'); if (domEl && domEl.value) { resolve(domEl.value); return; } var csrfEl = document.getElementById('csrf-token-value'); if (csrfEl && csrfEl.value && csrfEl.value.length > 20) { resolve(csrfEl.value); return; } var attempts = 0; var poll = setInterval(function () { attempts++; var pv = (window.portalContext || {}).csrfToken; if (pv && pv.length > 20) { clearInterval(poll); resolve(pv); return; } var el = document.getElementById('csrf-token-value'); if (el && el.value && el.value.length > 20) { clearInterval(poll); resolve(el.value); return; } if (attempts >= 30) { clearInterval(poll); fetch('/Account/Login', { credentials: 'same-origin', headers: { 'Accept': 'text/html' } }) .then(function (r) { return r.text(); }) .then(function (html) { var m = html.match(/name="__RequestVerificationToken"[^>]*value="([^"]+)"/); if (!m) m = html.match(/value="([^"]{40,})"[^>]*name="__RequestVerificationToken"/); if (m && m[1]) { resolve(m[1]); } else { reject(new Error('CSRF token not found')); } }) .catch(function (e) { reject(new Error('CSRF fetch failed: ' + e.message)); }); } }, 150); }); } /* ════════════════════════════════════════════════════════════ DATAVERSE API ════════════════════════════════════════════════════════════ */ function extractEntityId(data, response) { if (data && typeof data === 'object') { var fromBody = data.leadid || data.contactid || data.ongc_paymentevidenceid; if (!fromBody && data['@odata.id']) { var m = data['@odata.id'].match(/\(([0-9a-f-]{36})\)/i); if (m) fromBody = m[1]; } if (fromBody) return fromBody; } var headerVal = ''; if (response && typeof response.headers === 'object' && typeof response.headers.get === 'function') { headerVal = response.headers.get('OData-EntityId') || ''; } if (headerVal) { var m2 = headerVal.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i); if (m2) return m2[0]; } return null; } async function dataversePost(entitySet, payload) { var url = '/_api/' + entitySet; var token = await waitForToken(); var response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', '__RequestVerificationToken': token, 'OData-MaxVersion': '4.0', 'OData-Version': '4.0', 'Prefer': 'return=representation' }, body: JSON.stringify(payload) }); if (!response.ok) { var errMsg = 'API error ' + response.status; try { var errJson = await response.json(); errMsg = (errJson && errJson.error && errJson.error.message) || errMsg; } catch (e) { } throw new Error(errMsg); } var data = {}; try { data = await response.json(); } catch (e) { } return { id: extractEntityId(data, response), data: data }; } async function fetchLeadRef(leadId) { try { var token = await waitForToken(); var r = await fetch('/_api/leads(' + leadId + ')?$select=ongc_leadrefid,ongc_clientid', { method: 'GET', headers: { '__RequestVerificationToken': token, 'OData-MaxVersion': '4.0', 'OData-Version': '4.0', 'Accept': 'application/json' } }); if (!r.ok) return null; var d = await r.json(); return (d && (d.ongc_leadrefid || d.ongc_clientid)) || null; } catch (e) { return null; } } /* ════════════════════════════════════════════════════════════ SESSION STORAGE ════════════════════════════════════════════════════════════ */ function clearSession() { [state.leadIdKey, state.leadRefKey, state.evidenceIdKey, state.paymentInProgressKey].forEach(function (k) { try { sessionStorage.removeItem(k); } catch (e) { } }); state.leadId = null; state.leadRef = null; state.paymentEvidenceId = null; } function saveSession() { try { if (state.leadId) sessionStorage.setItem(state.leadIdKey, state.leadId); if (state.leadRef) sessionStorage.setItem(state.leadRefKey, state.leadRef); if (state.paymentEvidenceId) sessionStorage.setItem(state.evidenceIdKey, state.paymentEvidenceId); } catch (e) { } } /* ════════════════════════════════════════════════════════════ HELPERS ════════════════════════════════════════════════════════════ */ function round2(n) { return Math.round(n * 100) / 100; } function gVal(id) { var el = document.getElementById(id); return el ? el.value.trim() : ''; } function stripEmpty(payload) { Object.keys(payload).forEach(function (k) { if (payload[k] === '' || payload[k] === null || payload[k] === undefined) delete payload[k]; }); return payload; } /* ════════════════════════════════════════════════════════════ FEE CALCULATION ════════════════════════════════════════════════════════════ */ function getFeeBase() { var lvl = gVal('standardsLevel'); var cnt = gVal('entryModalityCount') || gVal('fullModalityCount'); return (lvl && cnt && FEE_MATRIX[lvl] && FEE_MATRIX[lvl][cnt]) ? FEE_MATRIX[lvl][cnt] : 0; } function calcFees() { var base = getFeeBase(); var surcharge = round2(base * config.ccSurchargeRate); var gst = round2((base + surcharge) * config.gstRate); var total = round2(base + surcharge + gst); return { base: round2(base), surcharge: surcharge, gst: gst, total: total }; } function diaUpdateFee() { var base = getFeeBase(); var el = document.getElementById('diaFeeAmount'); if (el) el.textContent = base > 0 ? base.toLocaleString('en-AU', { minimumFractionDigits: 2 }) : '0.00'; } /* ════════════════════════════════════════════════════════════ PROGRESS BAR ════════════════════════════════════════════════════════════ */ function buildProgress() { var c = document.getElementById('diaProgressSteps'); if (!c) return; c.innerHTML = ''; for (var i = 1; i <= TOTAL_PAGES; i++) { var div = document.createElement('div'); div.className = 'dia-step-item' + (state.currentPage === i ? ' active' : '') + (state.currentPage > i ? ' done' : ''); div.innerHTML = '
' + (state.currentPage > i ? '✓' : i) + '
' + '
' + (LABELS[i] || i) + '
'; c.appendChild(div); } } /* ════════════════════════════════════════════════════════════ PAGE NAVIGATION ════════════════════════════════════════════════════════════ */ function showPage(n) { if (state.isBusy && typeof n === 'number') return; document.querySelectorAll('.dia-form-page').forEach(function (el) { el.classList.remove('active'); }); var target = (n === 'success') ? document.getElementById('diaSuccess') : document.querySelector('.dia-form-page[data-page="' + n + '"]'); if (target) { target.classList.add('active'); window.scrollTo({ top: 0, behavior: 'smooth' }); } if (typeof n === 'number') state.currentPage = n; buildProgress(); if (n === 6) { diaUpdateFee(); } if (n === 7) { initSig(); diaUpdateFee(); } } function diaNextPage(n) { if (!state.isBusy && validatePage(n)) showPage(n + 1); } function diaPrevPage(n) { if (!state.isBusy) showPage(n - 1); } /* ════════════════════════════════════════════════════════════ VALIDATION ════════════════════════════════════════════════════════════ */ function req(id, errId) { var el = document.getElementById(id); var err = document.getElementById(errId); var ok = el && el.value.trim() !== ''; if (err) err.classList.toggle('visible', !ok); return ok; } function validatePage(n) { var ok = true; if (n === 1) { ok = req('contactFirstName', 'err_contactFirstName') && ok; ok = req('contactLastName', 'err_contactLastName') && ok; ok = req('contactPosition', 'err_contactPosition') && ok; ok = req('contactPhone', 'err_contactPhone') && ok; ok = req('contactEmail', 'err_contactEmail') && ok; } if (n === 2) { ok = req('lspnNumber', 'err_lspnNumber') && ok; ok = req('registeringType', 'err_registeringType') && ok; ok = req('providingType', 'err_providingType') && ok; ok = req('corporateGroup', 'err_corporateGroup') && ok; if (gVal('corporateGroup') === 'yes') ok = req('corporateName', 'err_corporateName') && ok; ok = req('previouslyAccredited', 'err_previouslyAccredited') && ok; if (gVal('previouslyAccredited') === 'yes') { ok = req('previousProvider', 'err_previousProvider') && ok; ok = req('previousExpiryDate', 'err_previousExpiryDate') && ok; } ok = req('sector', 'err_sector') && ok; if (gVal('sector') === 'other') ok = req('sectorOther', 'err_sectorOther') && ok; } if (n === 3) { ok = req('practiceName', 'err_practiceName') && ok; ok = req('practiceABN', 'err_practiceABN') && ok; ok = req('practicePhone', 'err_practicePhone') && ok; ok = req('practiceEmail', 'err_practiceEmail') && ok; } if (n === 4) { var cityOk = document.getElementById('streetCity') && document.getElementById('streetCity').value.trim(); var stateOk = document.getElementById('streetState') && document.getElementById('streetState').value; var pcOk = document.getElementById('streetPostcode') && document.getElementById('streetPostcode').value.trim(); var addrOk = cityOk && stateOk && pcOk; var addrErr = document.getElementById('err_streetAddress'); if (addrErr) addrErr.classList.toggle('visible', !addrOk); ok = !!addrOk && ok; var postalYes = document.getElementById('postalYes'); if (postalYes && postalYes.checked) { var pCityOk = document.getElementById('postalCity') && document.getElementById('postalCity').value.trim(); var pStateOk = document.getElementById('postalState') && document.getElementById('postalState').value; var pPcOk = document.getElementById('postalPostcode') && document.getElementById('postalPostcode').value.trim(); var postalOk = pCityOk && pStateOk && pPcOk; var postalErr = document.getElementById('err_postalAddress'); if (postalErr) postalErr.classList.toggle('visible', !postalOk); ok = !!postalOk && ok; } } if (n === 5) { var selected = document.querySelectorAll('.dia-modality-cb:checked').length > 0; var modErr = document.getElementById('err_modalities'); if (modErr) modErr.classList.toggle('visible', !selected); ok = selected && ok; ok = req('equipmentUnits', 'err_equipmentUnits') && ok; } if (n === 6) { ok = req('standardsLevel', 'err_standardsLevel') && ok; var lvl = gVal('standardsLevel'); if (lvl === 'entry') ok = req('entryModalityCount', 'err_entryModalityCount') && ok; if (lvl === 'full') ok = req('fullModalityCount', 'err_fullModalityCount') && ok; } if (!ok) { var first = document.querySelector('.dia-error-msg.visible'); if (first) first.scrollIntoView({ behavior: 'smooth', block: 'center' }); } return ok; } /* ════════════════════════════════════════════════════════════ CONDITIONALS ════════════════════════════════════════════════════════════ */ function diaCorporateChange() { toggle('grp_corporateName', gVal('corporateGroup') === 'yes'); } function diaPrevAccreditedChange() { toggle('grp_previousDetails', gVal('previouslyAccredited') === 'yes'); } function diaSectorChange() { toggle('grp_sectorOther', gVal('sector') === 'other'); } function diaPostalToggle(val) { toggle('grp_postalAddress', val === 'yes'); } function diaStandardsChange() { var v = gVal('standardsLevel'); toggle('grp_entryModalityCount', v === 'entry'); toggle('grp_fullModalityCount', v === 'full'); diaUpdateFee(); } function toggle(id, show) { var el = document.getElementById(id); if (el) el.classList.toggle('show', show); } /* ════════════════════════════════════════════════════════════ MODALITY CARDS ════════════════════════════════════════════════════════════ */ function bindModalityCards() { document.querySelectorAll('.dia-modality-card').forEach(function (card) { card.addEventListener('click', function () { var cb = card.querySelector('.dia-modality-cb'); if (cb) { cb.checked = !cb.checked; card.classList.toggle('selected', cb.checked); } updateModCount(); }); }); } function updateModCount() { var count = document.querySelectorAll('.dia-modality-cb:checked').length; var el = document.getElementById('diaModCount'); if (el) el.textContent = count + ' modalit' + (count === 1 ? 'y' : 'ies') + ' selected'; } /* ════════════════════════════════════════════════════════════ SIGNATURE CANVAS ════════════════════════════════════════════════════════════ */ function initSig() { var c = document.getElementById('diaSignatureCanvas'); if (!c) return; var fresh = c.cloneNode(true); c.parentNode.replaceChild(fresh, c); c = fresh; c.width = c.parentElement.clientWidth || 680; c.height = 120; state.sigCtx = c.getContext('2d'); state.sigCtx.strokeStyle = '#1A3A4A'; state.sigCtx.lineWidth = 2.2; state.sigCtx.lineCap = 'round'; state.sigCtx.lineJoin = 'round'; var ctx = state.sigCtx; function pos(e) { var r = c.getBoundingClientRect(); var pt = e.touches ? e.touches[0] : e; return { x: pt.clientX - r.left, y: pt.clientY - r.top }; } c.addEventListener('mousedown', function (e) { state.sigDrawing = true; ctx.beginPath(); var p = pos(e); ctx.moveTo(p.x, p.y); }); c.addEventListener('mousemove', function (e) { if (!state.sigDrawing) return; var p = pos(e); ctx.lineTo(p.x, p.y); ctx.stroke(); }); c.addEventListener('mouseup', function () { state.sigDrawing = false; }); c.addEventListener('mouseleave', function () { state.sigDrawing = false; }); c.addEventListener('touchstart', function (e) { e.preventDefault(); state.sigDrawing = true; ctx.beginPath(); var p = pos(e); ctx.moveTo(p.x, p.y); }, { passive: false }); c.addEventListener('touchmove', function (e) { e.preventDefault(); if (!state.sigDrawing) return; var p = pos(e); ctx.lineTo(p.x, p.y); ctx.stroke(); }, { passive: false }); c.addEventListener('touchend', function () { state.sigDrawing = false; }); } function diaClearSig() { var c = document.getElementById('diaSignatureCanvas'); if (state.sigCtx && c) state.sigCtx.clearRect(0, 0, c.width, c.height); } function isSigEmpty() { var c = document.getElementById('diaSignatureCanvas'); if (!c || !state.sigCtx) return true; var d = state.sigCtx.getImageData(0, 0, c.width, c.height).data; for (var i = 3; i < d.length; i += 4) { if (d[i] > 0) return false; } return true; } /* ════════════════════════════════════════════════════════════ PAYLOAD BUILDERS ════════════════════════════════════════════════════════════ */ function buildLeadPayload() { var practiceName = gVal('practiceName'); var postalDiff = document.getElementById('postalYes') && document.getElementById('postalYes').checked; var selected = []; document.querySelectorAll('.dia-modality-cb:checked').forEach(function (cb) { selected.push(cb.value); }); var payload = { subject: 'QIP Diagnostic Imaging Registration \u2013 ' + practiceName, firstname: gVal('contactFirstName'), lastname: gVal('contactLastName') || practiceName, jobtitle: gVal('contactPosition'), emailaddress1: gVal('contactEmail'), telephone1: gVal('contactPhone'), companyname: practiceName, websiteurl: gVal('practiceWebsite'), leadsourcecode: 8, /* Street address */ address1_line1: gVal('streetAddr0'), address1_line2: gVal('streetAddr1'), address1_city: gVal('streetCity'), address1_stateorprovince: gVal('streetState'), address1_postalcode: gVal('streetPostcode'), address1_country: 'Australia', /* Postal */ address2_line1: postalDiff ? gVal('postalAddr0') : '', address2_line2: postalDiff ? gVal('postalAddr1') : '', address2_city: postalDiff ? gVal('postalCity') : '', address2_stateorprovince: postalDiff ? gVal('postalState') : '', address2_postalcode: postalDiff ? gVal('postalPostcode') : '', address2_country: postalDiff ? 'Australia' : '', /* Custom ONGC fields */ ongc_enquirytype: 4, /* 4 = Diagnostic Imaging */ ongc_practicename: practiceName, ongc_practiceabn: gVal('practiceABN'), ongc_practicephone: gVal('practicePhone'), ongc_postalsameasstreet: !postalDiff, ongc_corporateentity: gVal('corporateName'), /* Diagnostic Imaging specific — stored in description */ description: JSON.stringify({ lspn: gVal('lspnNumber'), registeringType: gVal('registeringType'), providingType: gVal('providingType'), corporateGroup: gVal('corporateGroup'), previouslyAccredited: gVal('previouslyAccredited'), previousProvider: gVal('previousProvider'), previousExpiryDate: gVal('previousExpiryDate'), sector: gVal('sector'), sectorOther: gVal('sectorOther'), standardsLevel: gVal('standardsLevel'), modalities: selected.join(', '), equipmentUnits: gVal('equipmentUnits') }) }; return stripEmpty(payload); } function buildContactPayload() { var payload = { firstname: gVal('contactFirstName'), lastname: gVal('contactLastName'), jobtitle: gVal('contactPosition'), emailaddress1: gVal('contactEmail'), telephone1: gVal('contactPhone'), mobilephone: gVal('practicePhone') }; if (state.leadId) { payload['originatingleadid@odata.bind'] = '/leads(' + state.leadId + ')'; } if (config.contactTypeId) { payload['ongc_ContactType@odata.bind'] = '/ongc_contacttypes(' + config.contactTypeId + ')'; } return stripEmpty(payload); } function buildPaymentEvidencePayload() { var fees = calcFees(); var payload = { ongc_payername: (gVal('contactFirstName') + ' ' + gVal('contactLastName')).trim(), ongc_paymentamount: fees.base, ongc_surchargefee: fees.surcharge, ongc_gst: fees.gst, ongc_totalamount: fees.total, ongc_paymentstatus: 'pending-cc', ongc_transactionstatus: 'pending', ongc_paymentdate: new Date().toISOString(), ongc_responsemessage: 'Pending \u2013 QIP Diagnostic Imaging Stripe credit-card checkout initiated' }; if (state.leadId) { payload['ongc_Lead@odata.bind'] = '/leads(' + state.leadId + ')'; } return stripEmpty(payload); } /* ════════════════════════════════════════════════════════════ RECORD CREATION CHAIN ════════════════════════════════════════════════════════════ */ async function createAllRecords() { /* 1. Lead — critical */ setBusy(true, 'Creating registration record\u2026'); var lead = await dataversePost('leads', buildLeadPayload()); state.leadId = lead.id; if (!state.leadId) throw new Error('Lead created but GUID not returned. Check Dataverse Web API permissions.'); console.log('[DIA] Lead created:', state.leadId); /* 2. Fetch autonumber leadRef */ setBusy(true, 'Fetching registration reference\u2026'); var fetchedRef = await fetchLeadRef(state.leadId); state.leadRef = fetchedRef || null; console.log('[DIA] leadRef:', state.leadRef); saveSession(); /* 3. Contact — non-blocking */ setBusy(true, 'Creating contact record\u2026'); try { var cr = await Promise.allSettled([dataversePost('contacts', buildContactPayload())]); if (cr[0].status === 'rejected') console.warn('[DIA] Contact failed (non-fatal):', cr[0].reason && cr[0].reason.message); else console.log('[DIA] Contact created:', cr[0].value && cr[0].value.id); } catch (e) { console.warn('[DIA] Contact error (non-fatal):', e.message); } /* 4. PaymentEvidence — critical */ setBusy(true, 'Creating payment record\u2026'); var evidence = await dataversePost('ongc_paymentevidences', buildPaymentEvidencePayload()); if (evidence && evidence.id) { state.paymentEvidenceId = evidence.id; console.log('[DIA] Evidence created:', evidence.id); } else { console.warn('[DIA] Evidence GUID not returned — return page will create fallback record'); } saveSession(); } /* ════════════════════════════════════════════════════════════ STRIPE REDIRECT (shared /agpal-stripe-checkout) ════════════════════════════════════════════════════════════ */ function initiateStripePayment() { var fees = calcFees(); var params = new URLSearchParams({ leadId: state.leadId || '', leadRef: state.leadRef || '', paymentEvidenceId: state.paymentEvidenceId || '', amount: fees.total.toFixed(2), base: fees.base.toFixed(2), surcharge: fees.surcharge.toFixed(2), gst: fees.gst.toFixed(2), email: gVal('contactEmail'), name: (gVal('contactFirstName') + ' ' + gVal('contactLastName')).trim(), ref: 'QIP Diagnostic Imaging Registration \u2013 ' + gVal('practiceName'), returnUrl: window.location.href.split('?')[0] }); try { sessionStorage.setItem(state.paymentInProgressKey, '1'); if (state.leadId) sessionStorage.setItem(state.leadIdKey, state.leadId); if (state.leadRef) sessionStorage.setItem(state.leadRefKey, state.leadRef); if (state.paymentEvidenceId) sessionStorage.setItem(state.evidenceIdKey, state.paymentEvidenceId); } catch (e) { } /* location.replace so Back can't return to mid-payment form */ window.location.replace('/agpal-stripe-checkout?' + params.toString()); } /* ════════════════════════════════════════════════════════════ SUBMIT ENTRY POINT ════════════════════════════════════════════════════════════ */ async function diaSubmit() { /* Validate declarations */ var auth = document.getElementById('authCheck') && document.getElementById('authCheck').checked; var tc = document.getElementById('termsCheck') && document.getElementById('termsCheck').checked; var confirm = document.getElementById('confirmCheck') && document.getElementById('confirmCheck').checked; var af = gVal('authFirstName'); var al = gVal('authLastName'); var sigOk = !isSigEmpty(); var errEl = document.getElementById('diaSubmitError'); document.getElementById('err_authCheck') && document.getElementById('err_authCheck').classList.toggle('visible', !auth); document.getElementById('err_termsCheck') && document.getElementById('err_termsCheck').classList.toggle('visible', !tc); document.getElementById('err_confirmCheck') && document.getElementById('err_confirmCheck').classList.toggle('visible', !confirm); document.getElementById('err_signature') && document.getElementById('err_signature').classList.toggle('visible', !sigOk); document.getElementById('err_authFirstName') && document.getElementById('err_authFirstName').classList.toggle('visible', !af); document.getElementById('err_authLastName') && document.getElementById('err_authLastName').classList.toggle('visible', !al); if (!auth || !tc || !confirm || !sigOk || !af || !al) { if (errEl) errEl.classList.add('visible'); var first = document.querySelector('.dia-error-msg.visible'); if (first) first.scrollIntoView({ behavior: 'smooth', block: 'center' }); return; } if (errEl) errEl.classList.remove('visible'); try { await createAllRecords(); setBusy(true, 'Redirecting to payment\u2026'); initiateStripePayment(); } catch (err) { console.error('[DIA] Submit failed:', err); if (errEl) { errEl.classList.add('visible'); errEl.textContent = 'Could not submit registration: ' + (err.message || 'Unknown error') + '. Please try again.'; errEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); } setBusy(false); } } /* ════════════════════════════════════════════════════════════ SAVE (placeholder) & TOAST ════════════════════════════════════════════════════════════ */ function diaSave() { showToast('Progress saved.', 'success'); } function showToast(msg, type) { var el = document.getElementById('diaToast'); if (!el) return; el.textContent = msg; el.className = 'dia-toast ' + (type || '') + ' show'; setTimeout(function () { el.classList.remove('show'); }, 3000); } /* ════════════════════════════════════════════════════════════ INIT ════════════════════════════════════════════════════════════ */ document.addEventListener('DOMContentLoaded', function () { injectSpinner(); clearSession(); buildProgress(); bindModalityCards(); diaUpdateFee(); ['standardsLevel', 'entryModalityCount', 'fullModalityCount'].forEach(function (id) { var el = document.getElementById(id); if (el) el.addEventListener('change', diaUpdateFee); }); }); window.addEventListener('resize', function () { if (state.sigCtx) initSig(); }); /* ── Expose globals for inline onclick ── */ window.diaNextPage = diaNextPage; window.diaPrevPage = diaPrevPage; window.diaSave = diaSave; window.diaSubmit = diaSubmit; window.diaClearSig = diaClearSig; window.diaUpdateFee = diaUpdateFee; window.diaCorporateChange = diaCorporateChange; window.diaPrevAccreditedChange = diaPrevAccreditedChange; window.diaSectorChange = diaSectorChange; window.diaPostalToggle = diaPostalToggle; window.diaStandardsChange = diaStandardsChange; }());