88 lines
3 KiB
JavaScript
88 lines
3 KiB
JavaScript
/* 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();
|
||
})();
|