[object Object]

← back to Wallco Ai

/me/saved: add admin view-mode toggle pill (admin/live) — info@designerwallcoverings.com already gets dw_auth on trade-login allowlist (line 3667), but the toggle UI was only on /designs. Now flipped from /me/saved too.

a2a7d70d39dec1b748d6020b894edbd09b854e1f · 2026-05-28 12:39:51 -0700 · Steve Abrams

Files touched

Diff

commit a2a7d70d39dec1b748d6020b894edbd09b854e1f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu May 28 12:39:51 2026 -0700

    /me/saved: add admin view-mode toggle pill (admin/live) — info@designerwallcoverings.com already gets dw_auth on trade-login allowlist (line 3667), but the toggle UI was only on /designs. Now flipped from /me/saved too.
---
 server.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/server.js b/server.js
index 7cd7b15..f62eb99 100644
--- a/server.js
+++ b/server.js
@@ -3816,6 +3816,11 @@ app.get('/me/saved', (req, res) => {
   if (!u) {
     return res.redirect('/trade/login?return=' + encodeURIComponent('/me/saved'));
   }
+  // Admin-only floating view-mode pill (Steve 2026-05-28: "allow info acct to
+  // toggle admin/live on /me/saved"). info@designerwallcoverings.com gets a
+  // dw_auth admin JWT minted on trade-login (line ~3667 allowlist); without
+  // this toggle, /me/saved had no way to flip back to live for QA.
+  const _isAdminAuth = isAdmin(req);
   // Pull save rows joined to live DESIGNS array (DESIGNS is the in-memory
   // snapshot we already render everywhere). Designs that no longer exist in
   // the catalog are silently filtered out.
@@ -3944,6 +3949,57 @@ ${htmlHeader('/me/saved')}
        </div>`}
 </section>
 </main>
+${_isAdminAuth ? `
+<!-- Admin view-mode pill — same mechanism as /designs (cookie 'view_mode'),
+     ported here so info@ + steve@ can flip from /me/saved without bouncing
+     to /designs first. Cookie propagates to all routes. -->
+<style>
+  .view-toggle{position:fixed;right:14px;bottom:14px;z-index:9999;display:flex;gap:6px;align-items:center;padding:6px 10px;border-radius:999px;background:rgba(20,18,16,0.88);color:#f2eadb;font:11px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;box-shadow:0 4px 14px rgba(0,0,0,.35);backdrop-filter:blur(6px);user-select:none}
+  .view-toggle button{appearance:none;border:1px solid rgba(242,234,219,0.18);background:transparent;color:inherit;padding:5px 10px;border-radius:999px;font:inherit;cursor:pointer;transition:all .12s ease}
+  .view-toggle button.is-active{background:#f2eadb;color:#141210;border-color:#f2eadb}
+  .view-toggle button:hover:not(.is-active){background:rgba(242,234,219,0.12)}
+  .view-toggle-label{opacity:.55;margin-right:4px}
+</style>
+<div class="view-toggle" id="viewToggle" role="group" aria-label="View mode (admin only)">
+  <span class="view-toggle-label">View:</span>
+  <button type="button" data-mode="admin" id="vmAdmin">Admin</button>
+  <button type="button" data-mode="live"  id="vmLive">Live</button>
+</div>
+<script>
+(function(){
+  function setCookie(name, val, days){
+    var d = new Date(); d.setTime(d.getTime() + (days*86400000));
+    document.cookie = name + '=' + val + ';path=/;expires=' + d.toUTCString() + ';samesite=lax';
+  }
+  function readCookie(name){
+    var m = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]+)'));
+    return m ? decodeURIComponent(m[1]) : '';
+  }
+  function getMode(){
+    var url = new URL(window.location.href);
+    if (url.searchParams.get('view') === 'live') return 'live';
+    return readCookie('view_mode') === 'live' ? 'live' : 'admin';
+  }
+  function setActive(mode){
+    var a = document.getElementById('vmAdmin');
+    var l = document.getElementById('vmLive');
+    if (!a || !l) return;
+    a.classList.toggle('is-active', mode === 'admin');
+    l.classList.toggle('is-active', mode === 'live');
+  }
+  function applyMode(mode){
+    if (mode === getMode()) return;
+    setCookie('view_mode', mode, 365);
+    var url = new URL(window.location.href);
+    url.searchParams.delete('view');
+    window.location.replace(url.toString());
+  }
+  setActive(getMode());
+  var a = document.getElementById('vmAdmin'); if (a) a.addEventListener('click', function(){ applyMode('admin'); });
+  var l = document.getElementById('vmLive');  if (l) l.addEventListener('click', function(){ applyMode('live'); });
+})();
+</script>
+` : ''}
 ${FOOTER}
 <script>
 (function(){

← 09c554e hero: room slides use background-size:cover (full-width) ins  ·  back to Wallco Ai  ·  cactus-curator: hover any chip to swap flat tile → room mock 5f263d7 →