38960-vm/includes/pages/pharmacy_alerts.php
2026-03-21 12:43:58 +00:00

308 lines
13 KiB
PHP

<div class="container-fluid">
<h2 class="mt-4 mb-4"><?= __('pharmacy_alerts') ?></h2>
<ul class="nav nav-tabs" id="pharmacyAlertsTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="low-stock-tab" data-bs-toggle="tab" data-bs-target="#low-stock" type="button" role="tab" aria-controls="low-stock" aria-selected="true"><?= __('low_stock') ?></button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="expired-tab" data-bs-toggle="tab" data-bs-target="#expired" type="button" role="tab" aria-controls="expired" aria-selected="false"><?= __('expired_batches') ?></button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="near-expiry-tab" data-bs-toggle="tab" data-bs-target="#near-expiry" type="button" role="tab" aria-controls="near-expiry" aria-selected="false"><?= __('near_expiry') ?></button>
</li>
</ul>
<div class="tab-content" id="pharmacyAlertsTabContent">
<!-- Low Stock Tab -->
<div class="tab-pane fade show active" id="low-stock" role="tabpanel" aria-labelledby="low-stock-tab">
<div class="card mt-3 border-0 shadow-sm">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover" id="lowStockTable">
<thead>
<tr>
<th><?= __('drug_name') ?></th>
<th><?= __('stock') ?></th>
<th><?= __('reorder_level') ?></th>
<th><?= __('min_stock') ?></th>
<th><?= __('actions') ?></th>
</tr>
</thead>
<tbody>
<tr><td colspan="5" class="text-center"><?= __('loading') ?></td></tr>
</tbody>
</table>
</div>
<!-- Pagination Container -->
<div id="lowStockPagination" class="mt-3"></div>
</div>
</div>
</div>
<!-- Expired Tab -->
<div class="tab-pane fade" id="expired" role="tabpanel" aria-labelledby="expired-tab">
<div class="card mt-3 border-0 shadow-sm">
<div class="card-body">
<div class="alert alert-danger">
<i class="bi bi-exclamation-triangle-fill"></i> <?= __('these_batches_expired') ?>
</div>
<div class="table-responsive">
<table class="table table-hover" id="expiredTable">
<thead>
<tr>
<th><?= __('drug_name') ?></th>
<th><?= __('batch_number') ?></th>
<th><?= __('expiry_date') ?></th>
<th><?= __('quantity') ?></th>
<th><?= __('supplier') ?></th>
</tr>
</thead>
<tbody>
<tr><td colspan="5" class="text-center"><?= __('loading') ?></td></tr>
</tbody>
</table>
</div>
<!-- Pagination Container -->
<div id="expiredPagination" class="mt-3"></div>
</div>
</div>
</div>
<!-- Near Expiry Tab -->
<div class="tab-pane fade" id="near-expiry" role="tabpanel" aria-labelledby="near-expiry-tab">
<div class="card mt-3 border-0 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<label for="daysFilter" class="form-label me-2"><?= __('show_expiring_within') ?></label>
<select id="daysFilter" class="form-select d-inline-block w-auto">
<option value="30">30 <?= __('days') ?></option>
<option value="60">60 <?= __('days') ?></option>
<option value="90" selected>90 <?= __('days') ?></option>
<option value="180">180 <?= __('days') ?></option>
</select>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover" id="nearExpiryTable">
<thead>
<tr>
<th><?= __('drug_name') ?></th>
<th><?= __('batch_number') ?></th>
<th><?= __('expiry_date') ?></th>
<th><?= __('days_remaining') ?></th>
<th><?= __('quantity') ?></th>
<th><?= __('supplier') ?></th>
</tr>
</thead>
<tbody>
<tr><td colspan="6" class="text-center"><?= __('loading') ?></td></tr>
</tbody>
</table>
</div>
<!-- Pagination Container -->
<div id="nearExpiryPagination" class="mt-3"></div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
loadLowStock();
// Load other tabs when clicked
document.getElementById('expired-tab').addEventListener('shown.bs.tab', function (event) {
loadExpired();
});
document.getElementById('near-expiry-tab').addEventListener('shown.bs.tab', function (event) {
loadNearExpiry();
});
document.getElementById('daysFilter').addEventListener('change', function() {
loadNearExpiry();
});
});
function loadLowStock(page = 1) {
fetch(`api/pharmacy.php?action=get_low_stock&page=${page}&limit=10`)
.then(response => response.json())
.then(response => {
const tbody = document.querySelector('#lowStockTable tbody');
tbody.innerHTML = '';
const data = response.data || []; // Handle case where API might not return data key if error or old format (safety)
if (data.length === 0) {
tbody.innerHTML = '<tr><td colspan="5" class="text-center"><?= __('no_low_stock_found') ?></td></tr>';
document.getElementById('lowStockPagination').innerHTML = '';
return;
}
data.forEach(item => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${item.name_en} <br> <small class="text-muted">${item.name_ar || ''}</small></td>
<td><span class="badge bg-danger">${item.total_stock} ${item.unit || ''}</span></td>
<td>${item.reorder_level}</td>
<td>${item.min_stock_level}</td>
<td>
<a href="pharmacy_lpos.php" class="btn btn-sm btn-primary">
<i class="bi bi-cart-plus"></i> <?= __('order_stock') ?>
</a>
</td>
`;
tbody.appendChild(tr);
});
renderPagination(response.total, response.page, response.limit, 'lowStockPagination', loadLowStock);
})
.catch(error => console.error('Error loading low stock:', error));
}
function loadExpired(page = 1) {
fetch(`api/pharmacy.php?action=get_expired&page=${page}&limit=10`)
.then(response => response.json())
.then(response => {
const tbody = document.querySelector('#expiredTable tbody');
tbody.innerHTML = '';
const data = response.data || [];
if (data.length === 0) {
tbody.innerHTML = '<tr><td colspan="5" class="text-center"><?= __('no_expired_batches_found') ?></td></tr>';
document.getElementById('expiredPagination').innerHTML = '';
return;
}
data.forEach(item => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${item.drug_name} <br> <small class="text-muted">${item.drug_name_ar || ''}</small></td>
<td>${item.batch_number}</td>
<td class="text-danger fw-bold">${item.expiry_date}</td>
<td>${item.quantity}</td>
<td>${item.supplier_name || '-'}</td>
`;
tbody.appendChild(tr);
});
renderPagination(response.total, response.page, response.limit, 'expiredPagination', loadExpired);
})
.catch(error => console.error('Error loading expired:', error));
}
function loadNearExpiry(page = 1) {
const days = document.getElementById('daysFilter').value;
fetch(`api/pharmacy.php?action=get_near_expiry&days=${days}&page=${page}&limit=10`)
.then(response => response.json())
.then(response => {
const tbody = document.querySelector('#nearExpiryTable tbody');
tbody.innerHTML = '';
const data = response.data || [];
if (data.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" class="text-center"><?= __('no_batches_expiring_soon') ?></td></tr>';
document.getElementById('nearExpiryPagination').innerHTML = '';
return;
}
data.forEach(item => {
const tr = document.createElement('tr');
let badgeClass = 'bg-warning text-dark';
if (item.days_remaining < 30) badgeClass = 'bg-danger';
tr.innerHTML = `
<td>${item.drug_name} <br> <small class="text-muted">${item.drug_name_ar || ''}</small></td>
<td>${item.batch_number}</td>
<td>${item.expiry_date}</td>
<td><span class="badge ${badgeClass}">${item.days_remaining} <?= __('days') ?></span></td>
<td>${item.quantity}</td>
<td>${item.supplier_name || '-'}</td>
`;
tbody.appendChild(tr);
});
renderPagination(response.total, response.page, response.limit, 'nearExpiryPagination', loadNearExpiry);
})
.catch(error => console.error('Error loading near expiry:', error));
}
function renderPagination(total, page, limit, containerId, callback) {
const totalPages = Math.ceil(total / limit);
const container = document.getElementById(containerId);
container.innerHTML = '';
if (totalPages <= 1) return;
const ul = document.createElement('ul');
ul.className = 'pagination justify-content-center';
// Previous
const prevLi = document.createElement('li');
prevLi.className = `page-item ${page === 1 ? 'disabled' : ''}`;
prevLi.innerHTML = `<a class="page-link" href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a>`;
prevLi.onclick = (e) => {
e.preventDefault();
if (page > 1) callback(page - 1);
};
ul.appendChild(prevLi);
// Page Numbers logic
let startPage = Math.max(1, page - 2);
let endPage = Math.min(totalPages, page + 2);
if (startPage > 1) {
ul.appendChild(createPageItem(1, page, callback));
if (startPage > 2) {
const ellipsis = document.createElement('li');
ellipsis.className = 'page-item disabled';
ellipsis.innerHTML = '<span class="page-link">...</span>';
ul.appendChild(ellipsis);
}
}
for (let i = startPage; i <= endPage; i++) {
ul.appendChild(createPageItem(i, page, callback));
}
if (endPage < totalPages) {
if (endPage < totalPages - 1) {
const ellipsis = document.createElement('li');
ellipsis.className = 'page-item disabled';
ellipsis.innerHTML = '<span class="page-link">...</span>';
ul.appendChild(ellipsis);
}
ul.appendChild(createPageItem(totalPages, page, callback));
}
// Next
const nextLi = document.createElement('li');
nextLi.className = `page-item ${page === totalPages ? 'disabled' : ''}`;
nextLi.innerHTML = `<a class="page-link" href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a>`;
nextLi.onclick = (e) => {
e.preventDefault();
if (page < totalPages) callback(page + 1);
};
ul.appendChild(nextLi);
container.appendChild(ul);
}
function createPageItem(pageNum, currentPage, callback) {
const li = document.createElement('li');
li.className = `page-item ${pageNum === currentPage ? 'active' : ''}`;
li.innerHTML = `<a class="page-link" href="#">${pageNum}</a>`;
li.onclick = (e) => {
e.preventDefault();
callback(pageNum);
};
return li;
}
</script>