[object Object]

← back to Rentv 2026

pr-intelligence dashboard: every data point hrefs deeper — by_category→orgs?type=, by_role→people?department=, by_metro→people?metro=, coverage-gap cells→orgs?metro=&type= (was dead-end bars)

5c464c00231559b81fdcb23f46ce06847dde93db · 2026-08-05 14:01:27 -0700 · Steve Abrams

Files touched

Diff

commit 5c464c00231559b81fdcb23f46ce06847dde93db
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 5 14:01:27 2026 -0700

    pr-intelligence dashboard: every data point hrefs deeper — by_category→orgs?type=, by_role→people?department=, by_metro→people?metro=, coverage-gap cells→orgs?metro=&type= (was dead-end bars)
---
 public/admin/pr-intelligence/index.html | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/public/admin/pr-intelligence/index.html b/public/admin/pr-intelligence/index.html
index d3c41bab..4c494ffe 100644
--- a/public/admin/pr-intelligence/index.html
+++ b/public/admin/pr-intelligence/index.html
@@ -39,12 +39,12 @@
         <p style="margin:10px 0 0"><a class="btn sm" href="/admin/pr-intelligence/settings">Gate details & Arizona unlock →</a></p>
       </div>
       <div class="panel"><h3>Organizations by category</h3>
-        ${d.by_category.slice(0, 14).map((x) => bar(x.organization_type, x.n, d.by_category[0]?.n || 1)).join('') || '<div class="empty">No data yet</div>'}
+        ${d.by_category.slice(0, 14).map((x) => bar(x.organization_type, x.n, d.by_category[0]?.n || 1, '/admin/pr-intelligence/organizations?type=' + encodeURIComponent(x.organization_type))).join('') || '<div class="empty">No data yet</div>'}
       </div>
       <div class="panel"><h3>Contacts by role · metro</h3>
-        ${d.by_role.slice(0, 7).map((x) => bar(x.department, x.n, d.by_role[0]?.n || 1)).join('') || '<div class="empty">No contacts yet</div>'}
+        ${d.by_role.slice(0, 7).map((x) => bar(x.department, x.n, d.by_role[0]?.n || 1, '/admin/pr-intelligence/people?department=' + encodeURIComponent(x.department))).join('') || '<div class="empty">No contacts yet</div>'}
         <hr style="border:none;border-top:1px solid var(--line);margin:10px 0">
-        ${d.by_metro.slice(0, 7).map((x) => bar(x.metro, x.n, d.by_metro[0]?.n || 1)).join('') || '<div class="empty">No metro data</div>'}
+        ${d.by_metro.slice(0, 7).map((x) => bar(x.metro, x.n, d.by_metro[0]?.n || 1, '/admin/pr-intelligence/people?metro=' + encodeURIComponent(x.metro))).join('') || '<div class="empty">No metro data</div>'}
       </div>
     </div>
 
@@ -68,15 +68,17 @@
 
     <div class="panel"><h3>California coverage gaps ${d.coverage_gaps ? '<span style="color:var(--muted);font-weight:400;font-size:12px">generated ' + PR.date(d.coverage_gaps.generated_at) + '</span>' : ''}</h3>
       ${d.coverage_gaps ? `<p style="font-size:13px">${d.coverage_gaps.gap_count} empty metro×category cells remain. Sample:</p>
-        <div>${d.coverage_gaps.sample.map((g) => PR.badge(g.metro + ' · ' + g.type, 'amber')).join(' ')}</div>`
+        <div>${d.coverage_gaps.sample.map((g) => `<a href="/admin/pr-intelligence/organizations?metro=${encodeURIComponent(g.metro)}&type=${encodeURIComponent(g.type)}" title="Open this empty cell in Organizations">${PR.badge(g.metro + ' · ' + g.type, 'amber')}</a>`).join(' ')}</div>`
       : '<div class="empty">No coverage report yet — queue <code>generate-coverage-report</code> from Runs & Jobs.</div>'}
     </div>`;
 
-  function bar(label, n, max) {
-    return `<div style="display:flex;align-items:center;gap:8px;padding:2px 0;font-size:12.5px">
+  function bar(label, n, max, href) {
+    const row = `<div style="display:flex;align-items:center;gap:8px;padding:2px 0;font-size:12.5px">
       <span style="width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${PR.esc(label)}</span>
       <span class="bar" style="flex:1;height:8px;background:#eef1f5;border-radius:4px;overflow:hidden"><i style="display:block;height:100%;width:${Math.round(n / max * 100)}%;background:var(--accent)"></i></span>
       <b style="width:40px;text-align:right">${n}</b></div>`;
+    // Every data point hrefs to deeper data (Steve's rule) — drill into the filtered list.
+    return href ? `<a href="${href}" style="display:block;text-decoration:none;color:inherit" title="Drill into ${PR.esc(label)}">${row}</a>` : row;
   }
   function renderGate(checks) {
     const item = (ok, label, extra) => `<div class="gatechk"><span class="s">${ok ? '✅' : '❌'}</span><span>${label}${extra ? ' — ' + extra : ''}</span></div>`;

← 75b7680c search-index: HomesOnSpec LIVE from Kamatera (InventoryHome,  ·  back to Rentv 2026  ·  PR intel: OpenClaw masthead extractor + per-person phone/ema 25e5df28 →