' +
facilityBlock;
container.appendChild(sec);
}
}
/* SIGNATURE Box */
function initSig() {
var c = document.getElementById('nsqhsSigCanvas');
if (!c) return;
var fresh = c.cloneNode(true); c.parentNode.replaceChild(fresh, c); c = fresh;
c.width = c.parentElement.clientWidth || 680; c.height = 130;
sigCtx = c.getContext('2d'); sigCtx.strokeStyle = '#1d2d44'; sigCtx.lineWidth = 2.2; sigCtx.lineCap = 'round'; sigCtx.lineJoin = 'round';
var ctx = 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) { sigDrawing = true; ctx.beginPath(); var p = pos(e); ctx.moveTo(p.x, p.y); });
c.addEventListener('mousemove', function (e) { if (!sigDrawing) return; var p = pos(e); ctx.lineTo(p.x, p.y); ctx.stroke(); });
c.addEventListener('mouseup', function () { sigDrawing = false; }); c.addEventListener('mouseleave', function () { sigDrawing = false; });
c.addEventListener('touchstart', function (e) { e.preventDefault(); sigDrawing = true; ctx.beginPath(); var p = pos(e); ctx.moveTo(p.x, p.y); }, { passive: false });
c.addEventListener('touchmove', function (e) { e.preventDefault(); if (!sigDrawing) return; var p = pos(e); ctx.lineTo(p.x, p.y); ctx.stroke(); }, { passive: false });
c.addEventListener('touchend', function () { sigDrawing = false; });
}
function isSigEmpty() { var c = document.getElementById('nsqhsSigCanvas'); if (!c || !sigCtx) return true; var d = 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; }
/* COLLECT SITE DATA */
function collectSites() {
var n = parseInt(gVal('numSites')) || 0, sites = [];
for (var i = 1; i <= n; i++) {
var fts = Array.prototype.slice.call(document.querySelectorAll('.site-facility-cb-' + i + ':checked')).map(function (e) { return e.value; });
sites.push({ name: gVal('siteName_' + i), addr1: gVal('siteAddr1_' + i), addr2: gVal('siteAddr2_' + i), suburb: gVal('siteSuburb_' + i), state: gVal('siteState_' + i), postcode: gVal('sitePostcode_' + i), fte: gVal('siteFte_' + i), beds: gVal('siteBeds_' + i), facilityTypes: fts });
}
return sites;
}
/* PAYLOADS */
function buildLeadPayload(acctId) {
function buildNsqhsWebResponseHtml() {
var postalDiff = document.getElementById('postalYes') && document.getElementById('postalYes').checked;
var sites = collectSites();
var now = new Date().toLocaleString('en-AU', { timeZone: 'Australia/Sydney', dateStyle: 'medium', timeStyle: 'short' });
var STATE_LABELS = { '107150000': 'ACT', '107150001': 'NSW', '107150002': 'NT', '107150003': 'QLD', '107150004': 'SA', '107150005': 'TAS', '107150006': 'VIC', '107150007': 'National' };
function stateLabel(v) { return STATE_LABELS[v] || v || '—'; }
function row(label, value) {
if (!value && value !== 0) value = '—';
return '
'
+ '
' + label + '
'
+ '
' + value + '
'
+ '
';
}
function section(title) {
return '
' + title + '
';
}
var html = '
'
+ '
';
/* Header */
html += '
'
+ 'NSQHS Registration — Scope of Service
';
html += '
'
+ 'Submitted: ' + now + '
';
/* 1. Contact Details */
html += section('1. Contact Details');
html += row('QIP Client ID', gVal('qipClientId'));
html += row('Healthcare Service Name', gVal('serviceName'));
html += row('Preferred Contact Name', (gVal('preferredFirstName') + ' ' + gVal('preferredLastName')).trim());
html += row('Preferred Email', gVal('preferredEmail'));
html += row('Preferred Phone', gVal('preferredPhone'));
html += row('Alternate Contact Name', (gVal('alternateFirstName') + ' ' + gVal('alternateLastName')).trim());
html += row('Alternate Email', gVal('alternateEmail'));
html += row('Alternate Phone', gVal('alternatePhone'));
html += row('Website', gVal('website'));
html += row('Business / Trading Name', gVal('businessName'));
html += row('ABN', gVal('abn'));
html += row('ACN', gVal('acn'));
var streetAddr = [gVal('streetAddress1'), gVal('streetAddress2'), gVal('suburb'),
stateLabel(gVal('state')), gVal('postcode'), 'Australia'].filter(Boolean).join(', ');
html += row('Street Address', streetAddr);
if (postalDiff) {
var postalAddr = [gVal('postalAddress1'), gVal('postalSuburb'),
stateLabel(gVal('postalState')), gVal('postalPostcode'), 'Australia'].filter(Boolean).join(', ');
html += row('Postal Address', postalAddr);
} else {
html += row('Postal Address', 'Same as street address');
}
/* 2. Scope of Service */
html += section('2. Scope of Service');
html += row('Facility Sector', radioVal('facilitySector'));
var streams = getChecked('.stream-cb');
var streamDisplay = streams.length ? streams.join(', ') : '—';
if (streams.indexOf('Other') !== -1 && gVal('serviceStreamOther')) streamDisplay += ' (' + gVal('serviceStreamOther') + ')';
html += row('Service Stream(s)', streamDisplay);
html += row('Governance Structure', radioVal('governance'));
html += row('Corporate Entity', radioVal('corporateEntity') === 'Yes'
? 'Yes — ' + gVal('corporateName') : radioVal('corporateEntity'));
html += row('Currently Accredited', radioVal('currentlyAccredited'));
if (radioVal('currentlyAccredited') === 'Yes') {
html += row('Current Accreditation Provider', gVal('currentAccreditationProvider'));
var accStds = getChecked('.accred-std-cb');
html += row('Accredited Standards', accStds.length ? accStds.join(', ') : '—');
html += row('Accreditation Expiry Date', gVal('accreditationExpiryDate'));
html += row('Accreditation Other Info', gVal('accreditationOtherInfo'));
}
/* 3. Frameworks */
var fws = getChecked('.fw-cb');
if (fws.length) {
html += section('3. Additional Frameworks');
html += row('Frameworks', fws.join(', '));
if (gVal('fwMpsSites')) html += row('MPS Sites', gVal('fwMpsSites'));
if (gVal('fwPchsSites')) html += row('PCHS Sites', gVal('fwPchsSites'));
if (gVal('fwCosmeticSites')) html += row('Cosmetic Surgery Sites', gVal('fwCosmeticSites'));
if (gVal('fwClinicalTrials')) html += row('Clinical Trials', gVal('fwClinicalTrials'));
if (gVal('fwOtherDetails')) html += row('Other Framework Details', gVal('fwOtherDetails'));
}
/* 4. Sites — each site gets its own numbered sub-header */
html += section('4. Service Locations (' + (sites.length || 0) + ' site(s))');
if (sites.length) {
sites.forEach(function (s, i) {
var num = i + 1;
var siteName = s.name || ('Site ' + num);
var siteAddr = [s.addr1, s.addr2, s.suburb, stateLabel(s.state), s.postcode].filter(Boolean).join(', ') || '—';
/* Per-site divider header */
html += '
'
+ '
'
+ '📍 Site ' + num + ' — ' + siteName
+ '
';
html += row('Site Name', siteName);
html += row('Address', siteAddr);
html += row('Total FTE', s.fte || '—');
html += row('Total Beds', s.beds || '—');
if (s.facilityTypes && s.facilityTypes.length) {
html += row('Facility Type(s)', s.facilityTypes.join(', '));
}
/* Spacer between sites (skip after last) */
if (i < sites.length - 1) {
html += '
';
}
});
} else {
html += '
No sites entered.
';
}
/* 5. Additional Information */
html += section('5. Additional Information');
html += row('Additional Operations', gVal('additionalOperations'));
html += row('Additional Support Services', gVal('additionalSupportServices'));
/* 6. Authorisation */
html += section('6. Authorisation');
html += row('Authorised Representative', gVal('authRepName'));
html += row('Position', gVal('authRepPosition'));
html += row('Declaration Accepted', document.getElementById('declarationCheck') && document.getElementById('declarationCheck').checked ? 'Yes' : 'No');
html += row('Consent to Disclosure', document.getElementById('consentCheck') && document.getElementById('consentCheck').checked ? 'Yes' : 'No');
html += '
';
return html;
}
var org = gVal('serviceName') || gVal('businessName');
var postalDiff = document.getElementById('postalYes') && document.getElementById('postalYes').checked;
var p = strip({
subject: 'National Safety and Quality Health Service (NSQHS) Standards \u2013 ' + org,
firstname: gVal('preferredFirstName'), lastname: gVal('preferredLastName') || org,
emailaddress1: gVal('preferredEmail'), telephone1: gVal('preferredPhone'),
companyname: org, websiteurl: gVal('website'), leadsourcecode: 8,
address1_line1: gVal('streetAddress1'), address1_line2: gVal('streetAddress2'),
address1_city: gVal('suburb'), address1_stateorprovince: gVal('state'),
address1_postalcode: gVal('postcode'), address1_country: 'Australia',
address2_line1: postalDiff ? gVal('postalAddress1') : '',
address2_city: postalDiff ? gVal('postalSuburb') : '',
address2_stateorprovince: postalDiff ? gVal('postalState') : '',
address2_postalcode: postalDiff ? gVal('postalPostcode') : '',
address2_country: postalDiff ? 'Australia' : '',
ongc_enquirytype: 6,
ongc_practicename: org,
ongc_practiceabn: gVal('abn'),
ongc_practicephone: gVal('preferredPhone'),
ongc_clientid: gVal('qipClientId'),
ongc_postalsameasstreet: !postalDiff,
ongc_state: (function () { var m = { '107150000': 107150000, '107150001': 107150001, '107150002': 107150002, '107150003': 107150003, '107150004': 107150004, '107150005': 107150005, '107150006': 107150006, '107150007': 107150007 }; var v = gVal('state'); return v && m[v] ? m[v] : undefined; })(),
ongc_webresponse: buildNsqhsWebResponseHtml()
//description: JSON.stringify({
// qipClientId: gVal('qipClientId'), alternateFirst: gVal('alternateFirstName'), alternateLast: gVal('alternateLastName'),
// alternatePhone: gVal('alternatePhone'), alternateEmail: gVal('alternateEmail'),
// businessName: gVal('businessName'), acn: gVal('acn'),
// facilitySector: radioVal('facilitySector'),
// serviceStreams: getChecked('.stream-cb'), serviceStreamOther: gVal('serviceStreamOther'),
// governance: radioVal('governance'),
// corporateEntity: radioVal('corporateEntity'), corporateName: gVal('corporateName'),
// currentlyAccredited: radioVal('currentlyAccredited'),
// currentAccreditationProvider: gVal('currentAccreditationProvider'),
// accreditedStandards: getChecked('.accred-std-cb'),
// accreditationExpiryDate: gVal('accreditationExpiryDate'),
// accreditationOtherInfo: gVal('accreditationOtherInfo'),
// frameworks: getChecked('.fw-cb'),
// fwMpsSites: gVal('fwMpsSites'), fwPchsSites: gVal('fwPchsSites'), fwCosmeticSites: gVal('fwCosmeticSites'), fwClinicalTrials: gVal('fwClinicalTrials'), fwOtherDetails: gVal('fwOtherDetails'),
// numSites: gVal('numSites'), sites: collectSites(),
// additionalOperations: gVal('additionalOperations'), additionalSupportServices: gVal('additionalSupportServices'),
// authRepName: gVal('authRepName'), authRepPosition: gVal('authRepPosition')
//})
});
debugger;
if (config.businessId)
p['ongc_Business@odata.bind'] = '/ongc_businesses(' + config.businessId + ')';
if (acctId) p['parentaccountid@odata.bind'] = '/accounts(' + acctId + ')';
return p;
}
function buildContactPayload(acctId) {
/* companyname is lead-only; contacts link to account via parentcustomerid (customer lookup) */
var p = { firstname: gVal('preferredFirstName'), lastname: gVal('preferredLastName'), emailaddress1: gVal('preferredEmail'), telephone1: gVal('preferredPhone') };
if (acctId) p['parentcustomerid_account@odata.bind'] = '/accounts(' + acctId + ')';
if (leadId) p['originatingleadid@odata.bind'] = '/leads(' + leadId + ')';
if (config.contactTypeId) p['ongc_ContactType@odata.bind'] = '/ongc_contacttypes(' + config.contactTypeId + ')';
return strip(p);
}
/* ── STRIPE PAYMENT — commented out, not required yet ──────────────────
function buildEvidencePayload() {
var fees = calcFees();
var p = { ongc_payername: (gVal('preferredFirstName') + ' ' + gVal('preferredLastName')).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 NSQHS Stripe credit-card checkout initiated' };
if (leadId) p['ongc_Lead@odata.bind'] = '/leads(' + leadId + ')';
return strip(p);
}
── END STRIPE PAYMENT ─────────────────────────────────────────────────── */
/* ════════ ACCOUNT PAYLOAD ══════════════════════ */
function buildAccountPayload() {
var org = gVal('serviceName') || gVal('businessName');
return strip({
name: org,
telephone1: gVal('preferredPhone'),
emailaddress1: gVal('preferredEmail'),
websiteurl: gVal('website'),
address1_line1: gVal('streetAddress1'),
address1_line2: gVal('streetAddress2'),
address1_city: gVal('suburb'),
address1_stateorprovince: gVal('state'),
address1_postalcode: gVal('postcode'),
address1_country: 'Australia'
});
}
/* ════════ SITE PAYLOADS (ongc_site) ═════════════
One record per site entered in Step 4.
Fields: ongc_locationna, ongc_street1, ongc_street2,
ongc_suburb, ongc_state (choice int),
ongc_postcode, ongc_country (107150000 = Australia)
Relationship: ongc_Account@odata.bind -> /accounts(accountId)
════════════════════════════════════════════════ */
function buildSitePayloads(accountId) {
var n = parseInt(gVal('numSites')) || 0;
var payloads = [];
for (var i = 1; i <= n; i++) {
var stateRaw = gVal('siteState_' + i);
var stateVal = stateRaw ? parseInt(stateRaw, 10) : null;
var payload = strip({
ongc_locationname: gVal('siteName_' + i),
ongc_street1: gVal('siteAddr1_' + i),
ongc_street2: gVal('siteAddr2_' + i),
ongc_suburb: gVal('siteSuburb_' + i),
ongc_state: stateVal,
ongc_postcode: gVal('sitePostcode_' + i),
ongc_country: 107150000 /* Australia */
});
if (accountId) payload['ongc_Account@odata.bind'] = '/accounts(' + accountId + ')';
payloads.push(payload);
}
return payloads;
}
/* ════════ RECORD CREATION ════════════════════ */
async function createAllRecords() {
/* 1 — Account (healthcare service name) */
//setBusy(true, 'Creating healthcare service account\u2026');
var accountId = null;
//try {
// var acct = await dataversePost('accounts', buildAccountPayload());
// accountId = acct.id;
// console.log('[NSQHS] Account:', accountId);
//} catch (e) { console.warn('[NSQHS] Account creation failed:', e.message); }
/* 2 — Sites linked to the account */
//var siteCount = parseInt(gVal('numSites')) || 0;
//if (accountId && siteCount > 0) {
// setBusy(true, 'Creating site record(s)\u2026');
// var sitePayloads = buildSitePayloads(accountId);
// var siteResults = await Promise.allSettled(
// sitePayloads.map(function (p) { return dataversePost('ongc_sites', p); })
// );
// siteResults.forEach(function (r, idx) {
// if (r.status === 'fulfilled') console.log('[NSQHS] Site ' + (idx + 1) + ':', r.value && r.value.id);
// else console.warn('[NSQHS] Site ' + (idx + 1) + ' failed:', r.reason && r.reason.message);
// });
//}
/* 3 — Lead (linked to Account) */
setBusy(true, 'Creating registration record\u2026');
var lead = await dataversePost('leads', buildLeadPayload(accountId));
leadId = lead.id;
if (!leadId) throw new Error('Lead GUID not returned. Check Dataverse Web API permissions.');
console.log('[NSQHS] Lead:', leadId);
/* 4 — Lead reference */
setBusy(true, 'Fetching registration reference\u2026');
leadRef = await fetchLeadRef(leadId);
saveSession();
/* 5 — Contact */
//setBusy(true, 'Creating contact record\u2026');
//try {
// var cr = await Promise.allSettled([dataversePost('contacts', buildContactPayload(accountId))]);
// if (cr[0].status === 'rejected') console.warn('[NSQHS] Contact failed:', cr[0].reason && cr[0].reason.message);
// else console.log('[NSQHS] Contact:', cr[0].value && cr[0].value.id);
//} catch (e) { console.warn('[NSQHS] Contact error:', e.message); }
/* 6 — Payment evidence — STRIPE COMMENTED OUT (not required yet) */
/*
setBusy(true, 'Creating payment record\u2026');
var ev = await dataversePost('ongc_paymentevidences', buildEvidencePayload());
if (ev && ev.id) { evidenceId = ev.id; console.log('[NSQHS] Evidence:', evidenceId); }
else console.warn('[NSQHS] Evidence GUID not returned');
saveSession();
*/
}
/* ════════ STRIPE REDIRECT — commented out, not required yet ════════════
function initiateStripePayment() {
var fees = calcFees(), org = gVal('serviceName') || gVal('businessName');
var params = new URLSearchParams({
leadId: leadId || '', leadRef: leadRef || '', paymentEvidenceId: evidenceId || '',
amount: fees.total.toFixed(2), base: fees.base.toFixed(2), surcharge: fees.surcharge.toFixed(2), gst: fees.gst.toFixed(2),
email: gVal('preferredEmail'), name: (gVal('preferredFirstName') + ' ' + gVal('preferredLastName')).trim(),
ref: 'National Safety and Quality Health Service (NSQHS) Standards \u2013 ' + org,
returnUrl: window.location.href.split('?')[0]
});
try { sessionStorage.setItem(SK.inProgress, '1'); if (leadId) sessionStorage.setItem(SK.leadId, leadId); if (leadRef) sessionStorage.setItem(SK.leadRef, leadRef); if (evidenceId) sessionStorage.setItem(SK.evidence, evidenceId); } catch (e) { }
window.location.replace('/agpal-stripe-checkout?' + params.toString());
}
════════ END STRIPE REDIRECT ════════════════════════════════════════════ */
/* ════════ RESULT PAGE ══════════════════════════
Hides the form card and displays a success or failure
panel with the registration reference number.
════════════════════════════════════════════════ */
function showResult(success, ref, errMsg) {
setBusy(false);
/* Hide the entire form card */
var card = document.querySelector('.nsqhs-card');
if (card) card.style.display = 'none';
/* Build result panel */
var panel = document.createElement('div');
panel.className = 'nsqhs-card';
panel.style.cssText = 'text-align:center;padding:48px 32px;';
if (success) {
panel.innerHTML =
'
✓
' +
'
Registration Submitted Successfully
' +
'
Thank you for submitting your NSQHS scope of service. ' +
'A member of the QIP team will be in touch shortly.
' +
(ref
? '
' +
'
Reference Number
' +
'
' + ref + '
' +
'
'
: '') +
'
Please keep your reference number for future correspondence.
';
} else {
panel.innerHTML =
'
⚠
' +
'
Submission Failed
' +
'
' +
(errMsg || 'We were unable to submit your registration. Please try again or contact QIP for assistance.') +
'
' +
'';
}
/* Insert panel after the header */
var header = document.querySelector('.nsqhs-header');
var container = document.querySelector('.nsqhs-container');
if (header && header.nextSibling) {
container.insertBefore(panel, header.nextSibling);
} else if (container) {
container.appendChild(panel);
} else {
document.body.appendChild(panel);
}
window.scrollTo({ top: 0, behavior: 'smooth' });
clearSession();
}
/* ════════ BIND NAV ═══════════════════════════ */
function bindNav() {
var navMap = [[1, 'next1', 'prev2'], [2, 'next2', 'prev3'], [3, 'next3', 'prev4'], [4, 'next4', 'prev5'], [5, 'next5', 'prev6']];
navMap.forEach(function (item) {
var step = item[0], nextId = item[1], prevId = item[2];
var nextBtn = document.getElementById(nextId);
var prevBtn = document.getElementById(prevId);
if (nextBtn) nextBtn.addEventListener('click', function () { if (!isBusy && validateStep(step)) showStep(step + 1); });
if (prevBtn) prevBtn.addEventListener('click', function () { if (!isBusy) showStep(step); });
});
/* Prev buttons bound in navMap above */
/* Submit */
var sub = document.getElementById('finalSubmitBtn');
if (sub) sub.addEventListener('click', async function () {
if (isBusy) return;
if (!validateStep(6)) return;
var errEl = document.getElementById('nsqhsSubmitError');
if (errEl) errEl.classList.add('hidden');
try {
await createAllRecords();
setBusy(false);
/* Stripe redirect commented out — show result page instead */
/* initiateStripePayment(); */
showResult(true, leadRef || leadId || '');
} catch (err) {
console.error('[NSQHS] Submit failed:', err);
setBusy(false);
showResult(false, null, err.message || 'Could not submit. Please try again.');
}
});
}
/* ════════ FIELD CLEAR ERROR ══════════════════ */
function bindFieldClearError() {
document.addEventListener('input', function (e) { var fe = e.target.closest('.form-group') && e.target.closest('.form-group').querySelector('.field-error'); if (fe) fe.textContent = ''; });
document.addEventListener('change', function (e) { var fe = e.target.closest('.form-group') && e.target.closest('.form-group').querySelector('.field-error'); if (fe) fe.textContent = ''; });
}
/* ════════ INIT ═══════════════════════════════ */
function ready(fn) { if (document.readyState !== 'loading') { fn(); } else { document.addEventListener('DOMContentLoaded', fn); } }
ready(function () {
injectSpinner();
clearSession();
bindFieldClearError();
bindNav();
showStep(1);
});
/* window.addEventListener('resize', ...) — signature commented out */
/* window.addEventListener('resize', function () { if (sigCtx) initSig(); }); */
}());