add archive/unarchive UI to admin panel
This commit is contained in:
+37
-2
@@ -141,6 +141,7 @@
|
|||||||
<button class="tab" data-filter="installing" onclick="setFilter('installing')">Installing</button>
|
<button class="tab" data-filter="installing" onclick="setFilter('installing')">Installing</button>
|
||||||
<button class="tab" data-filter="completed" onclick="setFilter('completed')">Completed</button>
|
<button class="tab" data-filter="completed" onclick="setFilter('completed')">Completed</button>
|
||||||
<button class="tab" data-filter="cancelled" onclick="setFilter('cancelled')">Cancelled</button>
|
<button class="tab" data-filter="cancelled" onclick="setFilter('cancelled')">Cancelled</button>
|
||||||
|
<button class="tab" data-filter="archived" onclick="setFilter('archived')" style="color:var(--text-muted)">📦 Archived</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="orders-table">
|
<table class="orders-table">
|
||||||
@@ -178,6 +179,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="notes" id="notesList"></div>
|
<div class="notes" id="notesList"></div>
|
||||||
<div class="btn-row">
|
<div class="btn-row">
|
||||||
|
<button class="btn btn-ghost" onclick="toggleArchive()" id="archiveBtn">📦 Archive</button>
|
||||||
<button class="btn btn-ghost" onclick="closeModal()">Close</button>
|
<button class="btn btn-ghost" onclick="closeModal()">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -337,10 +339,13 @@ function esc(s) {
|
|||||||
function setFilter(f) {
|
function setFilter(f) {
|
||||||
currentFilter = f;
|
currentFilter = f;
|
||||||
document.querySelectorAll('.tab').forEach(t => t.classList.toggle('active', t.dataset.filter===f));
|
document.querySelectorAll('.tab').forEach(t => t.classList.toggle('active', t.dataset.filter===f));
|
||||||
// scroll active tab into view (mobile)
|
|
||||||
const active = document.querySelector('.tab.active');
|
const active = document.querySelector('.tab.active');
|
||||||
if (active) active.scrollIntoView({behavior:'smooth',inline:'center',block:'nearest'});
|
if (active) active.scrollIntoView({behavior:'smooth',inline:'center',block:'nearest'});
|
||||||
renderOrders();
|
if (f === 'archived') {
|
||||||
|
loadArchived();
|
||||||
|
} else {
|
||||||
|
loadOrders();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Modal ──
|
// ── Modal ──
|
||||||
@@ -356,6 +361,7 @@ async function openModal(id) {
|
|||||||
document.getElementById('detailDate').textContent = o.created_at||'-';
|
document.getElementById('detailDate').textContent = o.created_at||'-';
|
||||||
document.getElementById('detailStatus').value = o.status||'received';
|
document.getElementById('detailStatus').value = o.status||'received';
|
||||||
document.getElementById('noteInput').value = '';
|
document.getElementById('noteInput').value = '';
|
||||||
|
document.getElementById('archiveBtn').textContent = o.archived ? '📂 Unarchive' : '📦 Archive';
|
||||||
document.getElementById('notesList').innerHTML = '<div style="color:var(--text-dim);font-size:.85rem">Loading...</div>';
|
document.getElementById('notesList').innerHTML = '<div style="color:var(--text-dim);font-size:.85rem">Loading...</div>';
|
||||||
document.getElementById('detailModal').classList.add('open');
|
document.getElementById('detailModal').classList.add('open');
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
@@ -398,6 +404,35 @@ async function loadNotes(id) {
|
|||||||
document.getElementById('notesList').innerHTML = html;
|
document.getElementById('notesList').innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Archive Toggle ──
|
||||||
|
|
||||||
|
async function toggleArchive() {
|
||||||
|
if (!currentOrderId) return;
|
||||||
|
const o = orders.find(x => x.id === currentOrderId);
|
||||||
|
if (!o) return;
|
||||||
|
const currentlyArchived = o.archived || false;
|
||||||
|
const action = currentlyArchived ? 'unarchive' : 'archive';
|
||||||
|
if (!confirm('Are you sure you want to ' + action + ' order #' + currentOrderId + '?')) return;
|
||||||
|
const r = await fetch(API + '/admin/archive', {method:'POST',headers:{'Authorization':'Bearer '+token,'Content-Type':'application/json'},body:JSON.stringify({submission_id:currentOrderId,archived:!currentlyArchived})});
|
||||||
|
if (r.ok) {
|
||||||
|
o.archived = !currentlyArchived;
|
||||||
|
document.getElementById('archiveBtn').textContent = o.archived ? '📂 Unarchive' : '📦 Archive';
|
||||||
|
loadOrders();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadArchived() {
|
||||||
|
try {
|
||||||
|
const r = await fetch(API + '/admin/submissions?include_archived=1&per_page=200', {headers:{'Authorization':'Bearer '+token}});
|
||||||
|
if (r.status === 401) { logout(); return; }
|
||||||
|
if (!r.ok) return;
|
||||||
|
const d = await r.json();
|
||||||
|
orders = (d.submissions || []).filter(o => o.archived);
|
||||||
|
renderStats(d);
|
||||||
|
renderOrders();
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Theme ──
|
// ── Theme ──
|
||||||
|
|
||||||
function toggleTheme() {
|
function toggleTheme() {
|
||||||
|
|||||||
Reference in New Issue
Block a user