templates.js

4.30 KB
02/11/2025 07:30
JS
templates.js
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 => `
      <div class="template-card" data-id="${t.id}">
        <div class="template-name"><i class="fa-regular fa-file-lines"></i> ${t.name}</div>
        <div class="template-desc">${t.paperSize.toUpperCase()}</div>
      </div>
    `).join('');
    el.querySelectorAll('.template-card').forEach(card => {
      card.onclick = () => loadTemplateById(card.dataset.id);
    });
  }
};

function loadTemplateById(id) {
  const tpl = Templates.list.find(t => t.id === id);
  if (!tpl) return;
  clearCanvas(true);
  document.getElementById('paper-size').value = tpl.paperSize;
  changePaperSize();
  Pro.components = (tpl.components || []).map(c => ({id: 'comp-' + (Pro.idCounter++), type: c.type, data: {...c.data}}));
  document.getElementById('drop-zone').innerHTML = '';
  Pro.components.forEach(renderComponent);
  // If template contains store info, merge it into current store so templates load with shop defaults
  if (tpl.store) {
    // Merge but prefer existing non-empty values; only apply template store values that are non-empty
    const safe = Object.fromEntries(Object.entries(tpl.store).filter(([k, v]) => v !== undefined && v !== ''));
    Pro.data.store = {...Pro.data.store, ...safe};
    try {localStorage.setItem('pro.store', JSON.stringify(Pro.data.store));} catch (e) {}
  }
  if (tpl.vatRate !== undefined) {Pro.data.vatRate = tpl.vatRate; try {localStorage.setItem('pro.vatRate', String(Pro.data.vatRate));} catch (e) {} }
  fillDataForm();
  setTimeout(() => {renderBarcodes(); renderQRCodes(); bindInlineEditors();}, 30);
  localStorage.setItem('pro.lastTemplate', id);
}