[object Object]

← back to Commercialrealestate

CRCP list view: add Broker phone column + relabel agent phone

838f589edf6e420a83ce7feeab982f1d8fb6e367 · 2026-08-25 11:04:59 -0700 · Steve

Adds a 'Broker phone' field (firm/broker-of-record line) alongside the
existing agent phone, both as list columns. Resolver prefers the resolved
usre firm_phone, then broker-history current_broker.phone, then the raw
broker_phone, then a firm-tier agent line. Relabels the existing 'phone'
field 'Agent phone' for clarity; both are ALWAYS_ON. List/table only
(card view already shows broker phone via the Current-broker line).

Files touched

Diff

commit 838f589edf6e420a83ce7feeab982f1d8fb6e367
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Aug 25 11:04:59 2026 -0700

    CRCP list view: add Broker phone column + relabel agent phone
    
    Adds a 'Broker phone' field (firm/broker-of-record line) alongside the
    existing agent phone, both as list columns. Resolver prefers the resolved
    usre firm_phone, then broker-history current_broker.phone, then the raw
    broker_phone, then a firm-tier agent line. Relabels the existing 'phone'
    field 'Agent phone' for clarity; both are ALWAYS_ON. List/table only
    (card view already shows broker phone via the Current-broker line).
---
 public/index.html | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/public/index.html b/public/index.html
index 24593b4..596b7a9 100644
--- a/public/index.html
+++ b/public/index.html
@@ -866,7 +866,7 @@ const FIELDS = [
   {k:'score',      label:'Investment score',  card:1, col:1, def:1},
   {k:'deal',       label:'Deal score',        card:1, col:1, def:1},
   {k:'agent',      label:'Agent · contact',   card:1, col:1, def:1},
-  {k:'phone',      label:'Phone',             card:1, col:1, def:1},
+  {k:'phone',      label:'Agent phone',       card:1, col:1, def:1},
   {k:'email',      label:'Email',             card:1, col:1, def:0},
   {k:'firmweb',    label:'Firm website',      card:1, col:1, def:0},
   {k:'firm',       label:'Listing firm',      card:1, col:1, def:1},
@@ -889,6 +889,7 @@ const FIELDS = [
   {k:'brokerflag', label:'Prior-broker flag', card:1, col:0, def:1},
   {k:'txhist',     label:'Transaction history',card:1,col:0, def:0},
   {k:'brokerline', label:'Current broker',    card:1, col:1, def:1},
+  {k:'brokerPhone',label:'Broker phone',      card:0, col:1, def:1},
   {k:'coc',        label:'Cash-on-cash',      card:1, col:1, def:1},
   {k:'dscr',       label:'DSCR',              card:1, col:1, def:1},
   {k:'noi',        label:'Est. NOI',          card:1, col:1, def:1},
@@ -914,7 +915,7 @@ const FIELDS = [
 ];
 // Steve (2026-08-20): ALWAYS show agent · contact, phone, listing firm, current broker — never hideable,
 // override any persisted localStorage off-state (a prior toggle-off used to hide them forever despite def:1).
-const ALWAYS_ON = ['agent','phone','firm','brokerline','broker'];
+const ALWAYS_ON = ['agent','phone','brokerPhone','firm','brokerline','broker'];
 const VIS = (function(){ let s={}; try{ s=JSON.parse(localStorage.getItem('cre_fields')||'{}'); }catch(e){} const o={}; FIELDS.forEach(f=>o[f.k]=ALWAYS_ON.includes(f.k)?true:((f.k in s)?!!s[f.k]:!!f.def)); return o; })();
 function vis(k){ return !!VIS[k]; }
 function saveVis(){ ALWAYS_ON.forEach(k=>VIS[k]=true); try{ localStorage.setItem('cre_fields', JSON.stringify(VIS)); }catch(e){} }
@@ -1040,6 +1041,8 @@ function colCell(k,p){ const f=p.finance||{};
       const tier=a.phoneTier==='firm'?' <span class="tierb" title="Firm branch line'+(a.phoneCity?' — '+esc(a.phoneCity)+' office':'')+'">firm</span>':'';
       return `<span class="ain"><a href="${telHref(a.phone)}" title="Call ${esc(a.phone)}">📞 ${esc(a.phone)}</a>${tier} <button class="copyb" data-copyval="${esc(a.phone)}" title="Copy phone">⧉</button></span>`; }
     case 'email': { const a=agentInfo(p); return a.email?`<span class="ain"><a href="mailto:${esc(a.email)}" title="Email ${esc(a.email)}">✉ ${esc(a.email)}</a> <button class="copyb" data-copyval="${esc(a.email)}" title="Copy email">⧉</button></span>`:'—'; }
+    case 'brokerPhone': { const bp=brokerPhoneOf(p); if(!bp) return '—';
+      return `<span class="ain"><a href="${telHref(bp)}" title="Call broker ${esc(bp)}">📞 ${esc(bp)}</a> <button class="copyb" data-copyval="${esc(bp)}" title="Copy broker phone">⧉</button></span>`; }
     case 'firmweb': { const a=agentInfo(p); const w=a.firmWebsite; if(!w) return '—';
       const disp=String(w).replace(/^https?:\/\//,'').replace(/\/$/,''); const href=/^https?:\/\//.test(w)?w:'https://'+w;
       return `<a class="ain" href="${esc(href)}" target="_blank" rel="noopener noreferrer" title="Open the listing firm’s website">🔗 ${esc(disp)}</a>`; }
@@ -1111,6 +1114,7 @@ function fieldVal(p,k){ const f=p.finance||{};
     case 'addr': return p.address; case 'score': return p.composite; case 'deal': return p.deal&&p.deal.score;
     case 'agent': { const a=agentInfo(p); return a.name||('~'); } // contactless rows sort last (~ > letters)
     case 'phone': { const a=agentInfo(p); return a.phone||'~'; }   // rows without a resolved phone sort last
+    case 'brokerPhone': { const bp=brokerPhoneOf(p); return bp||'~'; }
     case 'email': { const a=agentInfo(p); return a.email||'~'; }
     case 'firmweb': { const a=agentInfo(p); return a.firmWebsite||'~'; }
     case 'firm': return firmLabel(p); case 'type': return p.type; case 'units': return p.units; case 'price': return p.price;
@@ -1298,6 +1302,18 @@ function agentInfo(p){
            firmWebsite:rv.firm_website||'', firmPhone:(rv.firm_phone && !isNat(rv.firm_phone))?rv.firm_phone:'', firmAddress:rv.firm_address||'',
            contacted_at:c.contacted_at||null, notes:c.notes||'', letters:(c.letters||[]) };
 }
+// Broker (listing broker of record) phone — the enriched current-broker line, distinct from the
+// agent/contact phone in agentInfo (which folds in the scraped row's broker_phone). Steve 2026-08-25:
+// "add broker and agent phone numbers to the fields."
+function brokerPhoneOf(p){
+  const a=agentInfo(p);
+  const bh=window.BROKER_HIST[p.id]||window.BROKER_HIST_ADDR[(p.address||'').toLowerCase().trim()];
+  const chist=(bh&&bh.current_broker&&bh.current_broker.phone)||'';
+  // Prefer a DISTINCT firm/broker-of-record line (resolved usre firm_phone or broker-history), then the
+  // raw row, then — if the agent's own resolved line IS a firm/branch line — use that (it's the broker
+  // office number). Keeps "Broker phone" the firm-of-record line, distinct from the agent-direct phone.
+  return a.firmPhone || chist || p.broker_phone || (a.phoneTier==='firm' ? a.phone : '') || '';
+}
 function gsearch(q){ return 'https://www.google.com/search?q='+encodeURIComponent(q); } // retained; no longer linked out
 function safeUrl(u){ u=String(u==null?'':u); return /^https?:\/\//i.test(u)?u:'#'; }
 // "↗ View property" — a link OUT to the real listing on whichever service it's on (Crexi / LoopNet /

← f700567 auto-data-snapshot: 2026-08-25T09:32:22 (2 data files) — dat  ·  back to Commercialrealestate  ·  chore: v0.24.0 (session close) — broker-phone list column [l 71519a5 →