[object Object]

← back to Fix Live Board

showroom: add tag-aware isShowroomProduct primitive (TK-11307)

2fe5feeab40a8955b5fdff87493351da2161eafa · 2026-09-08 15:37:03 -0700 · steve

A product is showroom-only if vendor is on showroom-vendors.json OR it carries
the 'Showroom' tag. Lets a shared-vendor line (MDC under 'Phillipe Romano') be
hidden from discovery/feed without hiding the vendor's sellable products.
Vendor list unchanged; tag is an additional product-level key. 11/11 unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JDeaFL4eeREBZX79tc4cnr

Files touched

Diff

commit 2fe5feeab40a8955b5fdff87493351da2161eafa
Author: steve <steve@designerwallcoverings.com>
Date:   Tue Sep 8 15:37:03 2026 -0700

    showroom: add tag-aware isShowroomProduct primitive (TK-11307)
    
    A product is showroom-only if vendor is on showroom-vendors.json OR it carries
    the 'Showroom' tag. Lets a shared-vendor line (MDC under 'Phillipe Romano') be
    hidden from discovery/feed without hiding the vendor's sellable products.
    Vendor list unchanged; tag is an additional product-level key. 11/11 unit tests.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01JDeaFL4eeREBZX79tc4cnr
---
 config/showroom-vendor.cjs | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/config/showroom-vendor.cjs b/config/showroom-vendor.cjs
index fa872fa..bca0411 100644
--- a/config/showroom-vendor.cjs
+++ b/config/showroom-vendor.cjs
@@ -46,6 +46,34 @@ function isShowroomVendor(vendor) {
   return _load().has(String(vendor).trim().toLowerCase());
 }
 
+// The product-level showroom TAG. A SHARED-vendor line (e.g. MDC under the shared
+// private label "Phillipe Romano", which also carries SELLABLE lines like Spazzolato/
+// Greenland/RIGO/Justin David) cannot be suppressed by vendor name without hiding that
+// vendor's sellable products. So a product is ALSO showroom-only if it carries this tag.
+// TK-11307.
+const SHOWROOM_TAG = 'showroom';
+
+/** Case-insensitive check: does this product's tags array/string include the Showroom tag? */
+function hasShowroomTag(tags) {
+  if (tags == null) return false;
+  const arr = Array.isArray(tags) ? tags : String(tags).split(',');
+  return arr.some(t => String(t).trim().toLowerCase() === SHOWROOM_TAG);
+}
+
+/**
+ * True iff the PRODUCT is showroom-only (addressable-but-not-discoverable): EITHER its
+ * vendor is on the showroom-vendors.json list, OR it carries the product-level "Showroom"
+ * tag. The tag path is how a shared-vendor line is hidden from discovery/feed surfaces
+ * WITHOUT hiding the vendor's sellable products. Callers pass the whole product object
+ * (must include `vendor` and `tags`). Never hardcode a vendor name — edit the JSON list
+ * for vendor-level, apply the "Showroom" tag for product-level. TK-11307.
+ */
+function isShowroomProduct(product) {
+  if (!product) return false;
+  if (isShowroomVendor(product.vendor)) return true;
+  return hasShowroomTag(product.tags);
+}
+
 /** The raw showroom-vendor names, as authored in showroom-vendors.json. */
 function showroomVendors() {
   try {
@@ -56,4 +84,4 @@ function showroomVendors() {
   }
 }
 
-module.exports = { isShowroomVendor, showroomVendors, LIST_PATH };
+module.exports = { isShowroomVendor, isShowroomProduct, hasShowroomTag, showroomVendors, LIST_PATH };

← 9ba8420 Add reusable isShowroomVendor() primitive keyed off showroom  ·  back to Fix Live Board  ·  showroom: rename tag to 'ShowroomOnly' — 'Showroom' collides d6185a7 →