diff --git a/public/js/bans.js b/public/js/bans.js
index 64e68c4..b7b6d86 100644
--- a/public/js/bans.js
+++ b/public/js/bans.js
@@ -49,6 +49,36 @@ function renderPage() {
renderPager(document.getElementById('pager'), page, Math.max(1, Math.ceil(allBans.length / PAGE_SIZE)), p => { page = p; renderPage(); });
}
+function askUnban(ip) {
+ const old = document.getElementById('unbanConfirmRow');
+ if (old) old.remove();
+ const tr = document.createElement('tr');
+ tr.id = 'unbanConfirmRow';
+ tr.innerHTML = `
+
+ Разблокировать ${esc(ip)}?
+
+
+ | `;
+ tr.querySelector('#unbanYes').addEventListener('click', () => doUnban(ip));
+ tr.querySelector('#unbanNo').addEventListener('click', () => tr.remove());
+ document.getElementById('bansBody').appendChild(tr);
+ tr.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
+}
+
+async function doUnban(ip) {
+ const res = await fetch(`${API}/api/bans/${encodeURIComponent(ip)}`, { method: 'DELETE', headers: hdr() });
+ if (res.ok) showToast('IP разблокирован: ' + ip);
+ else showToast('Ошибка разблокировки');
+ document.getElementById('unbanConfirmRow')?.remove();
+ loadBans();
+}
+
+document.getElementById('bansBody').addEventListener('click', e => {
+ const ip = e.target.closest('[data-unban]')?.dataset.unban;
+ if (ip) askUnban(ip);
+});
+
document.getElementById('bansBody').addEventListener('click', async e => {
const ip = e.target.closest('[data-unban]')?.dataset.unban;
if (!ip) return;