document.addEventListener('DOMContentLoaded', () => { let cart = []; const cartItemsContainer = document.getElementById('cart-items'); const cartTotalPrice = document.getElementById('cart-total-price'); const cartSubtotal = document.getElementById('cart-subtotal'); const checkoutBtn = document.getElementById('checkout-btn'); // Table Management let currentTableId = null; let currentTableName = null; const tableDisplay = document.getElementById('current-table-display'); const tableModalEl = document.getElementById('tableSelectionModal'); const tableSelectionModal = new bootstrap.Modal(tableModalEl); // Customer Search Elements const customerSearchInput = document.getElementById('customer-search'); const customerResults = document.getElementById('customer-results'); const selectedCustomerId = document.getElementById('selected-customer-id'); const clearCustomerBtn = document.getElementById('clear-customer'); const customerInfo = document.getElementById('customer-info'); const customerNameDisplay = document.getElementById('customer-name-display'); // Product Search & Filter const productSearchInput = document.getElementById('product-search-input'); let currentCategory = 'all'; let currentSearchQuery = ''; // Helper for currency function formatCurrency(amount) { const settings = (typeof COMPANY_SETTINGS !== 'undefined') ? COMPANY_SETTINGS : { currency_symbol: '$', currency_decimals: 2 }; const symbol = settings.currency_symbol || '$'; const decimals = parseInt(settings.currency_decimals || 2); return symbol + parseFloat(amount).toFixed(decimals); } // --- Product Filtering (Category + Search) --- function filterProducts() { const items = document.querySelectorAll('.product-item'); items.forEach(item => { const matchesCategory = (currentCategory == 'all' || item.dataset.categoryId == currentCategory); const name = item.querySelector('.card-title').textContent.toLowerCase(); const matchesSearch = name.includes(currentSearchQuery); if (matchesCategory && matchesSearch) { item.style.display = 'block'; } else { item.style.display = 'none'; } }); } window.filterCategory = function(categoryId, btnElement) { currentCategory = categoryId; // Update Active Button State if (btnElement) { document.querySelectorAll('.category-btn').forEach(btn => btn.classList.remove('active')); btnElement.classList.add('active'); } else if (typeof btnElement === 'undefined' && categoryId !== 'all') { // Try to find the button corresponding to this category ID // This might happen if triggered programmatically } filterProducts(); }; if (productSearchInput) { productSearchInput.addEventListener('input', (e) => { currentSearchQuery = e.target.value.trim().toLowerCase(); filterProducts(); }); } // --- Customer Search --- let searchTimeout; if (customerSearchInput) { customerSearchInput.addEventListener('input', (e) => { const query = e.target.value.trim(); clearTimeout(searchTimeout); if (query.length < 2) { customerResults.style.display = 'none'; return; } searchTimeout = setTimeout(() => { fetch(`api/search_customers.php?q=${encodeURIComponent(query)}`) .then(res => res.json()) .then(data => { customerResults.innerHTML = ''; if (data.length > 0) { data.forEach(cust => { const a = document.createElement('a'); a.href = '#'; a.className = 'list-group-item list-group-item-action'; a.innerHTML = `
${cust.name}
${cust.phone || ''}
`; a.onclick = (ev) => { ev.preventDefault(); selectCustomer(cust); }; customerResults.appendChild(a); }); customerResults.style.display = 'block'; } else { customerResults.innerHTML = '
No results found
'; customerResults.style.display = 'block'; } }); }, 300); }); // Close search on click outside document.addEventListener('click', (e) => { if (!customerSearchInput.contains(e.target) && !customerResults.contains(e.target)) { customerResults.style.display = 'none'; } }); } function selectCustomer(cust) { selectedCustomerId.value = cust.id; customerNameDisplay.textContent = cust.name; customerSearchInput.value = cust.name; // Show name in input customerSearchInput.disabled = true; // Lock input customerResults.style.display = 'none'; clearCustomerBtn.classList.remove('d-none'); // customerInfo.classList.remove('d-none'); } if (clearCustomerBtn) { clearCustomerBtn.addEventListener('click', () => { selectedCustomerId.value = ''; customerSearchInput.value = ''; customerSearchInput.disabled = false; clearCustomerBtn.classList.add('d-none'); customerInfo.classList.add('d-none'); customerSearchInput.focus(); }); } // --- Table & Order Type Logic --- const orderTypeInputs = document.querySelectorAll('input[name="order_type"]'); function checkOrderType() { const checked = document.querySelector('input[name="order_type"]:checked'); if (!checked) return; const selected = checked.value; if (selected === 'dine-in') { if (!currentTableId) openTableSelectionModal(); if (tableDisplay) tableDisplay.style.display = 'inline-block'; } else { if (tableDisplay) tableDisplay.style.display = 'none'; } } orderTypeInputs.forEach(input => { input.addEventListener('change', checkOrderType); }); function openTableSelectionModal() { const container = document.getElementById('table-list-container'); container.innerHTML = '
'; tableSelectionModal.show(); fetch('api/tables.php') .then(res => res.json()) .then(data => { if (data.success) { renderTables(data.tables); } else { container.innerHTML = `
${data.error}
`; } }) .catch(() => { container.innerHTML = `
Error loading tables.
`; }); } function renderTables(tables) { const container = document.getElementById('table-list-container'); container.innerHTML = ''; if (tables.length === 0) { container.innerHTML = '
No tables found.
'; return; } tables.forEach(table => { const isOccupied = table.is_occupied; const col = document.createElement('div'); col.className = 'col-6 col-md-4 col-lg-3'; col.innerHTML = `
${table.name}
${table.capacity} Pax
${isOccupied ? 'Occupied' : 'Available'}
`; container.appendChild(col); }); } window.selectTable = function(id, name) { currentTableId = id; currentTableName = name; if (tableDisplay) { tableDisplay.innerHTML = `Table: ${name}`; tableDisplay.style.display = 'block'; } tableSelectionModal.hide(); showToast(`Selected Table: ${name}`, 'success'); }; // --- Cart Logic --- document.querySelectorAll('.add-to-cart').forEach(card => { card.addEventListener('click', (e) => { // Find closest card just in case click was on child const target = e.currentTarget; const product = { id: target.dataset.id, name: target.dataset.name, price: parseFloat(target.dataset.price), quantity: 1 }; addToCart(product); }); }); function addToCart(product) { const existing = cart.find(item => item.id === product.id); if (existing) { existing.quantity++; } else { cart.push(product); } updateCart(); } window.changeQuantity = function(index, delta) { if (cart[index]) { cart[index].quantity += delta; if (cart[index].quantity <= 0) { removeFromCart(index); } else { updateCart(); } } }; function updateCart() { if (cart.length === 0) { cartItemsContainer.innerHTML = `

Cart is empty

`; cartSubtotal.innerText = formatCurrency(0); cartTotalPrice.innerText = formatCurrency(0); checkoutBtn.disabled = true; return; } cartItemsContainer.innerHTML = ''; let total = 0; cart.forEach((item, index) => { const itemTotal = item.price * item.quantity; total += itemTotal; const row = document.createElement('div'); row.className = 'd-flex justify-content-between align-items-center mb-3 border-bottom pb-2'; // Updated Cart Item Layout row.innerHTML = `
${item.name}
${formatCurrency(item.price)}
${item.quantity}
${formatCurrency(itemTotal)}
`; cartItemsContainer.appendChild(row); }); cartSubtotal.innerText = formatCurrency(total); cartTotalPrice.innerText = formatCurrency(total); checkoutBtn.disabled = false; } window.removeFromCart = function(index) { cart.splice(index, 1); updateCart(); }; // --- Checkout --- checkoutBtn.addEventListener('click', () => { if (cart.length === 0) return; const orderTypeInput = document.querySelector('input[name="order_type"]:checked'); const orderType = orderTypeInput ? orderTypeInput.value : 'dine-in'; if (orderType === 'dine-in' && !currentTableId) { showToast('Please select a table first', 'warning'); openTableSelectionModal(); return; } const totalAmount = cart.reduce((acc, item) => acc + (item.price * item.quantity), 0); const custId = selectedCustomerId.value; const orderData = { table_number: (orderType === 'dine-in') ? currentTableId : null, order_type: orderType, customer_id: custId || null, total_amount: totalAmount, items: cart.map(item => ({ product_id: item.id, quantity: item.quantity, unit_price: item.price })) }; // Show loading state checkoutBtn.disabled = true; checkoutBtn.innerHTML = ' Processing...'; fetch('api/order.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(orderData) }) .then(res => res.json()) .then(data => { checkoutBtn.disabled = false; checkoutBtn.innerHTML = 'Place Order '; if (data.success) { cart = []; updateCart(); // Reset customer if (clearCustomerBtn) clearCustomerBtn.click(); showToast(`Order #${data.order_id} placed!`, 'success'); } else { showToast(`Error: ${data.error}`, 'danger'); } }) .catch(err => { checkoutBtn.disabled = false; checkoutBtn.innerHTML = 'Place Order'; showToast('Network Error', 'danger'); }); }); function showToast(msg, type = 'primary') { const toastContainer = document.getElementById('toast-container'); const id = 'toast-' + Date.now(); const html = ` `; toastContainer.insertAdjacentHTML('beforeend', html); const el = document.getElementById(id); const t = new bootstrap.Toast(el, { delay: 3000 }); t.show(); el.addEventListener('hidden.bs.toast', () => el.remove()); } });