chore: move js to single file

This commit is contained in:
2026-06-10 17:23:09 +01:00
parent 4cefa3be76
commit ed65314fa5
9 changed files with 65 additions and 1508 deletions
+2 -133
View File
@@ -178,140 +178,9 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"></script>
<script src="assets/js/nav.js"></script>
<script src="assets/js/app.js"></script>
<script>
'use strict';
// ─── Load admin state ────────────────────────────────────────────────────────
async function loadAdmin() {
try {
const r = await fetch('/api/admin.php', { redirect: 'manual' });
if (r.type === 'opaqueredirect') { window.location.reload(); return; }
if (!r.ok) { window.location.replace('index.html'); return; }
const data = await r.json();
if (!data.is_admin) {
window.location.replace('index.html');
return;
}
document.querySelectorAll('.admin-nav-link').forEach(el => el.classList.remove('d-none'));
const name = data.name || data.username;
if (name) {
document.querySelectorAll('.nav-username').forEach(el => { el.textContent = name; });
}
document.getElementById('sandboxToggle').checked = data.sandbox_mode;
document.getElementById('sandboxBanner').style.display = data.sandbox_mode ? '' : 'none';
document.getElementById('count-log').textContent = data.delivery_log_total ?? '—';
document.getElementById('count-attendees').textContent = data.attendees ?? '—';
document.getElementById('count-templates').textContent = data.templates ?? '—';
document.getElementById('count-schedules').textContent = data.schedules ?? '—';
} catch (e) {
showResult('Failed to load admin data: ' + e.message, 'danger');
}
}
// ─── Sandbox toggle ──────────────────────────────────────────────────────────
document.getElementById('sandboxToggle').addEventListener('change', async () => {
try {
const data = await fetch('/api/admin.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'toggle_sandbox' }),
}).then(r => r.json());
document.getElementById('sandboxToggle').checked = data.sandbox_mode;
document.getElementById('sandboxBanner').style.display = data.sandbox_mode ? '' : 'none';
showResult(`Sandbox mode ${data.sandbox_mode ? 'enabled' : 'disabled'}.`, 'success');
} catch (e) {
showResult('Failed to toggle sandbox mode: ' + e.message, 'danger');
await loadAdmin(); // revert toggle visual state
}
});
// ─── Mark all as sandbox ─────────────────────────────────────────────────────
async function markAllSandbox() {
if (!confirm('Mark ALL existing delivery log entries as sandbox?\n\nThey will be excluded from cost calculations and success rate on the dashboard.')) {
return;
}
try {
const res = await fetch('/api/admin.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'mark_all_sandbox' }),
});
if (!res.ok) throw new Error((await res.json()).error ?? 'Failed');
showResult('All sends marked as sandbox.', 'success');
loadAdmin();
} catch (e) {
showResult('Failed: ' + e.message, 'danger');
}
}
// ─── Purge ───────────────────────────────────────────────────────────────────
const PURGE_LABELS = {
delivery_log: 'all delivery log entries',
attendees: 'all attendees, registrations and workshops',
templates: 'all SMS templates',
schedules: 'all scheduled rules',
};
async function purge(target, useDateFilter = false) {
const body = { action: 'purge', target };
if (useDateFilter) {
const before = document.getElementById('purgeBefore').value;
if (!before) {
alert('Please select a date first.');
return;
}
if (!confirm(`Purge all delivery log entries before ${before}?\n\nThis cannot be undone.`)) {
return;
}
body.before = before;
} else {
if (!confirm(`This will permanently delete ${PURGE_LABELS[target]}.\n\nThis cannot be undone. Are you sure?`)) {
return;
}
}
try {
const res = await fetch('/api/admin.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error ?? 'Purge failed');
const n = typeof data.purged === 'number' ? ` (${data.purged} rows)` : '';
showResult(`Purge completed successfully${n}.`, 'success');
loadAdmin();
} catch (e) {
showResult('Purge failed: ' + e.message, 'danger');
}
}
// ─── Toast/alert helper ──────────────────────────────────────────────────────
function showResult(msg, type) {
const el = document.getElementById('adminResult');
el.className = `alert alert-${type}`;
el.textContent = msg;
el.style.display = '';
clearTimeout(el._timer);
el._timer = setTimeout(() => { el.style.display = 'none'; }, 6000);
}
// ─── Init ────────────────────────────────────────────────────────────────────
loadAdmin();
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') loadAdmin(); });
</script>
<nav class="bottom-nav" aria-label="Navigation">
<a href="index.html" class="bottom-nav-item">
<i class="fa-solid fa-house"></i>