Initial commit - Admin Template HTML
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
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);
|
||||
})();
|
||||
});
|
||||
Reference in New Issue
Block a user