diff --git a/app/templates/index.html b/app/templates/index.html
index 130d2c9..f6c0b32 100644
--- a/app/templates/index.html
+++ b/app/templates/index.html
@@ -221,9 +221,13 @@
const visibleCount = document.getElementById('visible-count');
const allRows = [...document.querySelectorAll('#ap-table-body tr')];
- let ipMatchingMacs = null; // null = inactive; Set = active
+ let ipFilterActive = false;
- function normMac(s) { return (s || '').toUpperCase().replace(/-/g, ':'); }
+ function isTargetIp(ip) {
+ if (!ip) return false;
+ const last = parseInt((ip.split('.')[3] || ''), 10);
+ return last >= 150 && last <= 155;
+ }
function applyFilters() {
const q = filterInput.value.toLowerCase().trim();
@@ -234,9 +238,9 @@
const nameMatch = !q || name.includes(q) || site.includes(q);
let ipMatch = true;
- if (ipMatchingMacs !== null) {
+ if (ipFilterActive) {
const cb = row.querySelector('.ap-checkbox');
- ipMatch = ipMatchingMacs.has(normMac(cb?.dataset.mac));
+ ipMatch = isTargetIp(cb?.dataset.ip || '');
}
const visible = nameMatch && ipMatch;
@@ -252,18 +256,9 @@
// ── IP range filter button ─────────────────────────────────────────────────
const btnIpFilter = document.getElementById('btn-ip-filter');
const ipFilterLabel = document.getElementById('ip-filter-label');
- const ipFilterIcon = document.getElementById('ip-filter-icon');
- let cachedApClients = null;
-
- function isTargetIp(ip) {
- if (!ip) return false;
- const parts = ip.split('.');
- if (parts.length !== 4) return false;
- const last = parseInt(parts[3], 10);
- return last >= 150 && last <= 155;
- }
function setIpFilterActive(active) {
+ ipFilterActive = active;
if (active) {
btnIpFilter.classList.replace('bg-white', 'bg-blue-50');
btnIpFilter.classList.replace('hover:bg-gray-50', 'hover:bg-blue-100');
@@ -279,40 +274,9 @@
}
}
- btnIpFilter?.addEventListener('click', async () => {
- if (ipMatchingMacs !== null) {
- // Clear filter
- ipMatchingMacs = null;
- setIpFilterActive(false);
- applyFilters();
- return;
- }
-
- btnIpFilter.disabled = true;
- ipFilterLabel.textContent = 'Loading…';
- ipFilterIcon.classList.add('animate-spin');
-
- try {
- if (!cachedApClients) {
- const res = await fetch('/api/all-clients');
- if (!res.ok) { const e = await res.json(); throw new Error(e.detail || 'Request failed'); }
- cachedApClients = (await res.json()).ap_clients || {};
- }
-
- ipMatchingMacs = new Set();
- for (const [apMac, clients] of Object.entries(cachedApClients)) {
- if (clients.some(c => isTargetIp(c.ip))) ipMatchingMacs.add(apMac);
- }
-
- setIpFilterActive(true);
- applyFilters();
- } catch (e) {
- showToast('Failed to load client data: ' + e.message, 'error');
- ipFilterLabel.textContent = 'Filter .150–.155';
- } finally {
- btnIpFilter.disabled = false;
- ipFilterIcon.classList.remove('animate-spin');
- }
+ btnIpFilter?.addEventListener('click', () => {
+ setIpFilterActive(!ipFilterActive);
+ applyFilters();
});
// ── Refresh ────────────────────────────────────────────────────────────────