← back to Commercialrealestate
auto-save: 2026-07-31T10:57:10 (1 files) — public/crcp.html
75dfa64ba343d5f68fbabfb04ec6f9a6b2d43c5e · 2026-07-31 10:57:18 -0700 · Steve Abrams
Files touched
Diff
commit 75dfa64ba343d5f68fbabfb04ec6f9a6b2d43c5e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jul 31 10:57:18 2026 -0700
auto-save: 2026-07-31T10:57:10 (1 files) — public/crcp.html
---
public/crcp.html | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/public/crcp.html b/public/crcp.html
index 764e496..0730bf8 100644
--- a/public/crcp.html
+++ b/public/crcp.html
@@ -123,6 +123,16 @@
</div>
</div>
</div>
+ <div class="panel"><h3>⚠️ FHA approval expiring within 12 months <span class="c" id="xpC"></span></h3>
+ <table id="xpTbl"><thead><tr>
+ <th class="srt" data-col="project">Project</th>
+ <th class="srt" data-col="city">City</th>
+ <th class="srt" data-col="zip">ZIP</th>
+ <th class="srt" data-col="expires">Expires</th>
+ <th class="srt n" data-col="days">Days</th>
+ </tr></thead><tbody></tbody></table>
+ <div class="meta">Approved projects whose FHA certification lapses within a year — a buyer using FHA financing should confirm re-certification. FHA-approval PROXY signal, not lender-verified Fannie/Freddie warrantability.</div>
+ </div>
</div>
<div id="ov"><div id="modal"><button class="x" aria-label="Close" onclick="document.getElementById('ov').classList.remove('on')">✕</button><div id="mbody"></div></div></div>
<script>
@@ -342,6 +352,24 @@ function renderFirms(s){ if(!s) return; const rows=srt(s.topFirms||[], fmSort.co
document.querySelectorAll('#brTbl th.srt').forEach(th=>th.onclick=()=>{ const c=th.dataset.col; if(brSort.col===c) brSort.dir*=-1; else {brSort.col=c; brSort.dir=-1;} renderBrokers(lastStats); });
document.querySelectorAll('#fmTbl th.srt').forEach(th=>th.onclick=()=>{ const c=th.dataset.col; if(fmSort.col===c) fmSort.dir*=-1; else {fmSort.col=c; fmSort.dir=-1;} renderFirms(lastStats); });
+// Panel 7 — FHA approval expiring within 12 months. Own endpoint (daily-churn data → slow refresh,
+// not the 3s poll). Soonest-to-lapse first; the Days cell reddens under 30d, ambers under 90d.
+// Reuses the same srt()/markHdr() sort engine as the broker/firm tables.
+let xpSort={col:'days',dir:1}, xpData=[];
+const xesc=s=>String(s==null?'':s).replace(/[&<>"]/g,m=>({'&':'&','<':'<','>':'>','"':'"'}[m]));
+function renderExpiring(){
+ const rows=srt(xpData, xpSort.col, xpSort.dir);
+ $('#xpC').textContent=rows.length+' projects · soonest first · click a header to sort';
+ $('#xpTbl tbody').innerHTML=rows.map(r=>{
+ const urg=r.days<=30?'color:#c0392b;font-weight:600':r.days<=90?'color:#b8860b':'';
+ return `<tr><td>${xesc(r.project)}</td><td>${xesc(r.city)}</td><td>${xesc(r.zip)}</td><td>${xesc(r.expires)}</td><td class="n" style="${urg}">${r.days<=30?'⚠️ ':''}${r.days}d</td></tr>`;
+ }).join('');
+ markHdr('xpTbl',xpSort);
+}
+document.querySelectorAll('#xpTbl th.srt').forEach(th=>th.onclick=()=>{ const c=th.dataset.col; if(xpSort.col===c) xpSort.dir*=-1; else {xpSort.col=c; xpSort.dir=1;} renderExpiring(); });
+async function loadExpiring(){ try{ const d=await (await fetch('/api/fha-expiring?days=365')).json(); xpData=d.condos||[]; renderExpiring(); }catch(e){ $('#xpC').textContent='reconnecting…'; } }
+loadExpiring(); setInterval(loadExpiring, 300000);
+
async function poll(){
let s; try{ s=await (await fetch('/api/crcp/stats')).json(); }catch(e){ $('#livetxt').textContent='reconnecting…'; return; }
lastStats=s;
← ef3c162 graphics-drill-assert: env-overridable BASE (crcp app port m
·
back to Commercialrealestate
·
CRCP lending layer: HMDA mortgage-market dataset (TK-10090) c95a76a →