Ready.
`; $('previewFrame').srcdoc = html; } async function loadTemplateList(){ const r = await fetch('/api/pdf-template/list'); const d = await r.json(); const sel = $('templateSelect'); sel.innerHTML = ''; (d.templates||[]).forEach(n=>{ const o=document.createElement('option'); o.value=n; o.textContent=n; sel.appendChild(o); }); activeTemplateName = d.active || 'default'; sel.value = activeTemplateName; } async function loadActive(){ msg.textContent='Loading active template...'; const r = await fetch('/api/pdf-template'); const d = await r.json(); if(!r.ok){msg.textContent='Load failed';return;} applyTemplateToUi(d); msg.textContent='Active template loaded.'; } async function loadSelected(){ const name = $('templateSelect').value || 'default'; const r = await fetch(`/api/pdf-template/load/${encodeURIComponent(name)}`); const d = await r.json(); if(!r.ok){msg.textContent='Load selected failed';return;} applyTemplateToUi(d.template || {}); $('templateName').value = name; msg.textContent = `Template '${name}' loaded.`; } async function saveAs(){ const name = ($('templateName').value || '').trim(); if(!name){ msg.textContent='Enter template name.'; return; } const t = buildTemplateFromUi(); const r = await fetch('/api/pdf-template/save-as',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({name, template:t})}); const d = await r.json(); if(!r.ok){ msg.textContent='Save as failed'; return; } await loadTemplateList(); $('templateSelect').value = d.name; msg.textContent = `Template '${d.name}' saved.`; } async function activateSelected(){ const name = $('templateSelect').value || 'default'; const r = await fetch(`/api/pdf-template/activate/${encodeURIComponent(name)}`, {method:'POST'}); const d = await r.json(); if(!r.ok){ msg.textContent='Activate failed'; return; } applyTemplateToUi(d.template || {}); await loadTemplateList(); msg.textContent = `Active template: ${d.active}`; } async function deleteSelected(){ const name = $('templateSelect').value || ''; if(!name || name==='default'){ msg.textContent='Default cannot be deleted.'; return; } const r = await fetch(`/api/pdf-template/${encodeURIComponent(name)}`, {method:'DELETE'}); const d = await r.json(); if(!r.ok){ msg.textContent='Delete failed'; return; } await loadTemplateList(); await loadActive(); msg.textContent = `Deleted template: ${d.deleted}`; } $('loadBtn').addEventListener('click', loadActive); $('loadNamedBtn').addEventListener('click', loadSelected); $('saveAsBtn').addEventListener('click', saveAs); $('activateBtn').addEventListener('click', activateSelected); $('deleteBtn').addEventListener('click', deleteSelected); $('fromFormBtn').addEventListener('click', ()=>{ const t = buildTemplateFromUi(); $('jsonTemplate').value = JSON.stringify(t, null, 2); renderLivePreview(t); msg.textContent='UI applied into JSON.'; }); $('toFormBtn').addEventListener('click', ()=>{ try { const t = JSON.parse($('jsonTemplate').value || '{}'); applyTemplateToUi(t); msg.textContent='JSON applied into UI.'; } catch { msg.textContent='Invalid JSON'; } }); $('saveBtn').addEventListener('click', async ()=>{ let t={}; try { t = JSON.parse($('jsonTemplate').value || '{}'); } catch { msg.textContent='Invalid JSON'; return; } const r = await fetch('/api/pdf-template/save',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(t)}); const d = await r.json(); if(!r.ok){ msg.textContent='Save active failed'; return; } applyTemplateToUi(d.template || {}); const active = $('templateSelect').value || activeTemplateName || 'default'; await fetch('/api/pdf-template/save-as',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({name:active, template:d.template||{}})}); await loadTemplateList(); msg.textContent='Active template saved.'; }); $('resetBtn').addEventListener('click', async ()=>{ const r = await fetch('/api/pdf-template/reset',{method:'POST'}); const d = await r.json(); if(!r.ok){ msg.textContent='Reset failed'; return; } applyTemplateToUi(d.template || {}); msg.textContent='Defaults restored.'; }); $('previewPdfBtn').addEventListener('click', ()=>{ const q = $('sampleQuote').value.trim(); if(!q){ msg.textContent='Enter sample quote #'; return; } window.open(`/api/quotations/${encodeURIComponent(q)}/pdf`, '_blank'); }); (async function init(){ await loadTemplateList(); await loadActive(); })();