Urgent pipeline: step-by-step workflow walks staffer through emergency fills
Urgent contracts now show a 4-step action plan: Step 1 (red): Review pre-matched workers Step 2 (yellow): Call first choice — highest match score Step 3 (blue): Confirm or replace — backup is ready Step 4 (green): Send shift details to confirmed workers First-choice worker highlighted with red border + label. Backup workers shown with dimmed styling + 'BACKUP' label. Urgent cards show ALL matched workers + backups (not just 3). Non-urgent contracts split into 'In Progress' (still filling) and 'Ready to Go' (fully staffed) sections. The staffer doesn't stare at a red label wondering what to do. They follow the steps: review, call, confirm, send. Done. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c0ff7434cb
commit
45a95a9feb
@ -102,27 +102,58 @@ function renderMain(today,sum,roles,topWorkers,coverage){
|
|||||||
addStat(stats,'500K','Workers in System');
|
addStat(stats,'500K','Workers in System');
|
||||||
el.appendChild(stats);
|
el.appendChild(stats);
|
||||||
|
|
||||||
// INSIGHT 1: Contracts that need attention
|
// INSIGHT 1: Urgent pipeline — step-by-step workflow
|
||||||
if(today&&today.contracts){
|
if(today&&today.contracts){
|
||||||
var urgent=today.contracts.filter(function(c){return c.priority==='urgent'||c.filled<c.headcount});
|
var urgent=today.contracts.filter(function(c){return c.priority==='urgent'});
|
||||||
|
var needsWork=today.contracts.filter(function(c){return c.priority!=='urgent'&&c.filled<c.headcount});
|
||||||
var filled=today.contracts.filter(function(c){return c.filled>=c.headcount});
|
var filled=today.contracts.filter(function(c){return c.filled>=c.headcount});
|
||||||
|
|
||||||
if(urgent.length){
|
if(urgent.length){
|
||||||
var ins=makeInsight('urgent','Needs Your Attention',
|
var ins=makeInsight('urgent','Urgent Pipeline',
|
||||||
urgent.length+' contract'+(urgent.length>1?'s':'')+' need'+(urgent.length===1?'s':'')+' action — workers are pre-matched and ready',
|
urgent.length+' emergency contract'+(urgent.length>1?'s':'') +' — the system found workers, here\'s your action plan',
|
||||||
'The system analyzed '+sum.total_needed+' positions across all contracts and found the best available matches. These still need your confirmation.');
|
null);
|
||||||
|
// Pipeline steps explanation
|
||||||
|
var steps=document.createElement('div');
|
||||||
|
steps.style.cssText='display:flex;gap:4px;margin-bottom:16px;flex-wrap:wrap';
|
||||||
|
var stepData=[
|
||||||
|
['1','Review','Check the pre-matched workers below','#f85149'],
|
||||||
|
['2','Call first choice','Highest-rated worker gets the first call','#d29922'],
|
||||||
|
['3','Confirm or replace','If they can\'t make it, the backup is ready','#58a6ff'],
|
||||||
|
['4','Send details','Client address, start time, dress code','#3fb950']
|
||||||
|
];
|
||||||
|
stepData.forEach(function(s){
|
||||||
|
var sd=document.createElement('div');
|
||||||
|
sd.style.cssText='flex:1;min-width:120px;background:#0d1117;border-radius:8px;padding:10px;border-top:2px solid '+s[3];
|
||||||
|
var num=document.createElement('div');num.style.cssText='font-size:18px;font-weight:800;color:'+s[3];num.textContent='Step '+s[0];
|
||||||
|
var title=document.createElement('div');title.style.cssText='font-size:12px;font-weight:600;color:#f0f6fc;margin-top:2px';title.textContent=s[1];
|
||||||
|
var desc=document.createElement('div');desc.style.cssText='font-size:10px;color:#8b949e;margin-top:2px';desc.textContent=s[2];
|
||||||
|
sd.appendChild(num);sd.appendChild(title);sd.appendChild(desc);steps.appendChild(sd);
|
||||||
|
});
|
||||||
|
ins.appendChild(steps);
|
||||||
|
|
||||||
urgent.forEach(function(c){
|
urgent.forEach(function(c){
|
||||||
addContractInsight(ins,c);
|
addContractInsight(ins,c,true);
|
||||||
});
|
});
|
||||||
el.appendChild(ins);
|
el.appendChild(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-urgent that need work
|
||||||
|
if(needsWork.length){
|
||||||
|
var ins1b=makeInsight('warning','In Progress',
|
||||||
|
needsWork.length+' contract'+(needsWork.length>1?'s':'')+' still filling — workers matched, awaiting confirmation',
|
||||||
|
'These are standard priority. Workers are ranked by fit — start from the top.');
|
||||||
|
needsWork.forEach(function(c){
|
||||||
|
addContractInsight(ins1b,c,false);
|
||||||
|
});
|
||||||
|
el.appendChild(ins1b);
|
||||||
|
}
|
||||||
|
|
||||||
if(filled.length){
|
if(filled.length){
|
||||||
var ins2=makeInsight('opportunity','Ready to Confirm',
|
var ins2=makeInsight('opportunity','Ready to Go',
|
||||||
filled.length+' contract'+(filled.length>1?'s':'')+' fully matched — review and send outreach',
|
filled.length+' contract'+(filled.length>1?'s':'')+' fully staffed — review and send shift details',
|
||||||
'These contracts have enough qualified workers matched. The system ranked them by skills, reliability, and location fit.');
|
'All positions matched. The workers listed below are the system\'s best picks based on role, location, reliability, and certifications. Tap Call or SMS to confirm.');
|
||||||
filled.forEach(function(c){
|
filled.forEach(function(c){
|
||||||
addContractInsight(ins2,c);
|
addContractInsight(ins2,c,false);
|
||||||
});
|
});
|
||||||
el.appendChild(ins2);
|
el.appendChild(ins2);
|
||||||
}
|
}
|
||||||
@ -170,7 +201,7 @@ function makeInsight(type,headline,sub,explanation){
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addContractInsight(parent,c){
|
function addContractInsight(parent,c,isUrgent){
|
||||||
var isFilled=c.filled>=c.headcount;
|
var isFilled=c.filled>=c.headcount;
|
||||||
var cd=document.createElement('div');cd.style.cssText='background:#0d1117;border-radius:8px;padding:12px;margin-bottom:8px';
|
var cd=document.createElement('div');cd.style.cssText='background:#0d1117;border-radius:8px;padding:12px;margin-bottom:8px';
|
||||||
var hdr=document.createElement('div');hdr.style.cssText='display:flex;justify-content:space-between;align-items:center;margin-bottom:8px';
|
var hdr=document.createElement('div');hdr.style.cssText='display:flex;justify-content:space-between;align-items:center;margin-bottom:8px';
|
||||||
@ -184,15 +215,22 @@ function addContractInsight(parent,c){
|
|||||||
hdr.appendChild(left);hdr.appendChild(right);cd.appendChild(hdr);
|
hdr.appendChild(left);hdr.appendChild(right);cd.appendChild(hdr);
|
||||||
|
|
||||||
if(c.matches&&c.matches.length){
|
if(c.matches&&c.matches.length){
|
||||||
c.matches.slice(0,Math.min(c.headcount,3)).forEach(function(m,i){
|
var showCount=Math.min(c.headcount,isUrgent?c.headcount+2:3);
|
||||||
|
c.matches.slice(0,showCount).forEach(function(m,i){
|
||||||
var w=pw(m.chunk_text||'');if(!w.nm)w.nm=m.name||m.doc_id;
|
var w=pw(m.chunk_text||'');if(!w.nm)w.nm=m.name||m.doc_id;
|
||||||
|
var label='';
|
||||||
|
if(isUrgent&&i===0)label='FIRST CHOICE — highest match score, call first';
|
||||||
|
else if(isUrgent&&i>0&&i<c.headcount)label='';
|
||||||
|
else if(isUrgent&&i>=c.headcount)label='BACKUP — if someone above can\'t make it';
|
||||||
addWorkerInsight(cd,w.nm,
|
addWorkerInsight(cd,w.nm,
|
||||||
[w.role,w.loc].filter(Boolean).join(' · '),
|
[w.role,w.loc].filter(Boolean).join(' · '),
|
||||||
buildWhyText(w,c),i);
|
label||buildWhyText(w,c),i,
|
||||||
|
isUrgent&&i===0?'#f85149':isUrgent&&i>=c.headcount?'#484f58':null);
|
||||||
});
|
});
|
||||||
if(c.matches.length>3){
|
var remaining=c.matches.length-showCount;
|
||||||
|
if(remaining>0){
|
||||||
var more=document.createElement('div');more.style.cssText='font-size:11px;color:#58a6ff;padding:4px 10px;cursor:pointer';
|
var more=document.createElement('div');more.style.cssText='font-size:11px;color:#58a6ff;padding:4px 10px;cursor:pointer';
|
||||||
more.textContent='+ '+(c.matches.length-3)+' more matched workers';
|
more.textContent='+ '+remaining+' more available workers';
|
||||||
cd.appendChild(more);
|
cd.appendChild(more);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,8 +253,9 @@ function buildWhyText(w,c){
|
|||||||
return reasons.length?reasons.join(' · '):'Matched by AI based on role and skills';
|
return reasons.length?reasons.join(' · '):'Matched by AI based on role and skills';
|
||||||
}
|
}
|
||||||
|
|
||||||
function addWorkerInsight(parent,name,detail,why,idx){
|
function addWorkerInsight(parent,name,detail,why,idx,highlight){
|
||||||
var w=document.createElement('div');w.className='iworker';
|
var w=document.createElement('div');w.className='iworker';
|
||||||
|
if(highlight)w.style.borderLeft='3px solid '+highlight;
|
||||||
var av=document.createElement('div');av.className='av';av.style.background=AC[(idx||0)%AC.length];
|
var av=document.createElement('div');av.className='av';av.style.background=AC[(idx||0)%AC.length];
|
||||||
av.textContent=(name||'?').split(' ').map(function(n){return(n[0]||'').toUpperCase()}).join('').substring(0,2);
|
av.textContent=(name||'?').split(' ').map(function(n){return(n[0]||'').toUpperCase()}).join('').substring(0,2);
|
||||||
w.appendChild(av);
|
w.appendChild(av);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user