diff --git a/assets/js/main.js b/assets/js/main.js
index d547d9c..51e3e17 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -12,6 +12,13 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
+ // Global settings with fallbacks
+ const settings = (typeof COMPANY_SETTINGS !== 'undefined') ? COMPANY_SETTINGS : {
+ currency_symbol: '$',
+ currency_decimals: 2,
+ vat_rate: 0
+ };
+
let cart = [];
let currentOrderId = null; // Track order ID for updates
const cartItemsContainer = document.getElementById('cart-items');
@@ -49,11 +56,11 @@ document.addEventListener('DOMContentLoaded', () => {
let currentTableName = null;
const tableDisplay = document.getElementById('current-table-display');
const tableModalEl = document.getElementById('tableSelectionModal');
- const tableSelectionModal = new bootstrap.Modal(tableModalEl);
+ const tableSelectionModal = tableModalEl ? new bootstrap.Modal(tableModalEl) : null;
// Variant Management
const variantModalEl = document.getElementById('variantSelectionModal');
- const variantSelectionModal = new bootstrap.Modal(variantModalEl);
+ const variantSelectionModal = variantModalEl ? new bootstrap.Modal(variantModalEl) : null;
let pendingProduct = null;
// Customer Search Elements
@@ -67,7 +74,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Payment Modal
const paymentModalEl = document.getElementById('paymentSelectionModal');
- const paymentSelectionModal = new bootstrap.Modal(paymentModalEl);
+ const paymentSelectionModal = paymentModalEl ? new bootstrap.Modal(paymentModalEl) : null;
const paymentMethodsContainer = document.getElementById('payment-methods-container');
// Product Search & Filter
@@ -77,7 +84,6 @@ document.addEventListener('DOMContentLoaded', () => {
// 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);
@@ -106,8 +112,6 @@ document.addEventListener('DOMContentLoaded', () => {
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
}
filterProducts();
@@ -194,10 +198,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
// Populate Cart
- cart = data.items; // Assuming format matches
-
- // Note: In auto-VAT mode, we don't load data.order.discount into cartVatInput
- // as it will be re-calculated based on subtotal.
+ cart = data.items;
updateCart();
if (recallModal) recallModal.hide();
@@ -263,7 +264,6 @@ document.addEventListener('DOMContentLoaded', () => {
customerSearchInput.disabled = true; // Lock input
customerResults.style.display = 'none';
clearCustomerBtn.classList.remove('d-none');
- // customerInfo.classList.remove('d-none');
// Loyalty Logic
if (loyaltySection && typeof LOYALTY_SETTINGS !== 'undefined' && LOYALTY_SETTINGS.is_enabled) {
@@ -280,7 +280,6 @@ document.addEventListener('DOMContentLoaded', () => {
}
}
- // Reset redemption state when switching customer (though usually we clear first)
isLoyaltyRedemption = false;
}
@@ -291,9 +290,8 @@ document.addEventListener('DOMContentLoaded', () => {
customerSearchInput.value = '';
customerSearchInput.disabled = false;
clearCustomerBtn.classList.add('d-none');
- customerInfo.classList.add('d-none');
+ if (customerInfo) customerInfo.classList.add('d-none');
- // Hide Loyalty
if (loyaltySection) loyaltySection.classList.add('d-none');
isLoyaltyRedemption = false;
updateCart();
@@ -312,7 +310,6 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
- // --- STRICT ONE ITEM RESTRICTION ---
if (cart.length > 1) {
showToast("Can only redeem a free meal with exactly one item in cart!", "warning");
return;
@@ -332,8 +329,6 @@ document.addEventListener('DOMContentLoaded', () => {
if (result.isConfirmed) {
isLoyaltyRedemption = true;
updateCart();
-
- // Directly process order with Loyalty payment type
processOrder(null, 'Loyalty Redeem');
}
});
@@ -396,7 +391,7 @@ document.addEventListener('DOMContentLoaded', () => {
const selected = checked.value;
if (selected === 'dine-in') {
- if (!currentTableId) openTableSelectionModal();
+ if (!currentTableId && tableSelectionModal) openTableSelectionModal();
if (tableDisplay) tableDisplay.style.display = 'inline-block';
} else {
if (tableDisplay) tableDisplay.style.display = 'none';
@@ -408,7 +403,9 @@ document.addEventListener('DOMContentLoaded', () => {
});
function openTableSelectionModal() {
+ if (!tableSelectionModal) return;
const container = document.getElementById('table-list-container');
+ if (!container) return;
container.innerHTML = '
';
// Update Modal Title
@@ -436,6 +433,7 @@ document.addEventListener('DOMContentLoaded', () => {
function renderTables(tables) {
const container = document.getElementById('table-list-container');
+ if (!container) return;
container.innerHTML = '';
if (tables.length === 0) {
@@ -473,7 +471,7 @@ document.addEventListener('DOMContentLoaded', () => {
tableDisplay.innerHTML = `Table: ${name}`;
tableDisplay.style.display = 'block';
}
- tableSelectionModal.hide();
+ if (tableSelectionModal) tableSelectionModal.hide();
showToast(`Selected Table: ${name}`, 'success');
};
@@ -502,19 +500,20 @@ document.addEventListener('DOMContentLoaded', () => {
});
function openVariantModal(product) {
+ if (!variantSelectionModal) return;
pendingProduct = product;
- const variants = PRODUCT_VARIANTS[product.id] || [];
+ const variants = (typeof PRODUCT_VARIANTS !== 'undefined') ? (PRODUCT_VARIANTS[product.id] || []) : [];
const list = document.getElementById('variant-list');
const title = document.getElementById('variantModalTitle');
- title.textContent = `Select option for ${product.name}`;
+ if (title) title.textContent = `Select option for ${product.name}`;
+ if (!list) return;
list.innerHTML = '';
variants.forEach(v => {
const btn = document.createElement('button');
btn.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-center';
const adj = parseFloat(v.price_adjustment);
- const sign = adj > 0 ? '+' : '';
const finalPrice = product.base_price + adj;
btn.innerHTML = `
@@ -562,69 +561,71 @@ document.addEventListener('DOMContentLoaded', () => {
}
if (cart.length === 0) {
- cartItemsContainer.innerHTML = `
- `;
- cartSubtotal.innerText = formatCurrency(0);
- cartVatInput.value = 0;
- cartTotalPrice.innerText = formatCurrency(0);
+ if (cartItemsContainer) {
+ cartItemsContainer.innerHTML = `
+ `;
+ }
+ if (cartSubtotal) cartSubtotal.innerText = formatCurrency(0);
+ if (cartVatInput) cartVatInput.value = 0;
+ if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(0);
if (quickOrderBtn) quickOrderBtn.disabled = true;
if (placeOrderBtn) placeOrderBtn.disabled = true;
return;
}
- cartItemsContainer.innerHTML = '';
+ if (cartItemsContainer) cartItemsContainer.innerHTML = '';
let subtotal = 0;
cart.forEach((item, index) => {
const itemTotal = item.price * item.quantity;
subtotal += itemTotal;
- const row = document.createElement('div');
- row.className = 'd-flex justify-content-between align-items-center mb-3 border-bottom pb-2';
-
- const variantLabel = item.variant_name ? `${item.variant_name}` : '';
- const arabicNameDisplay = item.name_ar ? `${item.name_ar}
` : '';
+ if (cartItemsContainer) {
+ const row = document.createElement('div');
+ row.className = 'd-flex justify-content-between align-items-center mb-3 border-bottom pb-2';
+
+ const variantLabel = item.variant_name ? `${item.variant_name}` : '';
+ const arabicNameDisplay = item.name_ar ? `${item.name_ar}
` : '';
- row.innerHTML = `
-
-
${item.name}
- ${arabicNameDisplay}
-
${formatCurrency(item.price)} ${variantLabel}
-
-
-
- ${item.quantity}
-
-
-
-
${formatCurrency(itemTotal)}
-
-
- `;
- cartItemsContainer.appendChild(row);
+ row.innerHTML = `
+
+
${item.name}
+ ${arabicNameDisplay}
+
${formatCurrency(item.price)} ${variantLabel}
+
+
+
+ ${item.quantity}
+
+
+
+
${formatCurrency(itemTotal)}
+
+
+ `;
+ cartItemsContainer.appendChild(row);
+ }
});
- cartSubtotal.innerText = formatCurrency(subtotal);
+ if (cartSubtotal) cartSubtotal.innerText = formatCurrency(subtotal);
let vat = 0;
if (isLoyaltyRedemption) {
- // Internal trick: send negative VAT to represent discount for loyalty
vat = -subtotal;
} else {
- // Automatic VAT calculation from system settings
- const vatRate = parseFloat(COMPANY_SETTINGS.vat_rate) || 0;
+ const vatRate = parseFloat(settings.vat_rate) || 0;
vat = subtotal * (vatRate / 100);
}
- cartVatInput.value = vat.toFixed(2);
+ if (cartVatInput) cartVatInput.value = vat.toFixed(2);
let total = subtotal + vat;
if (total < 0) total = 0;
- cartTotalPrice.innerText = formatCurrency(total);
+ if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(total);
if (quickOrderBtn) quickOrderBtn.disabled = false;
if (placeOrderBtn) placeOrderBtn.disabled = false;
}
@@ -647,7 +648,7 @@ document.addEventListener('DOMContentLoaded', () => {
}).then((result) => {
if (result.isConfirmed) {
cart = [];
- cartVatInput.value = 0;
+ if (cartVatInput) cartVatInput.value = 0;
currentOrderId = null;
isLoyaltyRedemption = false;
updateCart();
@@ -707,7 +708,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (quickOrderBtn) {
quickOrderBtn.addEventListener('click', () => {
- if (validateOrder()) {
+ if (validateOrder() && paymentSelectionModal) {
paymentSelectionModal.show();
}
});
@@ -738,19 +739,19 @@ document.addEventListener('DOMContentLoaded', () => {
const orderTypeInput = document.querySelector('input[name="order_type"]:checked');
const orderType = orderTypeInput ? orderTypeInput.value : 'takeaway';
const subtotal = cart.reduce((acc, item) => acc + (item.price * item.quantity), 0);
- const vat = parseFloat(cartVatInput.value) || 0;
+ const vat = parseFloat(cartVatInput ? cartVatInput.value : 0) || 0;
const totalAmount = Math.max(0, subtotal + vat);
- const custId = selectedCustomerId.value;
+ const custId = selectedCustomerId ? selectedCustomerId.value : null;
const orderData = {
- order_id: currentOrderId, // Include ID if updating
+ order_id: currentOrderId,
table_number: (orderType === 'dine-in') ? currentTableId : null,
order_type: orderType,
customer_id: custId || null,
outlet_id: new URLSearchParams(window.location.search).get('outlet_id') || 1,
payment_type_id: paymentTypeId,
total_amount: totalAmount,
- vat: vat, // Send as vat
+ vat: vat,
redeem_loyalty: isLoyaltyRedemption,
items: cart.map(item => ({
product_id: item.id,
@@ -782,7 +783,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (quickOrderBtn) quickOrderBtn.disabled = false;
if (placeOrderBtn) placeOrderBtn.disabled = false;
- paymentSelectionModal.hide();
+ if (paymentSelectionModal) paymentSelectionModal.hide();
if (data.success) {
// Print Receipt
@@ -800,9 +801,9 @@ document.addEventListener('DOMContentLoaded', () => {
});
cart = [];
- cartVatInput.value = 0;
- currentOrderId = null; // Reset
- isLoyaltyRedemption = false; // Reset
+ if (cartVatInput) cartVatInput.value = 0;
+ currentOrderId = null;
+ isLoyaltyRedemption = false;
updateCart();
if (clearCustomerBtn) clearCustomerBtn.click();
showToast(`Order #${data.order_id} placed!`, 'success');
@@ -818,7 +819,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (quickOrderBtn) quickOrderBtn.disabled = false;
if (placeOrderBtn) placeOrderBtn.disabled = false;
- paymentSelectionModal.hide();
+ if (paymentSelectionModal) paymentSelectionModal.hide();
showToast('Network Error', 'danger');
});
};
@@ -839,7 +840,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (!currentOrderId) return;
const subtotal = cart.reduce((acc, item) => acc + (item.price * item.quantity), 0);
- const vat = parseFloat(cartVatInput.value) || 0;
+ const vat = parseFloat(cartVatInput ? cartVatInput.value : 0) || 0;
const totalAmount = Math.max(0, subtotal + vat);
const orderType = document.querySelector('input[name="order_type"]:checked').value;
@@ -858,7 +859,6 @@ document.addEventListener('DOMContentLoaded', () => {
};
function printReceipt(data) {
- const settings = (typeof COMPANY_SETTINGS !== "undefined") ? COMPANY_SETTINGS : {};
const width = 400;
const height = 800;
const left = (screen.width - width) / 2;
@@ -934,7 +934,10 @@ document.addEventListener('DOMContentLoaded', () => {
const loyaltyHtml = data.loyaltyRedeemed ? `* Loyalty Reward Applied *
` : '';
const subtotal = data.total - data.vat;
- const logoHtml = settings.logo_url ? `
` : '';
+ const baseUrl = (typeof BASE_URL !== 'undefined') ? BASE_URL : '';
+ const logoHtml = settings.logo_url ? `
` : '';
+ const outletName = (typeof CURRENT_OUTLET !== 'undefined') ? CURRENT_OUTLET.name : '';
+ const staffName = (typeof CURRENT_USER !== 'undefined') ? CURRENT_USER.name : '';
const html = `
@@ -971,7 +974,7 @@ document.addEventListener('DOMContentLoaded', () => {
- Staff: ${CURRENT_USER.name}
- ${tr['Staff']}: ${CURRENT_USER.name}
+ Staff: ${staffName}
+ ${tr['Staff']}: ${staffName}
@@ -1078,20 +1081,12 @@ document.addEventListener('DOMContentLoaded', () => {
checkOrderType();
// --- Add Customer Logic ---
- const addCustomerBtn = document.getElementById('add-customer-btn');
const addCustomerModalEl = document.getElementById('addCustomerModal');
- if (addCustomerBtn && addCustomerModalEl) {
- const addCustomerModal = new bootstrap.Modal(addCustomerModalEl);
- const saveCustomerBtn = document.getElementById('save-new-customer');
- const newCustomerName = document.getElementById('new-customer-name');
- const newCustomerPhone = document.getElementById('new-customer-phone');
-
- addCustomerBtn.addEventListener('click', () => {
- newCustomerName.value = '';
- newCustomerPhone.value = '';
- addCustomerModal.show();
- });
+ const saveCustomerBtn = document.getElementById('save-new-customer');
+ const newCustomerName = document.getElementById('new-customer-name');
+ const newCustomerPhone = document.getElementById('new-customer-phone');
+ if (saveCustomerBtn && newCustomerName && newCustomerPhone) {
saveCustomerBtn.addEventListener('click', () => {
const name = newCustomerName.value.trim();
const phone = newCustomerPhone.value.trim();
@@ -1115,7 +1110,10 @@ document.addEventListener('DOMContentLoaded', () => {
saveCustomerBtn.textContent = 'Save Customer';
if (data.success) {
- addCustomerModal.hide();
+ if (addCustomerModalEl) {
+ const modal = bootstrap.Modal.getInstance(addCustomerModalEl);
+ if (modal) modal.hide();
+ }
selectCustomer(data.customer);
showToast('Customer created successfully', 'success');
} else {
@@ -1129,4 +1127,4 @@ document.addEventListener('DOMContentLoaded', () => {
});
});
}
-});
+});
\ No newline at end of file
diff --git a/pos.php b/pos.php
index 9c4f423..2a667a9 100644
--- a/pos.php
+++ b/pos.php
@@ -539,6 +539,18 @@ if (!$loyalty_settings) {
+
+
+
+
-