Supply Chain KPI Charts :root{–navy:#071b49;–blue:#2454a6;–green:#17a36b;–amber:#f0a51a;–red:#c73535;–muted:#64708d;–line:rgba(7,27,73,.12);–bg:#f5f7fb;–card:#fff;–text:#17233f} *{box-sizing:border-box}body{margin:0;background:var(–bg);color:var(–text);font-family:Inter,Segoe UI,Arial,sans-serif}.wrap{max-width:1280px;margin:auto;padding:18px 24px 24px}.grid{display:grid;gap:16px}.kpis{grid-template-columns:repeat(4,1fr);margin-bottom:16px}.charts{grid-template-columns:1fr 1fr}.card{background:var(–card);border:1px solid var(–line);border-radius:16px;box-shadow:0 8px 22px rgba(7,27,73,.05);overflow:hidden}.kpi{padding:18px;transition:.15s transform,.15s box-shadow;cursor:pointer}.kpi:hover{transform:translateY(-2px);box-shadow:0 12px 26px rgba(7,27,73,.08)}.kpi.active{outline:2px solid var(–blue)}.kpi.primary{background:var(–navy);color:white}.kpiTop{display:flex;justify-content:space-between;align-items:center}.label{font-size:11px;letter-spacing:1.1px;text-transform:uppercase;color:var(–muted);font-family:Consolas,monospace}.primary .label{color:#aec0e6}.icon{width:34px;height:34px;border-radius:10px;background:#eef2f7;display:grid;place-items:center}.primary .icon{background:#153872}.value{font-size:36px;line-height:1;margin:18px 0 8px;font-weight:900;color:var(–navy)}.primary .value{color:white}.note{font-size:12px;color:var(–muted);font-family:Consolas,monospace}.primary .note{color:#cbd7ee}.up{color:var(–green);font-weight:800}.down{color:var(–red);font-weight:800}.head{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:16px 18px;border-bottom:1px solid var(–line)}.head h3{margin:0;color:var(–navy);font-size:14px;text-transform:uppercase;letter-spacing:.7px}.tabs{display:flex;gap:8px;flex-wrap:wrap}.tab{border:1px solid var(–line);background:#fff;border-radius:999px;padding:7px 11px;font-size:12px;cursor:pointer;font-weight:700;color:var(–text)}.tab.active{background:var(–navy);color:white;border-color:var(–navy)}.chartBox{position:relative;padding:14px 18px 18px}canvas{width:100%;height:300px;display:block;cursor:pointer}.tooltip{position:fixed;display:none;background:var(–navy);color:white;padding:9px 10px;border-radius:9px;font-size:12px;pointer-events:none;z-index:10;box-shadow:0 10px 24px rgba(0,0,0,.18);max-width:230px}@media(max-width:950px){.charts{grid-template-columns:1fr}.wrap{padding:14px}}

PO Completion Overview

Hover bars

Completion Trend

const monthly=[ {month:’Jan’,po:980,pack:910,load:840,asn:790},{month:’Feb’,po:1120,pack:1040,load:955,asn:910},{month:’Mar’,po:1260,pack:1185,load:1090,asn:1035},{month:’Apr’,po:1380,pack:1300,load:1215,asn:1160},{month:’May’,po:1510,pack:1435,load:1350,asn:1285},{month:’Jun’,po:1640,pack:1570,load:1490,asn:1420} ]; const latest=monthly.at(-1);let metric=’packRate’;let hoverItems=[];let activeKpi=’po’; const $=id=>document.getElementById(id);const tooltip=$(‘tooltip’); const fmt=n=>n.toLocaleString();const pct=(a,b)=>Math.round(a/b*1000)/10; function kpi(key,label,value,delta,up,primary,icon){return `
${label}${icon}
${value}
${up?’▲’:’▼’} ${delta} vs last month
`} function renderKpis(){ $(‘kpis’).innerHTML=kpi(‘po’,’Total POs’,fmt(latest.po),’8.6%’,true,true,’📄’)+kpi(‘pack’,’Pack Completion’,pct(latest.pack,latest.po)+’%’,’1.2%’,true,false,’📦’)+kpi(‘load’,’Load Completion’,pct(latest.load,latest.po)+’%’,’2.0%’,true,false,’🚚’)+kpi(‘asn’,’ASN Completion’,pct(latest.asn,latest.po)+’%’,’1.6%’,true,false,’✅’); document.querySelectorAll(‘.kpi’).forEach(el=>el.addEventListener(‘click’,()=>{activeKpi=el.dataset.kpi;renderKpis();drawBar()})); } function setupCanvas(canvas){const r=canvas.getBoundingClientRect(),dpr=window.devicePixelRatio||1;canvas.width=r.width*dpr;canvas.height=300*dpr;const ctx=canvas.getContext(‘2d’);ctx.setTransform(dpr,0,0,dpr,0,0);return{ctx,w:r.width,h:300}} function grid(ctx,w,h,l,t,b){ctx.strokeStyle=’rgba(7,27,73,.08)’;ctx.lineWidth=1;for(let i=0;ix.chart!==’bar’);ctx.clearRect(0,0,w,h);const data=[{stage:’PO’,value:latest.po},{stage:’Pack’,value:latest.pack},{stage:’Load’,value:latest.load},{stage:’ASN’,value:latest.asn}],l=48,t=18,b=42,g=28,max=Math.max(…data.map(d=>d.value))*1.15,bw=(w-l-24-g*(data.length-1))/data.length;grid(ctx,w,h,l,t,b);data.forEach((d,i)=>{const x=l+i*(bw+g),bh=d.value/max*(h-b-t),y=h-b-bh;ctx.fillStyle=(activeKpi.toLowerCase()===d.stage.toLowerCase()||activeKpi===’po’&&d.stage===’PO’)?’#071b49′:’#2454a6′;ctx.beginPath();ctx.roundRect(x,y,bw,bh,8);ctx.fill();ctx.fillStyle=’#64708d’;ctx.font=’12px Consolas’;ctx.textAlign=’center’;ctx.fillText(d.stage,x+bw/2,h-15);ctx.fillStyle=’#17233f’;ctx.font=’bold 12px Segoe UI’;ctx.fillText(fmt(d.value),x+bw/2,y-8);hoverItems.push({chart:’bar’,x,y,w:bw,h:bh,text:`${d.stage}
${fmt(d.value)} records`})})} function drawLine(){const c=$(‘lineChart’),{ctx,w,h}=setupCanvas(c);hoverItems=hoverItems.filter(x=>x.chart!==’line’);ctx.clearRect(0,0,w,h);const l=48,t=18,b=42;grid(ctx,w,h,l,t,b);const labels={packRate:’Pack completion’,loadRate:’Load completion’,asnRate:’ASN completion’};const values=monthly.map(d=>metric===’packRate’?pct(d.pack,d.po):metric===’loadRate’?pct(d.load,d.po):pct(d.asn,d.po));const max=100,min=Math.min(…values)-3,color=metric===’packRate’?’#2454a6′:metric===’loadRate’?’#17a36b’:’#c73535′;const pts=values.map((v,i)=>[l+i*(w-l-22)/(values.length-1),t+(max-v)/(max-min)*(h-b-t),v]);ctx.strokeStyle=color;ctx.lineWidth=3;ctx.beginPath();pts.forEach((p,i)=>i?ctx.lineTo(p[0],p[1]):ctx.moveTo(p[0],p[1]));ctx.stroke();pts.forEach((p,i)=>{ctx.fillStyle=color;ctx.beginPath();ctx.arc(p[0],p[1],5,0,Math.PI*2);ctx.fill();ctx.fillStyle=’#64708d’;ctx.font=’11px Consolas’;ctx.textAlign=’center’;ctx.fillText(monthly[i].month,p[0],h-15);hoverItems.push({chart:’line’,x:p[0]-10,y:p[1]-10,w:20,h:20,text:`${monthly[i].month}
${labels[metric]}: ${p[2]}%`})})} function render(){renderKpis();drawBar();drawLine()} function move(e){const r=e.target.getBoundingClientRect(),x=e.clientX-r.left,y=e.clientY-r.top,chart=e.target.id===’barChart’?’bar’:’line’,it=hoverItems.find(i=>i.chart===chart&&x>=i.x&&x=i.y&&y{$(id).addEventListener(‘mousemove’,move);$(id).addEventListener(‘mouseleave’,()=>tooltip.style.display=’none’)});document.querySelectorAll(‘.tab’).forEach(btn=>btn.addEventListener(‘click’,()=>{document.querySelectorAll(‘.tab’).forEach(b=>b.classList.remove(‘active’));btn.classList.add(‘active’);metric=btn.dataset.metric;drawLine()}));window.addEventListener(‘resize’,render);render();
Supply Chain KPI Charts

PO Completion Overview

Hover bars

Completion Trend