[object Object]

← back to All Designerwallcoverings

all-dw: show Mfr # (mfr_sku) + Mfr Name (supplier_name) as card fields

8c24b22442f6f3cb7014752193521c5f85e6817f · 2026-07-07 08:39:43 -0700 · Steve Abrams

Adds two toggleable card fields to the product grid, rendered only when
present. Server ships mfr_number/mfr_name in the payload and folds mfr_sku +
supplier_name into the search haystack; client registers them in FIELD_DEFS
with the h-mfrn/h-mfrname visibility system and renders them between
Vendor·Type and the facet chips. Verified against the DWQW-61447/61443 Adorn
cards (Mfr # NE50608 / NE50508).

Files touched

Diff

commit 8c24b22442f6f3cb7014752193521c5f85e6817f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 7 08:39:43 2026 -0700

    all-dw: show Mfr # (mfr_sku) + Mfr Name (supplier_name) as card fields
    
    Adds two toggleable card fields to the product grid, rendered only when
    present. Server ships mfr_number/mfr_name in the payload and folds mfr_sku +
    supplier_name into the search haystack; client registers them in FIELD_DEFS
    with the h-mfrn/h-mfrname visibility system and renders them between
    Vendor·Type and the facet chips. Verified against the DWQW-61447/61443 Adorn
    cards (Mfr # NE50608 / NE50508).
---
 public/index.html | 15 +++++++++++----
 server.js         |  8 +++++++-
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/public/index.html b/public/index.html
index 8e9e39b..a82c103 100644
--- a/public/index.html
+++ b/public/index.html
@@ -70,6 +70,11 @@
   .sku { font-weight:700; font-size:calc(13px*var(--fs)); color:var(--accent); word-break:break-all; }
   .ttl { color:var(--txt); font-size:calc(11.5px*var(--fs)); margin-top:3px; max-height:2.8em; overflow:hidden; }
   .vt { color:var(--mut); font-size:calc(10.5px*var(--fs)); margin-top:3px; }
+  /* manufacturer identity chips — mono number + muted supplier name (internal curation aid) */
+  .mfrn { margin-top:3px; font-size:calc(10px*var(--fs)); color:var(--txt); font-variant-numeric:tabular-nums; }
+  .mfrn b { color:var(--mut); font-weight:600; letter-spacing:.03em; }
+  .mfrname { margin-top:2px; font-size:calc(10px*var(--fs)); color:var(--mut); }
+  .mfrname b { letter-spacing:.03em; }
   .fac { margin-top:4px; font-size:calc(10.5px*var(--fs)); color:var(--accent); }
   .price { color:#e8e8ea; font-size:calc(12.5px*var(--fs)); font-weight:600; margin-top:4px; display:block; }
   /* active-or-staged date chip — admin curation aid (Steve rule: admin cards show created date+time) */
@@ -117,8 +122,8 @@
   td.acts-td a.disabled, td.acts-td .im.disabled { opacity:.35; pointer-events:none; color:var(--mut); }
   td.acts-td .intpanel { width:auto; margin-top:5px; }
   /* CARD FIELDS visibility toggles — all off = pure image-only texture wall */
-  .grid.h-sku .sku, .grid.h-ttl .ttl, .grid.h-vt .vt, .grid.h-fac .fac, .grid.h-price .price, .grid.h-when .when, .grid.h-act .acts { display:none; }
-  .grid.h-sku.h-ttl.h-vt.h-fac.h-price.h-when .meta { display:none; }
+  .grid.h-sku .sku, .grid.h-ttl .ttl, .grid.h-vt .vt, .grid.h-mfrn .mfrn, .grid.h-mfrname .mfrname, .grid.h-fac .fac, .grid.h-price .price, .grid.h-when .when, .grid.h-act .acts { display:none; }
+  .grid.h-sku.h-ttl.h-vt.h-mfrn.h-mfrname.h-fac.h-price.h-when .meta { display:none; }
 
   /* ── list view ── */
   .listwrap { padding:0 16px 30px; overflow-x:auto; }
@@ -246,7 +251,7 @@ document.querySelectorAll('details.sec').forEach((d) => {
 });
 
 /* CARD FIELDS: toggle which card elements render — all off = image-only texture wall */
-const FIELD_DEFS = [['sku', 'SKU'], ['ttl', 'Title'], ['vt', 'Vendor · Type'], ['fac', 'Color / Style / Material'], ['price', 'Price'], ['when', 'Active / Staged date'], ['act', 'Website / Internal buttons']];
+const FIELD_DEFS = [['sku', 'SKU'], ['ttl', 'Title'], ['vt', 'Vendor · Type'], ['mfrn', 'Mfr #'], ['mfrname', 'Mfr Name'], ['fac', 'Color / Style / Material'], ['price', 'Price'], ['when', 'Active / Staged date'], ['act', 'Website / Internal buttons']];
 let hiddenFields = loadSet('all_hidden_fields');
 function drawFieldToggles() {
   const row = document.getElementById('fieldsRow'); row.innerHTML = '';
@@ -544,9 +549,11 @@ function card(r) {
     ? `<div class="thumb" style="background-image:url('${r.image}')">${stBadge}</div>`
     : `<div class="thumb empty">${stBadge}no image</div>`;
   const vt = [r.vendor, r.type].filter(Boolean).join(' · ');
+  const mfrn = r.mfr_number ? `<div class="mfrn"><b>Mfr #</b> ${esc(r.mfr_number)}</div>` : '';
+  const mfrname = r.mfr_name ? `<div class="mfrname"><b>Mfr</b> ${esc(r.mfr_name)}</div>` : '';
   const fac = [...(r.colors || []), ...(r.styles || []), ...(r.materials || [])].slice(0, 4).join(' · ');
   const price = r.price ? `<span class="price">$${r.price.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span>` : '';
-  el.innerHTML = `${thumb}<div class="meta"><div class="sku">${r.sku || '—'}</div><div class="ttl" title="${(r.title || '').replace(/"/g, '&quot;')}">${r.title || ''}</div>${vt ? `<div class="vt">${vt}</div>` : ''}${fac ? `<div class="fac">${fac}</div>` : ''}${price}${whenChip(r).html}</div><div class="acts">${actButtonsHTML(r)}</div>`;
+  el.innerHTML = `${thumb}<div class="meta"><div class="sku">${r.sku || '—'}</div><div class="ttl" title="${(r.title || '').replace(/"/g, '&quot;')}">${r.title || ''}</div>${vt ? `<div class="vt">${vt}</div>` : ''}${mfrn}${mfrname}${fac ? `<div class="fac">${fac}</div>` : ''}${price}${whenChip(r).html}</div><div class="acts">${actButtonsHTML(r)}</div>`;
   const acts = el.querySelector('.acts'); if (acts) acts.addEventListener('click', (e) => { e.stopPropagation(); handleActsClick(e); });
   if (r.url) { el.style.cursor = 'pointer'; el.onclick = () => window.open(r.url, '_blank', 'noopener,noreferrer'); }
   return el;
diff --git a/server.js b/server.js
index 2afa537..0386192 100644
--- a/server.js
+++ b/server.js
@@ -102,6 +102,7 @@ async function snapSql() {
   const pubExpr = has.has('online_store_published') ? 'online_store_published' : "(upper(coalesce(status,'')) = 'ACTIVE')";
   return `
   SELECT id, shopify_id, handle, title, vendor, product_type, dw_sku, variant_sku, sku, pattern_name,
+         mfr_sku, supplier_name,
          tags, upper(coalesce(status,'')) AS status, image_url,
          ${priceExpr} AS price,
          ${pubExpr} AS online_store_published,
@@ -216,6 +217,11 @@ function deriveRow(r) {
     vendor: r.vendor || null,
     type: r.product_type || null,
     pattern: r.pattern_name || null,
+    // Manufacturer identifiers — admin curation aid (Steve rule: new-SKU go-live gate needs a real
+    // mfr NAME + mfr SKU number). mfr_number is the clean, ~93%-populated field; mfr_name comes from
+    // supplier_name and is rendered only when present (it's blank/inconsistent for some private labels).
+    mfr_number: r.mfr_sku || null,
+    mfr_name: r.supplier_name || null,
     status: r.status || null,
     lifecycle,
     image: r.image_url || null,
@@ -250,7 +256,7 @@ function deriveRow(r) {
     created: r.created_at_shopify ? new Date(r.created_at_shopify).getTime() : 0,
     updated: r.updated_at_shopify ? new Date(r.updated_at_shopify).getTime() : 0,
     // one lowercase haystack per row so search is a single .includes() pass
-    hay: [r.dw_sku, r.variant_sku, r.sku, r.title, r.vendor, r.product_type, r.pattern_name, r.tags].filter(Boolean).join(' ').toLowerCase(),
+    hay: [r.dw_sku, r.variant_sku, r.sku, r.mfr_sku, r.supplier_name, r.title, r.vendor, r.product_type, r.pattern_name, r.tags].filter(Boolean).join(' ').toLowerCase(),
   };
 }
 

← 94d8f0a This Item deep-link: capture full per-microsite handle set +  ·  back to All Designerwallcoverings  ·  live-stock coverage audit: classify all 254 display-vendors 93e37e2 →