← back to Gmc Viewer
fix: MC status value is 'approved' not 'active' (approved count was 0); summary recomputes live from cache
3da85f732ac0156972e7e764bb4c406505bafc30 · 2026-07-09 08:32:07 -0700 · steve
Files touched
M public/index.htmlM server.js
Diff
commit 3da85f732ac0156972e7e764bb4c406505bafc30
Author: steve <steve@designerwallcoverings.com>
Date: Thu Jul 9 08:32:07 2026 -0700
fix: MC status value is 'approved' not 'active' (approved count was 0); summary recomputes live from cache
---
public/index.html | 2 +-
server.js | 28 ++++++++++++++++------------
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/public/index.html b/public/index.html
index 6deb1c6..512830f 100644
--- a/public/index.html
+++ b/public/index.html
@@ -22,7 +22,7 @@ input[type=range]{vertical-align:middle}
.price{font-weight:700;font-size:13px}
.price.s{color:#e0a93b}.price.r{color:#5fd08a}
.st{display:inline-block;font-size:10px;padding:1px 6px;border-radius:10px;margin-top:4px}
-.st.active{background:#183a29;color:#5fd08a}.st.disapproved{background:#3a1a1a;color:#f08a8a}.st.pending{background:#3a331a;color:#e0c93b}.st.unknown{background:#232838;color:#8b93a3}
+.st.active,.st.approved{background:#183a29;color:#5fd08a}.st.disapproved{background:#3a1a1a;color:#f08a8a}.st.pending{background:#3a331a;color:#e0c93b}.st.unknown{background:#232838;color:#8b93a3}
.load{grid-column:1/-1;text-align:center;padding:20px;color:#8b93a3}
</style></head><body>
<header>
diff --git a/server.js b/server.js
index 44f56d3..9cd6972 100644
--- a/server.js
+++ b/server.js
@@ -15,6 +15,19 @@ let refreshing = false;
if (fs.existsSync(DATA)) { try { CATALOG = JSON.parse(fs.readFileSync(DATA, 'utf8')); console.log(`loaded ${CATALOG.items.length} cached offers`); } catch (e) {} }
+// Content API status values are 'approved' / 'disapproved' / 'pending' (NOT 'active').
+function computeSummary(items) {
+ return {
+ total: items.length,
+ approved: items.filter(i => i.status === 'approved').length,
+ disapproved: items.filter(i => i.status === 'disapproved').length,
+ pending: items.filter(i => i.status === 'pending').length,
+ at_425: items.filter(i => Math.abs(i.price - 4.25) < 0.01).length,
+ real_price: items.filter(i => i.price > 4.26).length,
+ by_country: items.reduce((a, i) => (a[i.country] = (a[i.country] || 0) + 1, a), {}),
+ };
+}
+
async function pull() {
if (refreshing) return; refreshing = true;
console.log('refreshing from Content API...');
@@ -46,16 +59,7 @@ async function pull() {
page = r.nextPageToken;
} while (page);
const items = [...byId.values()];
- const summary = {
- total: items.length,
- approved: items.filter(i => i.status === 'active').length,
- disapproved: items.filter(i => i.status === 'disapproved').length,
- pending: items.filter(i => i.status === 'pending').length,
- at_425: items.filter(i => Math.abs(i.price - 4.25) < 0.01).length,
- real_price: items.filter(i => i.price > 4.26).length,
- by_country: items.reduce((a, i) => (a[i.country] = (a[i.country] || 0) + 1, a), {}),
- };
- CATALOG = { generated_at: new Date().toISOString(), items, summary };
+ CATALOG = { generated_at: new Date().toISOString(), items, summary: computeSummary(items) };
fs.writeFileSync(DATA, JSON.stringify(CATALOG));
console.log(`refreshed: ${items.length} offers, ${summary.approved} approved, ${summary.disapproved} disapproved`);
} catch (e) { console.error('pull failed', e.message); }
@@ -67,14 +71,14 @@ const send = (res, code, body, type = 'application/json') => { res.writeHead(cod
const server = http.createServer((req, res) => {
if (req.headers.authorization !== AUTH) { res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="gmc"' }); return res.end('auth'); }
const u = new URL(req.url, 'http://x');
- if (u.pathname === '/api/summary') return send(res, 200, JSON.stringify({ generated_at: CATALOG.generated_at, summary: CATALOG.summary, refreshing }));
+ if (u.pathname === '/api/summary') return send(res, 200, JSON.stringify({ generated_at: CATALOG.generated_at, summary: computeSummary(CATALOG.items), refreshing }));
if (u.pathname === '/api/refresh') { pull(); return send(res, 200, JSON.stringify({ started: true })); }
if (u.pathname === '/api/products') {
const f = u.searchParams.get('filter') || 'all';
const q = (u.searchParams.get('q') || '').toLowerCase();
const limit = Math.min(2000, parseInt(u.searchParams.get('limit') || '500', 10));
let items = CATALOG.items;
- if (f === 'approved') items = items.filter(i => i.status === 'active');
+ if (f === 'approved') items = items.filter(i => i.status === 'approved');
else if (f === 'disapproved') items = items.filter(i => i.status === 'disapproved');
else if (f === 'pending') items = items.filter(i => i.status === 'pending');
else if (f === 'at425') items = items.filter(i => Math.abs(i.price - 4.25) < 0.01);
← 7e32dc7 gmc-viewer: local read-only viewer of live Google Merchant c
·
back to Gmc Viewer
·
auto-save: 2026-07-09T14:10:49 (1 files) — dw-ga4-custom-pix a07e983 →