window.renderDevices = window.renderDevices || (async function(){ const cont=document.getElementById('view_devices'); if(!cont) return; cont.innerHTML='<div class="loading">Loading devices…</div>'; try{ const headers = Object.assign({}, Auth && Auth.authHeaders ? Auth.authHeaders() : {}); const res = await fetch((window.API_BASE||'') + '/api/auth.php?action=list_devices', { headers }); if(!res.ok){ cont.innerHTML='<div class="error">Load failed</div>'; return; } const j = await res.json(); if(!j.status){ cont.innerHTML='<div class="error">Auth error</div>'; return; } cont.innerHTML=''; (j.devices||[]).forEach(d=>{ const el=document.createElement('div'); el.className='card'; el.innerHTML='<strong>'+ (d.device_label||d.device_id) +'</strong><div>'+ (d.platform||'') +'</div><div>Last seen: '+ (d.last_seen||'') +'</div><div>IP: '+ (d.ip||'') +'</div><div><button data-device="'+d.device_id+'" class="btn_revoke">Revoke</button></div>'; cont.appendChild(el); }); cont.querySelectorAll('.btn_revoke').forEach(b=> b.addEventListener('click', async function(){ const id=this.dataset.device; if(!confirm('Revoke device '+id+' ?')) return; const headers = Object.assign({'Content-Type':'application/json'}, Auth && Auth.authHeaders ? Auth.authHeaders() : {}); const res = await fetch((window.API_BASE||'') + '/api/auth.php?action=revoke_device',{ method:'POST', headers, body: JSON.stringify({ device_id: id }) }); if(!res.ok){ alert('Revoke failed'); return; } const j = await res.json(); if(j.status==1){ alert('Revoked'); renderDevices(); } else alert('Revoke error'); })); }catch(err){ console.error(err); cont.innerHTML='<div class="error">Network</div>'; } });