1import{j as e}from"./vendor-radix-BnNg3BH5.js";import{r as A,d as rt}from"./vendor-react-67mgcWXU.js";import{a as ae,u as Ue,c as We}from"./vendor-query-PMAhJHCS.js";import{C as S,d as R,a as ee,b as te,c as se}from"./card-DpKBVi42.js";import{B as X}from"./badge-Cl7apleB.js";import{P as ye}from"./progress-OXAVVpg3.js";import{d as at,s as P,u as Ke,B as G,a7 as Ge,T as Ie,l as Xe,k as K,m as Ye,w as qe,x as ze,y as He,z as Le,A as he,v as fe,L as it,D as nt,e as ct,f as lt,g as ot,a3 as dt,I as mt,a4 as Oe,G as ut,a6 as ie,U as xt,V as ht,W as ne,Y as ce}from"./index-Epr9psQo.js";import{T as Ne,a as we,b as Q,c as M,d as _e,e as b}from"./table-023rHGnC.js";import{f as pe}from"./formatLabel-C4RR0vUw.js";import{S as pt}from"./save-B2-eOoIe.js";import{C as Je}from"./calendar-Ce69BthR.js";import{T as ke}from"./triangle-alert-C6ISfBPd.js";import{A as Ve}from"./arrow-right-LjC5fuTq.js";import{T as jt}from"./trash-2-EIFrPvgK.js";import{a as Z}from"./addDays-Cy4sUjNt.js";import{d as Fe}from"./differenceInDays-BZV22iX5.js";import{s as me,f as O}from"./format-Bw8okCdv.js";import{M as gt}from"./metric-DK0Tcl4m.js";import{S as ft}from"./switch-ZTMCvIb3.js";import{G as vt}from"./gauge-mfYImdAE.js";import{C as yt}from"./calendar-clock-Dgofoxff.js";import{S as Nt}from"./sparkles-BcySMUTB.js";import{P as wt}from"./plus-DRTmwF2W.js";import{A as _t}from"./arrow-up-right-zF0c4Zfm.js";import{DecisionLog as bt}from"./DecisionLog-DR7W_BU8.js";import{A as kt,b as Dt,a as Mt}from"./avatar-DkXZyfFy.js";import{a as be}from"./addWeeks-QA4EuLDh.js";import{t as Ee}from"./en-US-DJiZ5LCQ.js";import{U as Ze}from"./users-uAR6_Qvs.js";import{C as Ct}from"./chevron-left-D3yfuHpM.js";import{C as et}from"./chevron-right-DQtszqux.js";import{L as Se}from"./layers-ByEfk1Gr.js";import{C as Re}from"./circle-check-Cv8aCTuA.js";import{D as St}from"./dollar-sign-CC-jyV1q.js";import{S as Pt}from"./scale-Cc_B3FHe.js";import{T as Tt}from"./target-CyHaUH9t.js";import"./vendor-supabase-CTlrDMdV.js";import"./vendor-charts-Dck3qfzI.js";import"./vendor-motion-CSzk-Fqg.js";import"./collapsible-CKRfPF8i.js";import"./index-Jdtl9AIN.js";import"./dropdown-menu-Duf4NJvQ.js";import"./circle-CPv7M1K7.js";import"./clock-BYWbH6MV.js";import"./link-2-Bu8oQt2W.js";import"./ellipsis-C6BfvtHH.js";import"./pen-BjcYRxrI.js";import"./message-square-7cL_4-It.js";import"./circle-alert-CFN03ksH.js";import"./vendor-editor-CEJKB4cc.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const Et=at("GripHorizontal",[["circle",{cx:"12",cy:"9",r:"1",key:"124mty"}],["circle",{cx:"19",cy:"9",r:"1",key:"1ruzo2"}],["circle",{cx:"5",cy:"9",r:"1",key:"1a8b28"}],["circle",{cx:"12",cy:"15",r:"1",key:"1e56xg"}],["circle",{cx:"19",cy:"15",r:"1",key:"1a92ep"}],["circle",{cx:"5",cy:"15",r:"1",key:"5r1jwy"}]]);function Rt(i,g){const m=Ee(i.start),p=Ee(i.end);let h=+m>+p;const w=h?me(p,g):me(m,g),v=h?me(m,g):me(p,g);w.setHours(15),v.setHours(15);const y=+v.getTime();let s=w,o=g?.step??1;if(!o)return[];o<0&&(o=-o,h=!h);const n=[];for(;+s<=y;)s.setHours(0),n.push(Ee(s)),s=be(s,o),s.setHours(15);return h?n.reverse():n}const At=new Set(["draft","cancelled","void"]);function Wt(i,g){return ae({queryKey:["program-financials",i,g],queryFn:async()=>{const m=[...g,i],[p,h]=await Promise.all([P.from("time_entries").select(` 7 project_id, 8 hours, 9 actual_minutes, 10 billable_minutes, 11 is_billable, 12 rate_override, 13 invoice_id, 14 profiles!time_entries_user_id_fkey(hourly_rate, profile_financials(hourly_cost)) 15 `).in("project_id",m),P.from("invoices").select("project_id, total_amount, amount_paid, status, paid_at").in("project_id",m)]);if(p.error)throw p.error;if(h.error)throw h.error;const w=new Map,v=s=>{let o=w.get(s);return o||(o={projectId:s,cost:0,billedValue:0,unbilledWip:0,hoursLogged:0,invoiced:0,collected:0},w.set(s,o)),o};for(const s of p.data||[]){if(!s.project_id)continue;const o=v(s.project_id),n=s.profiles,j=n?.profile_financials,_=(Array.isArray(j)?j[0]?.hourly_cost:j?.hourly_cost)||0,l=s.hours||(s.actual_minutes?s.actual_minutes/60:0),f=s.billable_minutes?s.billable_minutes/60:s.is_billable?l:0;o.hoursLogged+=l;const k=s.rate_override||n?.hourly_rate||0;if(o.cost+=l*(_||k*.4),s.is_billable){const x=f*k;o.billedValue+=x,s.invoice_id||(o.unbilledWip+=x)}}for(const s of h.data||[]){if(!s.project_id||At.has(s.status))continue;const o=v(s.project_id);o.invoiced+=s.total_amount||0,o.collected+=s.status==="paid"?s.total_amount||0:s.amount_paid||0}const y={cost:0,billedValue:0,unbilledWip:0,hoursLogged:0,invoiced:0,collected:0};for(const s of w.values())y.cost+=s.cost,y.billedValue+=s.billedValue,y.unbilledWip+=s.unbilledWip,y.hoursLogged+=s.hoursLogged,y.invoiced+=s.invoiced,y.collected+=s.collected;return{perProject:w,totals:y}},enabled:!!i})}function qt(i){if(i.health==="critical")return"critical";const g=i.budget||0,m=Math.min(Math.max(i.completion||0,0),100)/100;return g>0&&i.cost>g?"critical":g>0&&m>.1&&i.cost/m>g*1.15||i.health==="at_risk"?"at_risk":"on_track"}function zt(i){return i.includes("critical")?"critical":i.includes("at_risk")?"at_risk":"on_track"}function Ht(i,g){if(g.length===0)return new Set;const m=new Map(i.map(s=>[s.id,s])),p=new Map;g.forEach(s=>{if(!m.get(s.predecessor_project_id)?.end||!m.get(s.successor_project_id)?.end)return;const o=p.get(s.successor_project_id)||[];o.push(s),p.set(s.successor_project_id,o)});const h=new Map,w=new Set,v=s=>{if(h.has(s))return h.get(s);if(w.has(s))return null;const o=m.get(s);if(!o?.start||!o?.end)return null;w.add(s);const n=Math.max(1,Fe(o.end,o.start));let j={length:n,path:[s]};for(const _ of p.get(s)||[]){const l=v(_.predecessor_project_id);l&&l.length+_.lag_days+n>j.length&&(j={length:l.length+_.lag_days+n,path:[...l.path,s]})}return w.delete(s),h.set(s,j),j};let y=null;for(const s of i){const o=v(s.id);o&&o.path.length>1&&(!y||o.length>y.length)&&(y=o)}return new Set(y?.path||[])}function Lt({childProjects:i,onUpdate:g,programId:m,tenantId:p}){const{toast:h}=Ke(),w=Ue(),[v,y]=A.useState(new Map),[s,o]=A.useState(!1),[n,j]=A.useState(""),[_,l]=A.useState(""),f=A.useRef(null),k=A.useRef(null),[,x]=A.useState(0),{data:H=[]}=ae({queryKey:["program-dependencies",m],queryFn:async()=>{const{data:t,error:u}=await P.from("project_dependencies").select("id, predecessor_project_id, successor_project_id, lag_days").eq("program_id",m);if(u)throw u;return t||[]}}),E=We({mutationFn:async()=>{const{error:t}=await P.from("project_dependencies").insert({tenant_id:p,program_id:m,predecessor_project_id:n,successor_project_id:_});if(t)throw t},onSuccess:()=>{j(""),l(""),w.invalidateQueries({queryKey:["program-dependencies",m]})},onError:t=>
15{h({title:"Failed to add dependency",description:t.message,variant:"destructive"})}}),W=We({mutationFn:async t=>{const{error:u}=await P.from("project_dependencies").delete().eq("id",t);if(u)throw u},onSuccess:()=>w.invalidateQueries({queryKey:["program-dependencies",m]})}),D=i.flatMap(t=>{const u=v.get(t.id),C=u?.start_date||t.start_date,T=u?.end_date||t.end_date;return[C,T].filter(Boolean).map(re=>new Date(re))});if(D.length===0)return e.jsx(S,{children:e.jsx(R,{className:"py-8 text-center text-muted-foreground text-sm",children:"No projects have dates assigned yet."})});const L=new Date(Math.min(...D.map(t=>t.getTime()))),B=new Date(Math.max(...D.map(t=>t.getTime()))),F=Z(L,-14),$=Z(B,14),I=Math.max(1,Fe($,F)),U=t=>Fe(t,F)/I*100,a=[],N=new Date(F.getFullYear(),F.getMonth(),1);for(;N<=$;){const t=U(N);t>=0&&t<=100&&a.push({label:O(N,"MMM yyyy"),leftPct:t}),N.setMonth(N.getMonth()+1)}const q=t=>{const u=v.get(t.id),C=u?.start_date||t.start_date,T=u?.end_date||t.end_date;return{start:C?new Date(C):null,end:T?new Date(T):null}},z=i.map(t=>({id:t.id,...q(t)})),Y=Ht(z,H),J=new Map(i.map(t=>[t.id,t])),je=new Map(i.map((t,u)=>[t.id,u])),ge=new Set(H.filter(t=>{const u=z.find(T=>T.id===t.predecessor_project_id),C=z.find(T=>T.id===t.successor_project_id);return!u?.end||!C?.start?!1:C.start<Z(u.end,t.lag_days)}).map(t=>t.id)),r=(t,u,C)=>{t.preventDefault(),t.stopPropagation();const T=i.find(xe=>xe.id===u);if(!T)return;const{start:re,end:le}=q(T);if(!re||!le)return;f.current={projectId:u,mode:C,startX:t.clientX,originalStart:re,originalEnd:le};const V=xe=>{if(!f.current||!k.current)return;const De=k.current.getBoundingClientRect().width,st=(xe.clientX-f.current.startX)/De*100,Ce=Math.round(st/100*I);let oe=f.current.originalStart,de=f.current.originalEnd;f.current.mode==="move"?(oe=Z(f.current.originalStart,Ce),de=Z(f.current.originalEnd,Ce)):f.current.mode==="resize-start"?(oe=Z(f.current.originalStart,Ce),oe>=de&&(oe=Z(de,-1))):f.current.mode==="resize-end"&&(de=Z(f.current.originalEnd,Ce),de<=oe&&(de=Z(oe,1))),y(Te=>{const Be=new Map(Te);return Be.set(f.current.projectId,{start_date:O(oe,"yyyy-MM-dd"),end_date:O(de,"yyyy-MM-dd")}),Be}),x(Te=>Te+1)},ue=()=>{f.current=null,window.removeEventListener("mousemove",V),window.removeEventListener("mouseup",ue)};window.addEventListener("mousemove",V),window.addEventListener("mouseup",ue)},c=async()=>{if(v.size!==0){o(!0);try{for(const[t,u]of v){const{error:C}=await P.from("projects").update({start_date:u.start_date,end_date:u.end_date}).eq("id",t);if(C)throw C}h({title:`Updated ${v.size} workstream timeline${v.size>1?"s":""}`}),y(new Map),g()}catch(t){console.error("Error saving timeline:",t),h({title:"Error saving changes",variant:"destructive"})}finally{o(!1)}}},d=()=>{y(new Map)};return e.jsxs(S,{children:[e.jsx(ee,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(te,{className:"text-base",children:"Cross-Workstream Timeline"}),e.jsx(se,{children:"Drag bars to adjust workstream dates. Drag edges to resize."})]}),v.size>0&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(X,{variant:"secondary",children:[v.size," unsaved"]}),e.jsx(G,{variant:"outline",size:"sm",onClick:d,children:"Discard"}),e.jsxs(G,{size:"sm",onClick:c,disabled:s,children:[e.jsx(pt,{className:"h-3.5 w-3.5 mr-1.5"}),s?"Saving...":"Save Changes"]})]})]})}),e.jsxs(R,{children:[e.jsx("div",{className:"relative h-6 mb-2 ml-44",ref:k,children:a.map((t,u)=>e.jsx("div",{className:"absolute text-caption text-muted-foreground font-medium border-l border-border pl-1",style:{left:`${t.leftPct}%`,top:0,bottom:0},children:t.label},u))}),e.jsx(Ge,{children:e.jsxs("div",{className:"space-y-2 relative",children:[H.length>0&&e.jsx("svg",{className:"absolute top-0 bottom-0 pointer-events-none z-10",style:{left:"172px",right:"52px",width:"calc(100% - 224px)",height:"100%"},"aria-hidden":"true",children:H.map(t=>
15{const u=je.get(t.predecessor_project_id),C=je.get(t.successor_project_id),T=z.find(Me=>Me.id===t.predecessor_project_id),re=z.find(Me=>Me.id===t.successor_project_id);if(u==null||C==null||!T?.end||!re?.start)return null;const le=Math.min(100,Math.max(0,U(T.end))),V=Math.min(100,Math.max(0,U(re.start))),ue=u*40+16,xe=C*40+16,De=ge.has(t.id);return e.jsxs("g",{className:De?"text-destructive":"text-muted-foreground",children:[e.jsx("line",{x1:`${le}%`,y1:ue,x2:`${V}%`,y2:xe,stroke:"currentColor",strokeWidth:1.5,strokeDasharray:De?"4 2":void 0,opacity:.7}),e.jsx("circle",{cx:`${V}%`,cy:xe,r:3,fill:"currentColor",opacity:.8})]},t.id)})}),i.map(t=>{const{start:u,end:C}=q(t);if(!u||!C)return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-40 shrink-0 text-sm font-medium truncate",children:t.name}),e.jsx("div",{className:"flex-1 h-8 bg-muted/30 rounded flex items-center justify-center",children:e.jsx("span",{className:"text-xs text-muted-foreground",children:"No dates set"})})]},t.id);const T=U(u),re=Math.max(2,U(C)-T),le=v.has(t.id);return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-40 shrink-0 text-sm font-medium truncate",title:t.name,children:t.name}),e.jsxs("div",{className:"flex-1 h-8 bg-muted/30 rounded relative",children:[a.map((V,ue)=>e.jsx("div",{className:"absolute top-0 bottom-0 border-l border-border/30",style:{left:`${V.leftPct}%`}},ue)),e.jsxs(Ie,{children:[e.jsx(Xe,{asChild:!0,children:e.jsxs("div",{className:K("absolute top-1 bottom-1 rounded group","cursor-grab active:cursor-grabbing transition-shadow",le&&"ring-2 ring-primary/50",Y.has(t.id)&&"ring-2 ring-destructive/70",t.health==="critical"?"bg-destructive/60":t.health==="at_risk"?"bg-warning/60":"bg-primary/50"),style:{left:`${T}%`,width:`${re}%`},onMouseDown:V=>r(V,t.id,"move"),children:[e.jsx("div",{className:"absolute left-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-foreground
15/20 rounded-l",onMouseDown:V=>r(V,t.id,"resize-start")}),e.jsx("div",{className:K("h-full rounded",t.health==="critical"?"bg-destructive":t.health==="at_risk"?"bg-warning":"bg-primary"),style:{width:`${t.completion_percentage||0}%`}}),e.jsx("div",{className:"absolute right-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-foreground/20 rounded-r",onMouseDown:V=>r(V,t.id,"resize-end")}),e.jsx("div",{className:"absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-60 transition-opacity pointer-events-none",children:e.jsx(Et,{className:"h-3.5 w-3.5 text-foreground"})})]})}),e.jsx(Ye,{side:"bottom",children:e.jsxs("div",{className:"text-xs space-y-0.5",children:[e.jsx("p",{className:"font-medium",children:t.name}),e.jsxs("p",{className:"flex items-center gap-1",children:[e.jsx(Je,{className:"h-3 w-3"}),O(u,"MMM d, yyyy")," â ",O(C,"MMM d, yyyy")]}),e.jsxs("p",{children:[t.completion_percentage||0,"% complete"]}),Y.has(t.id)&&e.jsx("p",{className:"text-destructive font-medium",children:"On critical path"}),le&&e.jsx("p",{className:"text-primary font-medium",children:"Modified â unsaved"})]})})]})]}),e.jsxs("span",{className:"text-xs text-muted-foreground shrink-0 w-10 text-right",children:[t.completion_percentage||0,"%"]})]},t.id)})]})}),e.jsxs("div",{className:"mt-6 pt-4 border-t space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-sm font-medium",children:"Dependencies"}),Y.size>0&&e.jsxs(X,{variant:"outline",className:"text-destructive border-destructive/40 text-xs",children:["Critical path: ",Array.from(Y).map(t=>J.get(t)?.name).filter(Boolean).join(" â ")]})]}),H.length>0&&e.jsx("div",{className:"space-y-1.5",children:H.map(t=>{const u=ge.has(t.id);return e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[u&&e.jsx(ke,{className:"h-3.5 w-3.5 text-destructive shrink-0"}),e.jsx("span",{className:"truncate",children:J.get(t.predecessor_project_id)?.name||"Unknown"}),e.jsx(Ve,{className:"h-3.5 w-3.5 text-muted-foreground shrink-0"}
15),e.jsx("span",{className:"truncate",children:J.get(t.successor_project_id)?.name||"Unknown"}),u&&e.jsx("span",{className:"text-xs text-destructive",children:"starts before predecessor finishes"}),e.jsx(G,{variant:"ghost",size:"icon",className:"h-6 w-6 ml-auto","aria-label":"Remove dependency",onClick:()=>W.mutate(t.id),children:e.jsx(jt,{className:"h-3.5 w-3.5"})})]},t.id)})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(qe,{value:n,onValueChange:j,children:[e.jsx(ze,{className:"w-48 h-8 text-xs","aria-label":"Predecessor project",children:e.jsx(He,{placeholder:"Predecessorâ¦"})}),e.jsx(Le,{children:i.map(t=>e.jsx(he,{value:t.id,disabled:t.id===_,children:t.name},t.id))})]}),e.jsx(Ve,{className:"h-4 w-4 text-muted-foreground"}),e.jsxs(qe,{value:_,onValueChange:l,children:[e.jsx(ze,{className:"w-48 h-8 text-xs","aria-label":"Successor project",children:e.jsx(He,{placeholder:"Successorâ¦"})}),e.jsx(Le,{children:i.map(t=>e.jsx(he,{value:t.id,disabled:t.id===n,children:t.name},t.id))})]}),e.jsx(G,{size:"sm",variant:"outline",disabled:!n||!_||E.isPending,onClick:()=>E.mutate(),children:"Add Dependency"})]})]}),(()=>{const t=U(new Date);return t<0||t>100?null:e.jsxs("div",{className:"relative ml-44 mt-1",children:[e.jsx("div",{className:"absolute top-0 h-2 w-px bg-destructive",style:{left:`${t}%`}}),e.jsx("div",{className:"absolute top-2 text-caption text-destructive font-medium -translate-x-1/2",style:{left:`${t}%`},children:"Today"})]})})()]})]})}const $e={critical:8,high:5,medium:2,low:1},Ft={high:1.5,medium:1,low:.5},tt=["open","mitigating"],Ut=["open","pending"];function Kt(i,g){const m=$e[i]??$e.medium,p=g?Ft[g]??1:1;return m*p}function Bt(i,g){return(i==="high"||i==="critical")&&tt.includes(g)}function Ot(i){return ae({queryKey:["program-risk-rollup",[...i].sort()],enabled:i.length>0,queryFn:async()=>{const[g,m]=await Promise.all([P.from("project_risks").select("id, project_id, title, description, severity, likelihood, status, mitigation").in("project_id",i).in("status",tt).order("created_at",{ascending:!1}),P.from("decision_points").select("id, project_id, title, status, due_date").in("project_id",i).in("status",Ut).order("due_date",{ascending:!0,nullsFirst:!1})]);if(g.error)throw g.error;if(m.error)throw m.error;const p=new Date().toISOString().slice(0,10),h=(g.data||[]).map(n=>({id:n.id,project_id:n.project_id,title:n.title,description:n.description,severity:n.severity,likelihood:n.likelihood,status:n.status,mitigation:n.mitigation,escalated:Bt(n.severity,n.status)})),w=(m.data||[]).filter(n=>!!n.project_id).map(n=>({id:n.id,project_id:n.project_id,title:n.title,status:n.status,due_date:n.due_date,overdue:!!(n.due_date&&n.due_date<p)})),v=new Map,y=n=>{let j=v.get(n);return j||(j={project_id:n,score:0,openRisks:0,escalatedRisks:0,pendingDecisions:0,overdueDecisions:0},v.set(n,j)),j};for(const n of h){const j=y(n.project_id);j.score+=Kt(n.severity,n.likelihood),j.openRisks+=1,n.escalated&&(j.escalatedRisks+=1)}for(const n of w){const j=y(n.project_id);j.pendingDecisions+=1,n.overdue&&(j.overdueDecisions+=1,j.score+=3)}const s=[...v.values()].sort((n,j)=>j.score-n.score);return{programScore:s.reduce((n,j)=>n+j.score,0),childRisks:h,decisions:w,exposureByProject:s}}})}function Vt({programId:i,tenantId:g,childProjectIds:m,childProjectNames:p}){const{toast:h}=Ke(),w=Ue(),[v,y]=A.useState(!1),[s,o]=A.useState(!1),[n,j]=A.useState(!1),[_,l]=A.useState({title:"",description:"",severity:"medium",mitigation:""}),{data:f=[]}=ae({queryKey:["program-risks",i],queryFn:async()=>{const{data:a,error:N}=await P.from("program_risks").select("*").eq("program_id",i).order("created_at",{ascending:!1});if(N)throw N;return(a||[]).map(q=>({...q,source:"program"}))}}),{data:k=[]}=ae({queryKey:["program-scope-creep-risks",m],queryFn:async()=>{if(m.length===0)return[];const{data:a,error:N}=await P.from("scope_creep_alerts").select("id, project_id, variance_percent, alert_type, acknowledged_at, created_at, task_id").in("project_id",m).is("acknowledged_at",null).order("created_at",{ascending:!1});if(N)throw N;return(a||[]).map(q=>({id:q.id,title:`Scope creep: ${q.variance_percent?.toFixed(0)}% variance on task`,description:`${q.alert_type==="critical"?"Critical":"Warning"} scope creep detected in ${p.get(q.project_id)||"project"}`,severity:q.alert_type==="critical"?"critical":"medium",status:"open",mitigation:null,source:"scope_creep",projectName:p.get(q.project_id)}))},enabled:m.length>0}),{data:x}=Ot(m),H=(x?.childRisks||[]).filter(a=>n||a.escalated).map(a=>
15({id:a.id,title:a.title,description:a.description,severity:a.severity,status:a.status,mitigation:a.mitigation,source:"project",projectName:p.get(a.project_id),escalated:a.escalated})),E=(x?.childRisks||[]).filter(a=>a.escalated).length,W=(x?.childRisks||[]).length-E,D=x?.decisions||[],L=D.filter(a=>a.overdue),B=Math.max(1,...(x?.exposureByProject||[]).map(a=>a.score)),F=[...f.map(a=>({id:a.id,title:a.title,description:a.description,severity:a.severity,status:a.status,mitigation:a.mitigation,source:"program"})),...H,...k],$=async()=>{if(_.title.trim())try{const{error:a}=await P.from("program_risks").insert({program_id:i,tenant_id:g,title:_.title,description:_.description||null,severity:_.severity,mitigation:_.mitigation||null,status:"open"});if(a)throw a;h({title:"Risk added"}),y(!1),l({title:"",description:"",severity:"medium",mitigation:""}),w.invalidateQueries({queryKey:["program-risks",i]})}catch{h({title:"Error adding risk",variant:"destructive"})}},I=async()=>{o(!0);try{const a=m.map(z=>p.get(z)||"Unknown").join(", "),{data:N,error:q}=await P.functions.invoke("generate-program-risks",{body:{programId:i,tenantId:g,projectNames:a,existingRisks:f.map(z=>z.title)}});if(q)throw q;if(N?.risks&&N.risks.length>0){const z=N.risks.map(J=>({program_id:i,tenant_id:g,title:J.title,description:J.description,severity:J.severity||"medium",mitigation:J.mitigation||null,status:"open"})),{error:Y}=await P.from("program_risks").insert(z);if(Y)throw Y;h({title:`${N.risks.length} risks identified by AI`}),w.invalidateQueries({queryKey:["program-risks",i]})}else h({title:"No additional risks identified"})}catch(a){console.error("Error generating risks:",a),h({title:"Error generating risks",description:"Please try again",variant:"destructive"})}finally{o(!1)}},U=a=>a==="critical"||a==="high"?"destructive":a==="medium"?"secondary":"outline";return e.jsxs(e.Fragment,{children:[x&&x.exposureByProject.length>0&&e.jsxs(S,{className:"mb-4",children:[e.jsx(ee,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs(te,{className:"text-base flex items-center gap-2",children:[e.jsx(vt,{className:"h-4 w-4 text-muted-foreground"}),"Program Risk Exposure"]}),e.jsx(se,{children:"Rollup score from active child-project risks (severity à likelihood) and overdue decisions"})]}),e.jsxs("div",{className:"text-right",children:[e.jsx(gt,{size:"md",children:Math.round(x.programScore)}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[E," escalated · ",L.length," overdue decision",L.length!==1?"s":""]})]})]})}),e.jsx(R,{className:"space-y-2",children:x.exposureByProject.map(a=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-sm w-48 truncate",children:p.get(a.project_id)||"Project"}),e.jsx(ye,{value:a.score/B*100,className:"h-2 flex-1"}),e.jsxs("span",{className:"text-xs text-muted-foreground w-32 text-right",children:[Math.round(a.score)," · ",a.openRisks," risk",a.openRisks!==1?"s":"",a.escalatedRisks>0&&e.jsxs("span",{className:"text-destructive",children:[" (",a.escalatedRisks," esc.)"]})]})]},a.project_id))})]}),D.length>0&&e.jsxs(S,{className:"mb-4",children:[e.jsxs(ee,{className:"pb-3",children:[e.jsxs(te,{className:"text-base flex items-center gap-2",children:[e.jsx(yt,{className:"h-4 w-4 text-muted-foreground"}),"Decisions Needing Attention"]}),e.jsxs(se,{children:[D.length," open decision",D.length!==1?"s":""," across child projects",L.length>0&&e.jsxs("span",{className:"text-destructive ml-1",children:["⢠",L.length," overdue"]})]})]}),e.jsxs(R,{className:"space-y-2",children:[D.slice(0,8).map(a=>e.jsxs("div",{className:"flex items-center justify-between gap-3 text-sm",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"truncate font-medium",children:a.title}),e.jsx("p",{className:"text-xs text-muted-foreground",children:p.get(a.project_id)||"Project"})]}),e.jsx("div",{className:"flex items-center gap-2 shrink-0",children:a.due_date&&e.jsxs(X,{variant:a.overdue?"destructive":"outline",className:"text-caption",children:[a.overdue?"Overdue ":"Due ",new Date(a.due_date+"T00:00:00").toLocaleDateString()]})})]},a.id)),D.length>8&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["+",D.length-8," more"]})]})]}),e.jsxs(S,{children:[e.jsx(ee,{children:e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx(te,{className:"text-base",children:"Program Risk Register"}),e.jsxs(se,{children:[F.length," risk",F.length!==1?"s":""," identified",k.length>0&&e.jsxs("span",{className:"text-warning ml-1",children:["⢠",k.length," from scope creep"]}),E>0&&e.jsxs("span",{className:"text-destructive ml-1",children:["⢠",E," escalated from child projects"]})]}),W>0&&e.jsxs("div",{className:"flex items-center gap-2 mt-2",children:[e.jsx(ft,{id:"show-all-child-risks",checked:n,onCheckedChange:j}),e.jsxs(fe,{htmlFor:"show-all-child-risks",className:"text-xs text-muted-foreground cursor-pointer",children:["Show all child-project risks (",W," below escalation threshold)"]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(G,{variant:"outline",size:"sm",onClick:I,disabled:s,children:[s?e.jsx(it,{className:"h-3.5 w-3.5 mr-1.5 animate-spin"}):e.jsx(Nt,{className:"h-3.5 w-3.5 mr-1.5"}),s?"Analyzing...":"AI Identify Risks"]}),e.jsxs(G,{size:"sm",onClick:()=>y(!0),children:[e.jsx(wt,{className:"h-3.5 w-3.5 mr-1.5"}),"Add Risk"]})]})]})}),e.jsx(R,{children:F.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(ke,{className:"h-8 w-8 mx-auto mb-2 opacity-40"}),e.jsx("p",{className:"text-sm",children:"No risks identified yet"}),e.jsx("p",{className:"text-xs mt-1",children:"Use AI to analyze your program for potential risks"})]}):e.jsx("div",{className:"overflow-x-auto -mx-4 px-4 sm:mx-0 sm:px-0",children:e.jsxs(Ne,{children:[e.jsx(we,{children:e.jsxs(Q,{children:[e.jsx(M,{className:"min-w-[180px]",children:"Risk"}),e.jsx(M,{className:"min-w-[80px]",children:"Source"}),e.jsx(M,{className:"min-w-[80px]",children:"Severity"}),e.jsx(M,{className:"min-w-[80px]",children:"Status"}),e.jsx(M,{className:"min-w-[120px]",children:"Mitigation"})]})}),e.jsx(_e,{children:F.map(a=>e.jsxs(Q,{children:[e.jsx(b,{children:e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:a.title}),a.description&&e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 line-clamp-2",children:a.description})]})}),e.jsx(b,{children:e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(X,{variant:"outline",className:"text-caption",children:a.source==="program"?"Program":a.projectName||"Project"}),a.escalated&&e.jsxs(X,{variant:"destructive",className:"text-caption gap-0.5",children:[e.jsx(_t,{className:"h-2.5 w-2.5"}),"Escalated"]})]})}),e.jsx(b,{children:e.jsx(X,{variant:U(a.severity),children:pe(a.severity)})}),e.jsx(b,{children:e.jsx(X,{variant:"secondary",children:pe(a.status)})}),e.jsx(b,{className:"text-sm text-muted-foreground max-w-[200px] truncate",children:a.mitigation||"â"})]},a.id))})]})})})]}),e.jsx(nt,{open:v,onOpenChange:y,children:e.jsxs(ct,{children:[e.jsx(lt,{children:e.jsx(ot,{children:"Add Program Risk"})}),e.jsx(dt,{children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(fe,{children:"Risk Title"}),e.jsx(mt,{value:_.title,onChange:a=>l(N=>({...N,title:a.target.value})),placeholder:"e.g., Resource contention across workstreams"})]}),e.jsxs("div",{children:[e.jsx(fe,{children:"Description"}),e.jsx(Oe,{value:_.description,onChange:a=>l(N=>({...N,description:a.target.value})),placeholder:"Describe the risk and its potential impact...",rows:3})]}),e.jsxs("div",{children:[e.jsx(fe,{children:"Severity"}),e.jsxs(qe,{value:_.severity,onValueChange:a=>l(N=>({...N,severity:a})),children:[e.jsx(ze,{children:e.jsx(He,{})}),e.jsxs(Le,{children:[e.jsx(he,{value:"low",children:"Low"}),e.jsx(he,{value:"medium",children:"Medium"}),e.jsx(he,{value:"high",children:"High"}),e.jsx(he,{value:"critical",children:"Critical"})]})]})]}),e.jsxs("div",{children:[e.jsx(fe,{children:"Mitigation Plan"}),e.jsx(Oe,{value:_.mitigation,onChange:a=>l(N=>({...N,mitigation:a.target.value})),placeholder:"How will this risk be mitigated?",rows:2})]})]})}),e.jsxs(ut,{children:[e.jsx(G,{variant:"outline",onClick:()=>y(!1),children:"Cancel"}),e.jsx(G,{onClick:$,disabled:!_.title.trim(),children:"Add Risk"})]})]})})]})}const ve=8,Qe=40;function $t({projectId:i,programId:g,childProjectIds:m}){const[p,h]=A.useState(()=>me(new Date,{weekStartsOn:1}
15)),[w,v]=A.useState([]),[y,s]=A.useState(!0),o=A.useMemo(()=>Rt({start:p,end:be(p,ve-1)},{weekStartsOn:1}),[p]);A.useEffect(()=>{n()},[i,g,m,p]);const n=async()=>{s(!0);try{const l=m?.length?m:i?[i]:[];if(l.length===0){v([]);return}const{data:f}=await P.from("project_team_members").select("profile_id, hours_per_week, project_id, profiles(full_name, avatar_url, role)").in("project_id",l);if(!f||f.length===0){v([]);return}const k=O(p,"yyyy-MM-dd"),x=O(be(p,ve),"yyyy-MM-dd"),{data:H}=await P.from("time_entries").select("user_id, hours, date").in("project_id",l).gte("date",k).lte("date",x),E=new Map;f.forEach(W=>{const D=W.profile_id,L=E.get(D);if(L)L.capacityPerWeek=Math.max(L.capacityPerWeek,W.hours_per_week||Qe);else{const B=W.profiles;E.set(D,{profileId:D,name:B?.full_name||"Unknown",avatarUrl:B?.avatar_url||null,role:B?.role||null,weeklyHours:new Map,capacityPerWeek:W.hours_per_week||Qe})}o.forEach(B=>{const F=O(B,"yyyy-MM-dd"),$=E.get(D),I=$.weeklyHours.get(F)||{allocated:0,logged:0};I.allocated+=W.hours_per_week||0,$.weeklyHours.set(F,I)})}),(H||[]).forEach(W=>{const D=O(me(new Date(W.date),{weekStartsOn:1}),"yyyy-MM-dd"),L=E.get(W.user_id);if(L){const B=L.weeklyHours.get(D)||{allocated:0,logged:0};B.logged+=W.hours||0,L.weeklyHours.set(D,B)}}),v(Array.from(E.values()).sort((W,D)=>W.name.localeCompare(D.name)))}catch(l){console.error("Error loading workloads:",l)}finally{s(!1)}},j=(l,f)=>{const k=f>0?l/f*100:0;return k>100?"bg-destructive/70":k>80?"bg-warning/70":k>50?"bg-primary/60":k>0?"bg-primary/30":"bg-muted"},_=l=>l.split(" ").map(f=>f[0]).join("").slice(0,2).toUpperCase();return y?e.jsx(S,{children:e.jsx(R,{className:"py-12 text-center",children:e.jsx("div",{className:"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full mx-auto"})})}):w.length===0?e.jsx(S,{children:e.jsxs(R,{className:"py-12 text-center",children:[e.jsx(Ze,{className:"h-10 w-10 mx-auto mb-3 text-muted-foreground/40"}),e.jsx("p",{className:"text-muted-foreground",children:"No team members assigned to track workload"})]})}):e.jsxs(S,{children:[e.jsx(ee,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(te,{className:"text-base",children:"Team Workload"}),e.jsxs(se,{children:[w.length," team members · ",ve," week view"]})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(G,{variant:"ghost",size:"icon",className:"h-8 w-8",onClick:()=>h(be(p,-ve)),"aria-label":"Previous",children:e.jsx(Ct,{className:"h-4 w-4"})}),e.jsx(G,{variant:"outline",size:"sm",onClick:()=>h(me(new Date,{weekStartsOn:1})),children:"Today"}),e.jsx(G,{variant:"ghost",size:"icon",className:"h-8 w-8",onClick:()=>h(be(p,ve)),"aria-label":"Next",children:e.jsx(et,{className:"h-4 w-4"})})]})]})}),e.jsxs(R,{className:"overflow-x-auto",children:[e.jsx(Ge,{children:e.jsxs("table",{className:"w-full border-collapse",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left text-sm font-medium text-muted-foreground p-2 min-w-[200px] sticky left-0 bg-card z-10",children:"Team Member"}),o.map(l=>e.jsxs("th",{className:"text-center text-xs font-medium text-muted-foreground p-2 min-w-[80px]",children:[e.jsx("div",{children:O(l,"MMM d")}),e.jsx("div",{className:"text-caption font-normal",children:O(Z(l,4),"MMM d")})]},O(l,"yyyy-MM-dd")))]})}),e.jsx("tbody",{children:w.map(l=>e.jsxs("tr",{className:"border-t",children:[e.jsx("td",{className:"p-2 sticky left-0 bg-card z-10",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(kt,{className:"h-7 w-7",children:[e.jsx(Dt,{src:l.avatarUrl||void 0}),e.jsx(Mt,{className:"text-xs",children:_(l.name)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:l.name}),l.role&&e.jsx("p",{className:"text-xs text-muted-foreground",children:l.role})]})]})}),o.map(f=>{const k=O(f,"yyyy-MM-dd"),x=l.weeklyHours.get(k)||{allocated:0,logged:0},H=l.capacityPerWeek>0?Math.min(x.allocated/l.capacityPerWeek*100,120):0,E=x.allocated>l.capacityPerWeek;return e.jsx("td",{className:"p-1",children:e.jsxs(Ie,{children:[e.jsx(Xe,{asChild:!0,children:e.jsxs("div",{className:"relative h-10 w-full rounded bg-muted/30",children:[e.jsx("div",{className:K("absolute bottom-0 left-0 right-0 rounded transition-all",j(x.allocated,l.capacityPerWeek)),style:{height:`${Math.min(H,100)}%`}}),E&&e.jsx("div",{className:"absolute top-0 right-0",children:e.jsx(ke,{className:"h-3 w-3 text-destructive"})}),x.allocated>0&&e.jsxs("span",{className:"absolute inset-0 flex items-center justify-center text-caption font-medium",children:[x.allocated,"h"]})]})}),e.jsx(Ye,{children:e.jsxs("div",{className:"text-xs space-y-1",children:[e.jsx("p",{className:"font-medium",children:l.name}),e.jsxs("p",{children:["Week of ",O(f,"MMM d")]}),e.jsxs("p",{children:["Allocated: ",x.allocated,"h / ",l.capacityPerWeek,"h capacity"]}),x.logged>0&&e.jsxs("p",{children:["Logged: ",x.logged.toFixed(1),"h"]}),E&&e.jsxs("p",{className:"text-destructive font-medium",children:["Over-allocated by ",(x.allocated-l.capacityPerWeek).toFixed(0),"h"]})]})})]})},k)})]},l.profileId))})]})}),e.jsxs("div",{className:"flex items-center gap-4 mt-4 text-xs text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"h-3 w-3 rounded bg-primary/30"})," Under 50%"]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"h-3 w-3 rounded bg-primary/60"})," 50-80%"]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"h-3 w-3 rounded bg-warning/70"})," 80-100%"]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("div",{className:"h-3 w-3 rounded bg-destructive/70"})," Over 100%"]})]})]})]})}const Pe={active:{variant:"active",label:"Active"},completed:{variant:"completed",label:"Completed"},on_hold:{variant:"on_hold",label:"On Hold"},not_started:{variant:"draft",label:"Not Started"},in_progress:{variant:"in_progress",label:"In Progress"},cancelled:{variant:"cancelled",label:"Cancelled"}},Ae={excellent:{label:"Excellent",color:"text-success"},good:{label:"On Track",color:"text-success"},on_track:{label:"On Track",color:"text-success"},at_risk:{label:"At Risk",color:"text-warning"},critical:{label:"Critical",color:"text-destructive"}};function Bs({programId:i,programName:g,tenantId:m}){const p=rt(),h=Ue(),{toast:w}=Ke(),[v,y]=A.useState("overview"),{data:s=[],isLoading:o}=ae({queryKey:["program-children",i],queryFn:async()=>{const{data:r,error:c}=await P.from("projects").select("*, clients(name)").eq("parent_project_id",i).order("name");if(c)throw c;return r||[]}}),{data:n=[]}=ae({queryKey:["program-parent-workstreams",i],queryFn:async()=>{const{data:r,error:c}=await P.from("workstreams").select("*").eq("project_id",i).order("sort_order");if(c)throw c;return r||[]},enabled:s.length===0}),j=s.length===0&&n.length>0,_=A.useMemo(()=>s.map(r=>r.id),[s]),l=A.useMemo(()=>{const r=new Map;
15return s.forEach(c=>r.set(c.id,c.name)),r},[s]),{data:f=[]}=ae({queryKey:["program-team",i,s.map(r=>r.id)],queryFn:async()=>{if(s.length===0)return[];const r=s.map(t=>t.id),{data:c,error:d}=await P.from("project_team_members").select("*, profiles(full_name, avatar_url, hourly_rate, weekly_capacity_hours)").in("project_id",r);if(d)throw d;return c||[]},enabled:s.length>0}),{data:k=[]}=ae({queryKey:["program-deliverables",i,s.map(r=>r.id)],queryFn:async()=>{if(s.length===0)return[];const{data:r,error:c}=await P.from("deliverables").select("*, projects(name)").in("project_id",s.map(d=>d.id)).order("due_date");if(c)throw c;return r||[]},enabled:s.length>0}),{data:x}=Wt(i,_),H=s.reduce((r,c)=>r+(c.budget||0),0),E=H>0?s.reduce((r,c)=>r+(c.completion_percentage||0)*(c.budget||0),0)/H:s.length>0?s.reduce((r,c)=>r+(c.completion_percentage||0),0)/s.length:0,W=x?.totals.cost??0,D=x?.totals.invoiced??0,L=x?.totals.collected??0,B=x?.totals.unbilledWip??0,F=D>0?D:x?.totals.billedValue??0,$=F>0?(F-W)/F*100:null,I=A.useMemo(()=>{const r=new Map;return s.forEach(c=>{r.set(c.id,qt({health:c.health,budget:c.budget,cost:x?.perProject.get(c.id)?.cost??0,completion:c.completion_percentage}))}),r},[s,x]),U=zt(Array.from(I.values())),a=s.filter(r=>I.get(r.id)!=="on_track"),N=We({mutationFn:async()=>{for(const r of n){const{data:c,error:d}=await P.from("projects").insert({tenant_id:m,name:r.name,description:r.description,status:r.status||"active",budget:r.budget,start_date:r.start_date,end_date:r.end_date,completion_percentage:r.completion_percentage||0,parent_project_id:i}).select("id").single();if(d)throw d;const{error:t}=await P.from("workstreams").update({project_id:c.id}).eq("id",r.id);if(t)throw t;const{error:u}=await P.from("tasks").update({project_id:c.id}).eq("workstream_id",r.id);if(u)throw u}},onSuccess:()=>{w({title:"Workstreams promoted",description:"Each workstream is now a child project of this program."}),h.invalidateQueries({queryKey:["program-children",i]}),h.invalidateQueries({queryKey:["program-parent-workstreams",i]})},onError:r=>{w({title:"Failed to promote workstreams",description:r.message,variant:"destructive"}),h.invalidateQueries({queryKey:["program-children",i]}),h.invalidateQueries({queryKey:["program-parent-workstreams",i]})}}),q=k.filter(r=>r.due_date&&new Date(r.due_date)<new Date&&r.status!=="approved"&&r.status!=="completed"),z=new Map;f.forEach(r=>{const c=r.profile_id,d=z.get(c);d?(d.projectCount++,d.totalHours+=r.hours_per_week||0):z.set(c,{name:r.profiles?.full_name||"Unknown",avatar:r.profiles?.avatar_url,projectCount:1,totalHours:r.hours_per_week||0})});const Y=s.map(r=>r.start_date).filter(Boolean).sort(),J=s.map(r=>r.end_date).filter(Boolean).sort().reverse(),je=Y[0],ge=J[0];return o?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx("div",{className:"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full"})}):s.length===0&&!j?e.jsx(S,{children:e.jsxs(R,{className:"py-12 text-center",children:[e.jsx(Se,{className:"h-10 w-10 mx-auto mb-3 text-muted-foreground/40"}),e.jsx("p",{className:"text-muted-foreground",children:"No child projects in this program yet."}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:"Create projects with this program as their parent to see the dashboard."})]})}):j?e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"grid gap-3 grid-cols-2 lg:grid-cols-4",children:e.jsx(S,{children:e.jsx(R,{className:"py-4 px-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 shrink-0",children:e.jsx(Se,{className:"h-4 w-4 text-primary"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xl font-bold",children:n.length}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Workstreams"})]})]})})})}),e.jsxs(S,{children:[e.jsx(ee,{children:e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx(te,{className:"text-base",children:"Program Workstreams"}),e.jsx(se,{children:"This program has workstreams but no child projects yet. Promote them to child projects to unlock financial rollups, cross-project timeline, risks, and workload views."})]}),e.jsxs(G,{size:"sm",onClick:()=>N.mutate(),disabled:N.isPending,children:[e.jsx(Se,{className:"h-4 w-4 mr-1.5"}),N.isPending?"Promotingâ¦":"Promote to Child Projects"]})]})}),e.jsxs(Ne,{children:[e.jsx(we,{children:e.jsxs(Q,{children:[e.jsx(M,{children:"Workstream"}),e.jsx(M,{children:"Status"}),e.jsx(M,{className:"text-right",children:"Progress"})]})}),e.jsx(_e,{children:n.map(r=>e.jsxs(Q,{children:[e.jsx(b,{className:"font-medium",children:r.name}),e.jsx(b,{children:e.jsx(X,{variant:Pe[r.status||"not_started"]?.variant||"secondary",children:Pe[r.status||"not_started"]?.label||pe(r.status)})}),e.jsx(b,{className:"text-right",children:e.jsxs("div",{className:"flex items-center gap-2 justify-end",children:[e.jsx(ye,{value:r.completion_percentage||0,className:"h-1.5 w-16"}),e.jsxs("span",{className:"text-xs",children:[r.completion_percentage||0,"%"]})]})})]},r.id))})]})]})]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"grid gap-3 grid-cols-2 lg:grid-cols-5",children:[e.jsx(S,{children:e.jsx(R,{className:"py-4 px-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 shrink-0",children:e.jsx(Se,{className:"h-4 w-4 text-primary"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xl font-bold",children:s.length}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Projects"})]})]})})}),e.jsx(S,{children:e.jsx(R,{className:"py-4 px-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 shrink-0",children:e.jsx(Re,{className:"h-4 w-4 text-primary"})}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-xl font-bold",children:[E.toFixed(0),"%"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Avg Progress"})]})]})})}),e.jsx(S,{children:e.jsx(R,{className:"py-4 px-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 shrink-0",children:e.jsx(Ze,{className:"h-4 w-4 text-primary"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xl font-bold",children:z.size}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Team Members"})]})]})})}),e.jsx(S,{children:e.jsx(R,{className:"py-4 px-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:K("flex h-9 w-9 items-center justify-center rounded-lg shrink-0",U==="on_track"?"bg-success/10":U==="at_risk"?"bg-warning/10":"bg-destructive/10"),children:U==="on_track"?e.jsx(Re,{className:"h-4 w-4 text-success"}):e.jsx(ke,{className:K("h-4 w-4",U==="at_risk"?"text-warning":"text-destructive")}
15)}),e.jsxs("div",{children:[e.jsx("p",{className:K("text-xl font-bold",U==="on_track"?"text-success":U==="at_risk"?"text-warning":"text-destructive"),children:Ae[U]?.label}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Program Health"})]})]})})}),e.jsx(S,{children:e.jsx(R,{className:"py-4 px-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:K("flex h-9 w-9 items-center justify-center rounded-lg shrink-0",a.length>0?"bg-destructive/10":"bg-success/10"),children:a.length>0?e.jsx(ke,{className:"h-4 w-4 text-destructive"}):e.jsx(Re,{className:"h-4 w-4 text-success"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xl font-bold",children:a.length}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"At Risk"})]})]})})})]}),e.jsxs(S,{children:[e.jsxs(ee,{className:"pb-2",children:[e.jsxs(te,{className:"text-base flex items-center gap-2",children:[e.jsx(St,{className:"h-4 w-4"}),"Program P&L"]}),e.jsx(se,{children:"Live rollup from time entries and invoices across all child projects"})]}),e.jsx(R,{children:e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-lg font-semibold",children:ie(H)}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Budget"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-lg font-semibold",children:ie(D)}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Invoiced"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-lg font-semibold",children:ie(L)}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Collected"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-lg font-semibold",children:ie(B)}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Unbilled WIP"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-lg font-semibold",children:ie(W)}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Cost to Date"})]}),e.jsxs("div",{children:[e.jsx("p",{className:K("text-lg font-semibold",$!=null&&$<0&&"text-destructive"),children:$!=null?`${Math.round($)}%`:"â"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Margin"})]})]})})]}),je&&ge&&e.jsx(S,{children:e.jsxs(R,{className:"py-3 px-4",children:[e.jsxs("div",{className:"flex items-center justify-between text-sm mb-2",children:[e.jsxs("span",{className:"text-muted-foreground flex items-center gap-1.5",children:[e.jsx(Je,{className:"h-3.5 w-3.5"}),new Date(je).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})]}),e.jsxs("span",{className:"font-medium",children:[E.toFixed(0),"% Complete"]}),e.jsx("span",{className:"text-muted-foreground",children:new Date(ge).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})})]}),e.jsx(ye,{value:E,className:"h-2"})]})}),e.jsxs(xt,{value:v,onValueChange:y,children:[e.jsxs(ht,{children:[e.jsx(ne,{value:"overview",children:"Project Status"}),e.jsx(ne,{value:"milestones",children:"Milestones"}),e.jsx(ne,{value:"timeline",children:"Timeline"}),e.jsx(ne,{value:"team",children:"Team Allocation"}),e.jsx(ne,{value:"workload",children:"Workload"}),e.jsx(ne,{value:"deliverables",children:"Deliverables"}),e.jsx(ne,{value:"risks",children:"Risks"}),e.jsxs(ne,{value:"decisions",children:[e.jsx(Pt,{className:"h-3.5 w-3.5 mr-1.5"}),"Decisions"]})]}),e.jsx(ce,{value:"overview",className:"mt-4",children:e.jsx(S,{children:e.jsxs(Ne,{children:[e.jsx(we,{children:e.jsxs(Q,{children:[e.jsx(M,{children:"Project"}),e.jsx(M,{children:"Status"}),e.jsx(M,{children:"Health"}),e.jsx(M,{className:"text-right",children:"Budget"}),e.jsx(M,{className:"text-right",children:"Cost"}),e.jsx(M,{className:"text-right",children:"Invoiced"}),e.jsx(M,{className:"text-right",children:"Progress"}),e.jsx(M,{children:"Due Date"}),e.jsx(M,{className:"w-10"})]})}),e.jsx(_e,{children:s.map(r=>e.jsxs(Q,{className:"cursor-pointer hover:bg-muted/50",onClick:()=>p(`/projects/${r.id}`),children:[e.jsx(b,{className:"font-medium",children:r.name}),e.jsx(b,{children:e.jsx(X,{variant:Pe[r.status||"active"]?.variant||"secondary",children:Pe[r.status||"active"]?.label||pe(r.status)})}),e.jsx(b,{children:(()=>{const c=I.get(r.id)||"on_track";return e.jsx("span",{className:K("text-sm font-medium",Ae[c]?.color||"text-muted-foreground"),children:Ae[c]?.label||pe(c)})})()}),e.jsx(b,{className:"text-right",children:ie(r.budget||0)}),e.jsx(b,{className:K("text-right",(r.budget||0)>0&&(x?.perProject.get(r.id)?.cost??0)>(r.budget||0)&&"text-destructive font-medium"),children:ie(x?.perProject.get(r.id)?.cost??0)}),e.jsx(b,{className:"text-right",children:ie(x?.perProject.get(r.id)?.invoiced??0)}),e.jsx(b,{className:"text-right",children:e.jsxs("div",{className:"flex items-center gap-2 justify-end",children:[e.jsx(ye,{value:r.completion_percentage||0,className:"h-1.5 w-16"}),e.jsxs("span",{className:"text-xs",children:[r.completion_percentage||0,"%"]})]})}),e.jsx(b,{className:"text-muted-foreground text-sm",children:r.end_date?new Date(r.end_date).toLocaleDateString("en-US",{month:"short",day:"numeric"}):"â"}),e.jsx(b,{children:e.jsx(et,{className:"h-4 w-4 text-muted-foreground"})})]},r.id))})]})})}),e.jsx(ce,{value:"milestones",className:"mt-4",children:e.jsxs(S,{children:[e.jsxs(ee,{children:[e.jsx(te,{className:"text-base",children:"Program Milestones"}),e.jsxs(se,{children:["Key milestones aggregated across ",s.length," projects"]})]}),e.jsx(R,{children:(()=>{const r=[];if(k.forEach(d=>{d.due_date&&r.push({name:d.title||d.name||"Unnamed",dueDate:d.due_date,projectName:d.projects?.name||"Unknown",status:d.status||"draft",type:"deliverable"})}
15),s.forEach(d=>{d.end_date&&r.push({name:`${d.name} â Completion`,dueDate:d.end_date,projectName:d.name,status:d.status==="completed"?"completed":(d.completion_percentage||0)>=90?"in_progress":"not_started",type:"project_completion"})}),r.sort((d,t)=>new Date(d.dueDate).getTime()-new Date(t.dueDate).getTime()),r.length===0)return e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Tt,{className:"h-8 w-8 mx-auto mb-2 opacity-40"}),e.jsx("p",{children:"No milestones found across child projects"})]});const c=new Date;return e.jsx("div",{className:"space-y-3",children:r.map((d,t)=>{const u=new Date(d.dueDate),C=u<c&&d.status!=="completed"&&d.status!=="approved",T=d.status==="completed"||d.status==="approved";return e.jsxs("div",{className:K("flex items-center gap-3 p-3 rounded-lg border",C&&"border-destructive/30 bg-destructive/5",T&&"border-success/30 bg-success/5",!C&&!T&&"border-border"),children:[e.jsx("div",{className:K("h-3 w-3 rounded-full shrink-0",T?"bg-success":C?"bg-destructive":"bg-primary")}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm truncate",children:d.name}),e.jsx("p",{className:"text-xs text-muted-foreground",children:d.projectName})]}),e.jsx(X,{variant:d.type==="project_completion"?"secondary":"outline",className:"text-xs shrink-0",children:d.type==="project_completion"?"Project":"Deliverable"}),e.jsx("span",{className:K("text-sm shrink-0",C?"text-destructive font-medium":"text-muted-foreground"),children:u.toLocaleDateString("en-US",{month:"short",day:"numeric"})})]},t)})})})()})]})}),e.jsx(ce,{value:"timeline",className:"mt-4",children:e.jsx(Lt,{childProjects:s,programId:i,tenantId:m,onUpdate:()=>h.invalidateQueries({queryKey:["program-children",i]})})}),e.jsx(ce,{value:"team",className:"mt-4",children:e.jsxs(S,{children:[e.jsxs(ee,{children:[e.jsx(te,{className:"text-base",children:"Team Allocation Across Projects"}),e.jsxs(se,{children:[z.size," members allocated across ",s.length," projects"]})]}),e.jsx(R,{children:e.jsxs(Ne,{children:[e.jsx(we,{children:e.jsxs(Q,{children:[e.jsx(M,{children:"Team Member"}),e.jsx(M,{className:"text-right",children:"Projects"}),e.jsx(M,{className:"text-right",children:"Total Hrs/Wk"}),e.jsx(M,{children:"Utilization"})]})}),e.jsxs(_e,{children:[Array.from(z.entries()).map(([r,c])=>{const d=c.totalHours>0?Math.min(100,c.totalHours/40*100):0;return e.jsxs(Q,{children:[e.jsx(b,{className:"font-medium",children:c.name}),e.jsx(b,{className:"text-right",children:c.projectCount}),e.jsxs(b,{className:"text-right",children:[c.totalHours,"h"]}),e.jsx(b,{children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ye,{value:d,className:K("h-1.5 w-20",d>100&&"[&>div]:bg-destructive")}
15),e.jsxs("span",{className:K("text-xs",d>100?"text-destructive font-medium":"text-muted-foreground"),children:[d.toFixed(0),"%"]})]})})]},r)}),z.size===0&&e.jsx(Q,{children:e.jsx(b,{colSpan:4,className:"text-center py-8 text-muted-foreground",children:"No team members assigned yet"})})]})]})})]})}),e.jsx(ce,{value:"workload",className:"mt-4",children:e.jsx($t,{programId:i,childProjectIds:s.map(r=>r.id)})}),e.jsx(ce,{value:"deliverables",className:"mt-4",children:e.jsxs(S,{children:[e.jsx(ee,{children:e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{children:[e.jsx(te,{className:"text-base",children:"Program Deliverables"}),e.jsxs(se,{children:[k.length," deliverables across all projects",q.length>0&&e.jsxs("span",{className:"text-destructive ml-2",children:["⢠",q.length," overdue"]})]})]})})}),e.jsx(R,{children:e.jsxs(Ne,{children:[e.jsx(we,{children:e.jsxs(Q,{children:[e.jsx(M,{children:"Deliverable"}),e.jsx(M,{children:"Project"}),e.jsx(M,{children:"Status"}),e.jsx(M,{children:"Due Date"})]})}),e.jsxs(_e,{children:[k.map(r=>{const c=r.due_date&&new Date(r.due_date)<new Date&&r.status!=="approved"&&r.status!=="completed";return e.jsxs(Q,{children:[e.jsx(b,{className:"font-medium",children:r.title}),e.jsx(b,{className:"text-muted-foreground text-sm",children:r.projects?.name||"â"}),e.jsx(b,{children:e.jsx(X,{variant:"secondary",children:pe(r.status)})}),e.jsxs(b,{className:K("text-sm",c?"text-destructive font-medium":"text-muted-foreground"),children:[r.due_date?new Date(r.due_date).toLocaleDateString("en-US",{month:"short",day:"numeric"}):"â",c&&" (Overdue)"]})]},r.id)}),k.length===0&&e.jsx(Q,{children:e.jsx(b,{colSpan:4,className:"text-center py-8 text-muted-foreground",children:"No deliverables found across projects"})})]})]})})]})}),e.jsx(ce,{value:"risks",className:"mt-4",children:e.jsx(Vt,{programId:i,tenantId:m,childProjectIds:_,childProjectNames:l})}),e.jsx(ce,{value:"decisions",className:"mt-4",children:e.jsx(bt,{projectId:i,childProjectIds:_})})]})]})}export{Bs as ProgramDashboard};
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.