diff --git a/assets/js/main.js b/assets/js/main.js index 4a595d9..7969b51 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -63,6 +63,10 @@ document.addEventListener('DOMContentLoaded', () => { const pointsHistoryBody = document.getElementById('points-history-body'); const pointsHistoryEmpty = document.getElementById('points-history-empty'); + const addCustomerModalEl = document.getElementById('addCustomerModal'); + const addCustomerModal = addCustomerModalEl ? new bootstrap.Modal(addCustomerModalEl) : null; + const saveNewCustomerBtn = document.getElementById('save-new-customer'); + let currentTableId = null; let currentTableName = null; const tableDisplay = document.getElementById('current-table-display'); @@ -288,6 +292,92 @@ document.addEventListener('DOMContentLoaded', () => { }); } + if (redeemLoyaltyBtn) { + redeemLoyaltyBtn.addEventListener('click', () => { + if (!currentCustomer) return; + isLoyaltyRedemption = true; + processOrder(null, 'Loyalty Redeem'); + }); + } + + if (viewPointsHistoryBtn) { + viewPointsHistoryBtn.addEventListener('click', () => { + if (!currentCustomer || !pointsHistoryModal) return; + pointsHistoryBody.innerHTML = '
'; + pointsHistoryEmpty.classList.add('d-none'); + pointsHistoryModal.show(); + + fetch(`api/customer_loyalty_history.php?customer_id=${currentCustomer.id}`) + .then(res => res.json()) + .then(data => { + pointsHistoryBody.innerHTML = ''; + if (data.success && data.history.length > 0) { + data.history.forEach(h => { + const item = document.createElement('div'); + item.className = 'list-group-item px-0 border-0 border-bottom'; + const badgeClass = h.points_change > 0 ? 'bg-success' : 'bg-danger'; + item.innerHTML = ` +
+
${h.reason}
+ ${h.points_change > 0 ? '+' : ''}${h.points_change} +
+
${h.created_at}
+ `; + pointsHistoryBody.appendChild(item); + }); + } else { + pointsHistoryEmpty.classList.remove('d-none'); + } + }) + .catch(() => { + pointsHistoryBody.innerHTML = `
${_t('error')}
`; + }); + }); + } + + if (saveNewCustomerBtn) { + saveNewCustomerBtn.addEventListener('click', () => { + const name = document.getElementById('new-customer-name').value.trim(); + const phone = document.getElementById('new-customer-phone').value.trim(); + + if (!name || !phone) { + showToast('Please fill in both name and phone', 'warning'); + return; + } + + saveNewCustomerBtn.disabled = true; + saveNewCustomerBtn.innerHTML = ''; + + fetch('api/create_customer.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, phone }) + }) + .then(res => res.json()) + .then(data => { + saveNewCustomerBtn.disabled = false; + saveNewCustomerBtn.innerHTML = 'Add Customer'; + + if (data.success) { + showToast('Customer added successfully', 'success'); + selectCustomer(data.customer); + if (addCustomerModal) addCustomerModal.hide(); + + // Clear inputs + document.getElementById('new-customer-name').value = ''; + document.getElementById('new-customer-phone').value = ''; + } else { + showToast(data.error || 'Failed to add customer', 'danger'); + } + }) + .catch(() => { + saveNewCustomerBtn.disabled = false; + saveNewCustomerBtn.innerHTML = 'Add Customer'; + showToast('An error occurred', 'danger'); + }); + }); + } + window.checkOrderType = function() { const checked = document.querySelector('input[name="order_type"]:checked'); if (!checked) return; @@ -442,8 +532,8 @@ document.addEventListener('DOMContentLoaded', () => { if (typeof PAYMENT_TYPES !== 'undefined') { PAYMENT_TYPES.forEach(pt => { const col = document.createElement('div'); - col.className = 'col-6'; - col.innerHTML = ``; + col.className = 'col-12'; + col.innerHTML = ``; paymentMethodsContainer.appendChild(col); }); } @@ -464,7 +554,9 @@ document.addEventListener('DOMContentLoaded', () => { outlet_id: CURRENT_OUTLET ? CURRENT_OUTLET.id : 1, payment_type_id: paymentTypeId, total_amount: subtotal + vat, - vat: vat, items: cart.map(item => ({ product_id: item.id, quantity: item.quantity, unit_price: item.price, variant_id: item.variant_id })) + vat: vat, + items: cart.map(item => ({ product_id: item.id, quantity: item.quantity, unit_price: item.price, variant_id: item.variant_id })), + redeem_loyalty: isLoyaltyRedemption }; fetch('api/order.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(orderData) }) diff --git a/assets/js/main.js?v=533-538 b/assets/js/main.js?v=533-538 new file mode 100644 index 0000000..21df886 --- /dev/null +++ b/assets/js/main.js?v=533-538 @@ -0,0 +1,6 @@ + PAYMENT_TYPES.forEach(pt => { + const col = document.createElement('div'); + col.className = 'col-12'; + col.innerHTML = ``; + paymentMethodsContainer.appendChild(col); + }); diff --git a/pos.php b/pos.php index 028dbe4..954142d 100644 --- a/pos.php +++ b/pos.php @@ -106,7 +106,7 @@ if (!$loyalty_settings) { .product-card:active { transform: scale(0.95); } .product-card:hover { border-color: #0d6efd !important; box-shadow: 0 4px 12px rgba(0,0,0,0.08) !important; } - .category-btn { text-align: left; border: none; background: none; padding: 10px 12px; width: 100%; display: flex; align-items: center; gap: 10px; border-radius: 12px; color: #64748b; font-weight: 700; transition: all 0.2s; } + .category-btn { font-size: 1.1rem; text-align: left; border: none; background: none; padding: 10px 12px; width: 100%; display: flex; align-items: center; gap: 10px; border-radius: 12px; color: #64748b; font-weight: 700; transition: all 0.2s; } .category-btn:hover { background-color: #f1f5f9; color: #0f172a; } .category-btn.active { background-color: #0d6efd; color: white; box-shadow: 0 4px 6px -1px rgba(13, 110, 253, 0.3); } .search-dropdown { position: absolute; width: 100%; z-index: 1000; max-height: 200px; overflow-y: auto; display: none; } @@ -138,6 +138,23 @@ if (!$loyalty_settings) { body { overflow: visible !important; height: auto !important; } } .print-only { display: none; } + + /* Touch-friendly enhancements */ + .btn-touch { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + font-weight: 700; + border-radius: 12px; + } + .btn-group-touch .btn { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + font-weight: 700; + } + .input-group-touch .form-control, .input-group-touch .btn, .input-group-touch .input-group-text { + padding-top: 0.6rem; + padding-bottom: 0.6rem; + } @@ -157,8 +174,6 @@ if (!$loyalty_settings) {
Kitchen - Waiter - Orders
@@ -211,7 +226,7 @@ if (!$loyalty_settings) { - +
1): ?> @@ -267,25 +282,38 @@ if (!$loyalty_settings) {
-
+
> - + > - + > - +
-
- - - - +
+ + + +
+ + +
+
+ Loyalty Points +
+ 0 pts + +
+
+
+ +
@@ -305,10 +333,10 @@ if (!$loyalty_settings) {
- +
- - + +
@@ -374,6 +402,22 @@ if (!$loyalty_settings) {
+ + + @@ -391,7 +435,7 @@ if (!$loyalty_settings) { const translations = { 'en': { 'cart_empty': 'No Items in Cart', - 'remove': 'Remove', + 'remove': '', 'order_placed': 'Order Placed!', 'order_success': 'Order saved successfully', 'error': 'Error', diff --git a/qorder.php b/qorder.php index e37500b..c5afe1e 100644 --- a/qorder.php +++ b/qorder.php @@ -60,7 +60,7 @@ foreach ($variants_raw as $v) { body.lang-ar { font-family: var(--arabic-font); direction: rtl; text-align: right; } .category-nav { overflow-x: auto; white-space: nowrap; background: #fff; padding: 10px; position: sticky; top: 0; z-index: 1020; border-bottom: 1px solid #eee; } - .category-item { display: inline-block; padding: 8px 16px; border-radius: 20px; background: #f1f3f5; margin-right: 8px; font-weight: 500; font-size: 0.9rem; cursor: pointer; border: 1px solid transparent; } + .category-item { display: inline-block; padding: 8px 16px; border-radius: 20px; background: #f1f3f5; margin-right: 8px; font-weight: 500; font-size: 1.1rem; cursor: pointer; border: 1px solid transparent; } .lang-ar .category-item { margin-right: 0; margin-left: 8px; } .category-item.active { background: #0d6efd; color: #fff; }