[object Object]

← back to Momentum Landing

momentum-landing: add Memo/Stock/Price chip actions (shared vendor-requests module)

fcb438bb2275283526286b114ac853fec428ee1e · 2026-07-15 16:46:41 -0700 · Steve

Files touched

Diff

commit fcb438bb2275283526286b114ac853fec428ee1e
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jul 15 16:46:41 2026 -0700

    momentum-landing: add Memo/Stock/Price chip actions (shared vendor-requests module)
---
 public/index.html | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/public/index.html b/public/index.html
index ced41c2..842b46b 100644
--- a/public/index.html
+++ b/public/index.html
@@ -98,6 +98,9 @@ body.imgonly .grid:not(.list) .card .b{display:none}
 .lnk{color:var(--acc);text-decoration:none;border:1px solid var(--line);border-radius:6px;padding:2px 7px;font-size:11px}
 .lnk:hover{background:var(--panel)}
 .acts{display:flex;flex-wrap:wrap;gap:6px;margin-top:3px}
+#toast{position:fixed;left:50%;bottom:18px;transform:translateX(-50%) translateY(20px);max-width:min(560px,92vw);background:#1b1e24;color:var(--ink,#e8e6e1);border:1px solid var(--line,#2a2d33);border-radius:8px;padding:10px 16px;font-size:13px;box-shadow:0 8px 30px #0008;opacity:0;pointer-events:none;transition:.25s;z-index:60}
+#toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
+#toast.ok{border-color:#2a6a4a}#toast.err{border-color:#7a2a2a}
 .act{font-size:11px;font-weight:600;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:7px;padding:4px 10px;cursor:pointer}
 .act:hover{border-color:var(--acc)}
 #more{display:block;margin:8px auto 60px;background:var(--panel);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:9px 18px;cursor:pointer}
@@ -258,7 +261,7 @@ function card(p){
   const kv=(k,v)=>v?`<div class="kv"><span class="k">${k}</span><span class="v">${esc(v)}</span></div>`:'';
   const dot=BUCKET_HEX[p.color_bucket]||'#666';
   const whenTxt=fmtWhen(p.created_at);
-  return `<div class="card" data-href="/product/${encodeURIComponent(p.handle)}" data-handle="${esc(p.handle)}">
+  return `<div class="card" data-href="/product/${encodeURIComponent(p.handle)}" data-handle="${esc(p.handle)}" data-sku="${esc(p.dw_sku||'')}" data-mfr="${esc(p.momentum_sku||'')}" data-title="${esc(p.series||p.dw_sku||'')}">
     ${img}<div class="b">
     <span class="vend">${esc(p.category||'Wallcovering')}${p.series?(' · '+esc(p.series)):''}</span>
     <div class="ttl">${title}</div>
@@ -283,6 +286,9 @@ function card(p){
       ${kv('Width',p.width)}${kv('Price',p.price!=null?('$'+Number(p.price).toFixed(2)):null)}
       ${kv('Status',p.status)}${kv('Created',fmtWhen(p.created_at))}
       <div class="acts">
+        <button class="act reqact" data-act="memo" title="Log a memo-sample request">Memo</button>
+        <button class="act reqact" data-act="stock" title="Email the vendor a stock check">Stock</button>
+        <button class="act reqact" data-act="price" title="Email the vendor for current price">Price</button>
         ${p.dw_sku?`<button class="act" data-copy="${esc(p.dw_sku)}" onclick="copyTxt(this)" title="copy DW SKU">📋 DW</button>`:''}
         ${p.momentum_sku?`<button class="act" data-copy="${esc(p.momentum_sku)}" onclick="copyTxt(this)" title="copy mfr SKU">📋 Mfr</button>`:''}
         <a class="lnk" href="/product/${encodeURIComponent(p.handle)}">open ↗</a>
@@ -304,6 +310,25 @@ function copyTxt(btn){
   });
 }
 window.copyTxt=copyTxt;
+// Purchasing actions on each chip: Memo / Stock / Price → /api/request
+grid.addEventListener('click',async e=>{
+  const btn=e.target.closest('.reqact'); if(!btn)return;
+  e.stopPropagation();
+  const card=btn.closest('.card'), type=btn.dataset.act, old=btn.textContent;
+  btn.disabled=true; btn.textContent='…';
+  try{
+    const r=await fetch(location.origin+'/api/request',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({type,dw_sku:card.dataset.sku,mfr_sku:card.dataset.mfr,title:card.dataset.title})}).then(r=>r.json());
+    toast(r.ok?(r.message||('Logged '+(r.req_no||''))):(r.error||'request failed'),!!r.ok);
+  }catch(err){ toast('request failed: '+err.message,false); }
+  btn.disabled=false; btn.textContent=old;
+});
+let toastT=null;
+function toast(msg,ok){
+  let t=document.getElementById('toast');
+  if(!t){ t=document.createElement('div'); t.id='toast'; document.body.appendChild(t); }
+  t.textContent=msg; t.className='show '+(ok?'ok':'err');
+  clearTimeout(toastT); toastT=setTimeout(()=>t.className='',6000);
+}
 function applyFilters(){
   const q=$('#q').value.trim().toLowerCase(), pat=$('#pattern').value.trim().toLowerCase();
   VIEW=ALL.filter(p=>{

← 5b2ba11 auto-save: 2026-07-14T08:29:59 (1 files) — scripts/build-pro  ·  back to Momentum Landing  ·  (newest)