"find me a warehouse worker available today near Nashville" now: - Parses: role=warehouse, city=Nashville, available=true - Builds SQL: role LIKE '%warehouse%' AND city='Nashville' AND availability>0.5 - Returns: 12 Nashville warehouse workers with ZIP codes, availability %, reliability %, skills, certs, and archetype - Shows understanding tags so user sees what the system parsed - 414ms, 12 records — not a generic search, a targeted answer Recognizes 20 role keywords, 40+ cities, 10 states, availability/reliability signals from natural language. Falls through to vector search for anything the parser doesn't catch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
420 lines
25 KiB
HTML
420 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html><head>
|
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>Staffing Intelligence Console</title>
|
|
<style>
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:-apple-system,system-ui,sans-serif;background:#06090f;color:#c9d1d9;font-size:14px;line-height:1.5}
|
|
.bar{background:#0d1117;padding:14px 20px;border-bottom:1px solid #1b2130;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px}
|
|
.bar h1{font-size:15px;font-weight:600;color:#f0f6fc;letter-spacing:0.5px}
|
|
.bar .rt{font-size:11px;color:#484f58}
|
|
.wrap{max-width:960px;margin:0 auto;padding:20px 16px}
|
|
.brief-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;margin-bottom:24px}
|
|
.bcard{background:#0d1117;border:1px solid #1b2130;border-radius:10px;padding:18px;position:relative;overflow:hidden}
|
|
.bcard .label{font-size:9px;text-transform:uppercase;letter-spacing:1.5px;color:#484f58;margin-bottom:8px}
|
|
.bcard .headline{font-size:16px;font-weight:700;color:#f0f6fc;margin-bottom:4px}
|
|
.bcard .sub{font-size:12px;color:#8b949e;margin-bottom:12px}
|
|
.bcard .big{font-size:36px;font-weight:800;line-height:1}
|
|
.bcard.pulse{border-left:3px solid #58a6ff}
|
|
.bcard.bench{border-left:3px solid #d29922}
|
|
.bcard.gems{border-left:3px solid #3fb950}
|
|
.bcard.risk{border-left:3px solid #f85149}
|
|
.bcard.talent{border-left:3px solid #bc8cff}
|
|
.bcard.supply{border-left:3px solid #79c0ff}
|
|
.arch-row{display:flex;gap:4px;flex-wrap:wrap;margin-top:10px}
|
|
.arch-pill{padding:3px 10px;border-radius:10px;font-size:11px;font-weight:500}
|
|
.bench-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:12px}
|
|
.bench-row .st{width:24px;font-weight:600;color:#f0f6fc}
|
|
.bench-bar{flex:1;height:14px;background:#161b22;border-radius:4px;overflow:hidden;position:relative}
|
|
.bench-fill{height:100%;border-radius:4px;transition:width 0.8s}
|
|
.bench-row .pct{width:40px;text-align:right;font-size:11px;font-weight:600}
|
|
.wk{display:flex;align-items:center;gap:10px;padding:8px;background:#161b22;border-radius:6px;margin-bottom:4px}
|
|
.wk .av{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;color:#f0f6fc;flex-shrink:0}
|
|
.wk .info{flex:1;min-width:0}
|
|
.wk .nm{font-weight:600;color:#f0f6fc;font-size:13px}
|
|
.wk .det{color:#8b949e;font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
.wk .badge{padding:2px 8px;border-radius:8px;font-size:10px;font-weight:600;flex-shrink:0}
|
|
.prompts{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
|
|
.prompt-btn{padding:8px 16px;background:#161b22;border:1px solid #1b2130;border-radius:20px;color:#8b949e;font-size:12px;cursor:pointer;transition:all 0.2s}
|
|
.prompt-btn:hover{border-color:#58a6ff;color:#58a6ff;background:#0d1525}
|
|
.chat-box{background:#0d1117;border:1px solid #1b2130;border-radius:12px;overflow:hidden;margin-bottom:16px}
|
|
.chat-messages{min-height:60px;max-height:600px;overflow-y:auto;padding:16px}
|
|
.msg{margin-bottom:16px;animation:fadeIn 0.3s ease}
|
|
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
|
|
.msg.user{text-align:right}
|
|
.msg.user .bubble{display:inline-block;background:#1f3d68;color:#c9d6ff;padding:10px 16px;border-radius:16px 16px 4px 16px;max-width:70%;text-align:left;font-size:13px}
|
|
.msg.system .bubble{background:#161b22;border:1px solid #1b2130;border-radius:4px 16px 16px 16px;padding:16px;font-size:13px}
|
|
.msg .meta{font-size:10px;color:#484f58;margin-top:6px}
|
|
.msg .steps{margin-bottom:10px}
|
|
.msg .step{font-size:11px;color:#58a6ff;padding:2px 0}
|
|
.msg .summary{font-size:14px;font-weight:600;color:#f0f6fc;margin-bottom:8px}
|
|
.msg .note{font-size:11px;color:#8b949e;font-style:italic;margin-top:8px;padding:8px;background:#0d1117;border-radius:6px}
|
|
.result-card{background:#0d1117;border:1px solid #1b2130;border-radius:8px;padding:12px;margin-bottom:6px}
|
|
.result-card .rc-name{font-weight:600;color:#f0f6fc;font-size:13px}
|
|
.result-card .rc-detail{font-size:11px;color:#8b949e;margin-top:2px}
|
|
.result-card .rc-score{font-size:10px;color:#58a6ff;margin-top:4px}
|
|
.result-card .rc-skills{display:flex;gap:4px;flex-wrap:wrap;margin-top:6px}
|
|
.result-card .rc-skill{padding:2px 8px;background:#1a2744;color:#58a6ff;border-radius:8px;font-size:10px}
|
|
.result-card .rc-cert{padding:2px 8px;background:#1a3a2a;color:#3fb950;border-radius:8px;font-size:10px}
|
|
.source-card{background:#1a1a00;border:1px solid #854d0e;border-radius:8px;padding:12px;margin-bottom:10px}
|
|
.whatif-severity{display:inline-block;padding:3px 10px;border-radius:8px;font-size:11px;font-weight:700;margin-left:8px}
|
|
.input-bar{display:flex;gap:8px;padding:12px 16px;border-top:1px solid #1b2130;background:#0d1117}
|
|
.input-bar input{flex:1;padding:12px 16px;background:#06090f;border:1px solid #1b2130;border-radius:10px;color:#f0f6fc;font-size:14px;outline:none}
|
|
.input-bar input:focus{border-color:#58a6ff}
|
|
.input-bar button{padding:12px 20px;background:#58a6ff;border:none;border-radius:10px;color:#0d1117;font-weight:700;font-size:14px;cursor:pointer}
|
|
.input-bar button:hover{background:#79c0ff}
|
|
.input-bar button:disabled{opacity:0.4;cursor:default}
|
|
.thinking{display:flex;align-items:center;gap:8px;color:#58a6ff;font-size:12px;padding:12px}
|
|
.dots span{animation:blink 1.4s infinite both;margin:0 1px}
|
|
.dots span:nth-child(2){animation-delay:0.2s}
|
|
.dots span:nth-child(3){animation-delay:0.4s}
|
|
@keyframes blink{0%,80%,100%{opacity:0.2}40%{opacity:1}}
|
|
.supply-row{display:flex;justify-content:space-between;align-items:center;padding:5px 8px;font-size:12px;border-bottom:1px solid #0d1117}
|
|
.supply-row:last-child{border-bottom:none}
|
|
.supply-role{color:#f0f6fc;font-weight:500}
|
|
.supply-nums{color:#8b949e;font-size:11px}
|
|
.ft{text-align:center;padding:16px;color:#2d333b;font-size:10px}
|
|
@media(max-width:768px){.brief-grid{grid-template-columns:1fr}.msg.user .bubble{max-width:90%}}
|
|
</style></head><body>
|
|
<div class="bar">
|
|
<h1>Staffing Intelligence Console</h1>
|
|
<div class="rt" id="brief-time">Analyzing 500,000 profiles...</div>
|
|
</div>
|
|
<div class="wrap">
|
|
<div id="brief" class="brief-grid"><div style="grid-column:1/-1;text-align:center;padding:40px;color:#484f58">Scanning your entire workforce...</div></div>
|
|
<div class="prompts" id="prompts"></div>
|
|
<div class="chat-box">
|
|
<div class="chat-messages" id="chat"></div>
|
|
<div class="input-bar">
|
|
<input type="text" id="q" placeholder="Ask anything about your workforce..." onkeydown="if(event.key==='Enter'&&!event.shiftKey)send()">
|
|
<button id="send-btn" onclick="send()">Send</button>
|
|
</div>
|
|
</div>
|
|
<div class="ft">Powered by Lakehouse — Hybrid SQL + Vector Search across 500,000 embedded worker profiles</div>
|
|
</div>
|
|
<script>
|
|
var P=location.pathname.replace(/\/console\/?$/,'');
|
|
var A=location.origin+P;
|
|
var AC=['#1a2744','#1a3a2a','#2a1a3a','#3a2a1a','#1a3a3a','#2a2a1a','#3a1a2a','#1a2a3a'];
|
|
var briefData=null;
|
|
|
|
function api(path,body){
|
|
return fetch(A+path,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body||{})}).then(function(r){return r.json()})
|
|
}
|
|
|
|
function el(tag,css,text){var e=document.createElement(tag);if(css)e.style.cssText=css;if(text)e.textContent=text;return e}
|
|
function div(cls,text){var d=document.createElement('div');if(cls)d.className=cls;if(text)d.textContent=text;return d}
|
|
|
|
window.addEventListener('load',loadBrief);
|
|
|
|
function loadBrief(){
|
|
api('/intelligence/brief').then(function(d){
|
|
briefData=d;
|
|
var container=document.getElementById('brief');
|
|
container.textContent='';
|
|
document.getElementById('brief-time').textContent='Analyzed '+(d.pool.total||0).toLocaleString()+' profiles in '+(d.duration_ms||0)+'ms';
|
|
var pool=d.pool;
|
|
var relPct=pool.total?Math.round(pool.reliable/pool.total*100):0;
|
|
var elitePct=pool.total?Math.round(pool.elite/pool.total*100):0;
|
|
|
|
// Card 1: Workforce Pulse
|
|
var c1=makeCard('pulse','WORKFORCE PULSE','Your A-Team',pool.reliable.toLocaleString()+' workers with 80%+ reliability — '+relPct+'% of your pool');
|
|
var bigRow=el('div','display:flex;gap:20px;margin-bottom:12px');
|
|
addBigNum(bigRow,pool.total.toLocaleString(),'Total Workers','#f0f6fc');
|
|
addBigNum(bigRow,relPct+'%','Reliable','#3fb950');
|
|
addBigNum(bigRow,elitePct+'%','Elite (90%+)','#58a6ff');
|
|
c1.appendChild(bigRow);
|
|
if(d.archetypes&&d.archetypes.length){
|
|
var ar=div('arch-row');
|
|
var archColors={reliable:'#3fb950',communicator:'#58a6ff',flexible:'#d29922',leader:'#bc8cff',specialist:'#f0883e',improving:'#79c0ff',erratic:'#f85149',silent:'#484f58'};
|
|
d.archetypes.forEach(function(a){
|
|
var pct=pool.total?Math.round(a.cnt/pool.total*100):0;
|
|
var color=archColors[a.archetype]||'#484f58';
|
|
var pill=el('span','background:'+color+'20;color:'+color+';border:1px solid '+color+'40;padding:3px 10px;border-radius:10px;font-size:11px;font-weight:500',a.archetype+' '+pct+'%');
|
|
pill.className='arch-pill';ar.appendChild(pill);
|
|
});
|
|
c1.appendChild(ar);
|
|
}
|
|
container.appendChild(c1);
|
|
|
|
// Card 2: Geographic Bench
|
|
var c2=makeCard('bench','GEOGRAPHIC BENCH','Where You\'re Strong — and Thin','Reliable worker density by state');
|
|
var sorted=(d.bench||[]).slice().sort(function(a,b){return (b.total?b.reliable/b.total:0)-(a.total?a.reliable/a.total:0)});
|
|
sorted.forEach(function(s){
|
|
var pct=s.total?Math.round(s.reliable/s.total*100):0;
|
|
var color=pct>45?'#3fb950':pct>35?'#d29922':'#f85149';
|
|
var row=div('bench-row');
|
|
row.appendChild(el('span','width:24px;font-weight:600;color:#f0f6fc',s.state));
|
|
var bar=el('div','flex:1;height:14px;background:#161b22;border-radius:4px;overflow:hidden');
|
|
bar.appendChild(el('div','height:100%;border-radius:4px;background:'+color+';width:'+pct+'%;transition:width 0.8s'));
|
|
row.appendChild(bar);
|
|
row.appendChild(el('span','width:40px;text-align:right;font-size:11px;font-weight:600;color:'+color,pct+'%'));
|
|
row.appendChild(el('span','font-size:10px;color:#484f58;width:60px',s.total.toLocaleString()));
|
|
c2.appendChild(row);
|
|
});
|
|
var weakest=sorted[sorted.length-1];
|
|
if(weakest){
|
|
var wpct=weakest.total?Math.round(weakest.reliable/weakest.total*100):0;
|
|
c2.appendChild(makeCallout('Warning: '+weakest.state+' is your thinnest bench at '+wpct+'% reliable. If a client there ramps up, you may struggle to fill.','#1a1500','#854d0e'));
|
|
}
|
|
container.appendChild(c2);
|
|
|
|
// Card 3: Comeback Watch
|
|
if(d.gems&&d.gems.length){
|
|
var c3=makeCard('gems','COMEBACK WATCH',pool.improving.toLocaleString()+' Workers Improving','These workers crossed 80% reliability — they earned a second look');
|
|
d.gems.forEach(function(w){
|
|
addWorkerMini(c3,w.name,w.role+' · '+w.city+', '+w.state,'Reliability: '+Math.round(w.rel*100)+'% rising','#79c0ff','improving');
|
|
});
|
|
c3.appendChild(makeCallout('These workers were previously below threshold. The system detected their improvement automatically — no staffer had to track it.','#0d261a','#238636'));
|
|
container.appendChild(c3);
|
|
}
|
|
|
|
// Card 4: Risk Watch
|
|
if(d.risks&&d.risks.length){
|
|
var c4=makeCard('risk','RISK WATCH',pool.erratic.toLocaleString()+' Erratic + '+pool.silent_cnt.toLocaleString()+' Silent Workers','Low reliability + behavioral flags — review placement priority');
|
|
d.risks.forEach(function(w){
|
|
addWorkerMini(c4,w.name,w.role+' · '+w.city+', '+w.state,'Reliability: '+Math.round(w.rel*100)+'% · Responsiveness: '+Math.round(w.resp*100)+'%','#f85149',w.archetype);
|
|
});
|
|
c4.appendChild(makeCallout('Not firing — deprioritizing. Every failed placement costs time and client trust. The system flags these automatically so you don\'t learn the hard way.','#2d0d0d','#7f1d1d'));
|
|
container.appendChild(c4);
|
|
}
|
|
|
|
// Card 5: Ready & Waiting
|
|
if(d.untapped&&d.untapped.length){
|
|
var c5=makeCard('talent','READY & WAITING','Available + Reliable — Call These First','85%+ reliability and actively available right now');
|
|
d.untapped.forEach(function(w){
|
|
addWorkerMini(c5,w.name,w.role+' · '+w.city+', '+w.state,'Available: '+Math.round(w.avail*100)+'% · Reliable: '+Math.round(w.rel*100)+'%','#bc8cff','ready');
|
|
});
|
|
container.appendChild(c5);
|
|
}
|
|
|
|
// Card 6: Role Supply
|
|
if(d.supply&&d.supply.length){
|
|
var c6=makeCard('supply','ROLE SUPPLY','Workers by Role','Roles with high supply but low availability may indicate scheduling problems');
|
|
d.supply.slice(0,10).forEach(function(r){
|
|
var row=div('supply-row');
|
|
row.appendChild(el('span','color:#f0f6fc;font-weight:500',r.role));
|
|
var nums=el('span','color:#8b949e;font-size:11px');
|
|
nums.appendChild(el('strong','color:#f0f6fc',r.supply.toLocaleString()));
|
|
nums.appendChild(document.createTextNode(' total · '));
|
|
nums.appendChild(el('strong','color:#f0f6fc',r.available.toLocaleString()));
|
|
nums.appendChild(document.createTextNode(' available · rel '+Math.round(r.avg_rel*100)+'%'));
|
|
row.appendChild(nums);c6.appendChild(row);
|
|
});
|
|
container.appendChild(c6);
|
|
}
|
|
setupPrompts(d);
|
|
}).catch(function(e){
|
|
document.getElementById('brief').textContent='Failed to load brief: '+e.message;
|
|
});
|
|
}
|
|
|
|
function makeCard(cls,label,headline,sub){
|
|
var d=div('bcard '+cls);
|
|
d.appendChild(div('label',label));d.appendChild(div('headline',headline));d.appendChild(div('sub',sub));return d;
|
|
}
|
|
function addBigNum(parent,num,label,color){
|
|
var d=el('div','');
|
|
var n=el('div','font-size:36px;font-weight:800;line-height:1;color:'+color,num);
|
|
d.appendChild(n);d.appendChild(el('div','font-size:10px;color:#484f58;margin-top:2px',label));parent.appendChild(d);
|
|
}
|
|
function addWorkerMini(parent,name,detail,extra,color,badge){
|
|
var w=div('wk');
|
|
var av=el('div','width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;color:#f0f6fc;flex-shrink:0;background:'+AC[Math.floor(Math.random()*AC.length)]);
|
|
av.textContent=(name||'').split(' ').map(function(n){return(n[0]||'').toUpperCase()}).slice(0,2).join('');
|
|
var info=div('info');
|
|
info.appendChild(div('nm',name));info.appendChild(div('det',detail));
|
|
if(extra){var ex=div('det');ex.style.color='#58a6ff';ex.textContent=extra;info.appendChild(ex)}
|
|
w.appendChild(av);w.appendChild(info);
|
|
if(badge){var b=el('span','padding:2px 8px;border-radius:8px;font-size:10px;font-weight:600;background:'+(color||'#484f58')+'20;color:'+(color||'#484f58'),badge);w.appendChild(b)}
|
|
parent.appendChild(w);
|
|
}
|
|
function makeCallout(text,bg,border){
|
|
return el('div','font-size:11px;color:#8b949e;margin-top:8px;padding:8px 10px;background:'+(bg||'#0d1117')+';border:1px solid '+(border||'#1b2130')+';border-radius:6px;font-style:italic',text);
|
|
}
|
|
|
|
function setupPrompts(data){
|
|
var container=document.getElementById('prompts');container.textContent='';
|
|
var prompts=[];
|
|
if(data.gems&&data.gems[0])prompts.push('Find someone like '+data.gems[0].name+' but in OH');
|
|
prompts.push('Who could handle industrial electrical work?');
|
|
prompts.push('What if we lose our top 5 forklift operators?');
|
|
prompts.push('Which workers should we stop placing?');
|
|
if(data.supply&&data.supply.length>2){
|
|
var under=data.supply.slice().sort(function(a,b){return (a.available/a.supply)-(b.available/b.supply)})[0];
|
|
if(under)prompts.push('Show me available '+under.role+'s');
|
|
}
|
|
prompts.push('Find me a warehouse worker available today near Nashville');
|
|
prompts.push('Find bilingual workers with leadership skills');
|
|
prompts.forEach(function(p){
|
|
var btn=el('button','',p);btn.className='prompt-btn';
|
|
btn.onclick=function(){document.getElementById('q').value=p;send()};
|
|
container.appendChild(btn);
|
|
});
|
|
}
|
|
|
|
// ─── Chat ───
|
|
function send(){
|
|
var input=document.getElementById('q');
|
|
var q=input.value.trim();if(!q)return;
|
|
input.value='';
|
|
var chat=document.getElementById('chat');
|
|
var userMsg=div('msg user');var bubble=div('bubble',q);userMsg.appendChild(bubble);chat.appendChild(userMsg);
|
|
var thinking=el('div','display:flex;align-items:center;gap:8px;color:#58a6ff;font-size:12px;padding:12px');
|
|
thinking.appendChild(document.createTextNode('Querying 500K profiles'));
|
|
var dots=el('span','');dots.className='dots';
|
|
dots.appendChild(el('span','','.'));dots.appendChild(el('span','','.'));dots.appendChild(el('span','','.'));
|
|
thinking.appendChild(dots);chat.appendChild(thinking);chat.scrollTop=chat.scrollHeight;
|
|
document.getElementById('send-btn').disabled=true;
|
|
|
|
api('/intelligence/chat',{message:q}).then(function(d){
|
|
thinking.remove();document.getElementById('send-btn').disabled=false;
|
|
var msg=div('msg system');var bbl=div('bubble');
|
|
|
|
// Steps
|
|
if(d.queries_run&&d.queries_run.length){
|
|
var steps=div('steps');
|
|
d.queries_run.forEach(function(s){steps.appendChild(el('div','font-size:11px;color:#58a6ff;padding:2px 0','→ '+s))});
|
|
bbl.appendChild(steps);
|
|
}
|
|
bbl.appendChild(div('summary',d.summary||''));
|
|
|
|
// Type-specific rendering
|
|
if(d.type==='similar'&&d.source){
|
|
var sc=div('source-card');
|
|
sc.appendChild(el('div','font-size:10px;color:#d29922;text-transform:uppercase;letter-spacing:1px;margin-bottom:4px','Source Worker'));
|
|
sc.appendChild(el('div','font-weight:700;color:#f0f6fc;font-size:14px',d.source.name));
|
|
sc.appendChild(el('div','font-size:12px;color:#d29922',d.source.role+' · '+d.source.city+', '+d.source.state+' · Reliability: '+Math.round(d.source.rel*100)+'%'));
|
|
sc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:4px','Skills: '+(d.source.skills||'none')+' · Archetype: '+(d.source.archetype||'unknown')));
|
|
bbl.appendChild(sc);
|
|
renderResults(bbl,d.results);
|
|
if(d.sql_matches)bbl.appendChild(el('div','font-size:10px;color:#484f58;margin-top:6px','Filtered pool: '+d.sql_matches.toLocaleString()+' workers'));
|
|
}
|
|
else if(d.type==='discovery'){
|
|
renderResults(bbl,d.results);
|
|
if(d.note)bbl.appendChild(el('div','font-size:11px;color:#8b949e;font-style:italic;margin-top:8px;padding:8px;background:#0d1117;border-radius:6px',d.note));
|
|
}
|
|
else if(d.type==='whatif'){
|
|
var sevColors={HIGH:['#7f1d1d','#fca5a5'],MEDIUM:['#854d0e','#fcd34d'],LOW:['#238636','#86efac']};
|
|
var sc2=sevColors[d.risk_level]||sevColors.MEDIUM;
|
|
var sev=el('span','display:inline-block;padding:3px 10px;border-radius:8px;font-size:11px;font-weight:700;margin-left:8px;background:'+sc2[0]+';color:'+sc2[1],'RISK: '+d.risk_level);
|
|
bbl.querySelector('.summary').appendChild(sev);
|
|
|
|
bbl.appendChild(el('div','font-size:11px;color:#f85149;margin:8px 0 4px;font-weight:600','Workers you\'d lose:'));
|
|
(d.lost||[]).forEach(function(w){
|
|
var rc=div('result-card');rc.style.borderLeft='3px solid #f85149';
|
|
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:13px',w.name));
|
|
rc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:2px',w.role+' · '+w.city+', '+w.state+' · Reliability: '+Math.round(w.rel*100)+'%'));
|
|
bbl.appendChild(rc);
|
|
});
|
|
bbl.appendChild(el('div','font-size:11px;color:#3fb950;margin:12px 0 4px;font-weight:600','Remaining bench: '+d.reliable_remaining+' reliable workers across '+(d.bench||[]).length+' states ('+d.total_in_role+' total in role)'));
|
|
(d.bench||[]).forEach(function(b){
|
|
var row=el('div','display:flex;justify-content:space-between;padding:4px 8px;font-size:12px');
|
|
row.appendChild(el('span','color:#f0f6fc',b.state+' — '+b.total+' total'));
|
|
row.appendChild(el('span','color:'+(b.reliable>5?'#3fb950':'#f85149'),b.reliable+' reliable'));
|
|
bbl.appendChild(row);
|
|
});
|
|
}
|
|
else if(d.type==='risk'){
|
|
(d.results||[]).forEach(function(w){
|
|
var rc=div('result-card');rc.style.borderLeft='3px solid #f85149';
|
|
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:13px',w.name));
|
|
rc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:2px',w.role+' · '+w.city+', '+w.state));
|
|
rc.appendChild(el('div','font-size:10px;color:#f85149;margin-top:4px','Reliability: '+Math.round(w.rel*100)+'% · Responsiveness: '+Math.round(w.resp*100)+'% · Compliance: '+Math.round(w.compl*100)+'% · '+w.archetype));
|
|
bbl.appendChild(rc);
|
|
});
|
|
if(d.total_flagged)bbl.appendChild(el('div','font-size:10px;color:#484f58;margin-top:6px',d.total_flagged.toLocaleString()+' total workers match this risk profile'));
|
|
}
|
|
else if(d.type==='smart_search'){
|
|
// Show what the system understood
|
|
if(d.understood&&d.understood.length){
|
|
var tags=el('div','display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px');
|
|
d.understood.forEach(function(u){
|
|
tags.appendChild(el('span','padding:3px 10px;border-radius:10px;font-size:11px;background:#1a274420;color:#58a6ff;border:1px solid #1a274480',u));
|
|
});
|
|
bbl.appendChild(tags);
|
|
}
|
|
// Show SQL results with zip codes, availability, skills
|
|
if(d.sql_results&&d.sql_results.length){
|
|
d.sql_results.forEach(function(w){
|
|
var rc=div('result-card');
|
|
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:14px',w.name));
|
|
var locParts=[w.role,w.city+', '+w.state];
|
|
if(w.zip)locParts.push('ZIP: '+w.zip);
|
|
rc.appendChild(el('div','font-size:12px;color:#8b949e;margin-top:2px',locParts.join(' · ')));
|
|
// Metrics row
|
|
var metrics=[];
|
|
if(w.avail!==undefined)metrics.push('Available: '+Math.round(w.avail*100)+'%');
|
|
if(w.rel!==undefined)metrics.push('Reliable: '+Math.round(w.rel*100)+'%');
|
|
if(w.archetype)metrics.push(w.archetype);
|
|
if(metrics.length)rc.appendChild(el('div','font-size:11px;color:#58a6ff;margin-top:4px',metrics.join(' · ')));
|
|
// Skills + certs
|
|
if(w.skills||w.certifications){
|
|
var tagRow=el('div','display:flex;gap:4px;flex-wrap:wrap;margin-top:6px');
|
|
if(w.skills)(w.skills||'').split(',').forEach(function(s){s=s.trim();if(s)tagRow.appendChild(el('span','padding:2px 8px;background:#1a2744;color:#58a6ff;border-radius:8px;font-size:10px',s))});
|
|
if(w.certifications)(w.certifications||'').split(',').forEach(function(c){c=c.trim();if(c&&c!=='none')tagRow.appendChild(el('span','padding:2px 8px;background:#1a3a2a;color:#3fb950;border-radius:8px;font-size:10px',c))});
|
|
rc.appendChild(tagRow);
|
|
}
|
|
bbl.appendChild(rc);
|
|
});
|
|
}
|
|
// Also show vector results if different
|
|
if(d.vector_results&&d.vector_results.length&&(!d.sql_results||!d.sql_results.length)){
|
|
renderResults(bbl,d.vector_results);
|
|
}
|
|
}
|
|
else if(d.type==='search'||d.type==='answer'){
|
|
renderResults(bbl,d.results||d.sources||[]);
|
|
}
|
|
else if(d.type==='error'){
|
|
bbl.appendChild(el('div','color:#f85149;font-size:13px',d.summary));
|
|
}
|
|
|
|
if(d.duration_ms){
|
|
var meta=div('meta');
|
|
meta.appendChild(el('span','margin-right:12px',d.duration_ms+'ms'));
|
|
if(d.sql_matches)meta.appendChild(el('span','',d.sql_matches.toLocaleString()+' records scanned'));
|
|
bbl.appendChild(meta);
|
|
}
|
|
msg.appendChild(bbl);chat.appendChild(msg);chat.scrollTop=chat.scrollHeight;
|
|
}).catch(function(e){
|
|
thinking.remove();document.getElementById('send-btn').disabled=false;
|
|
var msg=div('msg system');var bbl=div('bubble');bbl.style.borderColor='#f85149';
|
|
bbl.appendChild(el('div','color:#f85149','Error: '+e.message));
|
|
msg.appendChild(bbl);chat.appendChild(msg);
|
|
});
|
|
}
|
|
|
|
function renderResults(parent,results){
|
|
if(!results||!results.length)return;
|
|
results.forEach(function(r){
|
|
var text=r.text||r.chunk_text||'';
|
|
var parts=text.split(/\u2014|\u2013|\u002D{2,}/);
|
|
var name=parts[0]?parts[0].trim():(r.name||r.doc_id||'Worker');
|
|
var rest=parts[1]?parts[1].trim():'';
|
|
var roleM=rest.match(/^(.+?)\s+in\s+(.+?)\./);
|
|
var skillM=rest.match(/Skills:\s*([^.]+)/);
|
|
var certM=rest.match(/Cert(?:s|ifications)?:\s*([^.]+)/);
|
|
var relM=rest.match(/Reliability:\s*([\d.]+)/);
|
|
var archM=rest.match(/Archetype:\s*(\w+)/);
|
|
|
|
var rc=div('result-card');
|
|
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:13px',name));
|
|
if(roleM)rc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:2px',roleM[1]+' · '+roleM[2]));
|
|
var scoreParts=[];
|
|
if(r.score)scoreParts.push('Match: '+Math.round(r.score*100)+'%');
|
|
if(relM)scoreParts.push('Reliability: '+Math.round(relM[1]*100)+'%');
|
|
if(archM)scoreParts.push(archM[1]);
|
|
if(scoreParts.length)rc.appendChild(el('div','font-size:10px;color:#58a6ff;margin-top:4px',scoreParts.join(' · ')));
|
|
|
|
if(skillM||certM){
|
|
var tags=el('div','display:flex;gap:4px;flex-wrap:wrap;margin-top:6px');
|
|
if(skillM)skillM[1].split(/[|,]/).forEach(function(s){if(s.trim()){tags.appendChild(el('span','padding:2px 8px;background:#1a2744;color:#58a6ff;border-radius:8px;font-size:10px',s.trim()))}});
|
|
if(certM)certM[1].split(/[|,]/).forEach(function(c){if(c.trim()&&c.trim()!=='none'){tags.appendChild(el('span','padding:2px 8px;background:#1a3a2a;color:#3fb950;border-radius:8px;font-size:10px',c.trim()))}});
|
|
rc.appendChild(tags);
|
|
}
|
|
parent.appendChild(rc);
|
|
});
|
|
}
|
|
</script></body></html>
|