Files
admintemplate-razor/wwwroot/js/datatables.js
T
2026-07-21 10:00:08 +07:00

216 lines
12 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function () {
const selectAll = document.getElementById('select-all-invoices');
const invoiceChecks = document.querySelectorAll('.invoice-checkbox');
const bulkToolbar = document.getElementById('bulk-toolbar');
const selectedCount = document.getElementById('selected-count');
if (selectAll && invoiceChecks.length) {
function updateBulkToolbar() {
const checked = document.querySelectorAll('.invoice-checkbox:checked');
const count = checked.length;
if (count > 0) {
bulkToolbar.classList.remove('hidden');
bulkToolbar.classList.add('flex');
selectedCount.textContent = count + ' selected';
invoiceChecks.forEach(function (cb) { cb.closest('tr').classList.toggle('bg-blue-50/40', cb.checked); });
} else {
bulkToolbar.classList.add('hidden');
bulkToolbar.classList.remove('flex');
selectedCount.textContent = '0 selected';
invoiceChecks.forEach(function (cb) { cb.closest('tr').classList.remove('bg-blue-50/40'); });
}
}
selectAll.addEventListener('change', function () {
invoiceChecks.forEach(function (cb) { cb.checked = selectAll.checked; });
updateBulkToolbar();
});
invoiceChecks.forEach(function (cb) {
cb.addEventListener('change', function () {
var allChecked = true;
invoiceChecks.forEach(function (c) { if (!c.checked) allChecked = false; });
selectAll.checked = allChecked;
updateBulkToolbar();
});
});
}
var expandBtns = document.querySelectorAll('.expand-btn');
expandBtns.forEach(function (btn) {
btn.addEventListener('click', function () {
var row = this.closest('tr');
var detailRow = row.nextElementSibling;
var icon = this.querySelector('.expand-icon');
if (detailRow && detailRow.classList.contains('expand-detail')) {
detailRow.classList.toggle('hidden');
if (detailRow.classList.contains('hidden')) { icon.style.transform = 'rotate(0deg)'; }
else { icon.style.transform = 'rotate(90deg)'; }
}
});
});
(function () {
var searchInput = document.getElementById('product-search');
var catSelect = document.getElementById('product-category');
var tbody = document.getElementById('product-tbody');
var infoEl = document.getElementById('product-info');
if (!searchInput || !catSelect || !tbody || !infoEl) return;
var productRows = Array.prototype.slice.call(tbody.querySelectorAll('tr'));
function filterProducts() {
var q = searchInput.value.toLowerCase().trim();
var cat = catSelect.value;
var visible = 0;
var lowStock = 0;
productRows.forEach(function (tr) {
var cells = tr.querySelectorAll('td');
if (cells.length < 5) return;
var sku = cells[0].textContent.toLowerCase();
var name = cells[1].textContent.toLowerCase();
var category = cells[2].textContent.trim();
var stockText = cells[3].textContent.trim();
var stockNum = parseInt(stockText.replace(/[^0-9-]/g, '')) || 0;
var matchSearch = q === '' || sku.indexOf(q) !== -1 || name.indexOf(q) !== -1;
var matchCat = cat === '' || category === cat;
if (matchSearch && matchCat) {
tr.style.display = '';
visible++;
if (stockNum > 0 && stockNum < 100) lowStock++;
} else {
tr.style.display = 'none';
}
});
infoEl.innerHTML = 'Showing <b class="text-gray-600">' + visible + '</b> of <b class="text-gray-600">' + productRows.length + '</b> products';
var lowEl = infoEl.parentElement.querySelector('.text-amber-600');
if (lowEl) lowEl.textContent = lowStock;
}
searchInput.addEventListener('input', filterProducts);
catSelect.addEventListener('change', filterProducts);
})();
(function () {
var tbody = document.getElementById('transactions-tbody');
var infoEl = document.getElementById('transactions-info');
var pageBtnsEl = document.getElementById('transactions-page-btns');
if (!tbody || !infoEl || !pageBtnsEl) return;
var perPage = 10;
var totalEntries = 120;
var totalPages = Math.ceil(totalEntries / perPage);
var currentPage = 1;
var accounts = [
'PT. MegaCorp - 001-234-5678', 'TechDistrib Inc. - 002-987-6543',
'CloudHost Ltd. - 003-456-7890', 'OfficePro Supply - 004-567-8901',
'MegaNetwork Corp - 005-678-9012', 'Consulting Plus - 006-789-0123',
'DataSys Solutions - 007-890-1234', 'GreenEnergy Corp - 008-901-2345',
'SmartBuild Ltd. - 009-012-3456', 'MediCare Supplies - 010-123-4567',
'AquaPure Systems - 011-234-5678', 'FinServe Global - 012-345-6789',
'LogiTrack Inc. - 013-456-7890', 'BioHealth Labs - 014-567-8901',
'EduPrime Academy - 015-678-9012'
];
var methods = ['Wire Transfer', 'Bank Transfer', 'Credit Card', 'ACH Transfer', 'Digital Wallet'];
var statuses = [
{ label: 'Success', chip: 'chip-green' },
{ label: 'Pending', chip: 'chip-amber' },
{ label: 'Processed', chip: 'chip-blue' },
{ label: 'Failed', chip: 'chip-red' }
];
function rand(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
function pick(arr) { return arr[rand(0, arr.length - 1)]; }
var allData = [];
for (var i = 1; i <= totalEntries; i++) {
var amount = rand(500, 50000) + rand(0, 99) / 100;
allData.push({
id: 'TRX-2026-' + String(i).padStart(3, '0'),
from: pick(accounts),
to: pick(accounts),
nominal: '$' + amount.toFixed(2),
status: pick(statuses),
method: pick(methods)
});
}
var originalData = [
{ id: 'TRX-2026-001', from: 'PT. MegaCorp - 001-234-5678', to: 'TechDistrib Inc. - 002-987-6543', nominal: '$24,500.00', status: { label: 'Success', chip: 'chip-green' }, method: 'Wire Transfer' },
{ id: 'TRX-2026-002', from: 'CloudHost Ltd. - 003-456-7890', to: 'PT. MegaCorp - 001-234-5678', nominal: '$12,800.00', status: { label: 'Pending', chip: 'chip-amber' }, method: 'Bank Transfer' },
{ id: 'TRX-2026-003', from: 'OfficePro Supply - 004-567-8901', to: 'PT. MegaCorp - 001-234-5678', nominal: '$6,200.00', status: { label: 'Processed', chip: 'chip-blue' }, method: 'Credit Card' },
{ id: 'TRX-2026-004', from: 'PT. MegaCorp - 001-234-5678', to: 'MegaNetwork Corp - 005-678-9012', nominal: '$32,000.00', status: { label: 'Failed', chip: 'chip-red' }, method: 'Wire Transfer' },
{ id: 'TRX-2026-005', from: 'Consulting Plus - 006-789-0123', to: 'PT. MegaCorp - 001-234-5678', nominal: '$18,000.00', status: { label: 'Success', chip: 'chip-green' }, method: 'Bank Transfer' },
{ id: 'TRX-2026-006', from: 'DataSys Solutions - 007-890-1234', to: 'PT. MegaCorp - 001-234-5678', nominal: '$45,200.00', status: { label: 'Pending', chip: 'chip-amber' }, method: 'ACH Transfer' },
{ id: 'TRX-2026-007', from: 'PT. MegaCorp - 001-234-5678', to: 'GreenEnergy Corp - 008-901-2345', nominal: '$28,900.00', status: { label: 'Processed', chip: 'chip-blue' }, method: 'Wire Transfer' },
{ id: 'TRX-2026-008', from: 'SmartBuild Ltd. - 009-012-3456', to: 'PT. MegaCorp - 001-234-5678', nominal: '$8,750.00', status: { label: 'Failed', chip: 'chip-red' }, method: 'Credit Card' },
{ id: 'TRX-2026-009', from: 'PT. MegaCorp - 001-234-5678', to: 'MediCare Supplies - 010-123-4567', nominal: '$19,300.00', status: { label: 'Success', chip: 'chip-green' }, method: 'Bank Transfer' },
{ id: 'TRX-2026-010', from: 'AquaPure Systems - 011-234-5678', to: 'PT. MegaCorp - 001-234-5678', nominal: '$11,400.00', status: { label: 'Pending', chip: 'chip-amber' }, method: 'ACH Transfer' }
];
for (var idx = 0; idx < originalData.length; idx++) {
allData[idx] = originalData[idx];
}
function renderPage(page) {
var start = (page - 1) * perPage;
var end = Math.min(start + perPage, totalEntries);
var html = '';
for (var i = start; i < end; i++) {
var d = allData[i];
html += '<tr class="bg-white hover:bg-gray-50/50 transition">' +
'<td class="px-4 py-3 text-sm text-gray-700 font-mono font-medium">' + d.id + '</td>' +
'<td class="px-4 py-3 text-sm text-gray-600">' + d.from + '</td>' +
'<td class="px-4 py-3 text-sm text-gray-600">' + d.to + '</td>' +
'<td class="px-4 py-3 text-sm text-gray-700 text-right font-mono">' + d.nominal + '</td>' +
'<td class="px-4 py-3 text-center"><span class="chip ' + d.status.chip + '">' + d.status.label + '</span></td>' +
'<td class="px-4 py-3 text-sm text-gray-600">' + d.method + '</td></tr>';
}
tbody.innerHTML = html;
infoEl.innerHTML = 'Showing <b class="text-gray-600">' + (start + 1) + '</b> to <b class="text-gray-600">' + end + '</b> of <b class="text-gray-600">' + totalEntries + '</b> entries';
var btnsHtml = '';
var prevDisabled = page === 1;
btnsHtml += '<button class="px-3 py-1.5 text-xs font-medium rounded-lg border border-gray-200 bg-white text-gray-500 hover:bg-gray-50 transition' + (prevDisabled ? ' cursor-not-allowed opacity-50' : '') + '" data-page="prev"' + (prevDisabled ? ' disabled' : '') + '>Previous</button>';
var maxVisible = 7;
var startPage, endPage;
if (totalPages <= maxVisible) {
startPage = 1;
endPage = totalPages;
} else {
var half = Math.floor(maxVisible / 2);
if (page <= half + 1) {
startPage = 1;
endPage = maxVisible;
} else if (page >= totalPages - half) {
startPage = totalPages - maxVisible + 1;
endPage = totalPages;
} else {
startPage = page - half;
endPage = page + half;
}
}
if (startPage > 1) {
btnsHtml += '<button class="px-3 py-1.5 text-xs font-medium rounded-lg border border-gray-200 bg-white text-gray-700 hover:bg-gray-50 transition" data-page="1">1</button>';
if (startPage > 2) {
btnsHtml += '<span class="px-1 text-gray-400">...</span>';
}
}
for (var p = startPage; p <= endPage; p++) {
var isActive = p === page;
btnsHtml += '<button class="px-3 py-1.5 text-xs font-medium rounded-lg border' +
(isActive ? ' bg-blue-600 text-white border-blue-600' : ' border-gray-200 bg-white text-gray-700 hover:bg-gray-50 transition') +
'" data-page="' + p + '">' + p + '</button>';
}
if (endPage < totalPages) {
if (endPage < totalPages - 1) {
btnsHtml += '<span class="px-1 text-gray-400">...</span>';
}
btnsHtml += '<button class="px-3 py-1.5 text-xs font-medium rounded-lg border border-gray-200 bg-white text-gray-700 hover:bg-gray-50 transition" data-page="' + totalPages + '">' + totalPages + '</button>';
}
var nextDisabled = page === totalPages;
btnsHtml += '<button class="px-3 py-1.5 text-xs font-medium rounded-lg border border-gray-200 bg-white text-gray-500 hover:bg-gray-50 transition' + (nextDisabled ? ' cursor-not-allowed opacity-50' : '') + '" data-page="next"' + (nextDisabled ? ' disabled' : '') + '>Next</button>';
pageBtnsEl.innerHTML = btnsHtml;
var btns = pageBtnsEl.querySelectorAll('button:not([disabled])');
btns.forEach(function (btn) {
btn.addEventListener('click', function () {
var target = this.getAttribute('data-page');
var newPage = page;
if (target === 'prev') newPage = page - 1;
else if (target === 'next') newPage = page + 1;
else newPage = parseInt(target);
if (newPage >= 1 && newPage <= totalPages) {
currentPage = newPage;
renderPage(currentPage);
}
});
});
}
renderPage(1);
})();
});