[object Object]

← back to Commercialrealestate

Fix ?shortlist=sfv-pool (robust reload via native localStorage restore — verified 953 checked off); clean sfv-pool sub-header; clean Pool field value

bb5a372707082612a252ec0a99079775f70e8acf · 2026-08-26 09:52:53 -0700 · Steve Abrams

Files touched

Diff

commit bb5a372707082612a252ec0a99079775f70e8acf
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 26 09:52:53 2026 -0700

    Fix ?shortlist=sfv-pool (robust reload via native localStorage restore — verified 953 checked off); clean sfv-pool sub-header; clean Pool field value
---
 public/mls.html      | 25 +++++++++++++++----------
 public/sfv-pool.html | 10 +++++-----
 2 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/public/mls.html b/public/mls.html
index d9aefb3..8a570d8 100644
--- a/public/mls.html
+++ b/public/mls.html
@@ -709,16 +709,21 @@ let _qT; $('#q').addEventListener('input',()=>{ clearTimeout(_qT); _qT=setTimeou
 // deep-link ?shortlist=sfv-pool — land here with the SFV $700k-$1.2M set already CHECKED OFF (starred) +
 // the Shortlist filter on, so the email / pool-page "open on CRCP" link shows exactly those listings here.
 // Named preset (not ~950 ids in the URL): fetch the current id set from /api/sfv-pool and star them.
-(async function(){
-  const preset=new URLSearchParams(location.search).get('shortlist'); if(preset!=='sfv-pool') return;
-  try{
-    const j=await (await fetch('/api/sfv-pool')).json();
-    const ids=[...(j.withPool||[]),...(j.withoutPool||[]),...(j.unknown||[])].map(r=>r.id);
-    ids.forEach(id=>SHORT.add(id)); saveShort();
-    F.shortlist=true; if(typeof updateShortBtn==='function') updateShortBtn();
-    const sc=$('#f_shortlist'); if(sc){ sc.checked=true; }   // reflect the filter checkbox if present
-    if(typeof render==='function') render();
-  }catch(e){ console.warn('sfv-pool preset failed', e); }
+// deep-link ?shortlist=sfv-pool — robust: don't race boot()/hydrateFilters(). Instead write the shortlist
+// (cre_shortlist) + turn on the shortlist filter (mlsFilters.shortlist=1) into localStorage, then reload
+// to a CLEAN /mls.html so the page's OWN native restore path (SHORT built from cre_shortlist at parse +
+// hydrateFilters applying mlsFilters) shows exactly these listings — no timing race.
+(function(){
+  const sp=new URLSearchParams(location.search); if(sp.get('shortlist')!=='sfv-pool') return;
+  fetch('/api/sfv-pool').then(r=>r.json()).then(j=>{
+    const ids=[...(j.withPool||[]),...(j.withoutPool||[]),...(j.unknown||[])].map(r=>r.id).filter(Boolean);
+    if(!ids.length){ location.replace('/mls.html'); return; }
+    let cur=[]; try{ cur=JSON.parse(localStorage.getItem('cre_shortlist')||'[]'); }catch(e){}
+    localStorage.setItem('cre_shortlist', JSON.stringify([...new Set([...cur, ...ids])]));
+    let mf={}; try{ mf=JSON.parse(localStorage.getItem('mlsFilters')||'{}')||{}; }catch(e){}
+    mf.shortlist=1; localStorage.setItem('mlsFilters', JSON.stringify(mf));
+    location.replace('/mls.html');   // native restore path applies both on the clean reload
+  }).catch(e=>{ console.warn('sfv-pool preset failed', e); location.replace('/mls.html'); });
 })();
 function exportCSV(){ const rows=filtered(); const cols=visCols(); const cv=(r,c)=>{let v=cval(r,c); v=(v==null?'':String(v)); return '"'+v.replace(/"/g,'""')+'"';};
   const csv=cols.map(c=>'"'+c.l+'"').join(',')+'\n'+rows.map(r=>cols.map(c=>cv(r,c)).join(',')).join('\n');
diff --git a/public/sfv-pool.html b/public/sfv-pool.html
index 3bf5d9e..06803a1 100644
--- a/public/sfv-pool.html
+++ b/public/sfv-pool.html
@@ -90,9 +90,9 @@
 <body>
 <div class="wrap">
   <h1>🏊 San Fernando Valley Homes · $700k – $1.2M</h1>
-  <div class="sub">Active single-family listings, split by swimming pool ·
-    <a href="/mls.html?shortlist=sfv-pool">open these on CRCP (checked off) →</a> ·
-    <a href="/mls.html">all LA listings →</a> · <span id="src"></span></div>
+  <div class="sub">Active single-family listings, split by swimming pool<br>
+    <a href="/mls.html?shortlist=sfv-pool">open these on CRCP (checked off) →</a> &nbsp;·&nbsp;
+    <a href="/mls.html">all LA listings →</a></div>
 
   <div class="stats" id="stats"></div>
 
@@ -184,7 +184,7 @@ function render() {
       <div class="addr" data-field="Address">${r.address||'—'}</div>
       <div class="price"><span data-field="Price">${money(r.price)}</span> <span data-field="$/sqft" style="font-size:12px;color:#8b949e;font-weight:400">${pp?'· '+pp:''}</span></div>
       <div class="meta"><span data-field="City">${r.city}</span> · <span data-field="Beds">${r.beds||'?'}</span> bd / <span data-field="Baths">${r.baths||'?'}</span> ba · <span data-field="Sqft">${r.sqft?(+r.sqft).toLocaleString():'—'}</span> sqft${lot?' · lot <span data-field="Lot">'+lot+'</span>':''} · <span data-field="DOM">${r.days_on_market!=null?r.days_on_market+'d':''}</span></div>
-      <div><span data-field="Pool">${poolBadge(r._pool)}</span></div>${feat}
+      <div><span data-field="Pool" class="badge ${r._pool==='true'?'pool':r._pool==='false'?'nopool':'pending'}">${r._pool==='true'?'🏊 Pool':r._pool==='false'?'No Pool':'Pending'}</span></div>${feat}
     </div>`;
   }).join('');
   $('#foot').textContent = `${rows.length} shown · pool status enriched from Redfin listing detail (structured POOL_FEATURES). "Pending" = detail not yet checked or field absent.`;
@@ -214,7 +214,7 @@ async function load() {
   const j = await r.json();
   DATA = { withPool:j.withPool||[], withoutPool:j.withoutPool||[], unknown:j.unknown||[] };
   allRows().forEach(x => byId.set(x.id, x));
-  $('#src').textContent = 'source: ' + (j.source||'?');
+  const _src = $('#src'); if (_src) _src.textContent = 'source: ' + (j.source||'?');
   // populate city dropdown
   const cities = [...new Set(allRows().map(r=>r.city))].sort();
   $('#city').insertAdjacentHTML('beforeend', cities.map(c=>`<option value="${c}">${c}</option>`).join(''));

← c87ea0c auto-data-snapshot: 2026-08-26T09:38:32 (3 data files) — dat  ·  back to Commercialrealestate  ·  sfv-pool map: Zillow-style price pins colored by pool + keyl 28b3bb2 →