[object Object]

← 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 →