first commit

This commit is contained in:
Colin-Joel Scupin
2026-08-05 01:29:39 +02:00
commit 86d4bcdc37
85 changed files with 7706 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
const resource=typeof GetParentResourceName==='function'?GetParentResourceName():'devx_admin';
const app=document.querySelector('#app'),playersEl=document.querySelector('#players'),editor=document.querySelector('#editor'),errorEl=document.querySelector('#error');
let players=[],weapons=[],selectedId=null;
async function post(event,data={}){const r=await fetch(`https://${resource}/${event}`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});return r.json()}
function esc(v){return String(v??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[c]))}
function error(t=''){errorEl.textContent=t;errorEl.classList.toggle('hidden',!t)}
function selected(){return players.find(p=>Number(p.source)===Number(selectedId))}
function renderPlayers(){const q=document.querySelector('#search').value.toLowerCase();playersEl.innerHTML='';players.filter(p=>`${p.source} ${p.fullName} ${p.connectionName}`.toLowerCase().includes(q)).forEach(p=>{const b=document.createElement('button');b.className=`player ${Number(p.source)===Number(selectedId)?'active':''}`;b.innerHTML=`<span>${p.source}</span><div><strong>${esc(p.fullName)}</strong><small>${esc(p.connectionName)}</small></div>`;b.onclick=()=>{selectedId=p.source;renderPlayers();renderEditor()};playersEl.appendChild(b)})}
function action(action,data={}){error('');return post('action',{action,target:selectedId,...data}).then(r=>{if(!r.ok)error(r.error||'Aktion fehlgeschlagen.');if(r.players){players=r.players;renderPlayers();renderEditor()}return r})}
function renderEditor(){const p=selected();if(!p){editor.className='editor empty';editor.innerHTML='<div><h2>Spieler auswählen</h2><p>Wähle links einen Online-Spieler aus.</p></div>';return}editor.className='editor';editor.innerHTML=`
<div class="editor-header"><div><h2>${esc(p.fullName)}</h2><p>Server-ID ${p.source} · Charakter ${p.characterId??''} · ${esc(p.phoneNumber||'keine Nummer')}</p></div><div class="badges"><span class="badge">${p.cash} $ bar</span><span class="badge">${p.bank} $ Bank</span><span class="badge">${p.rpXp} XP</span></div></div>
<div class="grid">
<div class="card"><h3>Geld bearbeiten</h3><div class="form-row"><input id="cash" type="number" min="0" value="${p.cash}"><button class="primary" data-act="setcash">Bargeld setzen</button></div><div class="form-row"><input id="bank" type="number" min="0" value="${p.bank}"><button class="primary" data-act="setbank">Bank setzen</button></div></div>
<div class="card"><h3>Identität</h3><div class="form-row"><input id="phone" value="${esc(p.phoneNumber||'')}"><button class="primary" data-act="setphone">Nummer setzen</button></div></div>
<div class="card"><h3>Waffe geben</h3><div class="form-row"><select id="weapon">${weapons.map(w=>`<option value="${w.name}">${esc(w.label)}</option>`).join('')}</select><button class="primary" data-act="giveweapon">Geben</button></div></div>
<div class="card"><h3>Spieleraktionen</h3><div class="button-grid"><button data-act="heal">Heilen</button><button data-act="freeze">${p.frozen?'Freigeben':'Einfrieren'}</button><button data-act="goto">Zu Spieler</button><button data-act="bring">Herholen</button></div></div>
<div class="card punish"><h3>Verwarnung / Trennung</h3><div class="punish-fields"><input id="reason" class="full-input" placeholder="Begründung"><input id="minutes" class="full-input" type="number" min="0" placeholder="Minuten (0 = permanent)"></div><div class="button-grid"><button class="danger" data-act="kick">Kicken</button><button class="danger" data-act="ban">Bannen</button></div></div>
</div>`;
editor.querySelectorAll('[data-act]').forEach(b=>b.onclick=()=>{const a=b.dataset.act;if(a==='setcash')action(a,{amount:document.querySelector('#cash').value});else if(a==='setbank')action(a,{amount:document.querySelector('#bank').value});else if(a==='setphone')action(a,{phoneNumber:document.querySelector('#phone').value});else if(a==='giveweapon')action(a,{weapon:document.querySelector('#weapon').value});else if(a==='kick'||a==='ban')action(a,{reason:document.querySelector('#reason').value,minutes:document.querySelector('#minutes').value});else action(a)})}
document.querySelector('#search').oninput=renderPlayers;document.querySelector('#refresh').onclick=()=>action('refresh');document.querySelector('#close').onclick=()=>post('close');document.addEventListener('keyup',e=>{if(e.key==='Escape')post('close')});
window.addEventListener('message',e=>{const d=e.data||{};if(d.action==='open')app.classList.remove('hidden');if(d.action==='close')app.classList.add('hidden');if(d.action==='state'){players=d.players||[];weapons=d.weapons||[];selectedId=players[0]?.source??null;renderPlayers();renderEditor()}if(d.action==='players'){players=d.players||[];renderPlayers();renderEditor()}});