diff --git a/app/templates/index.html b/app/templates/index.html
index 5cc67d4..cb4c1c6 100644
--- a/app/templates/index.html
+++ b/app/templates/index.html
@@ -72,9 +72,18 @@
-
Name |
- Site |
- IP Address |
+
+ Name ↕
+ |
+
+ Site ↕
+ |
+
+ IP Address ↕
+ |
MAC Address |
Model |
Status |
@@ -256,6 +265,69 @@
filterInput.addEventListener('input', applyFilters);
+ // ── Column sort ────────────────────────────────────────────────────────────
+ let sortCol = null;
+ let sortDir = 'asc';
+
+ const colIndex = { name: 2, site: 3, ip: 4 };
+
+ function ipToNum(ip) {
+ return (ip || '').split('.').reduce((acc, p) => {
+ const n = parseInt(p, 10);
+ return acc * 256 + (isNaN(n) ? 0 : n);
+ }, 0);
+ }
+
+ function getCellText(row, idx) {
+ return (row.querySelector(`td:nth-child(${idx})`)?.textContent || '').trim();
+ }
+
+ function updateSortIcons() {
+ document.querySelectorAll('[data-sort]').forEach(th => {
+ const icon = th.querySelector('.sort-icon');
+ if (!icon) return;
+ if (th.dataset.sort === sortCol) {
+ icon.textContent = sortDir === 'asc' ? '↑' : '↓';
+ icon.className = 'sort-icon text-blue-500';
+ } else {
+ icon.textContent = '↕';
+ icon.className = 'sort-icon text-gray-300';
+ }
+ });
+ }
+
+ document.querySelectorAll('[data-sort]').forEach(th => {
+ th.addEventListener('click', () => {
+ const col = th.dataset.sort;
+ if (sortCol === col) {
+ sortDir = sortDir === 'asc' ? 'desc' : 'asc';
+ } else {
+ sortCol = col;
+ sortDir = 'asc';
+ }
+
+ const idx = colIndex[col];
+ const tbody = document.getElementById('ap-table-body');
+ const rows = [...tbody.querySelectorAll('tr')];
+
+ rows.sort((a, b) => {
+ const av = getCellText(a, idx);
+ const bv = getCellText(b, idx);
+ let cmp;
+ if (col === 'ip') {
+ cmp = ipToNum(av) - ipToNum(bv);
+ } else {
+ cmp = av.localeCompare(bv, undefined, { sensitivity: 'base' });
+ }
+ return sortDir === 'asc' ? cmp : -cmp;
+ });
+
+ rows.forEach(row => tbody.appendChild(row));
+ updateSortIcons();
+ applyFilters();
+ });
+ });
+
// ── IP range filter button ─────────────────────────────────────────────────
const btnIpFilter = document.getElementById('btn-ip-filter');
const ipFilterLabel = document.getElementById('ip-filter-label');