Creative ideas + design notes
Commits with substantial prose (≥120 chars) — the rationale behind each move.
8e74e15 · 2026-06-02 · bulk endpoints: try/catch so settlement-trigger RAISE returns {blocked} not a crash
publish/unpublish/delete now catch DB errors; publish of a settlement-BLOCKed design returns
{ok:false,blocked:true,error} cleanly (the trigger RAISE no longer crashes the request).
Lets the CNCP settlement-review action buttons surface the gate honestly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b358ef8 · 2026-05-14 · feat: bulk tag editor for wallco rows
- POST /api/bulk/tag {ids, add:[], remove:[]}
- 'add' is idempotent (appends only if not already in tags array; per-tag scan via CASE WHEN $2 = ANY(tags))
- 'remove' uses array_remove for each tag in turn
- returns counts of added/removed/rows-affected
- new '+ Tag' button next to '⤓ CSV', enabled when selection > 0 AND source is editable (wallco only)
- frontend uses two prompt() inputs for add/remove comma-lists (low-friction, no modal); blank skips
- smoke-tested with 4 rows, verified add + remove round-trip cleanly
198d58c · 2026-05-14 · feat: 12-chip color filter strip (right-aligned in source bar)
- 12 hue buckets: black, white, grey, brown, beige, yellow, orange, red, pink, purple, blue, green
- hexToBucket() js HSL conversion — handles low-saturation rows (b/w/grey) before hue, narrow brown/beige bands at low L / mid-low S
- rowBucket() per kind: wallco→dominant_hex, patternbank→colors_hex[0], shopify/vintage→tag-match 'color-X'
- click chip to filter; click × or active chip to clear; persists in component state for current session
- grid + stat counts update reactively; load-more retains filter context note
- gracefully empty-states when no loaded row matches the picked hue with hint to load more
0598058 · 2026-05-14 · feat: source-context header bar + CSV export of selected rows
- new sub-header below controls shows: source id, editable/read-only pill, license note (italic gold) for archives
- new POST /api/export → kind-specific column projection (wallco: dig/category/pub/hex/tags/prompt; shopify: shopify_id/handle/title/vendor/sku/status/price/tags; patternbank: pattern_id/slug/designer/category/colors_hex; vintage: handle/title/vendor/era), proper RFC-4180 escaping, attachment filename
- new '⤓ CSV' button in controls bar, enabled while selection > 0 across ALL source kinds (including read-only ones — export is non-destructive)
- frontend exposes license_note from API into source-bar
724d1f8 · 2026-05-14 · feat: patternbank + vintage-wallpaper archive sources
- new poolPB (patternbank_archive db) + poolVW (vintage_wallpaper_archive db) with graceful safe() catch if db absent on a given machine
- /api/sources expands left rail when archives exist:
Patternbank archive (1,802) + top 20 categories
Vintage Hannah's Treasures (494) + decade buckets
- /api/products handles patternbank:all|cat:<c> and vintage:all|decade:<d> with same q + sort + offset semantics
- /img/:id handles patternbank (local file → remote_url fallback) + vintage (redirect to remote src)
- both kinds rendered readonly with internal-only license badge (PB / decade pill); deep-link button → source_url
- new sort axes: designer/category for patternbank, era ↑↓/vendor for vintage
c8d2297 · 2026-05-14 · feat: full keyboard navigation
shortcuts (when grid focused, not in search box):
- '/' focus search
- j/k or ↑/↓ move by one row (row = current --cols value)
- h/l or ←/→ move by one column
- Space or 'x' toggle selection on focused card
- Enter open detail modal
- 'a' select all, 'n' select none
- 'p' publish selected, 'u' unpublish, 'd' delete (all gated by selection size and read-only flag)
- 3-9 set density columns directly
- '?' show shortcut cheat sheet via toast
focus ring uses --pub green color, scrolls into view smoothly, cursor index resets to 0 on grid rerender, click syncs cursor for continuity
48decb7 · 2026-05-14 · feat: card-detail modal with full metadata
- new GET /api/product/:id?kind=… → full row from spoon_all_designs or shopify_products
- frontend: dblclick (any card) or shift-click (selectable) or click (readonly) opens modal
- 2-col layout: large image left, key/value rows right (status/sku/handle/vendor/price/tags/dimensions/prompt/etc.)
- dominant-hex swatch chip for wallco
- modal acts: 'Open on wallco.ai' / 'Open in Shopify Admin' deep links + inline publish/unpublish/delete buttons (wallco only)
- Esc closes, click-backdrop closes
42f74e8 · 2026-05-14 · feat: per-card deep-link hover actions
- shopify cards: 'S' = open in Shopify Admin (designer-laboratory-sandbox), '↗' = open on designerwallcoverings.com storefront
- wallco cards: '↗' = open on wallco.ai/design/:id
- buttons appear on hover above the meta strip, stopPropagation so click doesn't toggle selection
- tooltip on .lbl for truncated titles
a147034 · 2026-05-14 · feat: search box + load-more pagination
- /api/products accepts ?q=… → ILIKE on title/SKU/DIG/handle/tags for shopify, dig_number/category/tags for wallco
- /api/products returns has_more boolean
- frontend: search input (220px, debounce 240ms, esc to clear), 'Load more (N remaining)' button at bottom of flat-grid, fliepaper-bugs matrix view skips pagination (small fixed set)
4f1ef4e · 2026-05-14 · initial scaffold: 4Square admin product browser (loopback :9906)
- left-rail site picker: wallco.ai (32 categories) + DW Shopify (38 vendor/status slices)
- right-pane grid with sort + density slider per Steve's standing rule
- fliepaper-bugs 6x6 matrix mode + flat-grid for all other categories
- bulk publish/unpublish/delete/recolor on wallco rows; Shopify is read-only
- localhost-only bind, no auth (loopback == admin per wallco admin-gate)