[object Object]

← back to Rentv 2026

RENTV closings+deals editors: drill-down on every datum — badge→type, txn badge→txn, location & parties→search filters (href-everything rule), v0.20.1 — TK-10255

dbc79b26c1d1b761b541aa9be707442e30931219 · 2026-08-05 14:47:32 -0700 · Steve Abrams

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

Files touched

Diff

commit dbc79b26c1d1b761b541aa9be707442e30931219
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 5 14:47:32 2026 -0700

    RENTV closings+deals editors: drill-down on every datum — badge→type, txn badge→txn, location & parties→search filters (href-everything rule), v0.20.1 — TK-10255
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 package-lock.json    |  4 ++--
 package.json         |  2 +-
 public/closings.html | 12 ++++++++++--
 public/deals.html    | 17 +++++++++++++----
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 084a89ac..70719ec0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "rentv",
-  "version": "0.20.0",
+  "version": "0.20.1",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "rentv",
-      "version": "0.20.0",
+      "version": "0.20.1",
       "dependencies": {
         "express": "^4.21.2",
         "pg": "^8.22.0"
diff --git a/package.json b/package.json
index e99df0b5..4410cd46 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "rentv",
-  "version": "0.20.0",
+  "version": "0.20.1",
   "private": true,
   "main": "server.js",
   "scripts": {
diff --git a/public/closings.html b/public/closings.html
index c670c503..c7dea5a6 100644
--- a/public/closings.html
+++ b/public/closings.html
@@ -64,6 +64,7 @@
   .card .meta.parties{font-size:11px;gap:3px 8px}
   .card .meta.parties span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}
   .card .meta.parties .party{cursor:pointer;border-radius:4px}.card .meta.parties .party:hover{text-decoration:underline;color:var(--red)}
+  .drill{cursor:pointer}.badge.drill:hover{filter:brightness(1.25)}.card .meta .drill:hover{text-decoration:underline;color:var(--red)}
   .card .cardfoot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:10px;border-top:1px solid var(--line)}
   .card .more{font-size:12px;font-weight:700;color:var(--red);text-transform:uppercase;letter-spacing:.04em}
   .card .acts{display:flex;gap:6px}
@@ -225,7 +226,7 @@ function render(){
       <div class="ph" style="${ph}">
         <div class="badges">
           <span class="badge txn">Closed</span>
-          ${d.property_type?`<span class="badge">${esc(d.property_type)}</span>`:''}
+          ${d.property_type?`<span class="badge drill" data-filt="type" data-val="${esc(d.property_type)}" title="Filter by ${esc(d.property_type)}">${esc(d.property_type)}</span>`:''}
           ${man?'<span class="badge man">Manual</span>':''}
           ${edited?'<span class="badge edt">Edited</span>':''}
           ${hidden?'<span class="badge hid">Hidden</span>':''}
@@ -235,7 +236,7 @@ function render(){
       </div>
       <div class="body">
         <div class="addr">${esc(d.address||d.title)}</div>
-        ${loc?`<div class="meta"><span>📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
+        ${loc?`<div class="meta"><span class="drill" data-filt="q" data-val="${esc(loc)}" title="Filter by ${esc(loc)}">📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
         ${(d.buyer||d.seller||d.broker)?`<div class="meta parties">${d.buyer?`<span class="party" data-party="${esc(d.buyer)}" title="Buyer — click to see this party's deals">🟢 <b>${esc(d.buyer)}</b></span>`:''}${d.seller?`<span class="party" data-party="${esc(d.seller)}" title="Seller — click to filter">🔴 ${esc(d.seller)}</span>`:''}${d.broker?`<span class="party" data-party="${esc(d.broker)}" title="Broker — click to filter">🤝 ${esc(d.broker)}</span>`:''}</div>`:''}
         ${(d.address&&d.title)?`<h3>${esc(d.title)}</h3>`:''}
         <div class="cardfoot">
@@ -260,6 +261,13 @@ function render(){
   $('#grid').querySelectorAll('.party[data-party]').forEach(el=>{
     el.onclick=(e)=>{e.stopPropagation();const p=(el.getAttribute('data-party')||'').trim();fQ=p.toLowerCase();$('#q').value=p;render();};
   });
+  // Datum drilldown — property-type badge → type filter, location → search (href-everything rule).
+  $('#grid').querySelectorAll('.drill').forEach(el=>{
+    el.onclick=(e)=>{e.stopPropagation();const f=el.dataset.filt,v=(el.dataset.val||'').trim();
+      if(f==='type'){fType=v;pills();}
+      else if(f==='q'){fQ=v.toLowerCase();$('#q').value=v;}
+      render();};
+  });
 }
 
 // ── editor modal ──
diff --git a/public/deals.html b/public/deals.html
index 2b4d4928..a20c65a3 100644
--- a/public/deals.html
+++ b/public/deals.html
@@ -63,6 +63,7 @@
   .card .meta b{color:var(--ink)}
   .card .meta.parties{font-size:11px;gap:3px 8px}
   .card .meta.parties span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}
+  .drill{cursor:pointer}.badge.drill:hover{filter:brightness(1.25)}.card .meta .drill:hover{text-decoration:underline;color:var(--red)}
   .card .cardfoot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:10px;border-top:1px solid var(--line)}
   .card .more{font-size:12px;font-weight:700;color:var(--red);text-transform:uppercase;letter-spacing:.04em}
   .card .acts{display:flex;gap:6px}
@@ -253,8 +254,8 @@ function render(){
     return `<div class="card ${hidden?'hid':''} ${man?'man':''}" data-id="${esc(String(d.id))}">
       <div class="ph" style="${ph}">
         <div class="badges">
-          ${d.txn_type?`<span class="badge txn">${esc(d.txn_type)}</span>`:'<span class="badge txn">Deal</span>'}
-          ${d.property_type?`<span class="badge">${esc(d.property_type)}</span>`:''}
+          ${d.txn_type?`<span class="badge txn drill" data-filt="txn" data-val="${esc(d.txn_type)}" title="Filter by ${esc(d.txn_type)}">${esc(d.txn_type)}</span>`:'<span class="badge txn">Deal</span>'}
+          ${d.property_type?`<span class="badge drill" data-filt="type" data-val="${esc(d.property_type)}" title="Filter by ${esc(d.property_type)}">${esc(d.property_type)}</span>`:''}
           ${man?'<span class="badge man">Manual</span>':''}
           ${edited?'<span class="badge edt">Edited</span>':''}
           ${hidden?'<span class="badge hid">Hidden</span>':''}
@@ -264,8 +265,8 @@ function render(){
       </div>
       <div class="body">
         <div class="addr">${esc(d.address||d.title)}</div>
-        ${loc?`<div class="meta"><span>📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
-        ${(d.buyer||d.seller||d.broker)?`<div class="meta parties">${d.buyer?`<span title="Buyer">🟢 <b>${esc(d.buyer)}</b></span>`:''}${d.seller?`<span title="Seller">🔴 ${esc(d.seller)}</span>`:''}${d.broker?`<span title="Broker">🤝 ${esc(d.broker)}</span>`:''}</div>`:''}
+        ${loc?`<div class="meta"><span class="drill" data-filt="q" data-val="${esc(loc)}" title="Filter by ${esc(loc)}">📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
+        ${(d.buyer||d.seller||d.broker)?`<div class="meta parties">${d.buyer?`<span class="drill" data-filt="q" data-val="${esc(d.buyer)}" title="Buyer — filter by ${esc(d.buyer)}">🟢 <b>${esc(d.buyer)}</b></span>`:''}${d.seller?`<span class="drill" data-filt="q" data-val="${esc(d.seller)}" title="Seller — filter by ${esc(d.seller)}">🔴 ${esc(d.seller)}</span>`:''}${d.broker?`<span class="drill" data-filt="q" data-val="${esc(d.broker)}" title="Broker — filter by ${esc(d.broker)}">🤝 ${esc(d.broker)}</span>`:''}</div>`:''}
         ${(d.address&&d.title)?`<h3>${esc(d.title)}</h3>`:''}
         <div class="cardfoot">
           ${story}
@@ -286,6 +287,14 @@ function render(){
       if(act==='restore')return restoreDeal(id);
     };
   });
+  // Datum drilldown — txn badge → txn filter, property badge → type filter, location/parties → search (href-everything rule).
+  $('#grid').querySelectorAll('.drill').forEach(el=>{
+    el.onclick=(e)=>{e.stopPropagation();const f=el.dataset.filt,v=(el.dataset.val||'').trim();
+      if(f==='txn'){fTxn=v;renderPills();}
+      else if(f==='type'){fType=v;renderPills();}
+      else if(f==='q'){fQ=v.toLowerCase();$('#q').value=v;}
+      render();};
+  });
 }
 
 // ── editor modal ──

← 1b924b35 closings: FIX enrichment merge — feed deals now gap-fill buy  ·  back to Rentv 2026  ·  PR intel: tighten LinkedIn slug guard to require surname (Co 676a7464 →