[object Object]

← back to Nationalrealestate

deals/contractors/feed: make every displayed table column sortable

e36e0ecca1cd19b8afd592129dd55716ef8b876d · 2026-08-13 08:44:32 -0700 · Steve

deals.html: surface doc_number as a Table column + sort-select options
(doc_number:asc/desc) + click-to-sort header; server whitelist already had
pe.doc_number (injection-safe fixed ORDER BY fragment).

contractors.html: Phone was a displayed-but-unsortable column (bare <th> with
no data-k/indicator). Added phone to server SORT_COLS (c.phone), moved Phone
into TBL_COLS so its header is click-sortable + arrow-indicated, and added
Phone sort-select options.

commercial-feed.html: use_desc (Use) column was click-sortable but missing
from the sort <select> — added Use A→Z option (server SORT_COLS already had it).

Every column rendered in each Table view is now sortable (select + click) or,
for the action-only detail/open cell, correctly carries no sort affordance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit e36e0ecca1cd19b8afd592129dd55716ef8b876d
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 13 08:44:32 2026 -0700

    deals/contractors/feed: make every displayed table column sortable
    
    deals.html: surface doc_number as a Table column + sort-select options
    (doc_number:asc/desc) + click-to-sort header; server whitelist already had
    pe.doc_number (injection-safe fixed ORDER BY fragment).
    
    contractors.html: Phone was a displayed-but-unsortable column (bare <th> with
    no data-k/indicator). Added phone to server SORT_COLS (c.phone), moved Phone
    into TBL_COLS so its header is click-sortable + arrow-indicated, and added
    Phone sort-select options.
    
    commercial-feed.html: use_desc (Use) column was click-sortable but missing
    from the sort <select> — added Use A→Z option (server SORT_COLS already had it).
    
    Every column rendered in each Table view is now sortable (select + click) or,
    for the action-only detail/open cell, correctly carries no sort affordance.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public/commercial-feed.html | 1 +
 public/contractors.html     | 6 ++++--
 public/deals.html           | 5 ++++-
 src/server/contractors.ts   | 1 +
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/public/commercial-feed.html b/public/commercial-feed.html
index 98fe8c6..5db4980 100644
--- a/public/commercial-feed.html
+++ b/public/commercial-feed.html
@@ -83,6 +83,7 @@
       <option value="address:desc">Address Z→A</option>
       <option value="city:asc">City A→Z</option>
       <option value="type:asc">Type A→Z</option>
+      <option value="use_desc:asc">Use A→Z</option>
       <option value="sqft:desc">SqFt ↓</option>
       <option value="sqft:asc">SqFt ↑</option>
       <option value="year_built:desc">Built newest</option>
diff --git a/public/contractors.html b/public/contractors.html
index 5b77c30..fa8d63b 100644
--- a/public/contractors.html
+++ b/public/contractors.html
@@ -120,6 +120,8 @@
       <option value="expire_date:desc">Expires latest</option>
       <option value="expire_date:asc">Expires soonest</option>
       <option value="primary_class:asc">Primary class A→Z</option>
+      <option value="phone:asc">Phone ↑</option>
+      <option value="phone:desc">Phone ↓</option>
     </select>
     <span class="cg-seg" id="viewseg">
       <button data-view="grid" class="active" title="Grid">▦ Grid</button>
@@ -288,14 +290,14 @@ function card(r){
 const TBL_COLS = [
   ['business_name','Business'],['license_no','License #'],['license_status','Status'],
   ['city','City'],['county','County'],['zip','ZIP'],['primary_class','Class'],
-  ['issue_date','Issued'],['expire_date','Expires'],
+  ['issue_date','Issued'],['expire_date','Expires'],['phone','Phone'],
 ];
 function renderTable(){
   const [sk,sd]=SORT.split(':');
   const arrow=k=> k===sk ? (sd==='desc'?' ▾':' ▴') : '';
   let h='<table class="ctrtbl"><thead><tr>'+
     TBL_COLS.map(([k,l])=>`<th data-k="${k}" class="${k===sk?'sorted':''}">${esc(l)}${arrow(k)}</th>`).join('')+
-    '<th>Phone</th></tr></thead><tbody>';
+    '</tr></thead><tbody>';
   for(const r of PAGE){
     const cls=(r.classifications||[]).join(', ');
     h+='<tr>'+
diff --git a/public/deals.html b/public/deals.html
index c2981d2..e25088d 100644
--- a/public/deals.html
+++ b/public/deals.html
@@ -119,6 +119,8 @@
       <option value="year_built:asc">Built oldest</option>
       <option value="grantor:asc">Seller A→Z</option>
       <option value="grantee:asc">Buyer A→Z</option>
+      <option value="doc_number:asc">Doc # A→Z</option>
+      <option value="doc_number:desc">Doc # Z→A</option>
     </select>
     <span class="cg-seg" id="viewseg">
       <button data-view="grid" title="Grid">▦ Grid</button>
@@ -271,7 +273,7 @@ function headSort(k){ const c=curSort(); const nd=(c.k===k)?(c.d==='asc'?'desc':
 // ── TABLE view: dense all-columns spreadsheet, EVERY header click-to-sort ──
 const TBL=[['sale_date','Sale date'],['address','Address'],['city','City'],['ctype','Type'],
   ['sale_price','Price','num'],['sqft','SqFt','num'],['year_built','Built','num'],
-  ['grantor','Seller'],['grantee','Buyer']];
+  ['grantor','Seller'],['grantee','Buyer'],['doc_number','Doc #']];
 function renderTable(rows){
   const c=curSort(); const arr=k=> k===c.k?(c.d==='desc'?' ▾':' ▴'):'';
   let h='<table><thead><tr>'+
@@ -287,6 +289,7 @@ function renderTable(rows){
     h+=`<tr><td>${esc(r.sale_date)}</td><td>${addrOpen}</td><td>${cityDrill}</td><td>${typeDrill}</td>`+
       `<td class="num">${priceDrill}</td><td class="num">${r.sqft!=null?fmt(r.sqft):''}</td><td class="num">${yearDrill}</td>`+
       `<td>${esc(r.grantor)||'<span class="lbl">—</span>'}</td><td>${esc(r.grantee)||'<span class="lbl">—</span>'}</td>`+
+      `<td>${esc(r.doc_number)||'<span class="lbl">—</span>'}</td>`+
       `<td><a class="open" href="${drillUrl({id:r.id})}" data-id="${r.id}" title="Open deal detail">detail ›</a></td></tr>`;
   }
   h+='</tbody></table>';
diff --git a/src/server/contractors.ts b/src/server/contractors.ts
index a9fdb5b..0c981a9 100644
--- a/src/server/contractors.ts
+++ b/src/server/contractors.ts
@@ -58,6 +58,7 @@ const SORT_COLS: Record<string, string> = {
   issue_date: 'c.issue_date',
   expire_date: 'c.expire_date',
   primary_class: 'c.primary_class',
+  phone: 'c.phone',
 };
 
 /** Resolve ORDER BY from ?sort=&order= (whitelist); defaults to business_name ASC. */

← 27b936f nav-agent: v1.1 merge-mode asset refresh  ·  back to Nationalrealestate  ·  chore: gitignore *.bak (prevent tooling backup cruft) [TK-10 5a2f624 →