← back to Mfr Review Viewer Corruption
viewer: prominent 'Suggested real mfr → Approve into field' banner (from own-SKU record) + grey/disable foreign records so they can't be picked or deleted
ac960498c99411f1c7db35fe9b658813ba50e605 · 2026-08-27 11:14:51 -0700 · Steve Abrams
Files touched
Diff
commit ac960498c99411f1c7db35fe9b658813ba50e605
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 27 11:14:51 2026 -0700
viewer: prominent 'Suggested real mfr → Approve into field' banner (from own-SKU record) + grey/disable foreign records so they can't be picked or deleted
---
public/index.html | 43 +++++++++++++++++++++++++++++++++++--------
1 file changed, 35 insertions(+), 8 deletions(-)
diff --git a/public/index.html b/public/index.html
index 8e35304..2a14a0c 100644
--- a/public/index.html
+++ b/public/index.html
@@ -135,6 +135,16 @@
.remove-sug-btn { font-size:10px; padding:2px 8px; border-radius:6px; cursor:pointer; font-weight:700;
background:#3a1a1f; color:#ff9aa6; border:1px solid #6b2b33; margin-right:6px; }
.remove-sug-btn:hover { background:#5a2028; }
+ .mfr-suggest { margin:4px 0 6px; padding:6px 9px; background:rgba(34,197,94,.10); border:1px solid var(--green);
+ border-radius:7px; font-size:12px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
+ .mfr-suggest-code { color:var(--green); font-weight:700; font-family:ui-monospace,monospace; font-size:13px; }
+ .approve-mfr-btn { margin-left:auto; font-size:11px; padding:3px 10px; border-radius:6px; cursor:pointer;
+ background:var(--green); color:#04120f; border:none; font-weight:700; }
+ .approve-mfr-btn:hover { filter:brightness(1.1); }
+ .cand-row.foreign { opacity:.5; background:#141414; cursor:default; }
+ .cand-row.foreign:hover { border-color:var(--line); }
+ .foreign-badge { font-size:10px; padding:1px 6px; border-radius:6px; background:#2a2320; color:#d9b48a; font-weight:600; }
+ .del-wrap.del-disabled { color:var(--muted); opacity:.4; align-self:center; }
.cand-row .del-wrap { display:flex; align-items:center; gap:3px; margin-left:auto; }
.cand-row .del-chk { transform:scale(1.05); cursor:pointer; accent-color:var(--red); }
.cand-row .del-lbl { font-size:9px; color:var(--red); text-transform:uppercase; letter-spacing:.03em; }
@@ -490,6 +500,13 @@ function renderCandidates(sku, panel){
h += `<button class="keep-del-btn" data-keepdel="${esc(sku)}" ${keepRid?'':'disabled'} title="Mark every OTHER FmPro record of this SKU for deletion (keeps the one you chose)">🗑 Keep selected · delete the other ${otherCount}</button>`;
}
h += `</div>`;
+ const sug = j.suggestion||{};
+ if(sug.realMfr){
+ h += `<div class="mfr-suggest" title="The correct real mfr per FileMaker's OWN record for this SKU (not a foreign record that merely shares the number)">`+
+ `✅ Suggested real mfr: <span class="mfr-suggest-code">${esc(sug.realMfr)}</span>`+
+ (sug.keepRid?` <span class="cand-meta">(from FmPro #${esc(sug.keepRid)})</span>`:'')+
+ ` <button class="approve-mfr-btn" data-approvemfr="${esc(sku)}" data-mfr="${esc(sug.realMfr)}">Approve into field ↑</button></div>`;
+ }
if(!fm.length){
h += `<div class="cand-meta">no FileMaker master found`+(j.fmError?` — <span class="cand-err">${esc(j.fmError)}</span>`:'')+`</div>`;
} else {
@@ -502,13 +519,15 @@ function renderCandidates(sku, panel){
const rid = String(c.recordId);
const isKeep = keepRid && rid===String(keepRid);
const isDel = delSet.has(rid);
+ const foreign = !c.skuMatch; // belongs to a DIFFERENT SKU (shares a number) — view-only
const picked = pick!=null && pick===real && real!=='';
- h += `<label class="cand-row${picked?' picked':''}${isDel?' marked-del':''}">
- <input type="radio" name="cand-${esc(sku)}" ${picked?'checked':''} data-real="${esc(real)}" data-rid="${esc(rid)}" data-keepmfr="${esc(real)}" data-keepnote="${esc(c.mfrNote||'')}">
+ h += `<label class="cand-row${picked?' picked':''}${isDel?' marked-del':''}${foreign?' foreign':''}">
+ <input type="radio" name="cand-${esc(sku)}" ${picked?'checked':''} ${foreign?'disabled':''} data-real="${esc(real)}" data-rid="${esc(rid)}" data-keepmfr="${esc(real)}" data-keepnote="${esc(c.mfrNote||'')}">
<span class="cand-body">
<span class="cand-line"><span class="cand-rid">#${esc(c.recordId)}</span>`+
(c.series||c.jsPattern?`<span class="cand-meta">${esc(c.series)}|${esc(c.jsPattern)}</span>`:'')+
(c.mfrPattern?`<span class="cand-struct${isDw?' isdw':''}" title="Mfr Pattern (structured)">${esc(c.mfrPattern)}</span>`:'')+
+ (foreign?`<span class="foreign-badge" title="This record belongs to a DIFFERENT SKU (${esc(c.series)}|${esc(c.jsPattern)}) that merely shares a number — NOT this SKU. Cannot be picked or deleted here.">⚠ other SKU</span>`:'')+
(isDel?`<span class="del-tag">will be staged for deletion</span>`:'')+
`</span>`+
(c.mfrNote && c.mfrNote!==c.mfrPattern?`<span class="cand-line"><span class="cand-note" title="mfr note (real code lives here)">${esc(c.mfrNote)}</span></span>`:'')+
@@ -516,18 +535,20 @@ function renderCandidates(sku, panel){
`<span class="cand-line cand-meta">`+
(c.name?`${esc(c.name)} · `:'')+(c.color?`${esc(c.color)} · `:'')+(c.vid?`vid ${esc(c.vid)}`:'')+
`</span>`+
- `<span class="cand-line">`+
+ (foreign?'':`<span class="cand-line">`+
(c.sampleOrdered
? `<span class="samp-badge samp-yes" title="a client sample WAS ordered against this record — KEEP">🧾 sampled${c.sampleDate?' '+esc(c.sampleDate):''}</span>`
: `<span class="samp-badge samp-no" title="no client sample ever ordered — a 'master' template (deletable when its mfr is just the DW# placeholder)">⛔ never sampled</span>`)+
(c.deleteSuggested?`<span class="samp-badge samp-sug" title="auto-suggested for deletion by the rule (no sample + placeholder mfr, a keeper survives)">auto-delete</span>`:'')+
- `</span>`+
- (real?`<span class="cand-line">→ real mfr: <span class="cand-realmfr">${esc(real)}</span></span>`:'')+
- `</span>
- <span class="del-wrap" title="Mark THIS master for deletion (keep the rest)">
+ `</span>`)+
+ (real&&!foreign?`<span class="cand-line">→ real mfr: <span class="cand-realmfr">${esc(real)}</span></span>`:'')+
+ `</span>`+
+ (foreign
+ ? `<span class="del-wrap del-disabled" title="Foreign record — belongs to another SKU, cannot be deleted from here">—</span>`
+ : `<span class="del-wrap" title="Mark THIS master for deletion (keep the rest)">
<input type="checkbox" class="del-chk" data-delsku="${esc(sku)}" data-delrid="${esc(rid)}" ${isDel?'checked':''}>
<span class="del-lbl">🗑 delete<br>(keep rest)</span>
- </span></label>`;
+ </span>`)+`</label>`;
}
// per-SKU running summary
h += `<div class="prune-summary" data-prune="${esc(sku)}">${pruneSummaryText(sku)}</div>`;
@@ -588,6 +609,12 @@ function renderCandidates(sku, panel){
};
}
+ // wire the "Approve into field ↑" button (writes the suggested real mfr into the confirmed-mfr input)
+ const amBtn = panel.querySelector('.approve-mfr-btn');
+ if(amBtn){
+ amBtn.onclick = (ev)=>{ ev.preventDefault(); chooseMfr(sku, amBtn.dataset.mfr||''); amBtn.textContent='✓ approved'; };
+ }
+
// wire per-record "🗑 delete (keep rest)" checkboxes
for(const cb of panel.querySelectorAll('.del-chk')){
cb.onchange = ()=>{
← 2326b02 candidates: CRITICAL — scope keep/delete/mfr-suggest to own-
·
back to Mfr Review Viewer Corruption
·
executor: add belongs-to-SKU (skuMatch) guard to execute-tim e24c287 →