[object Object]

← back to Nationalrealestate

usreal broker desk: honest page-scoped sort labels + roster shows 'first N of TOTAL' + extract shared broker-desk.css (finish the dedupe) — Cody cycle-2 gate fixes (TK-10590)

53f52a8ff9e4c40595009fcfc68b773bc36d79c0 · 2026-08-15 08:30:57 -0700 · Steve Abrams

Files touched

Diff

commit 53f52a8ff9e4c40595009fcfc68b773bc36d79c0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Aug 15 08:30:57 2026 -0700

    usreal broker desk: honest page-scoped sort labels + roster shows 'first N of TOTAL' + extract shared broker-desk.css (finish the dedupe) — Cody cycle-2 gate fixes (TK-10590)
---
 public/broker-desk.css          | 31 +++++++++++++++++++++++++++++++
 public/broker-desk.js           | 18 ++++++++++--------
 public/commercial-brokers.html  | 32 +-------------------------------
 public/residential-brokers.html | 32 +-------------------------------
 4 files changed, 43 insertions(+), 70 deletions(-)

diff --git a/public/broker-desk.css b/public/broker-desk.css
new file mode 100644
index 0000000..3cf5344
--- /dev/null
+++ b/public/broker-desk.css
@@ -0,0 +1,31 @@
+/* broker-desk.css — shared styling for the usreal residential + commercial broker desks (TK-10590).
+   Single source so the two thin shells (residential-brokers.html / commercial-brokers.html) can't drift. */
+:root{--bg:#0a0d13;--panel:#11151d;--line:#222936;--fg:#e8ecf2;--muted:#8a93a3;--gold:#c8a24b;}
+*{box-sizing:border-box;}
+html,body{margin:0;background:var(--bg);color:var(--fg);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;}
+#topbar{display:flex;align-items:center;gap:14px;padding:10px 18px;background:rgba(17,21,29,.94);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;backdrop-filter:blur(6px);}
+.brand{font-size:16px;font-weight:700;white-space:nowrap;} .brand b{color:var(--gold);}
+nav{display:flex;gap:14px;font-size:13px;} nav a{color:var(--muted);text-decoration:none;} nav a:hover,nav a.active{color:var(--gold);}
+main{padding:16px 18px 60px;max-width:1200px;margin:0 auto;}
+.lede{color:var(--muted);font-size:13px;line-height:1.5;margin:6px 0 14px;}
+#controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:14px;}
+#tabs{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;}
+#tabs button{background:var(--panel);color:var(--muted);border:0;border-right:1px solid var(--line);padding:7px 14px;font-size:13px;cursor:pointer;}
+#tabs button:last-child{border-right:0;} #tabs button.active{background:var(--gold);color:var(--bg);font-weight:700;}
+input,select{background:var(--panel);color:var(--fg);border:1px solid var(--line);border-radius:8px;padding:7px 10px;font-size:13px;}
+#densWrap{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:13px;}
+#dens{accent-color:var(--gold);}
+#count{font-size:12px;color:var(--muted);margin-left:auto;}
+#grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;}
+.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:13px;}
+.card.firm{cursor:pointer;transition:border-color .12s;} .card.firm:hover{border-color:var(--gold);}
+.card .n{font-size:15px;font-weight:600;line-height:1.25;}
+.card .m{font-size:12px;color:var(--muted);margin-top:6px;display:flex;flex-wrap:wrap;gap:10px;}
+.agents{color:var(--gold);font-weight:700;}
+.lt{font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--gold);border:1px solid var(--line);border-radius:5px;padding:1px 6px;}
+.roster{margin-top:9px;padding-top:9px;border-top:1px solid var(--line);font-size:12px;color:#c3ccd8;display:none;}
+.roster div{padding:2px 0;}
+#pager{display:flex;align-items:center;gap:10px;justify-content:center;margin-top:16px;font-size:13px;color:var(--muted);}
+#pager button{background:var(--panel);color:var(--fg);border:1px solid var(--line);border-radius:8px;padding:6px 12px;cursor:pointer;}
+#pager button:disabled{opacity:.4;cursor:default;}
+#loading{padding:40px;text-align:center;color:var(--muted);}
diff --git a/public/broker-desk.js b/public/broker-desk.js
index 3695707..65e06d2 100644
--- a/public/broker-desk.js
+++ b/public/broker-desk.js
@@ -31,12 +31,12 @@
       <div id="tabs"><button data-t="firms" class="active">Firms</button><button data-t="brokers">${AGENTS?'Agents':'Brokers'}</button></div>
       <select id="city">${CITIES.map(([v,l])=>`<option value="${v}"${v===S.city?' selected':''}>${l}</option>`).join('')}</select>
       <input id="q" placeholder="Search name / firm / license…" style="width:200px">
-      <select id="sort" title="Sort this page">
-        <option value="">Sort: default</option>
-        <option value="name">Name A→Z</option>
-        <option value="firm">Firm A→Z</option>
-        <option value="agents">Agents ↓</option>
-        <option value="city">City A→Z</option>
+      <select id="sort" title="Sorts the current page only (server has no sort param)">
+        <option value="">Sort (this page)…</option>
+        <option value="name">Name A→Z (page)</option>
+        <option value="firm">Firm A→Z (page)</option>
+        <option value="agents">Agents ↓ (page)</option>
+        <option value="city">City A→Z (page)</option>
       </select>
       <label id="densWrap" title="Card density">▦ <input type="range" id="dens" min="200" max="380" step="20" value="${S.dens}"></label>
       <span id="count"></span>
@@ -96,9 +96,11 @@
     r.style.display='block';
     if (r.dataset.loaded) return;
     r.innerHTML='loading roster…';
-    const d = await j('/api/brokers?'+params({ limit:40, offset:0, firm:c.dataset.name }));
+    const d = await j('/api/brokers?'+params({ limit:50, offset:0, firm:c.dataset.name }));
     r.dataset.loaded='1';
-    r.innerHTML = (d.rows||[]).slice(0,30).map(b=>`<div>${esc(b.name)} <span style="color:var(--muted)">· ${esc(b.license_type)} · DRE ${esc(b.license_no)}</span></div>`).join('') || '<div style="color:var(--muted)">no roster rows</div>';
+    const rows = d.rows||[], total = d.total||rows.length;
+    const hdr = total>rows.length ? `<div style="color:var(--muted);margin-bottom:4px">showing first ${rows.length} of ${total.toLocaleString()} ${NOUN}</div>` : '';
+    r.innerHTML = hdr + (rows.map(b=>`<div>${esc(b.name)} <span style="color:var(--muted)">· ${esc(b.license_type)} · DRE ${esc(b.license_no)}</span></div>`).join('') || '<div style="color:var(--muted)">no roster rows</div>');
   }
   async function loadBrokers(){
     const d = await j('/api/brokers?'+params());
diff --git a/public/commercial-brokers.html b/public/commercial-brokers.html
index f9015ec..13c1598 100644
--- a/public/commercial-brokers.html
+++ b/public/commercial-brokers.html
@@ -5,37 +5,7 @@
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%230a0d13'/%3E%3Ctext x='8' y='12' font-size='10' text-anchor='middle' fill='%23c8a24b'%3ECR%3C/text%3E%3C/svg%3E">
 <title>USRealEstate — Commercial Brokers &amp; Firms</title>
-<style>
-  :root{--bg:#0a0d13;--panel:#11151d;--line:#222936;--fg:#e8ecf2;--muted:#8a93a3;--gold:#c8a24b;}
-  *{box-sizing:border-box;}
-  html,body{margin:0;background:var(--bg);color:var(--fg);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;}
-  #topbar{display:flex;align-items:center;gap:14px;padding:10px 18px;background:rgba(17,21,29,.94);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;backdrop-filter:blur(6px);}
-  .brand{font-size:16px;font-weight:700;white-space:nowrap;} .brand b{color:var(--gold);}
-  nav{display:flex;gap:14px;font-size:13px;} nav a{color:var(--muted);text-decoration:none;} nav a:hover,nav a.active{color:var(--gold);}
-  main{padding:16px 18px 60px;max-width:1200px;margin:0 auto;}
-  .lede{color:var(--muted);font-size:13px;line-height:1.5;margin:6px 0 14px;}
-  #controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:14px;}
-  #tabs{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;}
-  #tabs button{background:var(--panel);color:var(--muted);border:0;border-right:1px solid var(--line);padding:7px 14px;font-size:13px;cursor:pointer;}
-  #tabs button:last-child{border-right:0;} #tabs button.active{background:var(--gold);color:var(--bg);font-weight:700;}
-  input,select{background:var(--panel);color:var(--fg);border:1px solid var(--line);border-radius:8px;padding:7px 10px;font-size:13px;}
-  #densWrap{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:13px;}
-  #dens{accent-color:var(--gold);}
-  #count{font-size:12px;color:var(--muted);margin-left:auto;}
-  #grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;}
-  .card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:13px;}
-  .card.firm{cursor:pointer;transition:border-color .12s;} .card.firm:hover{border-color:var(--gold);}
-  .card .n{font-size:15px;font-weight:600;line-height:1.25;}
-  .card .m{font-size:12px;color:var(--muted);margin-top:6px;display:flex;flex-wrap:wrap;gap:10px;}
-  .agents{color:var(--gold);font-weight:700;}
-  .lt{font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--gold);border:1px solid var(--line);border-radius:5px;padding:1px 6px;}
-  .roster{margin-top:9px;padding-top:9px;border-top:1px solid var(--line);font-size:12px;color:#c3ccd8;display:none;}
-  .roster div{padding:2px 0;}
-  #pager{display:flex;align-items:center;gap:10px;justify-content:center;margin-top:16px;font-size:13px;color:var(--muted);}
-  #pager button{background:var(--panel);color:var(--fg);border:1px solid var(--line);border-radius:8px;padding:6px 12px;cursor:pointer;}
-  #pager button:disabled{opacity:.4;cursor:default;}
-  #loading{padding:40px;text-align:center;color:var(--muted);}
-</style>
+<link rel="stylesheet" href="/broker-desk.css">
 <link rel="stylesheet" href="/nav-drawer.css">
 <link rel="stylesheet" href="/geo-search.css">
   <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
diff --git a/public/residential-brokers.html b/public/residential-brokers.html
index 58dc976..9eb57bd 100644
--- a/public/residential-brokers.html
+++ b/public/residential-brokers.html
@@ -5,37 +5,7 @@
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%230a0d13'/%3E%3Ctext x='8' y='12' font-size='10' text-anchor='middle' fill='%23c8a24b'%3ERE%3C/text%3E%3C/svg%3E">
 <title>USRealEstate — Residential Brokers &amp; Agents</title>
-<style>
-  :root{--bg:#0a0d13;--panel:#11151d;--line:#222936;--fg:#e8ecf2;--muted:#8a93a3;--gold:#c8a24b;}
-  *{box-sizing:border-box;}
-  html,body{margin:0;background:var(--bg);color:var(--fg);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;}
-  #topbar{display:flex;align-items:center;gap:14px;padding:10px 18px;background:rgba(17,21,29,.94);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;backdrop-filter:blur(6px);}
-  .brand{font-size:16px;font-weight:700;white-space:nowrap;} .brand b{color:var(--gold);}
-  nav{display:flex;gap:14px;font-size:13px;} nav a{color:var(--muted);text-decoration:none;} nav a:hover,nav a.active{color:var(--gold);}
-  main{padding:16px 18px 60px;max-width:1200px;margin:0 auto;}
-  .lede{color:var(--muted);font-size:13px;line-height:1.5;margin:6px 0 14px;}
-  #controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:14px;}
-  #tabs{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;}
-  #tabs button{background:var(--panel);color:var(--muted);border:0;border-right:1px solid var(--line);padding:7px 14px;font-size:13px;cursor:pointer;}
-  #tabs button:last-child{border-right:0;} #tabs button.active{background:var(--gold);color:var(--bg);font-weight:700;}
-  input,select{background:var(--panel);color:var(--fg);border:1px solid var(--line);border-radius:8px;padding:7px 10px;font-size:13px;}
-  #densWrap{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:13px;}
-  #dens{accent-color:var(--gold);}
-  #count{font-size:12px;color:var(--muted);margin-left:auto;}
-  #grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;}
-  .card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:13px;}
-  .card.firm{cursor:pointer;transition:border-color .12s;} .card.firm:hover{border-color:var(--gold);}
-  .card .n{font-size:15px;font-weight:600;line-height:1.25;}
-  .card .m{font-size:12px;color:var(--muted);margin-top:6px;display:flex;flex-wrap:wrap;gap:10px;}
-  .agents{color:var(--gold);font-weight:700;}
-  .lt{font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--gold);border:1px solid var(--line);border-radius:5px;padding:1px 6px;}
-  .roster{margin-top:9px;padding-top:9px;border-top:1px solid var(--line);font-size:12px;color:#c3ccd8;display:none;}
-  .roster div{padding:2px 0;}
-  #pager{display:flex;align-items:center;gap:10px;justify-content:center;margin-top:16px;font-size:13px;color:var(--muted);}
-  #pager button{background:var(--panel);color:var(--fg);border:1px solid var(--line);border-radius:8px;padding:6px 12px;cursor:pointer;}
-  #pager button:disabled{opacity:.4;cursor:default;}
-  #loading{padding:40px;text-align:center;color:var(--muted);}
-</style>
+<link rel="stylesheet" href="/broker-desk.css">
 <link rel="stylesheet" href="/nav-drawer.css">
 <link rel="stylesheet" href="/geo-search.css">
   <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->

← e61c69f usreal: dedupe residential+commercial broker desks into shar  ·  back to Nationalrealestate  ·  usre: true server-side sort on /api/brokers + /api/firms (wh ce73325 →