[object Object]

← back to Marketing Command Center

clients panel: merged ★ All Prospects group (search/sort/filter/export across all ~5.9k firms; each tagged by city)

d544ba18faeec32c10959aa6b2c9c15c3f25e857 · 2026-07-16 11:58:51 -0700 · steve

Files touched

Diff

commit d544ba18faeec32c10959aa6b2c9c15c3f25e857
Author: steve <steve@designerwallcoverings.com>
Date:   Thu Jul 16 11:58:51 2026 -0700

    clients panel: merged ★ All Prospects group (search/sort/filter/export across all ~5.9k firms; each tagged by city)
---
 public/panels/clients.js | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/public/panels/clients.js b/public/panels/clients.js
index 92da8f5..6046c59 100644
--- a/public/panels/clients.js
+++ b/public/panels/clients.js
@@ -19,7 +19,7 @@ window.MCC_PANELS['clients'] = {
     // Normalize a record from either a "clients" (FM) or "prospects" (CSV) dataset.
     function norm(rec, kind) {
       if (kind === 'prospects') {
-        return { id: (rec.website || rec.title || '').toLowerCase(), label: rec.title || '(business)', sub: [rec.city].filter(Boolean).join(' · '),
+        return { id: (rec.website || rec.title || '').toLowerCase(), label: rec.title || '(business)', sub: [rec.city, rec._group].filter(Boolean).join(' · '),
                  email: rec.email || '', website: rec.website || '', phone: rec.phone || '', q: [rec.title, rec.city].filter(Boolean).join(' '),
                  _raw: rec, _all: Object.values(rec).filter(v => v && typeof v === 'string').join(' ').toLowerCase() };
       }
@@ -41,6 +41,17 @@ window.MCC_PANELS['clients'] = {
     } catch { $('#cl-banner').textContent = 'No client datasets staged yet (data/clients-manifest.json missing).'; return; }
     if (!MANIFEST.length) { $('#cl-banner').textContent = 'No client datasets staged yet.'; return; }
 
+    // Synthetic "All Prospects" group = every prospect city merged into one list.
+    const prospectDs = MANIFEST.filter(x => x.kind === 'prospects');
+    if (prospectDs.length > 1) {
+      const fmIdx = MANIFEST.findIndex(x => x.id === 'fm-clients');
+      MANIFEST.splice(fmIdx >= 0 ? fmIdx + 1 : 0, 0, {
+        id: 'all-prospects', label: '★ All Prospects', kind: 'prospects',
+        files: prospectDs.map(x => x.file), labels: prospectDs.map(x => x.label),
+        count: prospectDs.reduce((n, x) => n + (x.count || 0), 0),
+      });
+    }
+
     $('#cl-banner').hidden = true;
     $('#cl-groupcount').textContent = MANIFEST.length + ' groups';
     $('#cl-tabs').innerHTML = MANIFEST.map(d =>
@@ -55,7 +66,14 @@ window.MCC_PANELS['clients'] = {
       $('#cl-grouptitle').textContent = d.label;
       $('#cl-list').innerHTML = '<div class="loading">Loading…</div>';
       let data;
-      try { data = await jget('/data/' + d.file); } catch { $('#cl-list').innerHTML = '<div class="card muted">Could not load ' + esc(d.file) + '.</div>'; return; }
+      if (d.files) {                       // merged "All Prospects" — load every group, tag each with its city
+        const parts = await Promise.all(d.files.map(f => jget('/data/' + f).catch(() => null)));
+        const businesses = [];
+        parts.forEach((p, i) => { if (p) (p.businesses || []).forEach(b => businesses.push(Object.assign({ _group: d.labels[i] }, b))); });
+        data = { businesses, source: 'all prospect groups merged', with_email: businesses.filter(b => b.email).length };
+      } else {
+        try { data = await jget('/data/' + d.file); } catch { $('#cl-list').innerHTML = '<div class="card muted">Could not load ' + esc(d.file) + '.</div>'; return; }
+      }
       const arr = data.clients || data.businesses || [];
       RECS = arr.map(r => norm(r, d.kind));
       const nEmail = RECS.filter(r => r.email).length, nIg = RECS.filter(r => r._raw.instagram).length, nLi = RECS.filter(r => r._raw.linkedin).length;
@@ -147,7 +165,7 @@ window.MCC_PANELS['clients'] = {
       const blob = new Blob(['' + csv], { type: 'text/csv;charset=utf-8;' });
       const url = URL.createObjectURL(blob);
       const a = document.createElement('a');
-      a.href = url; a.download = d.file.replace(/\.json$/, '') + '.csv';
+      a.href = url; a.download = (d.file || ('prospects-' + d.id + '.json')).replace(/\.json$/, '') + '.csv';
       document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url);
     }
 

← 63885bc clients panel: quick filters (email/IG/LinkedIn/uncontacted)  ·  back to Marketing Command Center  ·  clients panel: dedup + field-merge in All Prospects (LA grou b1d1fc7 →