Autosave: 20260218-145439

This commit is contained in:
Flatlogic Bot 2026-02-18 14:54:39 +00:00
parent af4b79251b
commit 2621002fde
2 changed files with 89 additions and 34 deletions

View File

@ -137,8 +137,11 @@
<div class="logo"> <div class="logo">
<i class="bi bi-cart4 me-2"></i>Customer Display <i class="bi bi-cart4 me-2"></i>Customer Display
</div> </div>
<div id="customerName" class="badge bg-light text-dark fs-6 fw-normal border"> <div class="d-flex align-items-center">
Welcome <div id="debugInfo" class="me-3 badge bg-secondary" style="display: none;">Items: 0</div>
<div id="customerName" class="badge bg-light text-dark fs-6 fw-normal border">
Welcome
</div>
</div> </div>
</div> </div>
@ -181,17 +184,29 @@
</div> </div>
<script> <script>
let lastTimestamp = 0;
function formatMoney(amount) { function formatMoney(amount) {
return 'OMR ' + parseFloat(amount).toFixed(3); return 'OMR ' + parseFloat(amount).toFixed(3);
} }
function updateDisplay(data) { function updateDisplay(data) {
if (!data) return;
lastTimestamp = data.timestamp || 0;
// Debug info
const debugEl = document.getElementById('debugInfo');
if (debugEl) {
debugEl.innerText = 'Items: ' + (data.items ? data.items.length : 0);
// debugEl.style.display = 'block'; // Uncomment to show always
}
// Update Theme // Update Theme
if (data.theme) { if (data.theme) {
document.body.className = data.theme; document.body.className = data.theme;
} }
if (!data || !data.items || data.items.length === 0) { if (!Array.isArray(data.items) || data.items.length === 0) {
document.getElementById('activeCart').style.display = 'none'; document.getElementById('activeCart').style.display = 'none';
document.getElementById('welcomeScreen').style.display = 'flex'; document.getElementById('welcomeScreen').style.display = 'flex';
document.getElementById('customerName').innerText = 'Welcome'; document.getElementById('customerName').innerText = 'Welcome';
@ -208,43 +223,67 @@
document.getElementById('customerName').innerText = 'Welcome'; document.getElementById('customerName').innerText = 'Welcome';
} }
// Update Items // Update Items (Safer rendering)
const itemsList = document.getElementById('itemsList'); const itemsList = document.getElementById('itemsList');
itemsList.innerHTML = data.items.map(item => ` if (itemsList) {
<div class="cart-item"> itemsList.innerHTML = ''; // Clear existing
<div>
<div class="item-name">${item.name}</div> data.items.forEach(item => {
<div class="item-details"> try {
${item.qty} x ${formatMoney(item.price)} const row = document.createElement('div');
</div> row.className = 'cart-item';
</div>
<div class="item-price"> const name = item.name || 'Item';
${formatMoney(item.qty * item.price)} const price = parseFloat(item.price) || 0;
</div> const qty = parseFloat(item.qty) || 0;
</div> const total = price * qty;
`).join('');
// Scroll to bottom of list row.innerHTML = `
itemsList.scrollTop = itemsList.scrollHeight; <div>
<div class="item-name"></div>
<div class="item-details">
${qty} x ${formatMoney(price)}
</div>
</div>
<div class="item-price">
${formatMoney(total)}
</div>
`;
// Set text content safely
const nameEl = row.querySelector('.item-name');
if (nameEl) nameEl.textContent = name;
itemsList.appendChild(row);
} catch (err) {
console.error('Error rendering item:', err);
}
});
// Scroll to bottom of list
requestAnimationFrame(() => {
itemsList.scrollTop = itemsList.scrollHeight;
});
}
// Update Totals // Update Totals
document.getElementById('displaySubtotal').innerText = formatMoney(data.subtotal); document.getElementById('displaySubtotal').innerText = formatMoney(data.subtotal || 0);
if (data.discount > 0) { const discount = parseFloat(data.discount) || 0;
if (discount > 0) {
document.getElementById('displayDiscountRow').style.display = 'flex'; document.getElementById('displayDiscountRow').style.display = 'flex';
document.getElementById('displayDiscount').innerText = '- ' + formatMoney(data.discount); document.getElementById('displayDiscount').innerText = '- ' + formatMoney(discount);
} else { } else {
document.getElementById('displayDiscountRow').style.display = 'none'; document.getElementById('displayDiscountRow').style.display = 'none';
} }
if (data.loyalty > 0) { const loyalty = parseFloat(data.loyalty) || 0;
if (loyalty > 0) {
document.getElementById('displayLoyaltyRow').style.display = 'flex'; document.getElementById('displayLoyaltyRow').style.display = 'flex';
document.getElementById('displayLoyalty').innerText = '- ' + formatMoney(data.loyalty); document.getElementById('displayLoyalty').innerText = '- ' + formatMoney(loyalty);
} else { } else {
document.getElementById('displayLoyaltyRow').style.display = 'none'; document.getElementById('displayLoyaltyRow').style.display = 'none';
} }
document.getElementById('displayTotal').innerText = formatMoney(data.total); document.getElementById('displayTotal').innerText = formatMoney(data.total || 0);
} }
// Listen for storage events // Listen for storage events
@ -259,6 +298,19 @@
} }
}); });
// Polling fallback (every 1 second)
setInterval(() => {
const stored = localStorage.getItem('pos_cart_update');
if (stored) {
try {
const data = JSON.parse(stored);
if (data.timestamp && data.timestamp !== lastTimestamp) {
updateDisplay(data);
}
} catch (e) {}
}
}, 1000);
// Initial check // Initial check
const stored = localStorage.getItem('pos_cart_update'); const stored = localStorage.getItem('pos_cart_update');
if (stored) { if (stored) {

View File

@ -2868,7 +2868,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
<div class="p-3 border-bottom d-flex justify-content-between align-items-center"> <div class="p-3 border-bottom d-flex justify-content-between align-items-center">
<h6 class="m-0 fw-bold"><i class="bi bi-cart3 me-2"></i>Cart</h6> <h6 class="m-0 fw-bold"><i class="bi bi-cart3 me-2"></i>Cart</h6>
<div class="d-flex gap-2"> <div class="d-flex gap-2">
<button class="btn btn-sm btn-outline-info" onclick="window.open('customer-display.php', 'CustomerDisplay', 'width=1000,height=800')" title="Customer Display"><i class="bi bi-display me-1"></i> Customer Screen</button> <button class="btn btn-sm btn-outline-info" onclick="window.open('customer-display.php?v=<?= time() ?>', 'CustomerDisplay', 'width=1000,height=800')" title="Customer Display"><i class="bi bi-display me-1"></i> Customer Screen</button>
<button class="btn btn-sm btn-outline-warning" onclick="cart.openHeldCartsModal()" title="Held List"><i class="bi bi-list-task"></i></button> <button class="btn btn-sm btn-outline-warning" onclick="cart.openHeldCartsModal()" title="Held List"><i class="bi bi-list-task"></i></button>
<button class="btn btn-sm btn-outline-secondary" onclick="cart.hold()" title="Hold Cart"><i class="bi bi-pause-circle"></i></button> <button class="btn btn-sm btn-outline-secondary" onclick="cart.hold()" title="Hold Cart"><i class="bi bi-pause-circle"></i></button>
<button class="btn btn-sm btn-outline-danger" onclick="cart.clear()" title="Clear Cart"><i class="bi bi-trash"></i></button> <button class="btn btn-sm btn-outline-danger" onclick="cart.clear()" title="Clear Cart"><i class="bi bi-trash"></i></button>
@ -2968,7 +2968,10 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
?>, ?>,
broadcast() { broadcast() {
try { try {
const subtotal = this.items.reduce((sum, item) => sum + (parseFloat(item.price) * item.qty), 0); // Ensure items is an array
if (!Array.isArray(this.items)) this.items = [];
const subtotal = this.items.reduce((sum, item) => sum + (parseFloat(item.price) * parseFloat(item.qty)), 0);
let discountAmount = 0; let discountAmount = 0;
if (this.discount) { if (this.discount) {
discountAmount = this.discount.type === 'percentage' ? subtotal * (parseFloat(this.discount.value) / 100) : parseFloat(this.discount.value); discountAmount = this.discount.type === 'percentage' ? subtotal * (parseFloat(this.discount.value) / 100) : parseFloat(this.discount.value);
@ -2983,14 +2986,14 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
const payload = { const payload = {
items: this.items.map(i => ({ items: this.items.map(i => ({
name: (document.documentElement.lang === 'ar' ? (i.nameAr || i.nameEn) : (i.nameEn || i.nameAr)), name: (document.documentElement.lang === 'ar' ? (i.nameAr || i.nameEn) : (i.nameEn || i.nameAr)) || 'Unknown Item',
price: parseFloat(i.price), price: parseFloat(i.price) || 0,
qty: parseFloat(i.qty) qty: parseFloat(i.qty) || 0
})), })),
subtotal: subtotal, subtotal: parseFloat(subtotal) || 0,
discount: discountAmount, discount: parseFloat(discountAmount) || 0,
loyalty: loyaltyRedeemed, loyalty: parseFloat(loyaltyRedeemed) || 0,
total: total, total: parseFloat(total) || 0,
customerName: customerName, customerName: customerName,
theme: document.body.className, theme: document.body.className,
timestamp: Date.now() timestamp: Date.now()