diff --git a/index.php b/index.php index 5d253b8..ab02ec1 100644 --- a/index.php +++ b/index.php @@ -393,17 +393,20 @@ if (isset($_GET['action']) || isset($_POST['action'])) { } if ($action === 'search_items') { - file_put_contents('search_debug.log', date('Y-m-d H:i:s') . " - search_items call: q=" . ($_GET['q'] ?? '') . "\n", FILE_APPEND); header('Content-Type: application/json'); $q = $_GET['q'] ?? ''; - if (strlen($q) < 1) { - echo json_encode([]); - exit; - } + $searchTerm = "%$q%"; - $stmt = db()->prepare("SELECT * FROM stock_items WHERE name_en LIKE ? OR name_ar LIKE ? OR sku LIKE ? LIMIT 15"); + // Optimization: Fetch items with promotional prices calculated + $stmt = db()->prepare("SELECT * FROM stock_items WHERE name_en LIKE ? OR name_ar LIKE ? OR sku LIKE ? LIMIT 50"); $stmt->execute([$searchTerm, $searchTerm, $searchTerm]); - echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)); + $items = $stmt->fetchAll(PDO::FETCH_ASSOC); + + foreach ($items as &$item) { + $item['original_price'] = (float)$item['sale_price']; + $item['sale_price'] = getPromotionalPrice($item); + } + echo json_encode($items); exit; } @@ -6233,7 +6236,8 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; $registers = db()->query("SELECT * FROM cash_registers WHERE status = 'active'")->fetchAll(); $allow_zero_stock_sell = ($data['settings']['allow_zero_stock_sell'] ?? '1') === '1'; - $sql = "SELECT * FROM stock_items ORDER BY name_en ASC"; + // Optimization: Only load top 50 products initially to prevent heavy load + $sql = "SELECT * FROM stock_items ORDER BY id DESC LIMIT 50"; $products_raw = db()->query($sql)->fetchAll(PDO::FETCH_ASSOC); $products = []; foreach ($products_raw as $p) { @@ -7249,38 +7253,80 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; } }; - document.querySelectorAll('.product-card').forEach(card => { - card.addEventListener('click', () => { - const product = { - id: parseInt(card.dataset.id), - nameEn: card.dataset.nameEn, - nameAr: card.dataset.nameAr, - price: parseFloat(card.dataset.price), - stock_quantity: parseFloat(card.dataset.stockQuantity), - vatRate: parseFloat(card.dataset.vatRate) || 0 - }; - cart.add(product); - }); - }); - - document.getElementById('productSearch').addEventListener('input', (e) => { - const q = e.target.value.toLowerCase(); + function attachProductClickListeners() { document.querySelectorAll('.product-grid .product-card').forEach(card => { - const name = card.dataset.nameEn.toLowerCase() + ' ' + card.dataset.nameAr.toLowerCase(); - const sku = card.dataset.sku.toLowerCase(); - if (name.includes(q) || sku.includes(q)) { - card.style.display = 'flex'; - } else { - card.style.display = 'none'; - } + card.onclick = () => { + const product = { + id: parseInt(card.dataset.id), + nameEn: card.dataset.nameEn, + nameAr: card.dataset.nameAr, + price: parseFloat(card.dataset.price), + sku: card.dataset.sku, + stock_quantity: parseFloat(card.dataset.stockQuantity), + vatRate: parseFloat(card.dataset.vatRate) || 0 + }; + cart.add(product); + }; }); + } + attachProductClickListeners(); + + let searchTimeout = null; + document.getElementById('productSearch').addEventListener('input', (e) => { + clearTimeout(searchTimeout); + const q = e.target.value.trim(); + searchTimeout = setTimeout(async () => { + try { + const resp = await fetch('index.php?action=search_items&q=' + encodeURIComponent(q)); + const products = await resp.json(); + renderProductGrid(products); + } catch (err) { console.error(err); } + }, 300); }); - document.getElementById('barcodeInput').addEventListener('keypress', (e) => { + function renderProductGrid(products) { + const grid = document.getElementById('productGrid'); + const lang = document.documentElement.lang || 'en'; + if (products.length === 0) { + grid.innerHTML = '