registerPage('assessments', async (content, params = {}) => { document.getElementById('topbar-title').textContent = 'Assessments'; async function render(search = '') { const r = await api('assessments.php', { action: 'list', search }); if (!r.success) { document.getElementById('ass-table').innerHTML = emptyHTML(); return; } const rows = r.assessments; document.getElementById('ass-table').innerHTML = rows.length === 0 ? emptyHTML('No assessments found') : `
${rows.map(a => ``).join('')}
NameInfoNQFCreditsPass%Expiry (mo)Actions
${a.assessments_name} ${a.assessment_info || '—'} ${a.nqf_level} ${a.credits} ${(+a.passmark * 100).toFixed(0)}% ${a.expiry}
`; } content.innerHTML = `
${loadingHTML()}
`; document.getElementById('ass-search').addEventListener('input', e => render(e.target.value)); render(); window.assAdd = () => { document.getElementById('ass-modal-title').textContent = 'New Assessment'; document.getElementById('af-id').value = ''; document.getElementById('af-name').value = ''; document.getElementById('af-info').value = ''; document.getElementById('af-nqf').value = '1'; document.getElementById('af-credits').value = '1'; document.getElementById('af-passmark').value = '0.8'; document.getElementById('af-expiry').value = '36'; openModal('ass-modal'); }; window.assEdit = async (id) => { const r = await api('assessments.php', { action: 'get', id }); if (!r.success) { toast('Failed', 'error'); return; } const a = r.assessment; document.getElementById('ass-modal-title').textContent = 'Edit Assessment'; document.getElementById('af-id').value = a.record_id; document.getElementById('af-name').value = a.assessments_name; document.getElementById('af-info').value = a.assessment_info || ''; document.getElementById('af-nqf').value = a.nqf_level; document.getElementById('af-credits').value = a.credits; document.getElementById('af-passmark').value = a.passmark; document.getElementById('af-expiry').value = a.expiry; openModal('ass-modal'); }; window.assSave = async () => { const id = document.getElementById('af-id').value; const r = await api('assessments.php', { action: id ? 'update' : 'create', id, assessments_name: document.getElementById('af-name').value, assessment_info: document.getElementById('af-info').value, nqf_level: document.getElementById('af-nqf').value, credits: document.getElementById('af-credits').value, passmark: document.getElementById('af-passmark').value, expiry: document.getElementById('af-expiry').value, }, 'POST'); if (r.success) { toast(r.message, 'success'); closeModal('ass-modal'); render(); } else toast(r.error, 'error'); }; window.assDelete = async (id) => { if (!confirm('Delete this assessment and all its sections/questions?')) return; const r = await api('assessments.php', { action: 'delete', id }, 'POST'); if (r.success) { toast('Deleted', 'success'); render(); } else toast(r.error, 'error'); }; // ── Builder ──────────────────────────────────────────────────────────────── window.assBuilder = async (id) => { await renderBuilder(id); openModal('ass-builder-modal'); }; async function renderBuilder(assessmentId) { const body = document.getElementById('builder-body'); body.innerHTML = loadingHTML(); const r = await api('assessments.php', { action: 'get', id: assessmentId }); if (!r.success) { body.innerHTML = emptyHTML(); return; } const a = r.assessment; document.getElementById('builder-title').textContent = `Build: ${a.assessments_name}`; const sectionsHtml = (a.sections || []).map(sec => `
${sec.section_name}
${(sec.questions || []).map(q => `
${q.question}
`).join('') || '

No questions yet.

'}
`).join(''); body.innerHTML = `
${sectionsHtml || '

No sections yet. Add one below.

'}
`; } window.addSection = async (assId) => { const name = document.getElementById('new-section-name').value.trim(); if (!name) { toast('Enter a section name', 'error'); return; } const r = await api('assessments.php', { action: 'add_section', assessment_id: assId, section_name: name }, 'POST'); if (r.success) { toast('Section added', 'success'); await renderBuilder(assId); } else toast(r.error, 'error'); }; window.editSection = async (secId, current) => { const name = prompt('Rename section:', current); if (!name || name === current) return; const r = await api('assessments.php', { action: 'update_section', section_id: secId, section_name: name }, 'POST'); if (r.success) { toast('Section renamed', 'success'); const assId = /* reload */ document.getElementById('builder-title').dataset.id; await renderBuilder(assId); } else toast(r.error, 'error'); }; window.deleteSection = async (secId, assId) => { if (!confirm('Delete section and all its questions?')) return; const r = await api('assessments.php', { action: 'delete_section', section_id: secId }, 'POST'); if (r.success) { toast('Section deleted', 'success'); await renderBuilder(assId); } else toast(r.error, 'error'); }; window.addQuestion = async (secId, assId) => { const q = document.getElementById(`new-q-${secId}`).value.trim(); if (!q) { toast('Enter a question', 'error'); return; } const r = await api('assessments.php', { action: 'add_question', assessment_section_id: secId, question: q }, 'POST'); if (r.success) { toast('Question added', 'success'); await renderBuilder(assId); } else toast(r.error, 'error'); }; window.editQuestion = async (qId, current, assId) => { const q = prompt('Edit question:', current); if (!q || q === current) return; const r = await api('assessments.php', { action: 'update_question', question_id: qId, question: q }, 'POST'); if (r.success) { toast('Question updated', 'success'); await renderBuilder(assId); } else toast(r.error, 'error'); }; window.deleteQuestion = async (qId, assId) => { if (!confirm('Delete question?')) return; const r = await api('assessments.php', { action: 'delete_question', question_id: qId }, 'POST'); if (r.success) { toast('Question deleted', 'success'); await renderBuilder(assId); } else toast(r.error, 'error'); }; });