[object Object]

← back to Wallco Ai

Hot-or-not + room setting generalized to ALL wallco.ai lines

ed7d4f3de10bae83f4580288c08dd316aa100867 · 2026-05-27 14:06:24 -0700 · Steve Abrams

- /api/admin/drunk/list takes ?category=<line> (was hardwired to drunk samples);
  excludes heal derivatives; returns room_mockups.
- drunk-curator.html: line picker (45 lines from /api/admin/curator/collections),
  ?category= + ?admin= forwarding, title reflects line. Already had hot-or-not
  (HOT publishes + auto-renders living-room mockup; NOT → reject+defect registry)
  AND a live room setting (flat tile left, wallpaper-on-wall room right).
Verified: designer-zoo-calm 5,626 queue, tile+room both render.

Files touched

Diff

commit ed7d4f3de10bae83f4580288c08dd316aa100867
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed May 27 14:06:24 2026 -0700

    Hot-or-not + room setting generalized to ALL wallco.ai lines
    
    - /api/admin/drunk/list takes ?category=<line> (was hardwired to drunk samples);
      excludes heal derivatives; returns room_mockups.
    - drunk-curator.html: line picker (45 lines from /api/admin/curator/collections),
      ?category= + ?admin= forwarding, title reflects line. Already had hot-or-not
      (HOT publishes + auto-renders living-room mockup; NOT → reject+defect registry)
      AND a live room setting (flat tile left, wallpaper-on-wall room right).
    Verified: designer-zoo-calm 5,626 queue, tile+room both render.
---
 public/admin/drunk-curator.html | 30 +++++++++++++++++++++++++++---
 server.js                       | 15 +++++++++------
 2 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/public/admin/drunk-curator.html b/public/admin/drunk-curator.html
index b7a6a70..44d2675 100644
--- a/public/admin/drunk-curator.html
+++ b/public/admin/drunk-curator.html
@@ -40,7 +40,10 @@
 </head>
 <body>
 <header>
-  <h1>🔥 Drunk-Animals <small>· Hot or Not · tile + room</small></h1>
+  <h1>🔥 <span id="lineName">Hot or Not</span> <small>· tile + room</small></h1>
+  <select id="coll" title="pick a line" style="background:var(--panel);color:var(--ink);border:1px solid var(--line);border-radius:7px;padding:4px 9px;font-size:13px;max-width:300px;">
+    <option value="">drunk samples (default)</option>
+  </select>
   <div class="stats">
     <span>seen <b id="seen">0</b></span><span>🔥 hot <b id="hot">0</b></span>
     <span>👎 not <b id="not">0</b></span><span class="streak" id="streak"></span>
@@ -63,6 +66,9 @@
 
 <script>
 const $=s=>document.querySelector(s);
+const ADMIN=new URLSearchParams(location.search).get('admin');
+const CATEGORY=new URLSearchParams(location.search).get('category')||'';
+const q=s=>ADMIN?(s+(s.includes('?')?'&':'?')+'admin='+encodeURIComponent(ADMIN)):s;
 let QUEUE=[], i=0, hot=0, not=0, streak=0;
 function fmtDate(iso){ if(!iso)return''; try{return new Date(iso).toLocaleString(undefined,{month:'short',day:'numeric',hour:'numeric',minute:'2-digit'});}catch{return iso;} }
 function flash(e){ const f=$('#flash'); f.textContent=e; f.classList.add('show'); setTimeout(()=>f.classList.remove('show'),250); }
@@ -92,11 +98,29 @@ async function decide(v){
   if(i>=QUEUE.length) return; const d=QUEUE[i];
   if(v==='hot'){hot++;streak++;flash('🔥');}else{not++;streak=0;flash('👎');}
   i++; render();
-  try{ await fetch('/api/admin/drunk/decide',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:d.id,verdict:v})}); }catch{}
+  try{ await fetch(q('/api/admin/drunk/decide'),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id:d.id,verdict:v})}); }catch{}
 }
 document.addEventListener('keydown',e=>{ const k=e.key.toLowerCase();
+  if(e.target.tagName==='SELECT')return;
   if(e.key==='ArrowRight'||k==='h')decide('hot'); else if(e.key==='ArrowLeft'||k==='n')decide('not'); });
-(async function(){ const r=await fetch('/api/admin/drunk/list'); QUEUE=(await r.json()).items||[]; render(); })();
+
+// collection picker — switch the hot-or-not queue to any wallco.ai line
+async function loadCollections(){
+  try{
+    const r=await fetch(q('/api/admin/curator/collections')); const cols=(await r.json()).collections||[];
+    const sel=$('#coll');
+    for(const c of cols){
+      const o=document.createElement('option');
+      o.value=c.line; o.textContent=`${c.line} (${c.total})`;
+      if(c.line===CATEGORY) o.selected=true;
+      sel.appendChild(o);
+    }
+    sel.addEventListener('change',()=>{ location.href=q('/admin/drunk-curator?category='+encodeURIComponent(sel.value)); });
+  }catch{}
+}
+if(CATEGORY) $('#lineName').textContent=CATEGORY;
+loadCollections();
+(async function(){ const r=await fetch(q('/api/admin/drunk/list'+(CATEGORY?'?category='+encodeURIComponent(CATEGORY):''))); QUEUE=(await r.json()).items||[]; render(); })();
 </script>
 </body>
 </html>
diff --git a/server.js b/server.js
index 182872c..155bfb1 100644
--- a/server.js
+++ b/server.js
@@ -1143,15 +1143,18 @@ app.get('/admin/drunk-curator', (req, res) => {
 
 app.get('/api/admin/drunk/list', (req, res) => {
   if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
+  // ?category=<line> generalizes hot-or-not to ANY wallco.ai line (default =
+  // the original drunk-sample queue). Sanitized to a safe ILIKE fragment.
+  const cat = String(req.query.category || '').replace(/[^a-zA-Z0-9 ._·-]/g, '').slice(0, 40);
   try {
+    const where = cat
+      ? `category ILIKE '%${cat}%' AND is_published=FALSE AND (user_removed IS NULL OR user_removed=FALSE) AND local_path IS NOT NULL`
+      : `(category LIKE 'drunk-animals-sample%' OR category='drunk-animals-replfast' OR ((category LIKE 'drunk%' OR category LIKE 'stoned%') AND notes LIKE '%AUTO_HOT_CANDIDATE%')) AND is_published=FALSE AND (user_removed IS NULL OR user_removed=FALSE) AND local_path IS NOT NULL`;
     const rawJson = psqlQuery(
       "SELECT COALESCE(json_agg(t ORDER BY t.id), '[]'::json) FROM (" +
-        "SELECT id, category, generator, left(prompt,260) AS prompt, created_at " +
-        "FROM all_designs " +
-        "WHERE (category LIKE 'drunk-animals-sample%' OR category='drunk-animals-replfast' " +
-               "OR ((category LIKE 'drunk%' OR category LIKE 'stoned%') AND notes LIKE '%AUTO_HOT_CANDIDATE%')) " +
-          "AND is_published=FALSE AND (user_removed IS NULL OR user_removed=FALSE) " +
-          "AND local_path IS NOT NULL " +
+        "SELECT id, category, generator, left(prompt,260) AS prompt, created_at, room_mockups " +
+        "FROM all_designs WHERE " + where +
+        " AND local_path NOT LIKE '%midheal_%' AND local_path NOT LIKE '%edgeheal_%' AND local_path NOT LIKE '%smartfix_%'" +
       ") t;"
     );
     res.json({ ok: true, items: JSON.parse(rawJson || '[]') });

← 10cd2cf auto-decider TRIAGE mode: flag AUTO_HOT_CANDIDATE (no auto-p  ·  back to Wallco Ai  ·  drunk-curator (Hot or Not): fix votes silently dropped + sam 7462d55 →