pos.js

28.38 KB
14/10/2025 16:35
JS
pos.js
// POS System logic
class POS {
  constructor() {
    this.dbHelper = dbHelper;
    this.cart = null; // will be created after DB is initialized
    this.products = [];
    this.categories = []; // will be loaded from categories.json
    this.currentCategory = 'all';
    this.searchTerm = '';
    this.paymentMethod = 'cash';
    this.deliveryMethod = 'instore';
    this.shippingCost = 0; // will be loaded from settings

    // Initialize modals
    this.receiptModal = new Modal('receiptModal');

    // Initialize event listeners
    this.initEventListeners();
  }

  // Prepare PromptPay QR image based on settings and current cart total
  async preparePromptpayQR() {
    try {
      const promptpayEl = document.getElementById('promptpayPayment');
      if (!promptpayEl) return;

      const shopPhoneEntry = await this.dbHelper.getById('settings', 'shopPhone');
      const shopPhone = shopPhoneEntry && shopPhoneEntry.value ? String(shopPhoneEntry.value) : null;
      let idForPromptpay = '';
      if (shopPhone) {
        let digits = shopPhone.replace(/\D/g, '');
        if (digits.length === 10 && digits.startsWith('0')) {
          digits = '66' + digits.slice(1);
        }
        idForPromptpay = digits;
      }

      const shipping = (this.deliveryMethod === 'instore' || this.deliveryMethod === 'pickup') ? 0 : this.shippingCost;
      const amount = this.cart.getTotal(shipping).toFixed(2);

      const img = promptpayEl.querySelector('img');
      const infoP = promptpayEl.querySelector('p');

      function isValidPromptpayId(id) {
        if (!id) return false;
        if (!/^\d+$/.test(id)) return false;
        if (id.length === 11 && id.startsWith('66')) return true;
        if (id.length === 13) return true;
        return false;
      }

      if (img && idForPromptpay) {
        const candidates = [];
        if (isValidPromptpayId(idForPromptpay)) candidates.push(idForPromptpay);
        const raw = shopPhone ? shopPhone.replace(/\D/g, '') : '';
        if (raw && !candidates.includes(raw)) candidates.push(raw);
        if (raw && raw.length === 10 && raw.startsWith('0')) {
          const normalized = '66' + raw.slice(1);
          if (!candidates.includes(normalized)) candidates.unshift(normalized);
        }

        let attempt = 0;
        const tryNext = () => {
          if (attempt >= candidates.length) {
            img.removeAttribute('src');
            if (infoP) infoP.textContent = 'ไม่สามารถโหลด PromptPay QR ได้ — โปรดตรวจสอบค่า PromptPay ID ใน settings (shopPhone)';
            return;
          }
          const id = candidates[attempt];
          const url = `https://promptpay.io/${id}/${encodeURIComponent(amount)}.png`;
          img.onload = () => {
            img.alt = `PromptPay QR - ฿${amount}`;
            if (infoP) infoP.textContent = `สแกน QR Code เพื่อชำระเงิน ฿${amount}`;
          };
          img.onerror = () => {
            attempt += 1;
            tryNext();
          };
          img.src = url;
        };
        tryNext();
      } else {
        if (img) img.removeAttribute('src');
        if (infoP) infoP.textContent = 'PromptPay ID ไม่ถูกต้องหรือยังไม่ตั้งค่าในระบบ (settings.shopPhone)';
      }
    } catch (err) {
      console.error('Error preparing POS PromptPay QR:', err);
    }
  }

  async init() {
    try {
      // Initialize database
      await this.dbHelper.init();

      // Initialize with mock data if needed
      await this.dbHelper.initializeWithMockData();

      // Load categories
      await this.loadCategories();

      // Load products
      await this.loadProducts();

      // Create cart now that DB is available
      this.cart = new Cart();
      // Update cart UI
      this.cart.updateCartUI();

      console.log('POS initialized successfully');
    } catch (error) {
      console.error('Error initializing POS:', error);
    }
  }

  initEventListeners() {
    // Clear cart button
    const clearCartBtn = document.getElementById('clearCartBtn');
    if (clearCartBtn) {
      clearCartBtn.addEventListener('click', async () => {
        if (confirm('คุณต้องการล้างตะกร้าสินค้าใช่หรือไม่?')) {
          await this.cart.clearCart();
          this.updatePOSCartUI();
        }
      });
    }

    // Category filter
    const categoryItems = document.querySelectorAll('.pos-category');
    categoryItems.forEach(item => {
      item.addEventListener('click', () => {
        // Remove active class from all items
        categoryItems.forEach(i => i.classList.remove('active'));

        // Add active class to clicked item
        item.classList.add('active');

        // Filter products
        this.currentCategory = item.getAttribute('data-category');
        this.filterProducts();
      });
    });

    // Search functionality
    const searchInput = document.getElementById('posSearchInput');
    if (searchInput) {
      searchInput.addEventListener('input', (e) => {
        this.searchTerm = e.target.value.toLowerCase();
        this.filterProducts();
      });
    }

    // Payment method selection
    const paymentMethods = document.querySelectorAll('.payment-method');
    paymentMethods.forEach(method => {
      method.addEventListener('click', async () => {
        // Remove active class from all methods
        paymentMethods.forEach(m => m.classList.remove('active'));

        // Add active class to clicked method
        method.classList.add('active');

        // Update payment method
        this.paymentMethod = method.getAttribute('data-method');

        // Show/hide payment details
        document.getElementById('cashPayment').classList.add('hidden');
        document.getElementById('promptpayPayment').classList.add('hidden');
        document.getElementById('cardPayment').classList.add('hidden');

        if (this.paymentMethod === 'cash') {
          document.getElementById('cashPayment').classList.remove('hidden');
        } else if (this.paymentMethod === 'promptpay') {
          // prepare promptpay QR (extracted helper)
          await this.preparePromptpayQR();
          document.getElementById('promptpayPayment').classList.remove('hidden');
        } else if (this.paymentMethod === 'card') {
          document.getElementById('cardPayment').classList.remove('hidden');
        }
      });
    });

    // Delivery method selection
    const deliveryMethods = document.querySelectorAll('.delivery-method');
    deliveryMethods.forEach(dm => {
      dm.addEventListener('click', async () => {
        deliveryMethods.forEach(d => d.classList.remove('active'));
        dm.classList.add('active');
        this.deliveryMethod = dm.getAttribute('data-method');

        // Load shipping cost from settings
        try {
          const shippingEntry = await this.dbHelper.getById('settings', 'shippingCost');
          this.shippingCost = shippingEntry && typeof shippingEntry.value !== 'undefined' ? Number(shippingEntry.value) : 0;
        } catch (err) {
          console.error('Error reading shipping cost:', err);
          this.shippingCost = 0;
        }

        // Show/hide customer details and address only when delivery or pickup
        const customerDetailsEl = document.getElementById('customerDetails');
        const addressGroup = document.getElementById('customerAddressGroup');
        if (this.deliveryMethod === 'delivery') {
          if (customerDetailsEl) customerDetailsEl.classList.remove('hidden');
          if (addressGroup) addressGroup.classList.remove('hidden');
        } else if (this.deliveryMethod === 'pickup') {
          if (customerDetailsEl) customerDetailsEl.classList.remove('hidden');
          if (addressGroup) addressGroup.classList.add('hidden');
        } else {
          if (customerDetailsEl) customerDetailsEl.classList.add('hidden');
          if (addressGroup) addressGroup.classList.add('hidden');
        }

        // Refresh summary to include shipping when applicable
        this.updatePOSCartSummary();

        // If using PromptPay, refresh QR because amount changed
        if (this.paymentMethod === 'promptpay') {
          await this.preparePromptpayQR();
        }
      });
    });

    // Cash received input
    const cashReceivedInput = document.getElementById('cashReceived');
    if (cashReceivedInput) {
      cashReceivedInput.addEventListener('input', () => {
        this.calculateChange();
      });
    }

    // Process payment button
    const processPaymentBtn = document.getElementById('processPaymentBtn');
    if (processPaymentBtn) {
      processPaymentBtn.addEventListener('click', () => {
        this.processPayment();
      });
    }

    // Listen for cart updates so POS UI and PromptPay QR refresh in real-time
    window.addEventListener('cart:updated', async () => {
      try {
        this.updatePOSCartUI();
        // if current payment is PromptPay, refresh QR
        if (this.paymentMethod === 'promptpay') {
          await this.preparePromptpayQR();
        }
      } catch (err) {
        console.error('Error handling cart:updated in POS:', err);
      }
    });

    // Print receipt button
    const printReceiptBtn = document.getElementById('printReceiptBtn');
    if (printReceiptBtn) {
      printReceiptBtn.addEventListener('click', () => {
        this.printReceipt();
      });
    }

    // New transaction button
    const newTransactionBtn = document.getElementById('newTransactionBtn');
    if (newTransactionBtn) {
      newTransactionBtn.addEventListener('click', () => {
        this.newTransaction();
      });
    }
  }

  async loadCategories() {
    try {
      const cats = await this.dbHelper.getAll('categories');
      if (cats && cats.length > 0) {
        this.categories = cats;
      } else {
        try {
          const response = await fetch('mock/categories.json');
          if (response.ok) this.categories = await response.json(); else this.categories = [];
        } catch (err) {
          console.warn('Could not fetch mock categories', err);
          this.categories = [];
        }
      }

      if (!this.categories || this.categories.length === 0) this.categories = [{id: 'all', name: 'ทั้งหมด', icon: 'bi-grid-3x3-gap'}];
      this.renderCategories();
    } catch (error) {
      console.error('Error loading categories:', error);
      this.categories = [{id: 'all', name: 'ทั้งหมด', icon: 'bi-grid-3x3-gap'}];
      this.renderCategories();
    }
  }

  renderCategories() {
    const categoryList = document.querySelector('.pos-categories');
    if (categoryList && this.categories.length > 0) {
      // Prepend "ทั้งหมด" category dynamically
      const allCategory = `
        <div class="pos-category active" data-category="all">
          <i class="bi bi-grid-3x3-gap"></i>
          <span>ทั้งหมด</span>
        </div>
      `;

      const categoryHTML = this.categories.map((cat) => `
        <div class="pos-category" data-category="${cat.id}">
          <i class="bi ${cat.icon}"></i>
          <span>${cat.name}</span>
        </div>
      `).join('');

      categoryList.innerHTML = allCategory + categoryHTML;

      // Re-attach event listeners for new category items
      const categoryItems = document.querySelectorAll('.pos-category');
      categoryItems.forEach(item => {
        item.addEventListener('click', () => {
          // Remove active class from all items
          categoryItems.forEach(i => i.classList.remove('active'));
          // Add active class to clicked item
          item.classList.add('active');
          // Filter products
          this.currentCategory = item.getAttribute('data-category');
          this.filterProducts();
        });
      });
    }
  }

  async loadProducts() {
    try {
      const productsData = await this.dbHelper.getAll('products');
      this.products = productsData.map(product => new Product(product));
      this.renderProducts();
    } catch (error) {
      console.error('Error loading products:', error);
    }
  }

  renderProducts() {
    const productGrid = document.getElementById('posProductGrid');
    if (productGrid) {
      productGrid.innerHTML = this.products.map(product => product.renderPOSCard()).join('');

      // Add event listeners to product cards
      this.attachProductEventListeners();
    }
  }

  filterProducts() {
    let filteredProducts = this.products;

    // Filter by category
    if (this.currentCategory !== 'all') {
      filteredProducts = filteredProducts.filter(product => product.category === this.currentCategory);
    }

    // Filter by search term
    if (this.searchTerm) {
      filteredProducts = filteredProducts.filter(product =>
        product.name.toLowerCase().includes(this.searchTerm) ||
        product.description.toLowerCase().includes(this.searchTerm)
      );
    }

    // Render filtered products
    const productGrid = document.getElementById('posProductGrid');
    if (productGrid) {
      if (filteredProducts.length === 0) {
        productGrid.innerHTML = '<p>ไม่พบสินค้าที่ค้นหา</p>';
      } else {
        productGrid.innerHTML = filteredProducts.map(product => product.renderPOSCard()).join('');

        // Add event listeners to product cards
        this.attachProductEventListeners();
      }
    }
  }

  attachProductEventListeners() {
    // Product card click
    document.querySelectorAll('.pos-product-card').forEach(card => {
      card.addEventListener('click', async (e) => {
        const productId = card.getAttribute('data-id');

        // Find product
        const product = this.products.find(p => p.id === productId);
        if (product) {
          // Add to cart with quantity 1
          const success = await this.cart.addItem(product, 1);

          if (success) {
            toast.show('สินค้าถูกเพิ่มในตะกร้าแล้ว');
            this.updatePOSCartUI();
          } else {
            toast.show('เกิดข้อผิดพลาดในการเพิ่มสินค้า', 'error');
          }
        }
      });
    });
  }

  updatePOSCartUI() {
    // Update cart items
    const cartItemsContainer = document.getElementById('posCartItems');
    if (cartItemsContainer) {
      if (this.cart.items.length === 0) {
        cartItemsContainer.innerHTML = '<p>ตะกร้าสินค้าว่าง</p>';
      } else {
        cartItemsContainer.innerHTML = this.cart.items.map(item => `
          <div class="pos-cart-item">
            <div class="pos-cart-item-image">
              <img src="${item.image}" alt="${item.name}">
            </div>
            <div class="pos-cart-item-info">
              <div class="pos-cart-item-top">
                <div class="pos-cart-item-name">${item.name}</div>
                <div class="pos-cart-item-price">฿${item.price}</div>
              </div>
              <div class="pos-cart-item-bottom">
                <div class="pos-cart-item-quantity">
                  <button class="decrease-quantity" data-id="${item.id}">-</button>
                  <input type="number" value="${item.quantity}" min="1" class="quantity-input" data-id="${item.id}">
                  <button class="increase-quantity" data-id="${item.id}">+</button>
                </div>
                <div class="pos-cart-item-remove" data-id="${item.id}" title="ลบรายการ">
                  <i class="bi bi-trash"></i>
                </div>
              </div>
            </div>
          </div>
        `).join('');

        // Add event listeners to cart item buttons
        this.attachPOSCartItemEventListeners();
      }
    }

    // Update cart summary
    this.updatePOSCartSummary();
  }

  updatePOSCartSummary() {
    const subtotalElement = document.getElementById('posSubtotal');
    const discountElement = document.getElementById('posDiscount');
    const totalElement = document.getElementById('posTotal');

    if (subtotalElement) {
      subtotalElement.textContent = `฿${this.cart.getSubtotal()}`;
    }

    if (discountElement) {
      discountElement.textContent = `฿0`;
    }

    if (totalElement) {
      const shipping = (this.deliveryMethod === 'instore' || this.deliveryMethod === 'pickup') ? 0 : this.shippingCost;
      totalElement.textContent = `฿${this.cart.getTotal(shipping)}`;
    }
  }

  attachPOSCartItemEventListeners() {
    // Decrease quantity buttons
    document.querySelectorAll('.pos-cart-item .decrease-quantity').forEach(button => {
      button.addEventListener('click', async (e) => {
        const btn = e.currentTarget;
        const productId = btn.getAttribute('data-id') || btn.dataset.id;
        const input = document.querySelector(`.pos-cart-item .quantity-input[data-id="${productId}"]`);
        if (!input) return;
        const newQuantity = Math.max(1, parseInt(input.value) - 1);

        await this.cart.updateItemQuantity(productId, newQuantity);
        input.value = newQuantity;
        this.updatePOSCartUI();
      });
    });

    // Increase quantity buttons
    document.querySelectorAll('.pos-cart-item .increase-quantity').forEach(button => {
      button.addEventListener('click', async (e) => {
        const btn = e.currentTarget;
        const productId = btn.getAttribute('data-id') || btn.dataset.id;
        const input = document.querySelector(`.pos-cart-item .quantity-input[data-id="${productId}"]`);
        if (!input) return;
        const newQuantity = parseInt(input.value) + 1;

        await this.cart.updateItemQuantity(productId, newQuantity);
        input.value = newQuantity;
        this.updatePOSCartUI();
      });
    });

    // Quantity input fields
    document.querySelectorAll('.pos-cart-item .quantity-input').forEach(input => {
      input.addEventListener('change', async (e) => {
        const productId = e.target.getAttribute('data-id');
        const newQuantity = Math.max(1, parseInt(e.target.value) || 1);

        await this.cart.updateItemQuantity(productId, newQuantity);
        this.updatePOSCartUI();
      });
    });

    // Remove item buttons
    document.querySelectorAll('.pos-cart-item-remove').forEach(button => {
      button.addEventListener('click', async (e) => {
        const removeEl = e.target.closest('.pos-cart-item-remove');
        const productId = removeEl ? (removeEl.getAttribute('data-id') || removeEl.dataset.id) : null;
        if (!productId) return;
        await this.cart.removeItem(productId);
        this.updatePOSCartUI();
      });
    });
  }

  calculateChange() {
    const cashReceived = parseFloat(document.getElementById('cashReceived').value) || 0;
    const shipping = (this.deliveryMethod === 'instore' || this.deliveryMethod === 'pickup') ? 0 : this.shippingCost;
    const total = this.cart.getTotal(shipping);
    const change = cashReceived - total;

    document.getElementById('cashChange').value = change >= 0 ? change.toFixed(2) : '0.00';
  }

  async processPayment() {
    try {
      if (this.cart.items.length === 0) {
        toast.show('ตะกร้าสินค้าว่าง', 'warning');
        return;
      }

      // Validate payment
      if (this.paymentMethod === 'cash') {
        const cashReceived = parseFloat(document.getElementById('cashReceived').value) || 0;
        const shipping = (this.deliveryMethod === 'instore' || this.deliveryMethod === 'pickup') ? 0 : this.shippingCost;
        const total = this.cart.getTotal(shipping);

        if (cashReceived < total) {
          toast.show('จำนวนเงินที่รับมาไม่เพียงพอ', 'warning');
          return;
        }
      }

      // Create order object
      const customerName = document.getElementById('customerName').value.trim() || 'ลูกค้าหน้าร้าน';
      const customerPhone = document.getElementById('customerPhone').value.trim() || '-';
      const customerAddress = this.deliveryMethod === 'delivery' ? document.getElementById('customerAddress').value.trim() : '-';
      const shipping = (this.deliveryMethod === 'instore' || this.deliveryMethod === 'pickup') ? 0 : this.shippingCost;

      const order = {
        customerName: customerName,
        customerPhone: customerPhone,
        customerEmail: '-',
        customerAddress: customerAddress,
        deliveryMethod: this.deliveryMethod,
        paymentMethod: this.paymentMethod,
        items: this.cart.items.map(item => ({
          id: item.id,
          name: item.name,
          price: item.price,
          quantity: item.quantity
        })),
        subtotal: this.cart.getSubtotal(),
        shipping: shipping,
        total: this.cart.getTotal(shipping),
        status: 'completed',
        date: new Date().toISOString(),
        type: 'pos'
      };

      // Ensure order has an id (orders objectStore uses keyPath 'id')
      if (!order.id) {
        // Simple unique id: ORD-<timestamp>-<random>
        order.id = `ORD-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
      }

      // Save order to IndexedDB
      await this.dbHelper.add('orders', order);

      // Save to sales data
      await this.dbHelper.add('sales', {
        date: new Date().toISOString().split('T')[0], // YYYY-MM-DD format
        amount: order.total,
        type: 'pos'
      });

      // Show receipt
      this.showReceipt(order);

      // Clear cart
      await this.cart.clearCart();
      this.updatePOSCartUI();

      console.log('POS transaction completed successfully:', order);
    } catch (error) {
      console.error('Error processing payment:', error);
      toast.show('เกิดข้อผิดพลาดในการชำระเงิน', 'error');
    }
  }

  showReceipt(order) {
    // Generate receipt HTML
    const receiptHTML = `
            <div class="receipt">
                <div class="receipt-header">
                    <h2>ร้านขนมไทย</h2>
                    <p>123 ถนนขนมไทย แขวงขนมหวาน เขตหวานกรอบ กรุงเทพฯ 10100</p>
                    <p>โทร: 02-123-4567</p>
                </div>

                <div class="receipt-info">
                    <p>เลขที่: #${order.id}</p>
                    <p>วันที่: ${new Date(order.date).toLocaleDateString('th-TH')}</p>
                    <p>เวลา: ${new Date(order.date).toLocaleTimeString('th-TH')}</p>
                    <p>พนักงาน: แอดมิน</p>
                    <p>ชื่อผู้รับ: ${order.customerName}</p>
                    <p>เบอร์โทร: ${order.customerPhone}</p>
                    ${order.customerAddress !== '-' ? `<p>ที่อยู่: ${order.customerAddress}</p>` : ''}
                </div>

                <div class="receipt-items">
                    ${order.items.map(item => `
                        <div class="receipt-item">
                            <span>${item.name} x ${item.quantity}</span>
                            <span>฿${item.price * item.quantity}</span>
                        </div>
                    `).join('')}
                </div>

                <div class="receipt-summary">
                    <div class="receipt-summary-row">
                        <span>รวม:</span>
                        <span>฿${order.subtotal}</span>
                    </div>
                    <div class="receipt-summary-row">
                        <span>ค่าจัดส่ง:</span>
                        <span>฿${order.shipping}</span>
                    </div>
                    <div class="receipt-summary-row">
                        <span>ส่วนลด:</span>
                        <span>฿0</span>
                    </div>
                    <div class="receipt-summary-row total">
                        <span>ทั้งหมด:</span>
                        <span>฿${order.total}</span>
                    </div>
                    ${order.paymentMethod === 'cash' ? `
                        <div class="receipt-summary-row">
                            <span>รับเงิน:</span>
                            <span>฿${document.getElementById('cashReceived').value}</span>
                        </div>
                        <div class="receipt-summary-row">
                            <span>เงินทอน:</span>
                            <span>฿${document.getElementById('cashChange').value}</span>
                        </div>
                    ` : ''}
                </div>

                <div class="receipt-footer">
                    <p>ขอบคุณที่ใช้บริการ</p>
                    <p>โปรดกลับมาอีกนะคะ</p>
                </div>
            </div>
        `;

    // Update receipt modal
    document.getElementById('receiptContent').innerHTML = receiptHTML;

    // Open receipt modal
    this.receiptModal.open();
  }

  printReceipt() {
    // Print only the receipt content by opening a new window with the receipt HTML.
    try {
      const receiptEl = document.getElementById('receiptContent');
      if (!receiptEl) {
        window.print();
        return;
      }

      const receiptHTML = receiptEl.innerHTML;
      const printWindow = window.open('', '_blank', 'toolbar=0,location=0,menubar=0,width=800,height=900');
      if (!printWindow) {
        // Popup blocked — fallback to window.print()
        window.print();
        return;
      }
      // Use a minimal inline stylesheet to print only the receipt content
      const inlineStyles = `
        body { font-family: 'Mitr', sans-serif; color: #333; padding: 20px; }
        .receipt { max-width: 700px; margin: 0 auto; background: #fff; }
        .receipt-header { text-align: center; margin-bottom: 12px; }
        .receipt-header h2 { color: #8b6f47; margin: 0 0 6px 0; }
        .receipt-info p, .receipt-summary-row, .receipt-item { font-size: 14px; margin: 4px 0; }
        .receipt-items { margin: 12px 0; }
        .receipt-item { display:flex; justify-content:space-between; }
        .receipt-summary-row { display:flex; justify-content:space-between; }
        .receipt-summary-row.total { font-weight:700; margin-top:8px; }
        @media print { body { -webkit-print-color-adjust: exact; } }
      `;

      printWindow.document.open();
      printWindow.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>ใบเสร็จ</title><style>${inlineStyles}</style></head><body>${receiptHTML}</body></html>`);
      printWindow.document.close();
      printWindow.focus();

      // Give the new window some time to load styles/images before printing
      setTimeout(() => {
        try {
          printWindow.print();
        } catch (e) {
          console.warn('Print failed in popup, falling back to main window print', e);
          window.print();
        }
        // Close the print window after printing
        printWindow.close();
      }, 500);
    } catch (err) {
      console.error('Error printing receipt:', err);
      window.print();
    }
  }

  newTransaction() {
    // Close receipt modal
    this.receiptModal.close();

    // Reset payment method
    document.querySelectorAll('.payment-method').forEach(m => m.classList.remove('active'));
    document.querySelector('.payment-method[data-method="cash"]').classList.add('active');
    this.paymentMethod = 'cash';

    // Reset delivery method
    document.querySelectorAll('.delivery-method').forEach(d => d.classList.remove('active'));
    document.querySelector('.delivery-method[data-method="instore"]').classList.add('active');
    this.deliveryMethod = 'instore';

    // Hide customer details and address
    document.getElementById('customerDetails').classList.add('hidden');
    document.getElementById('customerAddressGroup').classList.add('hidden');

    // Reset customer fields
    document.getElementById('customerName').value = '';
    document.getElementById('customerPhone').value = '';
    document.getElementById('customerAddress').value = '';

    // Show cash payment details
    document.getElementById('cashPayment').classList.remove('hidden');
    document.getElementById('promptpayPayment').classList.add('hidden');
    document.getElementById('cardPayment').classList.add('hidden');

    // Reset cash inputs
    document.getElementById('cashReceived').value = '';
    document.getElementById('cashChange').value = '0.00';

    // Update summary
    this.updatePOSCartSummary();
  }
}

// Initialize POS when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
  const pos = new POS();
  pos.init();
});