PageSourceSearch

https://bliss-it-services.pages.dev/assets/AdminWorkflowPage-C-MXHerk.js

js bliss-it-services.pages.dev collected 2026-10-03 05:39:21 UTC 8,554 bytes, 1 lines download raw bytes

1import{a as i,j as s}from"./three-vendors-DGQpa7F9.js";import{l as C,B as F,L as k,f as W,a as q,b as R,cU as B,cV as V}from"./index-BxOGVMpa.js";function m(o){return o?new Date(o).getTime()<=Date.now():!1}function Q(o){return o?new Date(o).toLocaleDateString("en-US",{month:"short",day:"numeric"}):"Unscheduled"}function p(o){return String(o.salesOwner||o.solutionOwner||o.deliveryOwner||o.supportOwner||o.owner||"").trim()||"Unassigned"}const Y=["New Lead","Contacted","Demo Scheduled","Demo Complete","Qualified","Proposal Draft","Proposal Sent","Client Thinking","Approved","Delivery Active","Paused","Closed Won","Closed Lost"];function G(){const{session:o}=C(),[r,D]=i.useState([]),[d,b]=i.useState([]),[c,A]=i.useState([]),[f,w]=i.useState([]),[U,$]=i.useState([]),[x,u]=i.useState({}),[P,g]=i.useState(!0),[j,v]=i.useState(!1),[N,y]=i.useState(null),h=o?.role==="admin"||o?.role==="staff";i.useEffect(()=>{(async()=>{try{g(!0),y(null);const[e,l,t,a]=await Promise.all([W(),q(),R(),B()]);D(e),b(l),A(t),w(a.data.assignments),$(a.data.users),u(Object.fromEntries(a.data.assignments.map(S=>[S.key,S.userId])))}catch(e){y(e instanceof Error?e.message:"Failed to load workflow.")}finally{g(!1)}})()},[]);const L=i.useMemo(()=>new Map(f.map(n=>[n.key,n])),[f]),E=async()=>{if(h)try{v(!0);const n=await V(x);w(n.data.assignments),u(Object.fromEntries(n.data.assignments.map(e=>[e.key,e.userId])))}catch(n){alert(n instanceof Error?n.message:"Failed to save workflow setup.")}finally{v(!1)}},I=i.useMemo(()=>{const n=r.filter(a=>m(a.nextActionDue??a.nextFollowUp)).length,e=d.filter(a=>m(a.nextActionDue??a.followUpDate)).length,l=c.filter(a=>m(a.nextActionDue??null)).length,t=r.filter(a=>p(a)==="Unassigned").length+d.filter(a=>p(a)==="Unassigned").length+c.filter(a=>p(a)==="Unassigned").length;return[{label:"My leads",value:r.length,detail:`${r.filter(a=>a.status==="Qualified").length} qualified`,icon:"clients",tone:"cyan"},{label:"My proposals",value:d.length,detail:`${d.filter(a=>a.status==="Approved").length} approved`,icon:"book",tone:"gold"},{label:"My delivery queue",value:c.length,detail:`${c.filter(a=>a.handoffStatus==="pending_acceptance").length} handoffs`,icon:"projects",tone:"blue"},{label:"Overdue follow-ups",value:n+e+l,detail:"Due today or past due",icon:"warning",tone:n+e+l>0?"red":"blue"},{label:"Unassigned work",value:t,detail:"Needs an owner",icon:"team",tone
1:t>0?"red":"blue"}]},[c,r,d]),M=i.useMemo(()=>{const n=new Map;return[...r,...d,...c].forEach(e=>{const l=p(e);n.set(l,(n.get(l)||0)+1)}),[...n.entries()].sort((e,l)=>l[1]-e[1]).slice(0,8)},[c,r,d]),_=i.useMemo(()=>[...r.map(e=>({type:"Lead",title:e.name,owner:p(e),next:e.nextAction??e.nextStep,due:e.nextActionDue??e.nextFollowUp,href:`/dashboard/admin/leads/${e.id}`})),...d.map(e=>({type:"Proposal",title:e.title,owner:p(e),next:e.nextAction??e.nextStep,due:e.nextActionDue??e.followUpDate,href:`/dashboard/admin/proposals/${e.id}`})),...c.map(e=>({type:"Delivery",title:e.title,owner:p(e),next:e.nextAction??e.nextStep,due:e.nextActionDue??e.launchDate,href:`/dashboard/admin/engagements/${e.id}`}))].filter(e=>e.next||e.owner==="Unassigned"||m(e.due)).sort((e,l)=>{const t=e.due?new Date(e.due).getTime():Number.POSITIVE_INFINITY,a=l.due?new Date(l.due).getTime():Number.POSITIVE_INFINITY;return t-a}).slice(0,10),[c,r,d]),O=i.useMemo(()=>{const n=new Map(Y.map(e=>[e,{label:e,description:e==="Approved"?"Ready for delivery handoff":e==="Delivery Active"?"Build and launch work":e==="Client Thinking"?"Follow-up required":"Pipeline stage",records:[]}]));for(const e of r)(n.get(e.status)??n.get("New Lead"))?.records.push({id:e.id,type:"Lead",title:e.name,owner:p(e),href:`/dashboard/admin/leads/${e.id}`,next:e.nextAction??e.nextStep});for(const e of d){const l=e.status==="Draft"?"Proposal Draft":e.status;(n.get(l)??n.get("Proposal Draft"))?.records.push({id:e.id,type:"Proposal",title:e.title,owner:p(e),href:`/dashboard/admin/proposals/${e.id}`,next:e.nextAction??e.nextStep})}for(const e of c)(n.get(e.status)??n.get("Delivery Active"))?.records.push({id:e.id,type:"Delivery",title:e.title,owner:p(e),href:`/dashboard/admin/engagements/${e.id}`,next:e.nextAction??e.nextStep});return[...n.values()]},[c,r,d]);if(P)return s.jsx("div",{className:"admin-loading",children:s.jsx("p",{children:"Loading workflow..."})});if(N)return s.jsx("div",{className:"admin-error",children:s.jsx("p",{children:N})});const T=["executive_owner","marketing_director","lead_specialist","account_manager","creative_director","web_developer","support_owner"];return s.jsxs("div",{className:"admin-workflow-page",children:[s.jsx("section",{className:"admin-page-header",children:s.jsxs("div",{children:[s.jsx("p",{className:"eyebrow",children:"Sales to delivery"}),s.jsx("h2",{children:"Workflow"}),s.jsx("p",{className:"admin-page-subtitle",children:"Assigned leads, proposal handoffs, delivery queues, overdue follow-ups, and unassigned work."})]})}),s.jsx("section",{className:"admin-workflow-metrics",children:I.map(n=>s.jsxs("article",{className:`admin-workflow-metric admin-workflow-metric--${n.tone}`,children:[s.jsx("span",{className:"admin-workflow-metric-icon",children:s.jsx(F,{name:n.icon})}),s.jsxs("div",{className:"admin-workflow-metric-copy",children:[s.jsx("span",{children:n.label}),s.jsx("strong",{children:n.value}),s.jsx("small",{children:n.detail})]})]},n.label))}),s.jsxs("section",{className:"admin-panel admin-workflow-pipeline-panel",children:[s.jsx("div",{className:"admin-panel-header",children:s.jsxs("div",{children:[s.jsx("h3",{children:"Pipeline by stage"}),s.jsx("p",{className:"admin-page-subtitle",children:"Move from lead intake to proposal approval, delivery, and closeout."})]})}),s.jsx("div",{className:"admin-workflow-pipeline",children:O.map(n=>s.jsxs("article",{className:"admin-workflow-pipeline-stage",children:[s.jsxs("div",{className:"admin-workflow-pipeline-stage-head",children:[s.jsx("span",{children:n.label}),s.jsx("strong",{children:n.records.length})]}),s.jsx("small",{children:n.description}),s.jsxs("div",{className:"admin-workflow-pipeline-records",children:[n.records.slice(0,4).map(e=>s.jsxs(k,{to:e.href,className:"admin-workflow-pipeline-record",children:[s.jsx("span",{children:e.type}),s.jsx("strong",{children:e.title}),s.jsxs("small",{children:[e.owner,e.next?` • ${e.next}`:""]})]},`${e.type}-${e.id}`)),n.records.length>4&&s.jsxs("span",{className:"admin-workflow-pipeline-more",children:["+",n.records.length-4," more"]})]})]},n.label))})]}),s.jsxs("section",{className:"admin-panel",children:[s.jsxs("div",{className:"admin-panel-header",children:[s.jsxs("div",{children:[s.jsx("h3",{children:"Workflow setup"}),s.jsx("p",{className:"admin-page-subtitle",children:"Assign the default backend office owner for each lane. New leads, proposals, and engagements use these owners automatically."})]}),h&&s.jsx("button",{className:"admin-btn-primary",onClick:()=>void E(),disabled:j,children:j?"Saving...":"Save setup"})]}),s.jsx("div",{className:"admin-workflow-setup-grid",children:T.map(n=>{const e=L.get(n),l=x[n]??"";return s.jsxs("article",{className:"admin-workflow-setup-card",children:[s.jsx("span",{className:"admin-role-badge admin-role-staff",children:e?.title??n}),s.jsx("h4",{children:e?.ownerLabel||"Unassigned"}),s.jsx("p",{children:e?.description}),s.jsxs("select",{className:"admin-select",value:l||"",onChange:t=>u(a=>({...a,[n]:t.target.value||null})),disabled:!h,children:[s.jsx("option",{value:"",children:"Unassigned"}),U.map(t=>s.jsxs("option",{value:t.id,children:[t.name||t.email," (",t.role,t.workflow_role||t.workflowRole?` / ${t.workflow_role||t.workflowRole}`:"",")"]},`${n}-${t.id}`))]})]},n)})})]}),s.jsxs("section",{className:"admin-two-column",children:[s.jsxs("article",{className:"admin-panel",children:[s.jsx("div",{className:"admin-panel-header",children:s.jsx("h3",{children:"Priority queue"})}),s.jsx("div",{className:"admin-list-stack",children:_.map(n=>s.jsxs(k,{to:n.href,className:"admin-list-row",children:[s.jsx("span",{children:n.type}),s.jsx("strong",{children:n.title}),s.jsxs("small",{children:[n.owner," • ",n.next||"Needs next action"," • ",Q(n.due)]})]},`${n.type}-${n.href}`))})]}),s.jsxs("article",{className:"admin-panel",children:[s.jsx("div",{className:"admin-panel-header",children:s.jsx("h3",{children:"Owner load"})}),s.jsx("div",{className:"admin-list-stack",children:M.map(([n,e])=>s.jsxs("div",{className:"admin-list-row",children:[s.jsx("span",{children:n}),s.jsxs("strong",{children:[e," records"]})]},n))})]})]})]})}export{G as default};

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.