properties.js

12.48 KB
01/11/2025 01:48
JS
properties.js
function showProperties(comp) {
  const panel = document.getElementById('properties-content');
  if (!comp) {panel.innerHTML = '<div class="empty-hint">เลือกคอมโพเนนต์เพื่อแก้ไข</div>'; return;}
  const d = comp.data;
  let html = `<div class="prop-group"><h3>${getName(comp.type)}</h3>`;
  switch (comp.type) {
    case 'heading':
    case 'text':
    case 'footer':
      html += `
        <div class="prop-field"><label>ข้อความ</label><textarea onchange="upd('${comp.id}','text',this.value)">${d.text || ''}</textarea></div>
        <div class="prop-field"><label>จัดตำแหน่ง</label>
          <select onchange="upd('${comp.id}','align',this.value)">
            <option value="left" ${d.align === 'left' ? 'selected' : ''}>ซ้าย</option>
            <option value="center" ${d.align === 'center' ? 'selected' : ''}>กลาง</option>
            <option value="right" ${d.align === 'right' ? 'selected' : ''}>ขวา</option>
          </select>
        </div>
        <div class="prop-field"><label>ขนาด</label><input value="${d.size || '14px'}" onchange="upd('${comp.id}','size',this.value)"></div>
        <div class="prop-field"><label>แก้ inline</label><select onchange="upd('${comp.id}','inline',this.value==='true')"><option value="true" ${d.inline ? 'selected' : ''}>เปิด</option><option value="false" ${!d.inline ? 'selected' : ''}>ปิด</option></select></div>
      `;
      break;
    case 'logo':
      html += `
        <div class="prop-field"><label>URL (ว่าง = ใช้ของร้าน)</label><input value="${d.url || ''}" onchange="upd('${comp.id}','url',this.value)"></div>
        <div class="prop-field"><label>อัปโหลดรูป</label><input type="file" accept="image/*" onchange="handleImageUpload(this,'${comp.id}','url')"></div>
        <div class="prop-field"><label>ความกว้าง</label><input value="${d.width || '120px'}" onchange="upd('${comp.id}','width',this.value)"></div>
        <div class="prop-field"><label>จัดตำแหน่ง</label>
          <select onchange="upd('${comp.id}','align',this.value)">
            <option value="left" ${d.align === 'left' ? 'selected' : ''}>ซ้าย</option>
            <option value="center" ${d.align === 'center' ? 'selected' : ''}>กลาง</option>
            <option value="right" ${d.align === 'right' ? 'selected' : ''}>ขวา</option>
          </select>
        </div>`;
      break;
    case 'image':
      html += `
        <div class="prop-field"><label>URL</label><input value="${d.url || ''}" onchange="upd('${comp.id}','url',this.value)"></div>
        <div class="prop-field"><label>อัปโหลดรูป</label><input type="file" accept="image/*" onchange="handleImageUpload(this,'${comp.id}','url')"></div>
        <div class="prop-field"><label>ความกว้าง</label><input value="${d.width || '120px'}" onchange="upd('${comp.id}','width',this.value)"></div>
        <div class="prop-field"><label>จัดตำแหน่ง</label>
          <select onchange="upd('${comp.id}','align',this.value)">
            <option value="left" ${d.align === 'left' ? 'selected' : ''}>ซ้าย</option>
            <option value="center" ${d.align === 'center' ? 'selected' : ''}>กลาง</option>
            <option value="right" ${d.align === 'right' ? 'selected' : ''}>ขวา</option>
          </select>
        </div>`;
      break;
    case 'divider':
      html += `
        <div class="prop-field"><label>สไตล์</label>
          <select onchange="upd('${comp.id}','style',this.value)">
            <option value="solid" ${d.style === 'solid' ? 'selected' : ''}>solid</option>
            <option value="dashed" ${d.style === 'dashed' ? 'selected' : ''}>dashed</option>
            <option value="dotted" ${d.style === 'dotted' ? 'selected' : ''}>dotted</option>
          </select></div>
        <div class="prop-field"><label>ความหนา</label><input value="${d.thickness || '1px'}" onchange="upd('${comp.id}','thickness',this.value)"></div>
        <div class="prop-field"><label>สี</label><input type="color" value="${toColor(d.color || '#dddddd')}" onchange="upd('${comp.id}','color',this.value)"></div>`;
      break;
    case 'spacer':
      html += `<div class="prop-field"><label>ความสูง</label><input value="${d.height || '20px'}" onchange="upd('${comp.id}','height',this.value)"></div>`;
      break;
    case 'barcode':
      html += `
        <div class="prop-field"><label>ค่า</label><input value="${d.value || ''}" onchange="upd('${comp.id}','value',this.value)"></div>
        <div class="prop-field"><label>ความสูง</label><input value="${d.height || '50'}" onchange="upd('${comp.id}','height',this.value)"></div>`;
      html += `<div class="prop-field"><label>ความกว้างเส้น</label><input type="range" min="0.5" max="2" step="0.1" value="${d.width || '1'}" oninput="upd('${comp.id}','width',this.value)"></div>`;
      break;

    case 'promptpay':
      html += `
        <div class="prop-field"><label>ใช้ยอดรวมใบเสร็จ</label>
          <select onchange="upd('${comp.id}','useTotal',this.value==='true')">
            <option value="true" ${d.useTotal ? 'selected' : ''}>ใช้ยอดรวม</option>
            <option value="false" ${!d.useTotal ? 'selected' : ''}>กำหนดเอง</option>
          </select>
        </div>
        <div class="prop-field"><label>จำนวนเงิน (กรณีไม่ใช้ยอดรวม)</label><input type="number" step="0.01" value="${d.amount || ''}" onchange="upd('${comp.id}','amount',this.value)"></div>
        <div class="prop-field"><small>PromptPay ID ตั้งค่าที่ ข้อมูลร้าน</small></div>`;
      break;
    case 'payment-info':
      html += `
        <div class="prop-field"><label>วิธีชำระ</label>
          <select onchange="upd('${comp.id}','method',this.value)">
            <option value="เงินสด" ${d.method === 'เงินสด' ? 'selected' : ''}>เงินสด</option>
            <option value="โอน" ${d.method === 'โอน' ? 'selected' : ''}>โอน</option>
            <option value="บัตรเครดิต" ${d.method === 'บัตรเครดิต' ? 'selected' : ''}>บัตรเครดิต</option>
            <option value="PromptPay" ${d.method === 'PromptPay' ? 'selected' : ''}>PromptPay</option>
          </select>
        </div>
        <div class="prop-field"><label>รับเงินมา</label><input type="number" step="0.01" value="${d.cashReceived || ''}" onchange="upd('${comp.id}','cashReceived',this.value)"></div>`;
      break;
    case 'box':
      html += `
        <div class="prop-field"><label>Layout</label>
          <select onchange="upd('${comp.id}','layout',this.value)">
            <option value="block" ${d.layout === 'block' ? 'selected' : ''}>Block</option>
            <option value="flex" ${d.layout === 'flex' ? 'selected' : ''}>Flex</option>
            <option value="grid" ${d.layout === 'grid' ? 'selected' : ''}>Grid</option>
          </select>
        </div>
        <div class="prop-field"><label>Padding</label><input type="number" value="${d.padding || 10}" onchange="upd('${comp.id}','padding',this.value)"></div>
        <div class="prop-field"><label>Margin</label><input type="number" value="${d.margin || 5}" onchange="upd('${comp.id}','margin',this.value)"></div>
        <div class="prop-field"><label>Border Width</label><input type="number" value="${d.borderWidth || 1}" onchange="upd('${comp.id}','borderWidth',this.value)"></div>
        <div class="prop-field"><label>Border Style</label>
          <select onchange="upd('${comp.id}','borderStyle',this.value)">
            <option value="solid" ${d.borderStyle === 'solid' ? 'selected' : ''}>Solid</option>
            <option value="dashed" ${d.borderStyle === 'dashed' ? 'selected' : ''}>Dashed</option>
            <option value="dotted" ${d.borderStyle === 'dotted' ? 'selected' : ''}>Dotted</option>
            <option value="none" ${d.borderStyle === 'none' ? 'selected' : ''}>None</option>
          </select>
        </div>
        <div class="prop-field"><label>Border Color</label><input type="color" value="${toColor(d.borderColor || '#dddddd')}" onchange="upd('${comp.id}','borderColor',this.value)"></div>
        <div class="prop-field"><label>Background Color</label><input type="color" value="${toColor(d.backgroundColor || '#ffffff')}" onchange="upd('${comp.id}','backgroundColor',this.value)"></div>
        <div class="prop-field"><label>Border Radius</label><input type="number" value="${d.borderRadius || 4}" onchange="upd('${comp.id}','borderRadius',this.value)"></div>
        <div class="prop-field"><label>Width (px, ว่าง=auto)</label><input value="${d.width || ''}" onchange="upd('${comp.id}','width',this.value)"></div>
        <div class="prop-field"><label>Height (px, ว่าง=auto)</label><input value="${d.height || ''}" onchange="upd('${comp.id}','height',this.value)"></div>
        ${d.layout === 'flex' ? `
          <div class="prop-field"><label>Flex Direction</label>
            <select onchange="upd('${comp.id}','flexDirection',this.value)">
              <option value="row" ${d.flexDirection === 'row' ? 'selected' : ''}>Row</option>
              <option value="column" ${d.flexDirection === 'column' ? 'selected' : ''}>Column</option>
            </select>
          </div>
          <div class="prop-field"><label>Justify Content</label>
            <select onchange="upd('${comp.id}','justifyContent',this.value)">
              <option value="flex-start" ${d.justifyContent === 'flex-start' ? 'selected' : ''}>Start</option>
              <option value="center" ${d.justifyContent === 'center' ? 'selected' : ''}>Center</option>
              <option value="flex-end" ${d.justifyContent === 'flex-end' ? 'selected' : ''}>End</option>
              <option value="space-between" ${d.justifyContent === 'space-between' ? 'selected' : ''}>Space Between</option>
              <option value="space-around" ${d.justifyContent === 'space-around' ? 'selected' : ''}>Space Around</option>
            </select>
          </div>
          <div class="prop-field"><label>Align Items</label>
            <select onchange="upd('${comp.id}','alignItems',this.value)">
              <option value="stretch" ${d.alignItems === 'stretch' ? 'selected' : ''}>Stretch</option>
              <option value="flex-start" ${d.alignItems === 'flex-start' ? 'selected' : ''}>Start</option>
              <option value="center" ${d.alignItems === 'center' ? 'selected' : ''}>Center</option>
              <option value="flex-end" ${d.alignItems === 'flex-end' ? 'selected' : ''}>End</option>
            </select>
          </div>
        ` : ''}
        ${d.layout === 'grid' ? `
          <div class="prop-field"><label>Grid Columns</label><input value="${d.gridColumns || 'repeat(2, 1fr)'}" onchange="upd('${comp.id}','gridColumns',this.value)"></div>
        ` : ''}
        <div class="prop-field"><label>Gap</label><input type="number" value="${d.gap || 10}" onchange="upd('${comp.id}','gap',this.value)"></div>
      `;
      break;
    default:
      html += `<div class="empty-hint">ไม่มี properties</div>`;
  }
  html += `</div>`;
  panel.innerHTML = html;
}

function upd(id, key, val) {
  const comp = Pro.components.find(c => c.id === id); if (!comp) return;
  comp.data[key] = val;
  const el = document.getElementById(id);
  if (el) {
    const ctrl = el.querySelector('.component-controls')?.outerHTML || '';
    el.innerHTML = ctrl + renderComponentContent(comp);
  }
  setTimeout(() => {renderBarcodes(); renderQRCodes(); bindInlineEditors();}, 20);
}

function getName(type) {
  return ({
    heading: 'หัวข้อ', text: 'ข้อความ', logo: 'โลโก้', divider: 'เส้นแบ่ง', spacer: 'ช่องว่าง',
    'store-info': 'ข้อมูลร้าน', 'receipt-info': 'ข้อมูลใบเสร็จ', 'items-table': 'ตารางรายการ',
    summary: 'สรุปยอด', 'payment-info': 'ชำระเงิน', barcode: 'Barcode', qrcode: 'QR Code', promptpay: 'PromptPay', footer: 'ข้อความท้าย', box: 'กล่อง'
  })[type] || type;
}

function toColor(c) {
  // Accept #rrggbb or names; fallback to #ddd
  const ctx = document.createElement('canvas').getContext('2d');
  ctx.fillStyle = c; return ctx.fillStyle || '#dddddd';
}