[object Object]

← back to Dw Pairs Well

collection-grouped feed: vendor-FAMILY scope (catches all brand spellings) + collection_handle param

af1d38583b7c2d088f3a15b5663de76a677f6084 · 2026-06-26 07:29:54 -0700 · Steve

Files touched

Diff

commit af1d38583b7c2d088f3a15b5663de76a677f6084
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Jun 26 07:29:54 2026 -0700

    collection-grouped feed: vendor-FAMILY scope (catches all brand spellings) + collection_handle param
---
 server.js | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/server.js b/server.js
index 2158c5e..58550cc 100644
--- a/server.js
+++ b/server.js
@@ -639,17 +639,34 @@ function styleOf(tags) {
 app.get('/api/collection-grouped', async (req, res) => {
   try {
     const vendor = req.query.vendor ? String(req.query.vendor).slice(0, 120) : null;
+    const collHandle = req.query.collection_handle ? String(req.query.collection_handle).slice(0, 120) : null;
     const all = req.query.all === '1';
     const page = Math.max(1, parseInt(req.query.page, 10) || 1);
     const per = Math.max(1, Math.min(96, parseInt(req.query.per, 10) || 48));
     const sort = String(req.query.sort || 'newest').slice(0, 24);
-    if (!vendor && !all) {
-      return res.status(400).json({ ok: false, error: 'pass ?vendor=<name> or ?all=1 (collection proxy for local testing)' });
+    if (!vendor && !collHandle && !all) {
+      return res.status(400).json({ ok: false, error: 'pass ?vendor=<name>, ?collection_handle=<handle>, or ?all=1' });
     }
 
+    // VENDOR-FAMILY scope: a brand collection spans multiple vendor spellings
+    // ("Designers Guild" / "Designer's Guild Europe" / "Designers Guild Europe").
+    // Derive an alnum-only family key from the vendor or the collection handle
+    // (drop trailing wallpaper/wallcovering/fabric), match the normalized vendor.
+    function familyKey(s) {
+      if (!s) return null;
+      let w = String(s).toLowerCase().replace(/[-_]/g, ' ')
+        .replace(/\b(wallpaper|wallcovering|wallcoverings|fabric|fabrics|collection)\b/g, ' ')
+        .trim().split(/\s+/).filter(Boolean).slice(0, 2).join('');
+      return w.replace(/[^a-z0-9]/g, '') || null;
+    }
+    const fam = familyKey(vendor) || familyKey(collHandle);
+
     const params = [];
     let where = `sp.status = 'ACTIVE' AND sp.title IS NOT NULL AND sp.handle IS NOT NULL AND sp.dw_sku IS NOT NULL AND sp.image_url IS NOT NULL`;
-    if (vendor) { params.push(vendor); where += ` AND sp.vendor = $${params.length}`; }
+    if (fam && !all) {
+      params.push(fam + '%');
+      where += ` AND regexp_replace(lower(sp.vendor), '[^a-z0-9]', '', 'g') LIKE $${params.length}`;
+    }
 
     const r = await pool.query(`
       SELECT sp.dw_sku, sp.handle, sp.title, sp.vendor, sp.mfr_sku, sp.pattern_name, sp.tags,

← 99f1752 collection-grouped: real sort (hue/style/colorways/az) in fe  ·  back to Dw Pairs Well  ·  auto-save: 2026-06-26T07:43:29 (2 files) — tools/grouped-pre 0fa1972 →