[object Object]

← back to Wallco Ai

cactus-curator: per-card Bad/Digital/Unpublish animate out + reset stale 'all' filter

0b5f50185cf6742a5c787ea00b9e1a2d4283fce0 · 2026-05-29 12:41:17 -0700 · Steve Abrams

two UX fixes Steve flagged 2026-05-29 ('bad bulk not working / nor a
bad hook... debug' + 'how do i see published/unpublished/undecided???'):

1. per-card decide() for bad/digital/unpublish now mirrors bulk: add
   'moved-to-etsy' class + setTimeout(el.remove, 300). The SQL update
   was already firing correctly — the bug was visual. Card sat there
   with a REMOVED pill making the click feel broken. Etsy + Live skip
   this branch (Etsy self-hides, Live should stay visible).

2. one-time localStorage migration: stale cc_filter='all' resets to
   'undecided' (the in-code default). without it, prior sessions
   pinned the Show dropdown to 'All (live)' which kept Bad-removed
   cards visible. After the migration runs once per browser, future
   manual filter picks are still honored.

related cleanup: confirmed per-card Bad on a real id (#9840) returns
{ok:true, action:bad} and the PG row has is_published=f, user_removed=t —
the action was always landing, just invisible.

Files touched

Diff

commit 0b5f50185cf6742a5c787ea00b9e1a2d4283fce0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri May 29 12:41:17 2026 -0700

    cactus-curator: per-card Bad/Digital/Unpublish animate out + reset stale 'all' filter
    
    two UX fixes Steve flagged 2026-05-29 ('bad bulk not working / nor a
    bad hook... debug' + 'how do i see published/unpublished/undecided???'):
    
    1. per-card decide() for bad/digital/unpublish now mirrors bulk: add
       'moved-to-etsy' class + setTimeout(el.remove, 300). The SQL update
       was already firing correctly — the bug was visual. Card sat there
       with a REMOVED pill making the click feel broken. Etsy + Live skip
       this branch (Etsy self-hides, Live should stay visible).
    
    2. one-time localStorage migration: stale cc_filter='all' resets to
       'undecided' (the in-code default). without it, prior sessions
       pinned the Show dropdown to 'All (live)' which kept Bad-removed
       cards visible. After the migration runs once per browser, future
       manual filter picks are still honored.
    
    related cleanup: confirmed per-card Bad on a real id (#9840) returns
    {ok:true, action:bad} and the PG row has is_published=f, user_removed=t —
    the action was always landing, just invisible.
---
 public/admin/cactus-curator.html | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/public/admin/cactus-curator.html b/public/admin/cactus-curator.html
index 6fa744b..2b07397 100644
--- a/public/admin/cactus-curator.html
+++ b/public/admin/cactus-curator.html
@@ -245,7 +245,17 @@ const grid = $('grid');
 const LS = {
   get d(){ return +(localStorage.getItem('cc_density')||5); }, set d(v){ localStorage.setItem('cc_density',v); },
   get s(){ return localStorage.getItem('cc_sort')||'rank'; },   set s(v){ localStorage.setItem('cc_sort',v); },
-  get f(){ return localStorage.getItem('cc_filter')||'undecided'; }, set f(v){ localStorage.setItem('cc_filter',v); },
+  get f(){
+    // One-time migration (Steve 2026-05-29): stale localStorage from earlier sessions
+    // may pin filter='all', which makes Bad-removed cards keep showing up with REMOVED
+    // pills and feel like the Bad click is broken. Reset 'all' → 'undecided' once.
+    if (!localStorage.getItem('cc_filter_migrated_undecided_2026_05_29')
+        && localStorage.getItem('cc_filter') === 'all') {
+      localStorage.setItem('cc_filter', 'undecided');
+    }
+    localStorage.setItem('cc_filter_migrated_undecided_2026_05_29','1');
+    return localStorage.getItem('cc_filter')||'undecided';
+  }, set f(v){ localStorage.setItem('cc_filter',v); },
 };
 
 let ALL = [];                 // every design from the API
@@ -668,6 +678,15 @@ async function decide(id, action, el){
       // button land inside the card. Original PNG is backed up alongside as
       // __preseam.png — restore-preseam reverses the swap.
       runFixAndDisplay(id, el);
+    } else if (['bad','digital','unpublish'].includes(action) && el) {
+      // Steve 2026-05-29: per-card Bad/Digital/Unpublish now animate the card
+      // out of the grid on success (mirrors bulk's 300ms fade+remove). Without
+      // this the card sits there with a REMOVED pill while the SQL update has
+      // already landed, making the click feel broken. Etsy + Live skip this
+      // because Etsy already self-hides via its own path and Live keeps the
+      // card visible (now-published, no reason to drop it from the queue).
+      el.classList.add('moved-to-etsy');
+      setTimeout(() => el.remove(), 300);
     }
   } catch(e){
     el?.classList.remove('decided');

← fe9624d harden(db): psqlExecLocal throws on psql error (ON_ERROR_STO  ·  back to Wallco Ai  ·  Add 6 room-left PDP theme variants V12-V17 (room setting lef 79f45cc →