verae-edge-billing/admin/sales-rates.js

88 lines
3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* global fetch */
(async function () {
const status = document.getElementById('status');
const channelEl = document.getElementById('channel');
const segmentEl = document.getElementById('segment');
const rowsEl = document.getElementById('rows');
const overageEl = document.getElementById('overage');
const prepaidEl = document.getElementById('prepaid');
function authHeaders() {
const token = localStorage.getItem('adminToken') || sessionStorage.getItem('adminToken');
const key = localStorage.getItem('adminKey') || '';
const h = { 'content-type': 'application/json' };
if (token) h.authorization = `Bearer ${token}`;
if (key) h['x-admin-key'] = key;
return h;
}
let table = null;
let skus = [];
function renderRows() {
if (!table) return;
const ch = channelEl.value;
const seg = segmentEl.value;
const rates = (table.rates[ch] && table.rates[ch][seg]) || {};
rowsEl.innerHTML = skus
.map(
(sku) =>
`<tr><td><code>${sku}</code></td><td><input class="sku" data-sku="${sku}" type="number" min="0" step="1" value="${
rates[sku] ?? 0
}" /></td></tr>`,
)
.join('');
}
async function load() {
status.textContent = 'Loading…';
const res = await fetch('/admin/api/channel-rates', { headers: authHeaders() });
if (!res.ok) {
status.className = 'err';
status.textContent = `Load failed (${res.status}). Sign in at /admin/ first.`;
return;
}
const data = await res.json();
table = data.table;
skus = data.skus;
channelEl.innerHTML = data.channels.map((c) => `<option value="${c}">${c}</option>`).join('');
segmentEl.innerHTML = data.segments.map((s) => `<option value="${s}">${s}</option>`).join('');
overageEl.value = table.overageMultiplier;
prepaidEl.value = table.prepaidOverageMultiplier;
renderRows();
status.className = 'ok';
status.textContent = data.note || 'Loaded.';
}
channelEl.addEventListener('change', renderRows);
segmentEl.addEventListener('change', renderRows);
document.getElementById('save').addEventListener('click', async () => {
if (!table) return;
const ch = channelEl.value;
const seg = segmentEl.value;
if (!table.rates[ch]) table.rates[ch] = {};
if (!table.rates[ch][seg]) table.rates[ch][seg] = {};
rowsEl.querySelectorAll('input[data-sku]').forEach((inp) => {
table.rates[ch][seg][inp.getAttribute('data-sku')] = Number(inp.value) || 0;
});
table.overageMultiplier = Number(overageEl.value) || 1.5;
table.prepaidOverageMultiplier = Number(prepaidEl.value) || 0.75;
const res = await fetch('/admin/api/channel-rates', {
method: 'PUT',
headers: authHeaders(),
body: JSON.stringify(table),
});
if (!res.ok) {
status.className = 'err';
status.textContent = `Save failed (${res.status})`;
return;
}
const data = await res.json();
table = data.table;
status.className = 'ok';
status.textContent = `Saved ${ch} × ${seg}.`;
});
load();
})();