Account Section UI Changes
This commit is contained in:
@@ -523,6 +523,20 @@ tr:hover td{ background:#fbfdff; }
|
||||
.entry-summary-cards { gap: 12px; }
|
||||
.entry-summary-card { min-width: 140px; }
|
||||
}
|
||||
|
||||
/* Table pagination wrapper */
|
||||
.table-pagination-wrapper {
|
||||
margin-top: 20px;
|
||||
border-top: 1px solid #eef3fb;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
/* Modal pagination wrapper */
|
||||
.modal-pagination-wrapper {
|
||||
margin-top: 15px;
|
||||
border-top: 1px solid #eef3fb;
|
||||
padding-top: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="account-container">
|
||||
@@ -551,6 +565,7 @@ tr:hover td{ background:#fbfdff; }
|
||||
|
||||
<!-- Panels -->
|
||||
<div class="account-panels" id="account-panels">
|
||||
<!-- Payment Sent Table -->
|
||||
<div class="panel-card">
|
||||
<div class="panel-title">
|
||||
<span>Payment Sent to China</span>
|
||||
@@ -564,11 +579,34 @@ tr:hover td{ background:#fbfdff; }
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="paymentTableBody">
|
||||
<tr><td colspan="8" class="empty-state">Loading entries...</td></tr>
|
||||
<!-- Entries will be loaded here -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination for Payment Table -->
|
||||
<div class="table-pagination-wrapper">
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-info" id="paymentPageInfo">Showing 0 entries</div>
|
||||
<div class="pagination-controls">
|
||||
<button class="pagination-img-btn" id="paymentPrevBtn" title="Previous page">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="pagination-pages" id="paymentPaginationPages">
|
||||
<!-- Page numbers will be inserted here -->
|
||||
</div>
|
||||
<button class="pagination-img-btn" id="paymentNextBtn" title="Next page">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Order Dispatch Table -->
|
||||
<div class="panel-card">
|
||||
<div class="panel-title">
|
||||
<span>Order Dispatch Status</span>
|
||||
@@ -583,9 +621,31 @@ tr:hover td{ background:#fbfdff; }
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="orderTableBody">
|
||||
<tr><td colspan="8" class="empty-state">Loading entries...</td></tr>
|
||||
<!-- Entries will be loaded here -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination for Order Table -->
|
||||
<div class="table-pagination-wrapper">
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-info" id="orderPageInfo">Showing 0 entries</div>
|
||||
<div class="pagination-controls">
|
||||
<button class="pagination-img-btn" id="orderPrevBtn" title="Previous page">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="pagination-pages" id="orderPaginationPages">
|
||||
<!-- Page numbers will be inserted here -->
|
||||
</div>
|
||||
<button class="pagination-img-btn" id="orderNextBtn" title="Next page">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -649,29 +709,29 @@ tr:hover td{ background:#fbfdff; }
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="consolidateOrdersBody">
|
||||
<tr><td colspan="14" class="empty-state">Loading available orders...</td></tr>
|
||||
<!-- Orders will be loaded here -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination Controls -->
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-info" id="pageInfo">Showing 1 to 10 of 0 entries</div>
|
||||
<div class="pagination-controls">
|
||||
<button class="pagination-img-btn" id="prevPageBtn" title="Previous page">
|
||||
<!-- Left arrow SVG -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="pagination-pages" id="paginationPages">
|
||||
<!-- Page numbers will be inserted here -->
|
||||
<!-- Pagination for Create Order Modal -->
|
||||
<div class="modal-pagination-wrapper">
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-info" id="modalPageInfo">Showing 0 entries</div>
|
||||
<div class="pagination-controls">
|
||||
<button class="pagination-img-btn" id="modalPrevBtn" title="Previous page">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="pagination-pages" id="modalPaginationPages">
|
||||
<!-- Page numbers will be inserted here -->
|
||||
</div>
|
||||
<button class="pagination-img-btn" id="modalNextBtn" title="Next page">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<button class="pagination-img-btn" id="nextPageBtn" title="Next page">
|
||||
<!-- Right arrow SVG -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -682,8 +742,6 @@ tr:hover td{ background:#fbfdff; }
|
||||
<button type="submit" class="btn">Create Order</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="helper-note">Tip: Select orders from the list to include them in this consolidated entry. You can also search orders above.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -787,7 +845,6 @@ function jsonFetch(url, opts = {}) {
|
||||
opts.headers = Object.assign({'Content-Type':'application/json','X-CSRF-TOKEN': csrfToken}, opts.headers || {});
|
||||
if(opts.body && typeof opts.body !== 'string') opts.body = JSON.stringify(opts.body);
|
||||
return fetch(url, opts).then(r => {
|
||||
// attempt to parse json even on non-ok to get backend message
|
||||
return r.json().catch(() => { throw new Error('Invalid server response'); });
|
||||
});
|
||||
}
|
||||
@@ -796,9 +853,13 @@ let entries = [];
|
||||
let availableOrders = [];
|
||||
let currentEntry = null;
|
||||
|
||||
/* Pagination state */
|
||||
/* Single pagination state for both tables */
|
||||
let currentPage = 1;
|
||||
const ordersPerPage = 10;
|
||||
const entriesPerPage = 10;
|
||||
|
||||
/* Separate pagination state for modal */
|
||||
let modalCurrentPage = 1;
|
||||
const modalOrdersPerPage = 10;
|
||||
|
||||
/* small util */
|
||||
function escapeHtml(s){ if(s === null || s === undefined) return ''; return String(s).replace(/[&<>"']/g, m => ({'&':'&','<':'<','>':'>','"':'"',"'":"'"}[m])); }
|
||||
@@ -828,9 +889,17 @@ function bindUI(){
|
||||
document.getElementById('cancelCreateModal').addEventListener('click', closeCreateOrderModal);
|
||||
document.getElementById('createOrderInlineForm').addEventListener('submit', submitCreateOrderInline);
|
||||
|
||||
// Pagination buttons
|
||||
document.getElementById('prevPageBtn').addEventListener('click', goToPreviousPage);
|
||||
document.getElementById('nextPageBtn').addEventListener('click', goToNextPage);
|
||||
// Payment Table Pagination
|
||||
document.getElementById('paymentPrevBtn').addEventListener('click', () => goToPreviousPage());
|
||||
document.getElementById('paymentNextBtn').addEventListener('click', () => goToNextPage());
|
||||
|
||||
// Order Table Pagination
|
||||
document.getElementById('orderPrevBtn').addEventListener('click', () => goToPreviousPage());
|
||||
document.getElementById('orderNextBtn').addEventListener('click', () => goToNextPage());
|
||||
|
||||
// Modal Pagination
|
||||
document.getElementById('modalPrevBtn').addEventListener('click', () => goToModalPreviousPage());
|
||||
document.getElementById('modalNextBtn').addEventListener('click', () => goToModalNextPage());
|
||||
|
||||
document.getElementById('refreshBtn').addEventListener('click', () => { loadDashboard(); });
|
||||
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
||||
@@ -848,34 +917,58 @@ function bindUI(){
|
||||
function goToPreviousPage() {
|
||||
if (currentPage > 1) {
|
||||
currentPage--;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
renderBothTables();
|
||||
updateBothPaginationControls();
|
||||
}
|
||||
}
|
||||
|
||||
function goToNextPage() {
|
||||
const totalPages = Math.ceil(availableOrders.length / ordersPerPage);
|
||||
const totalPages = Math.ceil(entries.length / entriesPerPage);
|
||||
if (currentPage < totalPages) {
|
||||
currentPage++;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
renderBothTables();
|
||||
updateBothPaginationControls();
|
||||
}
|
||||
}
|
||||
|
||||
function updatePaginationControls() {
|
||||
const totalPages = Math.ceil(availableOrders.length / ordersPerPage);
|
||||
const prevBtn = document.getElementById('prevPageBtn');
|
||||
const nextBtn = document.getElementById('nextPageBtn');
|
||||
const pageInfo = document.getElementById('pageInfo');
|
||||
const paginationPages = document.getElementById('paginationPages');
|
||||
function goToModalPreviousPage() {
|
||||
if (modalCurrentPage > 1) {
|
||||
modalCurrentPage--;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updateModalPaginationControls();
|
||||
}
|
||||
}
|
||||
|
||||
function goToModalNextPage() {
|
||||
const totalPages = Math.ceil(availableOrders.length / modalOrdersPerPage);
|
||||
if (modalCurrentPage < totalPages) {
|
||||
modalCurrentPage++;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updateModalPaginationControls();
|
||||
}
|
||||
}
|
||||
|
||||
function updateBothPaginationControls() {
|
||||
const totalPages = Math.ceil(entries.length / entriesPerPage);
|
||||
|
||||
// Update both pagination controls
|
||||
updatePaginationControls('payment', totalPages);
|
||||
updatePaginationControls('order', totalPages);
|
||||
}
|
||||
|
||||
function updatePaginationControls(tableType, totalPages) {
|
||||
const prevBtn = document.getElementById(tableType + 'PrevBtn');
|
||||
const nextBtn = document.getElementById(tableType + 'NextBtn');
|
||||
const pageInfo = document.getElementById(tableType + 'PageInfo');
|
||||
const paginationPages = document.getElementById(tableType + 'PaginationPages');
|
||||
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
|
||||
// Update page info text
|
||||
const startIndex = (currentPage - 1) * ordersPerPage + 1;
|
||||
const endIndex = Math.min(currentPage * ordersPerPage, availableOrders.length);
|
||||
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${availableOrders.length} entries`;
|
||||
const startIndex = (currentPage - 1) * entriesPerPage + 1;
|
||||
const endIndex = Math.min(currentPage * entriesPerPage, entries.length);
|
||||
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${entries.length} entries`;
|
||||
|
||||
// Generate page numbers
|
||||
paginationPages.innerHTML = '';
|
||||
@@ -908,49 +1001,113 @@ function updatePaginationControls() {
|
||||
}
|
||||
}
|
||||
|
||||
function updateModalPaginationControls() {
|
||||
const totalPages = Math.ceil(availableOrders.length / modalOrdersPerPage);
|
||||
const prevBtn = document.getElementById('modalPrevBtn');
|
||||
const nextBtn = document.getElementById('modalNextBtn');
|
||||
const pageInfo = document.getElementById('modalPageInfo');
|
||||
const paginationPages = document.getElementById('modalPaginationPages');
|
||||
|
||||
prevBtn.disabled = modalCurrentPage === 1;
|
||||
nextBtn.disabled = modalCurrentPage === totalPages || totalPages === 0;
|
||||
|
||||
// Update page info text
|
||||
const startIndex = (modalCurrentPage - 1) * modalOrdersPerPage + 1;
|
||||
const endIndex = Math.min(modalCurrentPage * modalOrdersPerPage, availableOrders.length);
|
||||
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${availableOrders.length} orders`;
|
||||
|
||||
// Generate page numbers
|
||||
paginationPages.innerHTML = '';
|
||||
|
||||
if (totalPages <= 7) {
|
||||
// Show all pages
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
addModalPageButton(i, paginationPages);
|
||||
}
|
||||
} else {
|
||||
// Show first page, current page range, and last page
|
||||
addModalPageButton(1, paginationPages);
|
||||
|
||||
if (modalCurrentPage > 3) {
|
||||
paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
}
|
||||
|
||||
const start = Math.max(2, modalCurrentPage - 1);
|
||||
const end = Math.min(totalPages - 1, modalCurrentPage + 1);
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
addModalPageButton(i, paginationPages);
|
||||
}
|
||||
|
||||
if (modalCurrentPage < totalPages - 2) {
|
||||
paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
}
|
||||
|
||||
addModalPageButton(totalPages, paginationPages);
|
||||
}
|
||||
}
|
||||
|
||||
function addPageButton(pageNumber, container) {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'pagination-page-btn';
|
||||
|
||||
if (pageNumber === currentPage) {
|
||||
button.classList.add('active');
|
||||
}
|
||||
|
||||
button.textContent = pageNumber;
|
||||
button.addEventListener('click', () => {
|
||||
currentPage = pageNumber;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
renderBothTables();
|
||||
updateBothPaginationControls();
|
||||
});
|
||||
container.appendChild(button);
|
||||
}
|
||||
|
||||
function addModalPageButton(pageNumber, container) {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'pagination-page-btn';
|
||||
|
||||
if (pageNumber === modalCurrentPage) {
|
||||
button.classList.add('active');
|
||||
}
|
||||
|
||||
button.textContent = pageNumber;
|
||||
button.addEventListener('click', () => {
|
||||
modalCurrentPage = pageNumber;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updateModalPaginationControls();
|
||||
});
|
||||
container.appendChild(button);
|
||||
}
|
||||
|
||||
function renderBothTables() {
|
||||
renderPaymentTable(entries);
|
||||
renderOrderTable(entries);
|
||||
}
|
||||
|
||||
/* ---------- Create Order Modal Functions ---------- */
|
||||
function openCreateOrderModal(){
|
||||
const modal = document.getElementById('createOrderModal');
|
||||
modal.classList.add('modal-open');
|
||||
loadAvailableOrders();
|
||||
// focus first input
|
||||
setTimeout(()=> document.getElementById('inline_description').focus(), 220);
|
||||
}
|
||||
|
||||
function closeCreateOrderModal(){
|
||||
const modal = document.getElementById('createOrderModal');
|
||||
modal.classList.remove('modal-open');
|
||||
// reset form and pagination
|
||||
document.getElementById('createOrderInlineForm').reset();
|
||||
currentPage = 1;
|
||||
modalCurrentPage = 1; // Reset modal pagination when closing
|
||||
}
|
||||
|
||||
/* ---------- Loaders ---------- */
|
||||
function loadDashboard(){
|
||||
// show loading placeholders
|
||||
document.getElementById('paymentTableBody').innerHTML = '<tr><td colspan="8" class="empty-state">Loading entries...</td></tr>';
|
||||
document.getElementById('orderTableBody').innerHTML = '<tr><td colspan="8" class="empty-state">Loading entries...</td></tr>';
|
||||
jsonFetch('/admin/account/dashboard')
|
||||
.then(res => {
|
||||
if(!res.success) throw new Error(res.message || 'Failed to load dashboard');
|
||||
entries = res.entries || [];
|
||||
renderPaymentTable(entries);
|
||||
renderOrderTable(entries);
|
||||
renderBothTables();
|
||||
document.getElementById('entriesCount').textContent = entries.length;
|
||||
})
|
||||
.catch(err => {
|
||||
@@ -967,14 +1124,14 @@ function loadAvailableOrders(){
|
||||
.then(res => {
|
||||
if(!res.success) throw new Error(res.message || 'Failed to load orders');
|
||||
availableOrders = res.orders || [];
|
||||
currentPage = 1; // Reset to first page when loading new orders
|
||||
modalCurrentPage = 1; // Reset to first page when loading new orders
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
updateModalPaginationControls();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
tbody.innerHTML = '<tr><td colspan="14" class="empty-state">Unable to load orders</td></tr>';
|
||||
updatePaginationControls();
|
||||
updateModalPaginationControls();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -982,11 +1139,18 @@ function loadAvailableOrders(){
|
||||
function renderPaymentTable(list){
|
||||
const body = document.getElementById('paymentTableBody');
|
||||
body.innerHTML = '';
|
||||
|
||||
if(!list || list.length === 0){
|
||||
body.innerHTML = '<tr><td colspan="8" class="empty-state">No entries found</td></tr>';
|
||||
return;
|
||||
}
|
||||
list.forEach(entry => {
|
||||
|
||||
// Calculate pagination
|
||||
const startIndex = (currentPage - 1) * entriesPerPage;
|
||||
const endIndex = startIndex + entriesPerPage;
|
||||
const paginatedEntries = list.slice(startIndex, endIndex);
|
||||
|
||||
paginatedEntries.forEach(entry => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td>${escapeHtml(entry.entry_no)}</td>
|
||||
@@ -1011,11 +1175,18 @@ function renderPaymentTable(list){
|
||||
function renderOrderTable(list){
|
||||
const body = document.getElementById('orderTableBody');
|
||||
body.innerHTML = '';
|
||||
|
||||
if(!list || list.length === 0){
|
||||
body.innerHTML = '<tr><td colspan="8" class="empty-state">No entries found</td></tr>';
|
||||
return;
|
||||
}
|
||||
list.forEach(entry => {
|
||||
|
||||
// Calculate pagination
|
||||
const startIndex = (currentPage - 1) * entriesPerPage;
|
||||
const endIndex = startIndex + entriesPerPage;
|
||||
const paginatedEntries = list.slice(startIndex, endIndex);
|
||||
|
||||
paginatedEntries.forEach(entry => {
|
||||
const tr = document.createElement('tr');
|
||||
const pending = Number(entry.pending_amount || 0);
|
||||
const pendingHtml = pending <= 0 ? '<span class="status-badge pending-badge-green">Completed</span>' : `<span class="status-badge pending-badge-red">${formatCurrency(pending)}</span>`;
|
||||
@@ -1047,12 +1218,13 @@ function renderConsolidateOrders(list){
|
||||
|
||||
if(!list || list.length === 0){
|
||||
body.innerHTML = '<tr><td colspan="14" class="empty-state">No available orders</td></tr>';
|
||||
updateModalPaginationControls();
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate pagination
|
||||
const startIndex = (currentPage - 1) * ordersPerPage;
|
||||
const endIndex = startIndex + ordersPerPage;
|
||||
// Calculate pagination for modal
|
||||
const startIndex = (modalCurrentPage - 1) * modalOrdersPerPage;
|
||||
const endIndex = startIndex + modalOrdersPerPage;
|
||||
const paginatedOrders = list.slice(startIndex, endIndex);
|
||||
|
||||
paginatedOrders.forEach(order => {
|
||||
@@ -1156,14 +1328,19 @@ async function submitCreateOrderInline(e){
|
||||
/* ---------- Search ---------- */
|
||||
function handleSearch(){
|
||||
const q = document.getElementById('main-search').value.trim().toLowerCase();
|
||||
if(!q){ renderPaymentTable(entries); renderOrderTable(entries); return; }
|
||||
if(!q){
|
||||
renderBothTables();
|
||||
return;
|
||||
}
|
||||
const filtered = entries.filter(e => {
|
||||
return String(e.entry_no || '').toLowerCase().includes(q) ||
|
||||
String(e.description || '').toLowerCase().includes(q) ||
|
||||
String(e.region || '').toLowerCase().includes(q);
|
||||
});
|
||||
renderPaymentTable(filtered);
|
||||
renderOrderTable(filtered);
|
||||
entries = filtered;
|
||||
currentPage = 1; // Reset to first page when searching
|
||||
renderBothTables();
|
||||
updateBothPaginationControls();
|
||||
}
|
||||
|
||||
/* ---------- Entry details & installments ---------- */
|
||||
@@ -1289,10 +1466,6 @@ async function submitInstallment(e){
|
||||
if(btn){ btn.disabled = false; btn.textContent = 'Create Installment'; }
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- Utilities ---------- */
|
||||
// ensure consolidate area visible by default
|
||||
document.addEventListener('DOMContentLoaded', () => { document.getElementById('consolidateArea').style.display = 'block'; });
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
Reference in New Issue
Block a user