PageSourceSearch

https://nrex.ai/assets/admin.analytics-GIkNmn_r.js

js nrex.ai collected 2026-10-05 14:40:23 UTC 6,945 bytes, 1 lines download raw bytes

1import{s as p,j as e}from"./index-C98cF--x.js";import{A as M,S as h,f as _,P as b,a as j,E as S}from"./AdminUI-BIcvd4GG.js";import{g as q}from"./pricing.service-MaG0exzX.js";import{u}from"./use-supabase-query-DpTm7BVj.js";import"./inbox-bLVK3vbt.js";import"./triangle-alert-v66o_bs1.js";async function A(){const{data:n,error:i}=await p.from("contracts").select("id, value, created_at, procurement_request_id").order("created_at",{ascending:!0});if(i)throw new Error(i.message);if(!n||n.length===0)return[];const s=Array.from(new Set(n.map(a=>a.procurement_request_id).filter(Boolean)));let c=new Map;if(s.length>0){const{data:a}=await p.from("line_items").select("procurement_request_id, quantity, unit_price").in("procurement_request_id",s);for(const r of a??[]){const d=r.procurement_request_id;c.set(d,(c.get(d)??0)+Number(r.quantity??0)*Number(r.unit_price??0))}}const l=new Map;for(const a of n){const r=new Date(a.created_at),d=r.toLocaleString("en-US",{month:"short"}),m=`${r.getFullYear()}-${d}`,x=c.get(a.procurement_request_id)??0,f=Math.max(0,x-Number(a.value??0));l.set(m,(l.get(m)??0)+f)}return Array.from(l.entries()).map(([a,r])=>({month:a.split("-")[1],savings:Math.round(r)}))}async function $(){const{data:n,error:i}=await p.from("suppliers").select("id, name, industries, service_areas, trust_score, compliance_score, response_time_hours, capacity").order("trust_score",{ascending:!1}).limit(8);if(i)throw new Error(i.message);return(n??[]).map(s=>({id:s.id,name:s.name,industries:s.industries??[],region:(s.service_areas??[])[0]??"—",trust:Math.round(Number(s.trust_score??0)),compliance:Math.round(Number(s.compliance_score??0)),on_time_pct:Math.round(Number(s.capacity?.on_time_pct??90)),avg_response_h:Number(s.response_time_hours??24)}))}async function B(){const{data:n,error:i}=await p.from("bid_submissions").select("procurement_request_id, price");if(i)throw new Error(i.message);const s=new Map;for(const c of n??[]){const l=s.get(c.procurement_request_id)??[];l.push(Number(c.price)),s.set(c.procurement_request_id,l)}return Array.from(s.entries()).map(([c,l])=>{const a=Math.min(...l),r=Math.max(...l),d=a>0?+((r-a)/a*100).toFixed(2):0;return{request_id:c,min:a,max:r,variance:d,count:l.length}})}async function R(){const{count:n}=await p.from("suppliers").select("id",{count:"exact",head:!0}).eq("status","active");return n??0}function T(){const n=u(()=>A()),i=u(()=>q()),s=u(()=>$()),c=u(()=>B()),l=u(()=>R()),a=n.data??[],r=i.data??[],d=s.data??[],m=c.data??[],x=a.reduce((t,o)=>t+o.savings,0),f=Math.max(...a.map(t=>t.savings),1),N=m.length?m.reduce((t,o)=>t+o.variance,0)/m.length:0,y=r.length?Math.min(...r.flatMap(t=>[t.market,t.fair,t.bids])):0,w=r.length?Math.max(...r.flatMap(t=>[t.market,t.fair,t.bids])):1,k=t=>100-(t-y)/(w-y||1)*100,v=t=>r.length?r.map((o,g)=>`${g===0?"M":"L"}${g/(r.length-1)*100},${k(o[t])}`).join(" "):"";return e.jsxs(M,{eyebrow:"Data intelligence layer",title:"Analytics",subtitle:"Pricing trends, supplier performance, bid variance, and realized savings — computed live from your procurement data.",children:[e.jsxs("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8",children:[e.jsx(h,{label:"Realized savings",value:_(x),accent:"emerald",delta:`${a.length} months`}),e.jsx(h,{label:"Active suppliers",value:String(l.data??0),accent:"blue",delta:"status = active"}),e.jsx(h,{label:"Avg bid variance",value:`${N.toFixed(1)}%`,accent:"gold",delta:`${m.length} requests`}),e.jsx(h,{label:"Tracked requests",value:String(m.length),delta:"with bids"})]}),e.jsxs("div",{className:"grid grid-cols-1 xl:grid-cols-3 gap-6 mb-6",children:[e.jsx("div",{className:"xl:col-span-2",children:e.jsx(b,{title:"Realized savings — by month",children:e.jsx(j,{loading:n.loading,error:n.error,data:a,onRetry:n.refresh,empty:{title:"No completed contracts yet",body:"Once contracts are signed, realized savings vs estimated value will show here."},children:t=>e.jsx("div",{className:"flex items-end gap-3 h-56",children:t.map(o=>e.jsxs("div",{className:"flex-1 flex flex-col items-center gap-2",children:[e.jsx("div",{className:"w-full flex-1 flex items-end",children:e.jsx("div",{className:"w-full rounded-t-md bg-gradient-to-t from-gold/80 to-gold/30 border-t border-gold/60",style:{height:`${o.savings/f*100}%`}})}),e.jsx("div",{className:"text-[10px] uppercase tracking-wider text-muted-foreground",children:o.month}),e.jsx("div",{className:"text-[11px] tabular-nums text-foreground
1/70",children:_(o.savings)})]},o.month))})})})}),e.jsx(b,{title:"Supplier leaderboard",children:e.jsx(j,{loading:s.loading,error:s.error,data:d,onRetry:s.refresh,empty:{title:"No suppliers yet",body:"Onboard suppliers to populate the leaderboard."},children:t=>e.jsx("div",{className:"space-y-2.5",children:t.map((o,g)=>e.jsxs("div",{className:"flex items-center gap-3 rounded-md border border-white/5 bg-white/[0.02] p-2.5",children:[e.jsx("div",{className:"h-8 w-8 rounded-md bg-gold/10 border border-gold/20 text-gold text-xs font-semibold flex items-center justify-center",children:g+1}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-xs font-medium truncate",children:o.name}),e.jsx("div",{className:"text-[10px] text-muted-foreground",children:o.region})]}),e.jsxs("div",{className:"text-right",children:[e.jsx("div",{className:"text-xs font-semibold text-gold tabular-nums",children:o.trust}),e.jsx("div",{className:"text-[10px] text-muted-foreground",children:"trust"})]})]},o.id))})})})]}),e.jsxs(b,{title:"Pricing trend — Market / Fair / Bids",action:e.jsxs("div",{className:"flex gap-3 text-[10px] uppercase tracking-wider",children:[e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"h-2 w-2 rounded-full bg-sky-400"})," Market"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"h-2 w-2 rounded-full bg-gold"})," Fair"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"h-2 w-2 rounded-full bg-emerald-400"})," Bids"]})]}),children:[e.jsx(j,{loading:i.loading,error:i.error,data:r,onRetry:i.refresh,empty:{title:"No pricing history yet",body:"Aggregated pricing_history rows will plot here."},children:()=>e.jsxs("svg",{viewBox:"0 0 100 100",preserveAspectRatio:"none",className:"w-full h-64",children:[[20,40,60,80].map(t=>e.jsx("line",{x1:"0",x2:"100",y1:t,y2:t,stroke:"oklch(1 0 0 / 0.05)",strokeWidth:"0.2"},t)),e.jsx("path",{d:v("market"),stroke:"oklch(0.65 0.15 220)",strokeWidth:"0.6",fill:"none"}),e.jsx("path",{d:v("fair"),stroke:"oklch(0.82 0.13 85)",strokeWidth:"0.8",fill:"none"}),e.jsx("path",{d:v("bids"),stroke:"oklch(0.7 0.15 150)",strokeWidth:"0.6",fill:"none",strokeDasharray:"1.5 1"})]})}),!i.loading&&!i.error&&r.length===0&&e.jsx("div",{className:"mt-2",children:e.jsx(S,{title:"No pricing history yet",body:"As soon as pricing_history rows arrive, the trend will render here."})})]})]})}export{T as component};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.