const Templates = { list: [], loadAll() { const custom = JSON.parse(localStorage.getItem('pro.customTemplates') || '[]'); const builtin = [ { id: 'modern-80', name: 'โมเดิร์น 80mm', paperSize: '80mm', components: [ {type: 'logo', data: {url: '', width: '120px', align: 'center'}}, {type: 'store-info', data: {inline: true}}, {type: 'divider', data: {style: 'solid', color: '#333', thickness: '2px'}}, {type: 'receipt-info', data: {inline: true}}, {type: 'items-table', data: {}}, {type: 'divider', data: {style: 'dashed', color: '#ccc'}}, {type: 'summary', data: {}}, {type: 'payment-info', data: {method: 'เงินสด'}}, {type: 'footer', data: {text: 'ขอบคุณที่ใช้บริการ', align: 'center', size: '12px', inline: true}}, {type: 'promptpay', data: {useTotal: true}} ] }, { id: 'invoice-a4', name: 'Invoice A4', paperSize: 'a4', components: [ {type: 'logo', data: {url: '', width: '180px', align: 'center'}}, {type: 'heading', data: {text: 'INVOICE', align: 'right', size: '28px', inline: true}}, {type: 'divider', data: {style: 'solid', color: '#4a90e2'}}, {type: 'store-info', data: {inline: true}}, {type: 'receipt-info', data: {inline: true}}, {type: 'items-table', data: {}}, {type: 'summary', data: {}}, {type: 'footer', data: {text: 'ชำระเงินภายใน 7 วัน', align: 'left', size: '12px', inline: true}}, {type: 'barcode', data: {}} ] } ]; this.list = [...builtin, ...custom]; }, saveCurrent(name, desc) { const tpl = { id: 'custom-' + Date.now(), name, desc, paperSize: document.getElementById('paper-size').value, components: Pro.components.map(c => ({type: c.type, data: {...c.data}})), // store snapshot as part of this custom template so template can include shop defaults store: {...Pro.data.store}, vatRate: Pro.data.vatRate }; const arr = JSON.parse(localStorage.getItem('pro.customTemplates') || '[]'); arr.push(tpl); localStorage.setItem('pro.customTemplates', JSON.stringify(arr)); // Best-effort: also save template to server storage/templates/ try { fetch('api/save_template.php', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(tpl)}).then(r => r.json()).then(res => { // Optionally: could store returned path in template metadata }).catch(() => {}); } catch (e) {} return tpl; }, renderList() { const el = document.getElementById('templates-list'); el.innerHTML = this.list.map(t => `