[object Object]

← back to Commercialrealestate

crcp: drilldown on Warrantability (FHA proxy) — bars + tile open filtered condo list

e25aad36748aea15349e66bda15f8811962ebe96 · 2026-07-31 10:54:08 -0700 · Steve Abrams

Both warrantability bars and the FHA-approved tile now click through to a modal
listing the actual condos (via existing /api/fha-condos), with FHA-approved /
FHA-expired / All tabs, server-side search, and each row hrefs into
/condos.html?status=&q= (chain to the record). No dead-end data points. TK-10092

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

Files touched

Diff

commit e25aad36748aea15349e66bda15f8811962ebe96
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Jul 31 10:54:08 2026 -0700

    crcp: drilldown on Warrantability (FHA proxy) — bars + tile open filtered condo list
    
    Both warrantability bars and the FHA-approved tile now click through to a modal
    listing the actual condos (via existing /api/fha-condos), with FHA-approved /
    FHA-expired / All tabs, server-side search, and each row hrefs into
    /condos.html?status=&q= (chain to the record). No dead-end data points. TK-10092
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public/crcp.html | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/public/crcp.html b/public/crcp.html
index 26257f8..764e496 100644
--- a/public/crcp.html
+++ b/public/crcp.html
@@ -73,6 +73,12 @@
   .cinfo a,.cinfo span{font-size:13px;background:var(--panel2);border:1px solid var(--line);border-radius:18px;padding:5px 11px;color:var(--fg);text-decoration:none;}
   .sec{margin-top:14px;} .sec h4{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:0 0 7px;border-top:1px solid var(--line);padding-top:10px;}
   .litem{display:flex;justify-content:space-between;font-size:13px;padding:4px 0;} .litem .a{color:var(--fg);} .litem .m{color:var(--muted);}
+  /* warrantability drill-down (TK-10092): clickable bars + modal list */
+  .wclk{cursor:pointer;border-radius:8px;padding:2px 8px;margin:0 -8px;transition:background .12s;} .wclk:hover{background:var(--panel2);} .wclk:hover .prog span:first-child{color:var(--gold);}
+  .wtabs{display:flex;gap:6px;flex-wrap:wrap;margin:10px 0 4px;}
+  .wtab{background:var(--panel2);border:1px solid var(--line);border-radius:16px;padding:5px 11px;font-size:12px;color:var(--muted);cursor:pointer;} .wtab.on{border-color:var(--gold);color:var(--fg);} .wtab .c{color:var(--gold);font-weight:700;}
+  .wsearch{width:100%;box-sizing:border-box;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:8px 10px;color:var(--fg);font-size:13px;margin:8px 0 2px;}
+  a.wrow{text-decoration:none;border-radius:6px;padding:5px 6px;margin:0 -6px;} a.wrow:hover{background:var(--panel2);} a.wrow:hover .a{color:var(--gold);}
   .btn{background:var(--gold);color:#1a1206;border:0;border-radius:9px;padding:9px 14px;font-size:13px;font-weight:700;cursor:pointer;margin-right:8px;}
   .btn.alt{background:transparent;color:var(--draft);border:1px solid var(--draft);}
   .gate{font-size:11px;color:var(--staged);margin-top:6px;}
@@ -240,10 +246,46 @@ async function openSegment(key){
     ${(key==='sfr-bankstmt'||key==='nonqm')?leadSourcesHtml():''}`;
   document.querySelectorAll('.brow3').forEach(r=>r.onclick=e=>{ if(e.target.tagName==='A') return; openContact(r.dataset.name, r.dataset.id, key); });
 }
+// Warrantability (FHA proxy) drill-down — count -> filtered condo list -> each row hrefs into the
+// full Condos page (?status=&q=). Data from /api/fha-condos (data/fha-approved-condos.json). TK-10092.
+async function openWarrant(status){
+  status = status || 'fha_approved';
+  const ov=$('#ov'), mb=$('#mbody'); ov.classList.add('on'); mb.innerHTML='<div class="meta">loading…</div>';
+  const q = window._waQ || '';
+  let d; try{ d=await (await fetch('/api/fha-condos?status='+encodeURIComponent(status)+'&q='+encodeURIComponent(q))).json(); }
+  catch(e){ mb.innerHTML='<div class="meta">error loading warrantability list</div>'; return; }
+  if(d.error){ mb.innerHTML='<div class="meta">'+d.error+'</div>'; return; }
+  const titles={ fha_approved:'✅ FHA-approved condos', fha_expired:'⚑ FHA-expired condos (flag / review)', all:'All condos · FHA proxy' };
+  const rows=d.condos||[];
+  const nApp=(lastStats&&lastStats.fhaApproved)||0, nExp=(lastStats&&lastStats.fhaExpired)||0;
+  const chip=(v,l,n)=>`<button class="wtab${v===status?' on':''}" data-st="${v}">${l} <span class="c">${fmt(n)}</span></button>`;
+  mb.innerHTML=`<h2>${titles[status]||status}</h2>
+    <div class="mfirm">${esc(d.label||'')}</div>
+    <div class="wtabs">${chip('fha_approved','FHA-approved',nApp)}${chip('fha_expired','FHA-expired',nExp)}${chip('all','All',nApp+nExp)}</div>
+    <input id="waSearch" class="wsearch" type="text" placeholder="filter these condos — project, city, zip, address… (server-side)" value="${esc(q)}">
+    <div class="sec"><h4>${fmt(d.count)} condo${d.count===1?'':'s'}${d.count>rows.length?` · showing first ${fmt(rows.length)}`:''} — click one to open it in the full Condos page</h4>
+      ${rows.length?rows.map(c=>{
+        const proj=esc(c.project_name||c.condo_id||'—');
+        const loc=[c.city,c.zip].filter(Boolean).join(' ');
+        const conc=c.fha_concentration?` · ${esc(c.fha_concentration)} FHA`:'';
+        const meth=c.approval_method?` · ${esc(c.approval_method)}`:'';
+        const dates=c.expiration_date?` · exp ${esc(c.expiration_date)}`:(c.status_date?` · ${esc(c.status_date)}`:'');
+        const href=`/condos.html?status=${encodeURIComponent(status==='all'?'all':status)}&q=${encodeURIComponent(c.project_name||c.city||'')}`;
+        return `<a class="litem wrow" href="${href}" title="Open ${proj} in the Condos page">
+          <span class="a">${proj}</span>
+          <span class="m">${esc(loc)}${conc}${meth}${dates}</span></a>`;
+      }).join(''):'<div class="meta">none in this bucket</div>'}
+    </div>
+    <div class="meta" style="margin-top:10px"><a href="/condos.html?status=${encodeURIComponent(status)}" style="color:var(--gold)">Open the full Condos page for this filter ↗</a></div>`;
+  mb.querySelectorAll('.wtab').forEach(b=>b.onclick=()=>{ const bx=mb.querySelector('#waSearch'); window._waQ = bx?bx.value:''; openWarrant(b.dataset.st); });
+  const box=mb.querySelector('#waSearch');
+  if(box){ let t; box.oninput=()=>{ clearTimeout(t); t=setTimeout(()=>{ window._waQ=box.value; openWarrant(status); }, 300); };
+    box.focus(); box.setSelectionRange(box.value.length, box.value.length); }
+}
 const fmt=n=>n==null?'—':Number(n).toLocaleString();
 let prev={};
 function tile(k,key,v,sub,cls){ const d=(prev[key]!=null&&v>prev[key])?('+'+(v-prev[key])):'';
-  return `<div class="tile ${cls||''}"><div class="k">${k}</div><div class="v">${fmt(v)}</div><div class="sub">${sub||''}</div><div class="delta ${d?'show':''}">${d}</div></div>`; }
+  return `<div class="tile ${cls||''}" data-key="${key}"><div class="k">${k}</div><div class="v">${fmt(v)}</div><div class="sub">${sub||''}</div><div class="delta ${d?'show':''}">${d}</div></div>`; }
 function bar(label,have,total,color){ const pct=total?Math.round(100*have/total):0;
   return `<div style="margin-bottom:10px"><div class="prog"><span>${label}</span><span>${fmt(have)} / ${fmt(total)} · ${pct}%</span></div><div class="bar"><i style="width:${pct}%;background:${color||'linear-gradient(90deg,var(--gold),var(--active))'}"></i></div></div>`; }
 
@@ -314,6 +356,10 @@ async function poll(){
     tile('FHA-approved','fhaApproved',s.fhaApproved,'warrantable (proxy)','active'),
     tile('Broker edges','edges',s.edges,'broker↔listing','gold')
   ].join('');
+  // FHA-approved tile drills into the warrantability list too (TK-10092, "all data points href")
+  const fhaTile=document.querySelector('#tiles .tile[data-key="fhaApproved"]');
+  if(fhaTile){ fhaTile.style.cursor='pointer'; fhaTile.title='Click to list the FHA-approved condos';
+    fhaTile.onclick=()=>{ window._waQ=''; openWarrant('fha_approved'); }; }
   // enrichment bars (the LIVE populating)
   $('#enrLbl').textContent = (s.brokers_phone||0)+' phone · '+(s.brokers_email||0)+' email';
   $('#enrBars').innerHTML = bar('Phone captured', s.brokers_phone||0, s.brokers, 'var(--active)')
@@ -324,8 +370,13 @@ async function poll(){
   $('#enrMeta').innerHTML = enr>penr ? `<span class="has">▲ +${enr-penr} contacts since last refresh — Job B populating…</span>` : (enr===0?'Job B (broker enrichment) queued — contacts will populate here live.':'enrichment idle / complete');
   renderBrokers(s);
   // warrantability
-  $('#wa').innerHTML = bar('FHA-approved', s.fhaApproved||0, (s.fhaApproved||0)+(s.fhaExpired||0), 'var(--active)')
-    + bar('FHA-expired (flag/review)', s.fhaExpired||0, (s.fhaApproved||0)+(s.fhaExpired||0), 'var(--staged)');
+  const waTot=(s.fhaApproved||0)+(s.fhaExpired||0);
+  $('#wa').innerHTML =
+      `<div class="wclk" data-st="fha_approved" title="Click to list the ${fmt(s.fhaApproved||0)} FHA-approved condos">`
+        + bar('FHA-approved', s.fhaApproved||0, waTot, 'var(--active)') + `</div>`
+    + `<div class="wclk" data-st="fha_expired" title="Click to list the ${fmt(s.fhaExpired||0)} FHA-expired condos">`
+        + bar('FHA-expired (flag/review)', s.fhaExpired||0, waTot, 'var(--staged)') + `</div>`;
+  document.querySelectorAll('#wa .wclk').forEach(el=>el.onclick=()=>{ window._waQ=''; openWarrant(el.dataset.st); });
   renderFirms(s);
   prev=s;
   // flash changed tiles

← f5e7a1a crcp graphics.html: make every datum drillable (TK-10091)  ·  back to Commercialrealestate  ·  CRCP lending layer: hub page + compliance-gated loan-officer 84529ce →