+1
@@ -0,0 +1 @@
|
||||
const $=id=>document.getElementById(id);let manual=false;function esc(s){return String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]))}function msg(t,e=false){$('msg').textContent=t;$('msg').className='msg'+(e?' err':'');$('msg').classList.remove('hidden')}async function api(p,o={}){if(o.body&&typeof o.body!=='string'){o.headers={'Content-Type':'application/json',...(o.headers||{})};o.body=JSON.stringify(o.body)}const r=await fetch(p,{credentials:'same-origin',...o});const x=await r.json().catch(()=>({}));if(!r.ok)throw new Error(x.error||`HTTP ${r.status}`);return x}const cr=m=>(Number(m||0)/1e6).toLocaleString('de-DE',{maximumFractionDigits:3});async function load(){const x=await api('/api/admin/overview');manual=x.manual_credits_enabled;$('loginBox').classList.add('hidden');$('panel').classList.remove('hidden');$('manual').textContent=manual?'MANUELLER TEST-CREDIT-BYPASS IST AKTIV. Nur auf dem privaten Listener verwenden.':'Manuelle Credits sind deaktiviert (CS_ALLOW_MANUAL_CREDITS=0).';$('customers').innerHTML=(x.customers||[]).map(c=>`<div class="customer" data-id="${esc(c.id)}"><div><strong>${esc(c.username)}</strong><div class="small">${esc(c.id)} · Reward ${esc(c.reward_client_id||'—')}</div></div><div>${cr(c.balance_micros)} Credits</div><div>${c.running}/${c.workers} Worker aktiv</div>${manual?'<div class="grant"><input class="amount" type="number" min="0.001" step="1" placeholder="Credits"><button class="grantBtn">+ TEST</button></div>':'<div></div>'}</div>`).join('');document.querySelectorAll('.grantBtn').forEach(b=>b.onclick=async()=>{const row=b.closest('.customer');const n=Number(row.querySelector('.amount').value);if(!n)return;try{await api('/api/admin/credits/grant',{method:'POST',body:{customer_id:row.dataset.id,credits:n,reason:'admin-ui'}});msg(`${n} Test-Credits gebucht`);await load()}catch(e){msg(e.message,true)}})}$('login').onclick=async()=>{try{await api('/api/admin/login',{method:'POST',body:{Username:$('user').value,Password:$('pass').value}});await load()}catch(e){msg(e.message,true)}};$('logout').onclick=async()=>{await api('/api/admin/logout',{method:'POST'}).catch(()=>{});location.reload()};load().catch(()=>{});
|
||||
+1
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Neural Hunt · Customer Admin</title><link rel="stylesheet" href="/styles.css"></head><body><main><div class="eyebrow">NEURAL HUNT · PRIVATE CONTROL PLANE</div><h1>Customer Service Admin</h1><div id="msg" class="msg hidden"></div><section id="loginBox"><label>Admin<input id="user"></label><label>Passwort<input id="pass" type="password"></label><button id="login">ANMELDEN</button></section><section id="panel" class="hidden"><div class="head"><p>Dieser Listener gehört ausschließlich hinter VPN / privates Netz.</p><button id="logout">ABMELDEN</button></div><div id="manual" class="notice"></div><div id="customers"></div></section></main><script src="/app.js" defer></script></body></html>
|
||||
+1
@@ -0,0 +1 @@
|
||||
:root{color-scheme:dark;--bg:#080b10;--card:#111821;--line:#293746;--text:#edf4fb;--muted:#8fa1b2;--accent:#54f0a6}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.45 ui-monospace,monospace}main{max-width:1100px;margin:auto;padding:34px 20px}.eyebrow{color:var(--accent);letter-spacing:.2em}h1{font:700 38px system-ui}section,.customer{border:1px solid var(--line);background:var(--card);border-radius:12px;padding:16px;margin:12px 0}label{display:block;color:var(--muted);margin:10px 0}input{display:block;width:100%;margin-top:5px;background:#090e14;color:var(--text);border:1px solid var(--line);border-radius:8px;padding:10px}button{background:var(--accent);border:0;border-radius:8px;padding:9px 12px;font-weight:900;cursor:pointer}.hidden{display:none!important}.head,.row{display:flex;justify-content:space-between;gap:12px;align-items:center}.customer{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:10px;align-items:center}.small{font-size:12px;color:var(--muted);word-break:break-all}.grant{display:flex;gap:6px}.grant input{margin:0}.msg,.notice{padding:10px;border-radius:8px;background:#18261f;margin:10px 0}.msg.err{background:#32171d}@media(max-width:800px){.customer{grid-template-columns:1fr}.head,.row{align-items:flex-start;flex-direction:column}}
|
||||
Reference in New Issue
Block a user