← back to Chinoiseriewallpaper
/api/facets honors q + aesthetic filters (counts reflect filtered result set, not raw catalog)
d1bbc00cce7823dc62d71bef7be45d38135b3f71 · 2026-06-01 07:24:36 -0700 · Steve
Files touched
Diff
commit d1bbc00cce7823dc62d71bef7be45d38135b3f71
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Jun 1 07:24:36 2026 -0700
/api/facets honors q + aesthetic filters (counts reflect filtered result set, not raw catalog)
---
server.js | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/server.js b/server.js
index ebffa9c..4a3310f 100644
--- a/server.js
+++ b/server.js
@@ -217,13 +217,13 @@ app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
-// ── API — products ─────────────────────────────────────────────────────────
-app.get('/api/products', (req, res) => {
- const { q, aesthetic, page = 1, limit = 60, sort = 'newest' } = req.query;
- let list = PRODUCTS_PRE;
-
- if (q) {
- const needle = q.toLowerCase();
+// ── Shared filter ──────────────────────────────────────────────────────────
+// Applies the same q + aesthetic narrowing used by /api/products. `skip`
+// names a dimension to NOT apply (so /api/facets can compute per-dimension
+// counts against the otherwise-filtered set).
+function filterProducts(list, { q, aesthetic } = {}, skip) {
+ if (q && skip !== 'q') {
+ const needle = String(q).toLowerCase();
// Vendor names intentionally excluded from search to keep DW vendor identity
// out of customer-facing surfaces (standing rule, MEMORY.md 2026-05-20).
list = list.filter(p =>
@@ -231,9 +231,16 @@ app.get('/api/products', (req, res) => {
(p.tags || []).some(t => t.toLowerCase().includes(needle))
);
}
- if (aesthetic && aesthetic !== 'all') {
+ if (aesthetic && aesthetic !== 'all' && skip !== 'aesthetic') {
list = list.filter(p => p.aesthetic === aesthetic);
}
+ return list;
+}
+
+// ── API — products ─────────────────────────────────────────────────────────
+app.get('/api/products', (req, res) => {
+ const { q, aesthetic, page = 1, limit = 60, sort = 'newest' } = req.query;
+ let list = filterProducts(PRODUCTS_PRE, { q, aesthetic });
list = sortProducts(list, sort);
const total = list.length;
@@ -262,12 +269,18 @@ app.get('/api/sliders', (req, res) => {
});
// ── API — facets ───────────────────────────────────────────────────────────
+// Counts reflect the FILTERED result set, not the unfiltered catalog. Each
+// aesthetic count is computed against the q-narrowed set (skipping the
+// aesthetic dimension itself, so motif chips still show their reachable
+// totals after a search). `total` is the fully-filtered count.
app.get('/api/facets', (req, res) => {
+ const { q, aesthetic } = req.query;
const aesthetics = {};
- for (const p of PRODUCTS_PRE) {
+ for (const p of filterProducts(PRODUCTS_PRE, { q, aesthetic }, 'aesthetic')) {
aesthetics[p.aesthetic] = (aesthetics[p.aesthetic] || 0) + 1;
}
- res.json({ aesthetics, total: PRODUCTS_PRE.length });
+ const total = filterProducts(PRODUCTS_PRE, { q, aesthetic }).length;
+ res.json({ aesthetics, total });
});
// ── API — health ───────────────────────────────────────────────────────────
← 586ac8c scrub residual 3rd-party vendor names from products.json sou
·
back to Chinoiseriewallpaper
·
Remove Big Red widget — never UX-worked, collided with Help a3ba7a8 →