← back to Commercialrealestate
property-detail drill: Cody Cycle-3 fixes (Escape-close + stale-render guard)
59bdb783fcb50c294c04577da28bb230ec34d6f3 · 2026-08-06 17:36:21 -0700 · Steve Abrams
- Wire #propModal into the Escape keydown handler (was login/role only) — modal
consistency + a11y.
- Add _pdSeq in-flight guard to openPropDetail so a slow fetch from an earlier
click can't overwrite a newer drill's render on rapid clicks.
Dropped phantom: XSS — every interpolation already routes through esc() or is
Number()-coerced (Cody's own read confirmed no exploitable sink).
Verified: drill opens, Escape closes, JS parses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit 59bdb783fcb50c294c04577da28bb230ec34d6f3
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 6 17:36:21 2026 -0700
property-detail drill: Cody Cycle-3 fixes (Escape-close + stale-render guard)
- Wire #propModal into the Escape keydown handler (was login/role only) — modal
consistency + a11y.
- Add _pdSeq in-flight guard to openPropDetail so a slow fetch from an earlier
click can't overwrite a newer drill's render on rapid clicks.
Dropped phantom: XSS — every interpolation already routes through esc() or is
Number()-coerced (Cody's own read confirmed no exploitable sink).
Verified: drill opens, Escape closes, JS parses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/deals-flow.html | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/public/deals-flow.html b/public/deals-flow.html
index 0385c25..10e3a85 100644
--- a/public/deals-flow.html
+++ b/public/deals-flow.html
@@ -277,7 +277,7 @@ $('#loginForm').addEventListener('submit',e=>{e.preventDefault();doLogin();});
$('#liMagic').onclick=magicSignIn;
$('#liMagic').addEventListener('keydown',e=>{if(e.key==='Enter'||e.key===' '){e.preventDefault();magicSignIn();}});
$('#loginModal').addEventListener('click',e=>{if(e.target.id==='loginModal')closeLogin();});
-document.addEventListener('keydown',e=>{if(e.key==='Escape'){closeLogin();closeRole();}});
+document.addEventListener('keydown',e=>{if(e.key==='Escape'){closeLogin();closeRole();const pm=document.getElementById('propModal');if(pm)pm.classList.remove('on');}});
// magic-link fallback (kept for email accounts)
async function magicSignIn(){const email=prompt('Email for a magic-link sign-in:');if(!email)return;const r=await api('/auth/request',{method:'POST',body:JSON.stringify({email})});if(r.magic_link){if(confirm('Dev mode — open your magic-link to sign in now?'))location.href=r.magic_link;}else alert('Check your email for a sign-in link.');}
// ── first-run industry / role picker ──
@@ -314,10 +314,13 @@ $('#fSaved').addEventListener('click',async e=>{const del=e.target.closest('[dat
// href-drill rule: card values drill to their filtered view (reuses the rail F filters + keeps rail chips in sync)
function syncRailActive(attr,set){const map={s:'#fSrc',u:'#fUse',y:'#fYear',c:'#fConf'},el=$(map[attr]);if(el)el.querySelectorAll('.chip').forEach(ch=>ch.classList.toggle('active',set.has(ch.dataset[attr])));}
// ── property-detail drill: fetch the free public-record dossier + render inline ──
+let _pdSeq=0; // guards against a stale fetch overwriting a newer one on rapid clicks (Cody Cycle-3)
async function openPropDetail(ain){
+ const seq=++_pdSeq;
const m=$('#propModal'),body=$('#pmBody'),title=$('#pmTitle');
title.textContent='Property '+ain; body.innerHTML='<span style="color:var(--mut)">Loading public records…</span>'; m.classList.add('on');
- let d; try{ d=await api('/api/property/'+encodeURIComponent(ain)); }catch(err){ body.innerHTML='<span style="color:var(--bad,#f85149)">Lookup failed: '+esc(err.message)+'</span>'; return; }
+ let d; try{ d=await api('/api/property/'+encodeURIComponent(ain)); }catch(err){ if(seq===_pdSeq)body.innerHTML='<span style="color:var(--bad,#f85149)">Lookup failed: '+esc(err.message)+'</span>'; return; }
+ if(seq!==_pdSeq)return; // a newer drill superseded this one — drop the stale render
if(!d||!d.found){ body.innerHTML='<span class="mut">No assessor record for AIN '+esc(ain)+'.</span>'; return; }
const p=d.parcel||{};
const row=(k,v)=>(v||v===0)?`<div style="display:flex;gap:8px;padding:3px 0;border-bottom:1px solid var(--line)"><span style="color:var(--mut);min-width:140px;flex-shrink:0">${k}</span><span>${esc(String(v))}</span></div>`:'';
← e087624 deals-flow: property-detail drill — click a county deal -> i
·
back to Commercialrealestate
·
CRCP mls: surface '🕓 Newest (first seen)' at top of sort dr f6db22c →