← back to Sample Followup Sweep
5x sweep 2: console sort/render no longer crash on vendors with 0 outstanding items (TK-12320)
a4ab26982a4715b9879fa08633756dd542c7ae92 · 2026-09-26 09:08:43 -0700 · Steve Abrams
Files touched
Diff
commit a4ab26982a4715b9879fa08633756dd542c7ae92
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Sep 26 09:08:43 2026 -0700
5x sweep 2: console sort/render no longer crash on vendors with 0 outstanding items (TK-12320)
---
server.js | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/server.js b/server.js
index 59be810..0adfaec 100644
--- a/server.js
+++ b/server.js
@@ -286,8 +286,9 @@ function sentInfo(v){const c=S.contacts[v.slug]||{};const be=(S.sent&&S.sent.byE
let last=null,count=0;for(const a of addrs){const e=be[a];if(e){count+=e.count||1;if(!last||e.lastSent>last)last=e.lastSent;}}
return{sent:!!last,lastSent:last,count};}
function fmtSent(iso){try{const d=new Date(iso);return d.toLocaleString(undefined,{month:'short',day:'numeric',hour:'numeric',minute:'2-digit'});}catch(e){return iso;}}
+function age0(v){return (v.items&&v.items[0]&&v.items[0].age)||0;}
function sorted(){const k=document.getElementById('sort').value;localStorage.setItem('sfsort',k);const a=[...S.fleet.vendors];
- if(k==='items')a.sort((x,y)=>y.count-x.count);if(k==='age')a.sort((x,y)=>y.items[0].age-x.items[0].age);
+ if(k==='items')a.sort((x,y)=>y.count-x.count);if(k==='age')a.sort((x,y)=>age0(y)-age0(x));
if(k==='name')a.sort((x,y)=>x.name.localeCompare(y.name));if(k==='ready')a.sort((x,y)=>(ready(y)?1:0)-(ready(x)?1:0));
if(k==='unsent')a.sort((x,y)=>(sentInfo(x).sent?1:0)-(sentInfo(y).sent?1:0));
if(k==='sent')a.sort((x,y)=>{const sx=sentInfo(x),sy=sentInfo(y);return (sy.lastSent||'').localeCompare(sx.lastSent||'');});return a;}
@@ -325,7 +326,7 @@ function render(){const t=document.getElementById('rows');t.innerHTML='';for(con
'<td><b>'+esc(v.name)+'</b><div class=vid>'+esc(v.vid)+'</div></td>'+
'<td><button class=exp data-exp="'+v.slug+'">▶ '+v.count+'</button></td>'+
'<td>'+(v.reReqCount?'<span class="badge rrb">'+v.reReqCount+'</span>':'<span class=muted>–</span>')+'</td>'+
- '<td>'+v.items[0].age+'d</td>'+
+ '<td>'+(v.items&&v.items.length?v.items[0].age+'d':'-')+'</td>'+
'<td>'+(noChase?'<span class="badge dead" title="'+esc(c.disposition_reason||'')+'">NO-CHASE</span>':'<span class="badge '+(r?'ok':'need')+'">'+(r?'READY':'NEEDS')+'</span>')+replyBadge(v)+'</td>'+
'<td class="sentcell">'+sentCell(v)+'</td>'+
'<td class="fmcell">'+fmCell(v)+'</td>'+
← 32af305 5x sweep 1: npm test runs .cjs suites and fails on any faili
·
back to Sample Followup Sweep
·
5x report (TK-12320) f5257c2 →