hanoman 0.9.7 → 0.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +556 -117
  3. package/dist/server.js +1365 -482
  4. package/package.json +1 -1
  5. package/prisma/migrations/20260925120000_spec_project_notification_created_idx/migration.sql +6 -0
  6. package/prisma/schema.prisma +8 -0
  7. package/web/assets/{ChangelogScreen-C-C71Zn_.js → ChangelogScreen-BzuBQwxY.js} +1 -1
  8. package/web/assets/{DalangHanomanScreen-Go6ETy3r.js → DalangHanomanScreen-6Z1RoINb.js} +1 -1
  9. package/web/assets/{DocPreviewModal-CZ4rZ_h-.js → DocPreviewModal-CIDz4ZzG.js} +1 -1
  10. package/web/assets/{DocsWorkspace-BDfP0ML1.js → DocsWorkspace-CQ_EsxYz.js} +1 -1
  11. package/web/assets/{IdeScreen-DFRme37j.js → IdeScreen-C0dHzGLc.js} +1 -1
  12. package/web/assets/{LeadScreen-ASzNKRLX.js → LeadScreen-BHU9MYR1.js} +1 -1
  13. package/web/assets/{ReviewScreen-CyFWhxL1.js → ReviewScreen-DZi2r33C.js} +1 -1
  14. package/web/assets/SchedulerScreen-B5IdNK-B.js +1 -0
  15. package/web/assets/{SettingsScreen-siSgzEnH.js → SettingsScreen-CCGup_hQ.js} +1 -1
  16. package/web/assets/{TeamScreen-DzKZHKyR.js → TeamScreen-DV6IwXuC.js} +1 -1
  17. package/web/assets/{TerminalScreen-mLiyHYQV.js → TerminalScreen-DFnBKKa2.js} +1 -1
  18. package/web/assets/{TriageScreen-D5iyoK-3.js → TriageScreen-DoHczdu8.js} +1 -1
  19. package/web/assets/{VpsScreen-BhjULQaT.js → VpsScreen-CghVzou6.js} +1 -1
  20. package/web/assets/index-B3niUZnk.js +1014 -0
  21. package/web/assets/{live-Jy46oHWQ.js → live-fPTkukus.js} +1 -1
  22. package/web/index.html +1 -1
  23. package/web/assets/SchedulerScreen-Bii5m-K1.js +0 -1
  24. package/web/assets/index-CCJTT5hd.js +0 -1005
@@ -1 +1 @@
1
- import{h as E,e as b,t as se,q as ne,j as e,f as H,aq as L,B as m,a as u,I as ie,S as Y,R as le,x as J,p as re,d as $,w as oe,D as ce,ar as de,aC as ue}from"./index-CCJTT5hd.js";import{R as c}from"./react-DfGhg7ZW.js";import{L as pe}from"./live-Jy46oHWQ.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const me=5e3,z=20;function U({total:a,page:r,onPage:s,unit:o}){const n=ce(a,r,z);return e.jsx(oe,{page:n.page,pageCount:n.pageCount,total:a,from:n.from,to:n.to,onPage:s,unit:o})}function Q(a,r=Date.now()){if(!a)return"—";const s=Math.max(0,r-new Date(a).getTime()),o=Math.floor(s/6e4);if(o<1)return"baru saja";if(o<60)return`${o}m`;const n=Math.floor(o/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const xe={tinggi:"ok",sedang:"neutral",ragu:"warn"},ge={berlaku:"ok",ditimpa:"warn",dibatalkan:"neutral",gagal:"err"},he={answer:"jawaban",order:"urutan kerja",collision:"tabrakan area",quality:"mutu hasil",refusal:"tindakan ditolak"},je={contract:"kontrak",detected:"deteksi otomatis",pulse:"denyut"},be={menunggu:"warn",sebagian:"info",selesai:"ok",dibatalkan:"neutral"},ke=new Set(["menunggu","sebagian"]),fe={tunggal:"sekali jalan",submit:"di-submit",operator:"dibatalkan operator",kedaluwarsa:"kedaluwarsa"};function q({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function ve({title:a,count:r,empty:s,children:o}){return e.jsx(L,{eyebrow:`lead · ${a.toLowerCase()}`,title:`${a} (${r})`,children:r===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:s}):o})}function ye({cfg:a,onWrite:r,busy:s}){var n;const o=(i,p)=>Math.max(p,Number(i)||p);return e.jsxs(L,{eyebrow:"lead · kendali",title:"hanoman-lead",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:12},children:[e.jsx(m,{tone:a.enabled?a.paused?"warn":"ok":"neutral",children:a.enabled?a.paused?"dijeda":"aktif":"mati"}),a.enabled?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:s,onClick:()=>r({...a,enabled:!1,paused:!1}),children:"Matikan"}):e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,enabled:!0}),children:"Nyalakan"}),a.enabled&&(a.paused?e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,paused:!1}),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:s,onClick:()=>r({...a,paused:!0}),children:"Pause"}))]}),e.jsxs("div",{style:{display:"flex",gap:14,flexWrap:"wrap",alignItems:"center"},children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["denyut tiap",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"denyut lead (menit)",placeholder:"5",value:String(a.everyMin),disabled:s,onChange:i=>r({...a,everyMin:o(i.target.value,1)})}),"menit"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["batas waktu putusan",e.jsx($,{type:"number",min:10,style:{width:84},"aria-label":"batas waktu putusan (detik)",placeholder:"600",value:String(a.timeoutSec),disabled:s,onChange:i=>r({...a,timeoutSec:o(i.target.value,10)})}),"detik"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["maks jawaban otomatis/sesi",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"maksimum jawaban otomatis per sesi",placeholder:"3",value:String(a.maxAutoAnswers),disabled:s,onChange:i=>r({...a,maxAutoAnswers:o(i.target.value,1)})})]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["syarat sebelum integrasi ke main",e.jsx(Y,{size:"sm","aria-label":"syarat sebelum integrasi ke main",value:a.requireGreenBeforeIntegrate?"wajib":"bebas",disabled:s,onChange:i=>r({...a,requireGreenBeforeIntegrate:i.target.value==="wajib"}),options:[{value:"wajib",label:"plan tuntas"},{value:"bebas",label:"tanpa syarat"}]})]})]}),e.jsxs("div",{"data-testid":"lead-engine-line",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:10},children:["mesin: ",(n=a.engine)!=null&&n.enabled?e.jsxs(e.Fragment,{children:[a.engine.agent==="codex"?"Codex CLI":"Claude Code"," · ",e.jsx("code",{children:a.engine.model})," · ",e.jsx("code",{children:a.engine.effort})]}):e.jsx(e.Fragment,{children:"ikut default global · atur di Settings → Model sesi"})]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:6},children:"Lead memutuskan lalu melapor. Produksi/VPS dan penghapusan data terkunci secara teknis — apa pun setelannya."})]})}function we({options:a,multi:r,value:s,onChange:o}){const n=i=>{if(!r){o([i]);return}o(s.includes(i)?s.filter(p=>p!==i):[...s,i])};return e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:6},children:a.map(i=>r?e.jsx(de,{checked:s.includes(i),label:i,onChange:()=>n(i)},i):e.jsx(ue,{checked:s.includes(i),label:i,onChange:()=>n(i)},i))})}function Se({d:a,onOverride:r,onCancel:s,busyId:o}){var C;const[n,i]=c.useState(!1),[p,w]=c.useState(""),[v,S]=c.useState([]),h=(a.choices??[]).length>0?a.choices:a.choiceIndex!=null&&a.choice?[{index:a.choiceIndex,option:a.choice}]:[],k=a.options??[],y=((C=a.select)==null?void 0:C.mode)==="multi";return e.jsxs("div",{style:{padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[e.jsx(m,{tone:ge[a.status]??"neutral",size:"sm",children:a.status}),e.jsx(m,{tone:xe[a.confidence]??"neutral",size:"sm",children:a.confidence}),e.jsx(m,{tone:"neutral",size:"sm",children:he[a.kind]??a.kind}),e.jsx(m,{tone:"neutral",size:"sm",children:je[a.gate]??a.gate}),a.weighty&&e.jsx(m,{tone:"warn",size:"sm",children:"berbobot"}),h.length>0&&k.length>0&&e.jsx(m,{tone:"brass",size:"sm",children:h.length>1?`${h.length} dari ${k.length} opsi`:`opsi ${h[0].index}/${k.length}`}),(a.missing??[]).length>0&&e.jsx(m,{tone:"warn",size:"sm",children:"kurang konteks"}),e.jsx("span",{style:{flex:1}}),e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:Q(a.createdAt)})]}),e.jsx("div",{style:{marginTop:6,fontSize:"var(--text-sm)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.question.slice(0,400)}),e.jsx("div",{style:{marginTop:4,color:"var(--text-strong)",fontWeight:500,whiteSpace:"pre-wrap"},children:h.length?h.map(j=>j.option).join(" · "):a.answer||e.jsx("em",{style:{fontWeight:400,color:"var(--text-muted)"},children:"tak ada jawaban"})}),e.jsx("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.reason}),a.refs.length>0&&e.jsx("div",{style:{marginTop:6,display:"flex",gap:6,flexWrap:"wrap"},children:a.refs.map(j=>e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-muted)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"1px 6px"},children:j},j))}),(a.missing??[]).length>0&&e.jsxs("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["Yang kurang: ",a.missing.join(" · ")]}),e.jsxs("div",{style:{marginTop:8,display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:[a.projectId,a.specId?` · ${a.specId}`:"",a.sessionId?` · ${a.sessionId}`:"",a.action!=="none"?` · ${a.action}`:""]}),e.jsx("span",{style:{flex:1}}),a.status==="berlaku"&&!n&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"edit-3",onClick:()=>i(!0),children:"Timpa"}),a.status==="berlaku"&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:o===a.id,onClick:()=>s(a.id),children:"Batalkan"})]}),n&&e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[k.length>0&&e.jsx(we,{options:k,multi:y,value:v,onChange:S}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx($,{style:{flex:1},"aria-label":`jawaban operator untuk ${a.id}`,placeholder:"mis. pilih opsi 2, pakai Node 22",value:p,onChange:j=>w(j.target.value)}),e.jsx(u,{size:"sm",leftIcon:"check",disabled:!p.trim()&&v.length===0||o===a.id,onClick:()=>{r(a.id,p.trim()||v.join("; "),v),i(!1),w(""),S([])},children:"Simpan"})]})]})]})}function Be({projects:a,onProjectChanged:r,onToast:s,onGotoTerminal:o}){const[n,i]=c.useState(null),[p,w]=c.useState([]),[v,S]=c.useState([]),[h,k]=c.useState(0),[y,C]=E("lead","decPage",1,J),[j,G]=c.useState(0),[P,M]=E("lead","flowPage",1,J),[N,B]=c.useState("loading"),[O,T]=c.useState(!1),[I,f]=c.useState(null),[x,X]=E("lead","filter","all",re),d=c.useCallback((t=!1)=>{t||B("loading"),Promise.all([b.getLeadStatus(),b.getLeadDecisions({projectId:x==="all"?void 0:x,page:y,limit:z}),b.getLeadFlows({projectId:x==="all"?void 0:x,page:P,limit:z}).catch(()=>({items:[],total:0,page:1,pageSize:z}))]).then(([l,g,D])=>{i(l),w(g.items??[]),k(g.total??0),S(D.items??[]),G(D.total??0),B("ready")}).catch(()=>{t||B("error")})},[x,y,P]);c.useEffect(()=>{d()},[d]),se(x,()=>{C(1),M(1)}),ne({topic:"lead",params:{projectId:x==="all"?void 0:x,decPage:y,flowPage:P,limit:z},apply:t=>{i(t.status),w(t.decisions.items),k(t.decisions.total),S(t.flows.items),G(t.flows.total),B("ready")},refetch:()=>d(!0),pollMs:me});const A=c.useCallback(async t=>{T(!0);try{await b.putLeadConfig(t),s("Setelan lead tersimpan","ok","save"),d(!0)}catch{s("Gagal menyimpan setelan lead","err","x-circle")}finally{T(!1)}},[d,s]),_=c.useCallback(async(t,l)=>{f(t);try{await b.updateProject(t,{leadOptIn:l}),await r(t),d(!0),s(l?"Project dipimpin lead":"Project dilepas dari lead","ok")}catch{s("Gagal mengubah opt-in","err","x-circle")}finally{f(null)}},[d,r,s]),W=c.useCallback(async(t,l)=>{if(!n)return;const g=new Set(n.config.pausedProjects);l?g.add(t):g.delete(t),await A({...n.config,pausedProjects:[...g]})},[n,A]),Z=c.useCallback(async(t,l,g=[])=>{f(t);try{const D=await b.overrideLeadDecision(t,l,"",g);s(D.delivered?"Jawaban kamu dikirim ke sesi":"Keputusan ditimpa","ok","check"),d(!0)}catch{s("Gagal menimpa keputusan","err","x-circle")}finally{f(null)}},[d,s]),K=c.useCallback(async(t,l)=>{f(t);try{await(l==="submit"?b.submitLeadFlow(t):b.cancelLeadFlow(t)),s(l==="submit"?"Rantai di-submit":"Rantai dibatalkan","ok","check"),d(!0)}catch{s("Gagal menutup rantai","err","x-circle")}finally{f(null)}},[d,s]),ee=c.useCallback(async t=>{f(t);try{await b.cancelLeadDecision(t),s("Keputusan dibatalkan","ok"),d(!0)}catch{s("Gagal membatalkan keputusan","err","x-circle")}finally{f(null)}},[d,s]);if(N==="loading")return e.jsx(H,{kind:"loading"});if(N==="error"||!n)return e.jsx(H,{kind:"error",hint:"Gagal memuat status lead.",action:()=>d(),actionLabel:"Coba lagi"});const F=new Set(n.projects.map(t=>t.projectId)),V=n.waiting,ae=new Set(n.deciding),te=new Set(n.queued??[]),R=n.gate??{inFlight:0,queued:0,capacity:1};return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(ye,{cfg:n.config,onWrite:A,busy:O}),e.jsxs(L,{eyebrow:"lead · project",title:"Project yang dipimpin",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Lead hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>{const l=n.projects.find(g=>g.projectId===t.id);return e.jsxs(q,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),l&&e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[l.decisions24h," keputusan/24j · ",l.openSessions," sesi"]}),e.jsx(m,{tone:F.has(t.id)?l!=null&&l.paused?"warn":"ok":"neutral",size:"sm",children:F.has(t.id)?l!=null&&l.paused?"dijeda":"dipimpin":"mati"}),F.has(t.id)&&(l!=null&&l.paused?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"play",disabled:O,onClick:()=>W(t.id,!1),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:O,onClick:()=>W(t.id,!0),children:"Pause"})),F.has(t.id)?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:I===t.id,onClick:()=>_(t.id,!1),children:"Lepas"}):e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>_(t.id,!0),children:"Pimpin"})]},t.id)})]}),e.jsxs(ve,{title:"Sesi menunggu keputusan",count:V.length,empty:"Tak ada sesi yang menunggu keputusan.",children:[R.queued>0&&e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",marginBottom:8},children:["Gerbang lead: ",R.inFlight,"/",R.capacity," diputuskan · ",R.queued," antre menunggu slot."]}),V.map(t=>{const l=ae.has(t)?"sedang diputuskan":te.has(t)?"antre":"menunggu";return e.jsxs(q,{children:[e.jsx(ie,{name:l==="sedang diputuskan"?"loader":l==="antre"?"clock":"help-circle"}),e.jsx("span",{style:{flex:1,fontFamily:"var(--font-mono)",color:"var(--text-strong)"},children:t}),e.jsx(m,{tone:l==="menunggu"?"warn":"ok",size:"sm",children:l}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>o(t),children:"Ambil alih"})]},t)})]}),e.jsxs(L,{eyebrow:"lead · rantai keputusan",title:`Rantai (${j})`,children:[v.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada rantai. Satu rantai adalah satu urusan — beberapa pertanyaan berurutan sampai di-submit."}):v.map(t=>e.jsxs(q,{children:[e.jsx(m,{tone:be[t.status]??"neutral",size:"sm",children:t.status}),e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)"},children:t.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[t.steps," langkah · ",Q(t.openedAt),t.closeReason?` · ${fe[t.closeReason]??t.closeReason}`:""]}),ke.has(t.status)&&e.jsxs(e.Fragment,{children:[e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>K(t.id,"submit"),children:"Submit"}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:I===t.id,onClick:()=>K(t.id,"cancel"),children:"Batalkan"})]})]},t.id)),e.jsx(U,{total:j,page:P,onPage:M,unit:"rantai"})]}),e.jsxs(L,{eyebrow:"lead · jejak keputusan",title:`Keputusan (${h})`,actions:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(Y,{size:"sm",value:x,"aria-label":"saring project",onChange:t=>X(t.target.value),options:[{value:"all",label:"semua project"},...a.map(t=>({value:t.id,label:t.name}))]}),e.jsx(le,{screen:"lead",active:x==="all"?0:1}),e.jsx(pe,{})]}),children:[p.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada keputusan. Lead menulis satu baris di sini setiap kali ia memutuskan."}):p.map(t=>e.jsx(Se,{d:t,onOverride:Z,onCancel:ee,busyId:I},t.id)),e.jsx(U,{total:h,page:y,onPage:C,unit:"keputusan"})]})]})}export{Be as LeadScreen};
1
+ import{h as E,e as b,t as se,q as ne,j as e,f as H,aq as L,B as m,a as u,I as ie,S as Y,R as le,x as J,p as re,d as $,w as oe,D as ce,ar as de,aC as ue}from"./index-B3niUZnk.js";import{R as c}from"./react-DfGhg7ZW.js";import{L as pe}from"./live-fPTkukus.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const me=5e3,z=20;function U({total:a,page:r,onPage:s,unit:o}){const n=ce(a,r,z);return e.jsx(oe,{page:n.page,pageCount:n.pageCount,total:a,from:n.from,to:n.to,onPage:s,unit:o})}function Q(a,r=Date.now()){if(!a)return"—";const s=Math.max(0,r-new Date(a).getTime()),o=Math.floor(s/6e4);if(o<1)return"baru saja";if(o<60)return`${o}m`;const n=Math.floor(o/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const xe={tinggi:"ok",sedang:"neutral",ragu:"warn"},ge={berlaku:"ok",ditimpa:"warn",dibatalkan:"neutral",gagal:"err"},he={answer:"jawaban",order:"urutan kerja",collision:"tabrakan area",quality:"mutu hasil",refusal:"tindakan ditolak"},je={contract:"kontrak",detected:"deteksi otomatis",pulse:"denyut"},be={menunggu:"warn",sebagian:"info",selesai:"ok",dibatalkan:"neutral"},ke=new Set(["menunggu","sebagian"]),fe={tunggal:"sekali jalan",submit:"di-submit",operator:"dibatalkan operator",kedaluwarsa:"kedaluwarsa"};function q({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function ve({title:a,count:r,empty:s,children:o}){return e.jsx(L,{eyebrow:`lead · ${a.toLowerCase()}`,title:`${a} (${r})`,children:r===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:s}):o})}function ye({cfg:a,onWrite:r,busy:s}){var n;const o=(i,p)=>Math.max(p,Number(i)||p);return e.jsxs(L,{eyebrow:"lead · kendali",title:"hanoman-lead",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:12},children:[e.jsx(m,{tone:a.enabled?a.paused?"warn":"ok":"neutral",children:a.enabled?a.paused?"dijeda":"aktif":"mati"}),a.enabled?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:s,onClick:()=>r({...a,enabled:!1,paused:!1}),children:"Matikan"}):e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,enabled:!0}),children:"Nyalakan"}),a.enabled&&(a.paused?e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,paused:!1}),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:s,onClick:()=>r({...a,paused:!0}),children:"Pause"}))]}),e.jsxs("div",{style:{display:"flex",gap:14,flexWrap:"wrap",alignItems:"center"},children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["denyut tiap",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"denyut lead (menit)",placeholder:"5",value:String(a.everyMin),disabled:s,onChange:i=>r({...a,everyMin:o(i.target.value,1)})}),"menit"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["batas waktu putusan",e.jsx($,{type:"number",min:10,style:{width:84},"aria-label":"batas waktu putusan (detik)",placeholder:"600",value:String(a.timeoutSec),disabled:s,onChange:i=>r({...a,timeoutSec:o(i.target.value,10)})}),"detik"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["maks jawaban otomatis/sesi",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"maksimum jawaban otomatis per sesi",placeholder:"3",value:String(a.maxAutoAnswers),disabled:s,onChange:i=>r({...a,maxAutoAnswers:o(i.target.value,1)})})]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["syarat sebelum integrasi ke main",e.jsx(Y,{size:"sm","aria-label":"syarat sebelum integrasi ke main",value:a.requireGreenBeforeIntegrate?"wajib":"bebas",disabled:s,onChange:i=>r({...a,requireGreenBeforeIntegrate:i.target.value==="wajib"}),options:[{value:"wajib",label:"plan tuntas"},{value:"bebas",label:"tanpa syarat"}]})]})]}),e.jsxs("div",{"data-testid":"lead-engine-line",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:10},children:["mesin: ",(n=a.engine)!=null&&n.enabled?e.jsxs(e.Fragment,{children:[a.engine.agent==="codex"?"Codex CLI":"Claude Code"," · ",e.jsx("code",{children:a.engine.model})," · ",e.jsx("code",{children:a.engine.effort})]}):e.jsx(e.Fragment,{children:"ikut default global · atur di Settings → Model sesi"})]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:6},children:"Lead memutuskan lalu melapor. Produksi/VPS dan penghapusan data terkunci secara teknis — apa pun setelannya."})]})}function we({options:a,multi:r,value:s,onChange:o}){const n=i=>{if(!r){o([i]);return}o(s.includes(i)?s.filter(p=>p!==i):[...s,i])};return e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:6},children:a.map(i=>r?e.jsx(de,{checked:s.includes(i),label:i,onChange:()=>n(i)},i):e.jsx(ue,{checked:s.includes(i),label:i,onChange:()=>n(i)},i))})}function Se({d:a,onOverride:r,onCancel:s,busyId:o}){var C;const[n,i]=c.useState(!1),[p,w]=c.useState(""),[v,S]=c.useState([]),h=(a.choices??[]).length>0?a.choices:a.choiceIndex!=null&&a.choice?[{index:a.choiceIndex,option:a.choice}]:[],k=a.options??[],y=((C=a.select)==null?void 0:C.mode)==="multi";return e.jsxs("div",{style:{padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[e.jsx(m,{tone:ge[a.status]??"neutral",size:"sm",children:a.status}),e.jsx(m,{tone:xe[a.confidence]??"neutral",size:"sm",children:a.confidence}),e.jsx(m,{tone:"neutral",size:"sm",children:he[a.kind]??a.kind}),e.jsx(m,{tone:"neutral",size:"sm",children:je[a.gate]??a.gate}),a.weighty&&e.jsx(m,{tone:"warn",size:"sm",children:"berbobot"}),h.length>0&&k.length>0&&e.jsx(m,{tone:"brass",size:"sm",children:h.length>1?`${h.length} dari ${k.length} opsi`:`opsi ${h[0].index}/${k.length}`}),(a.missing??[]).length>0&&e.jsx(m,{tone:"warn",size:"sm",children:"kurang konteks"}),e.jsx("span",{style:{flex:1}}),e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:Q(a.createdAt)})]}),e.jsx("div",{style:{marginTop:6,fontSize:"var(--text-sm)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.question.slice(0,400)}),e.jsx("div",{style:{marginTop:4,color:"var(--text-strong)",fontWeight:500,whiteSpace:"pre-wrap"},children:h.length?h.map(j=>j.option).join(" · "):a.answer||e.jsx("em",{style:{fontWeight:400,color:"var(--text-muted)"},children:"tak ada jawaban"})}),e.jsx("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.reason}),a.refs.length>0&&e.jsx("div",{style:{marginTop:6,display:"flex",gap:6,flexWrap:"wrap"},children:a.refs.map(j=>e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-muted)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"1px 6px"},children:j},j))}),(a.missing??[]).length>0&&e.jsxs("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["Yang kurang: ",a.missing.join(" · ")]}),e.jsxs("div",{style:{marginTop:8,display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:[a.projectId,a.specId?` · ${a.specId}`:"",a.sessionId?` · ${a.sessionId}`:"",a.action!=="none"?` · ${a.action}`:""]}),e.jsx("span",{style:{flex:1}}),a.status==="berlaku"&&!n&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"edit-3",onClick:()=>i(!0),children:"Timpa"}),a.status==="berlaku"&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:o===a.id,onClick:()=>s(a.id),children:"Batalkan"})]}),n&&e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[k.length>0&&e.jsx(we,{options:k,multi:y,value:v,onChange:S}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx($,{style:{flex:1},"aria-label":`jawaban operator untuk ${a.id}`,placeholder:"mis. pilih opsi 2, pakai Node 22",value:p,onChange:j=>w(j.target.value)}),e.jsx(u,{size:"sm",leftIcon:"check",disabled:!p.trim()&&v.length===0||o===a.id,onClick:()=>{r(a.id,p.trim()||v.join("; "),v),i(!1),w(""),S([])},children:"Simpan"})]})]})]})}function Be({projects:a,onProjectChanged:r,onToast:s,onGotoTerminal:o}){const[n,i]=c.useState(null),[p,w]=c.useState([]),[v,S]=c.useState([]),[h,k]=c.useState(0),[y,C]=E("lead","decPage",1,J),[j,G]=c.useState(0),[P,M]=E("lead","flowPage",1,J),[N,B]=c.useState("loading"),[O,T]=c.useState(!1),[I,f]=c.useState(null),[x,X]=E("lead","filter","all",re),d=c.useCallback((t=!1)=>{t||B("loading"),Promise.all([b.getLeadStatus(),b.getLeadDecisions({projectId:x==="all"?void 0:x,page:y,limit:z}),b.getLeadFlows({projectId:x==="all"?void 0:x,page:P,limit:z}).catch(()=>({items:[],total:0,page:1,pageSize:z}))]).then(([l,g,D])=>{i(l),w(g.items??[]),k(g.total??0),S(D.items??[]),G(D.total??0),B("ready")}).catch(()=>{t||B("error")})},[x,y,P]);c.useEffect(()=>{d()},[d]),se(x,()=>{C(1),M(1)}),ne({topic:"lead",params:{projectId:x==="all"?void 0:x,decPage:y,flowPage:P,limit:z},apply:t=>{i(t.status),w(t.decisions.items),k(t.decisions.total),S(t.flows.items),G(t.flows.total),B("ready")},refetch:()=>d(!0),pollMs:me});const A=c.useCallback(async t=>{T(!0);try{await b.putLeadConfig(t),s("Setelan lead tersimpan","ok","save"),d(!0)}catch{s("Gagal menyimpan setelan lead","err","x-circle")}finally{T(!1)}},[d,s]),_=c.useCallback(async(t,l)=>{f(t);try{await b.updateProject(t,{leadOptIn:l}),await r(t),d(!0),s(l?"Project dipimpin lead":"Project dilepas dari lead","ok")}catch{s("Gagal mengubah opt-in","err","x-circle")}finally{f(null)}},[d,r,s]),W=c.useCallback(async(t,l)=>{if(!n)return;const g=new Set(n.config.pausedProjects);l?g.add(t):g.delete(t),await A({...n.config,pausedProjects:[...g]})},[n,A]),Z=c.useCallback(async(t,l,g=[])=>{f(t);try{const D=await b.overrideLeadDecision(t,l,"",g);s(D.delivered?"Jawaban kamu dikirim ke sesi":"Keputusan ditimpa","ok","check"),d(!0)}catch{s("Gagal menimpa keputusan","err","x-circle")}finally{f(null)}},[d,s]),K=c.useCallback(async(t,l)=>{f(t);try{await(l==="submit"?b.submitLeadFlow(t):b.cancelLeadFlow(t)),s(l==="submit"?"Rantai di-submit":"Rantai dibatalkan","ok","check"),d(!0)}catch{s("Gagal menutup rantai","err","x-circle")}finally{f(null)}},[d,s]),ee=c.useCallback(async t=>{f(t);try{await b.cancelLeadDecision(t),s("Keputusan dibatalkan","ok"),d(!0)}catch{s("Gagal membatalkan keputusan","err","x-circle")}finally{f(null)}},[d,s]);if(N==="loading")return e.jsx(H,{kind:"loading"});if(N==="error"||!n)return e.jsx(H,{kind:"error",hint:"Gagal memuat status lead.",action:()=>d(),actionLabel:"Coba lagi"});const F=new Set(n.projects.map(t=>t.projectId)),V=n.waiting,ae=new Set(n.deciding),te=new Set(n.queued??[]),R=n.gate??{inFlight:0,queued:0,capacity:1};return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(ye,{cfg:n.config,onWrite:A,busy:O}),e.jsxs(L,{eyebrow:"lead · project",title:"Project yang dipimpin",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Lead hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>{const l=n.projects.find(g=>g.projectId===t.id);return e.jsxs(q,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),l&&e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[l.decisions24h," keputusan/24j · ",l.openSessions," sesi"]}),e.jsx(m,{tone:F.has(t.id)?l!=null&&l.paused?"warn":"ok":"neutral",size:"sm",children:F.has(t.id)?l!=null&&l.paused?"dijeda":"dipimpin":"mati"}),F.has(t.id)&&(l!=null&&l.paused?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"play",disabled:O,onClick:()=>W(t.id,!1),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:O,onClick:()=>W(t.id,!0),children:"Pause"})),F.has(t.id)?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:I===t.id,onClick:()=>_(t.id,!1),children:"Lepas"}):e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>_(t.id,!0),children:"Pimpin"})]},t.id)})]}),e.jsxs(ve,{title:"Sesi menunggu keputusan",count:V.length,empty:"Tak ada sesi yang menunggu keputusan.",children:[R.queued>0&&e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",marginBottom:8},children:["Gerbang lead: ",R.inFlight,"/",R.capacity," diputuskan · ",R.queued," antre menunggu slot."]}),V.map(t=>{const l=ae.has(t)?"sedang diputuskan":te.has(t)?"antre":"menunggu";return e.jsxs(q,{children:[e.jsx(ie,{name:l==="sedang diputuskan"?"loader":l==="antre"?"clock":"help-circle"}),e.jsx("span",{style:{flex:1,fontFamily:"var(--font-mono)",color:"var(--text-strong)"},children:t}),e.jsx(m,{tone:l==="menunggu"?"warn":"ok",size:"sm",children:l}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>o(t),children:"Ambil alih"})]},t)})]}),e.jsxs(L,{eyebrow:"lead · rantai keputusan",title:`Rantai (${j})`,children:[v.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada rantai. Satu rantai adalah satu urusan — beberapa pertanyaan berurutan sampai di-submit."}):v.map(t=>e.jsxs(q,{children:[e.jsx(m,{tone:be[t.status]??"neutral",size:"sm",children:t.status}),e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)"},children:t.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[t.steps," langkah · ",Q(t.openedAt),t.closeReason?` · ${fe[t.closeReason]??t.closeReason}`:""]}),ke.has(t.status)&&e.jsxs(e.Fragment,{children:[e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>K(t.id,"submit"),children:"Submit"}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:I===t.id,onClick:()=>K(t.id,"cancel"),children:"Batalkan"})]})]},t.id)),e.jsx(U,{total:j,page:P,onPage:M,unit:"rantai"})]}),e.jsxs(L,{eyebrow:"lead · jejak keputusan",title:`Keputusan (${h})`,actions:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(Y,{size:"sm",value:x,"aria-label":"saring project",onChange:t=>X(t.target.value),options:[{value:"all",label:"semua project"},...a.map(t=>({value:t.id,label:t.name}))]}),e.jsx(le,{screen:"lead",active:x==="all"?0:1}),e.jsx(pe,{})]}),children:[p.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada keputusan. Lead menulis satu baris di sini setiap kali ia memutuskan."}):p.map(t=>e.jsx(Se,{d:t,onOverride:Z,onCancel:ee,busyId:I},t.id)),e.jsx(U,{total:h,page:y,onPage:C,unit:"keputusan"})]})]})}export{Be as LeadScreen};
@@ -1 +1 @@
1
- import{at as A,av as K,j as e,f as l,v as L,aq as y,a as k,aB as N,au as q,I as G,B as J,ax as O,e as d}from"./index-CCJTT5hd.js";import{R as a}from"./react-DfGhg7ZW.js";import{D as Q}from"./DocPreviewModal-CZ4rZ_h-.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function ee({specId:r,title:X,onBack:S,kind:x="spec"}){const R=x==="session"?d.sessionReview:d.specReview,F=x==="session"?d.sessionReviewFile:d.specReviewFile,[o,B]=a.useState(null),[f,c]=a.useState("loading"),[C,P]=a.useState(""),[s,g]=a.useState(""),[i,p]=a.useState(null),[u,z]=a.useState("diff"),[T,v]=a.useState(0),[M,D]=a.useState("list"),[V,h]=a.useState(!1),[E,m]=a.useState("files");a.useEffect(()=>{let t=!0;return c("loading"),R(r).then(n=>{var j;t&&(B(n),c("ready"),g(((j=n.changed[0])==null?void 0:j.path)??n.files[0]??""))}).catch(n=>{t&&((n==null?void 0:n.status)===409?(c("empty"),P(String((n==null?void 0:n.message)??""))):c("error"))}),()=>{t=!1}},[r,T]),a.useEffect(()=>{if(!s){p(null);return}let t=!0;return p(null),h(!1),F(r,s).then(n=>{t&&p(n)}).catch(()=>{t&&p(null)}),()=>{t=!1}},[r,s]);const H=a.useMemo(()=>A((o==null?void 0:o.files)??[]),[o]),W=(o==null?void 0:o.changed)??[],w=!!i&&!i.binary&&i.content!==null&&K(s),U=x==="session"?d.sessionReviewFileDownloadUrl:d.specReviewFileDownloadUrl,b=t=>{g(t),m("viewer")};return f==="loading"?e.jsx(l,{kind:"loading",title:"Memuat review…",hint:r}):f==="error"?e.jsx(l,{kind:"error",title:"Gagal memuat review",hint:r,action:()=>v(t=>t+1)}):f==="empty"?e.jsx(l,{kind:"empty",icon:"git-branch",title:"Belum ada worktree untuk di-review",hint:C||"Jalankan atau lanjutkan sesi backlog item ini dulu.",action:S,actionLabel:"Kembali ke backlog"}):e.jsxs(e.Fragment,{children:[e.jsx(L,{ariaLabel:"Panel Review",active:E,onActiveChange:t=>m(t),masterWidth:300,panels:[{id:"files",label:"Files",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"10px 12px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsx("span",{className:"hn-eyebrow",children:r}),e.jsx(k,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",onClick:()=>v(t=>t+1),children:"Muat ulang"})]}),e.jsxs("div",{style:{maxHeight:640,overflow:"auto",padding:"6px 4px"},children:[e.jsx(N,{label:"Changed",changed:W,selected:s,onSelect:b,view:M,onView:D}),e.jsx("div",{className:"hn-eyebrow",style:{padding:"6px 8px",marginTop:8,borderTop:"1px solid var(--border-hair)"},children:"Files"}),H.map(t=>e.jsx(q,{node:t,selected:s,onSelect:b},t.path))]})]})},{id:"viewer",label:"Viewer",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"10px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(G,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:s||"—"}),(i==null?void 0:i.status)&&e.jsx(J,{tone:i.status==="D"?"err":i.status==="A"?"ok":"brass",size:"sm",children:i.status}),e.jsx("span",{style:{flex:1}}),w&&e.jsx(k,{size:"sm",variant:"secondary",leftIcon:"book-open",onClick:()=>h(!0),children:"Preview"}),e.jsx("div",{style:{display:"flex",gap:2,background:"var(--bone-100)",borderRadius:"var(--radius-pill)",padding:2},children:["diff","source"].map(t=>e.jsx("button",{onClick:()=>z(t),style:{padding:"4px 12px",border:"none",cursor:"pointer",borderRadius:"var(--radius-pill)",fontSize:12,textTransform:"capitalize",background:u===t?"var(--surface-card)":"transparent",color:u===t?"var(--text-strong)":"var(--text-muted)",fontWeight:u===t?600:400},children:t},t))})]}),e.jsx("div",{style:{maxHeight:640,overflow:"auto",background:"var(--surface-card)"},children:s?i?i.binary?e.jsx(l,{kind:"empty",icon:"file",title:"Berkas biner",hint:"Tak dapat di-review dari dashboard."}):u==="diff"?e.jsxs("div",{style:{padding:"10px 0"},children:[e.jsx(O,{diff:i.diff??"",emptyHint:"File ini bagian dari project tapi tak diubah backlog ini."}),i.truncated&&e.jsx("div",{style:{padding:"8px 12px",fontSize:11,color:"var(--text-subtle)"},children:"… dipotong pada 256 KB."})]}):i.content===null?e.jsx(l,{kind:"empty",icon:"trash-2",title:"File dihapus",hint:"Tak ada isi untuk ditampilkan."}):e.jsx("pre",{style:{margin:0,padding:"12px 16px",fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:i.content}):e.jsx(l,{kind:"loading",title:"Memuat file…",hint:s}):e.jsx(l,{kind:"empty",icon:"file-text",title:"Pilih file",hint:"Pilih file dari changed atau tree."})})]})}]}),V&&w&&e.jsx(Q,{path:s,text:i.content??"",eyebrow:r,download:t=>U(r,s,t),onClose:()=>h(!1)})]})}export{ee as ReviewScreen};
1
+ import{at as A,av as K,j as e,f as l,v as L,aq as y,a as k,aB as N,au as q,I as G,B as J,ax as O,e as d}from"./index-B3niUZnk.js";import{R as a}from"./react-DfGhg7ZW.js";import{D as Q}from"./DocPreviewModal-CIDz4ZzG.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function ee({specId:r,title:X,onBack:S,kind:x="spec"}){const R=x==="session"?d.sessionReview:d.specReview,F=x==="session"?d.sessionReviewFile:d.specReviewFile,[o,B]=a.useState(null),[f,c]=a.useState("loading"),[C,P]=a.useState(""),[s,g]=a.useState(""),[i,p]=a.useState(null),[u,z]=a.useState("diff"),[T,v]=a.useState(0),[M,D]=a.useState("list"),[V,h]=a.useState(!1),[E,m]=a.useState("files");a.useEffect(()=>{let t=!0;return c("loading"),R(r).then(n=>{var j;t&&(B(n),c("ready"),g(((j=n.changed[0])==null?void 0:j.path)??n.files[0]??""))}).catch(n=>{t&&((n==null?void 0:n.status)===409?(c("empty"),P(String((n==null?void 0:n.message)??""))):c("error"))}),()=>{t=!1}},[r,T]),a.useEffect(()=>{if(!s){p(null);return}let t=!0;return p(null),h(!1),F(r,s).then(n=>{t&&p(n)}).catch(()=>{t&&p(null)}),()=>{t=!1}},[r,s]);const H=a.useMemo(()=>A((o==null?void 0:o.files)??[]),[o]),W=(o==null?void 0:o.changed)??[],w=!!i&&!i.binary&&i.content!==null&&K(s),U=x==="session"?d.sessionReviewFileDownloadUrl:d.specReviewFileDownloadUrl,b=t=>{g(t),m("viewer")};return f==="loading"?e.jsx(l,{kind:"loading",title:"Memuat review…",hint:r}):f==="error"?e.jsx(l,{kind:"error",title:"Gagal memuat review",hint:r,action:()=>v(t=>t+1)}):f==="empty"?e.jsx(l,{kind:"empty",icon:"git-branch",title:"Belum ada worktree untuk di-review",hint:C||"Jalankan atau lanjutkan sesi backlog item ini dulu.",action:S,actionLabel:"Kembali ke backlog"}):e.jsxs(e.Fragment,{children:[e.jsx(L,{ariaLabel:"Panel Review",active:E,onActiveChange:t=>m(t),masterWidth:300,panels:[{id:"files",label:"Files",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"10px 12px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsx("span",{className:"hn-eyebrow",children:r}),e.jsx(k,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",onClick:()=>v(t=>t+1),children:"Muat ulang"})]}),e.jsxs("div",{style:{maxHeight:640,overflow:"auto",padding:"6px 4px"},children:[e.jsx(N,{label:"Changed",changed:W,selected:s,onSelect:b,view:M,onView:D}),e.jsx("div",{className:"hn-eyebrow",style:{padding:"6px 8px",marginTop:8,borderTop:"1px solid var(--border-hair)"},children:"Files"}),H.map(t=>e.jsx(q,{node:t,selected:s,onSelect:b},t.path))]})]})},{id:"viewer",label:"Viewer",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"10px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(G,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:s||"—"}),(i==null?void 0:i.status)&&e.jsx(J,{tone:i.status==="D"?"err":i.status==="A"?"ok":"brass",size:"sm",children:i.status}),e.jsx("span",{style:{flex:1}}),w&&e.jsx(k,{size:"sm",variant:"secondary",leftIcon:"book-open",onClick:()=>h(!0),children:"Preview"}),e.jsx("div",{style:{display:"flex",gap:2,background:"var(--bone-100)",borderRadius:"var(--radius-pill)",padding:2},children:["diff","source"].map(t=>e.jsx("button",{onClick:()=>z(t),style:{padding:"4px 12px",border:"none",cursor:"pointer",borderRadius:"var(--radius-pill)",fontSize:12,textTransform:"capitalize",background:u===t?"var(--surface-card)":"transparent",color:u===t?"var(--text-strong)":"var(--text-muted)",fontWeight:u===t?600:400},children:t},t))})]}),e.jsx("div",{style:{maxHeight:640,overflow:"auto",background:"var(--surface-card)"},children:s?i?i.binary?e.jsx(l,{kind:"empty",icon:"file",title:"Berkas biner",hint:"Tak dapat di-review dari dashboard."}):u==="diff"?e.jsxs("div",{style:{padding:"10px 0"},children:[e.jsx(O,{diff:i.diff??"",emptyHint:"File ini bagian dari project tapi tak diubah backlog ini."}),i.truncated&&e.jsx("div",{style:{padding:"8px 12px",fontSize:11,color:"var(--text-subtle)"},children:"… dipotong pada 256 KB."})]}):i.content===null?e.jsx(l,{kind:"empty",icon:"trash-2",title:"File dihapus",hint:"Tak ada isi untuk ditampilkan."}):e.jsx("pre",{style:{margin:0,padding:"12px 16px",fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:i.content}):e.jsx(l,{kind:"loading",title:"Memuat file…",hint:s}):e.jsx(l,{kind:"empty",icon:"file-text",title:"Pilih file",hint:"Pilih file dari changed atau tree."})})]})}]}),V&&w&&e.jsx(Q,{path:s,text:i.content??"",eyebrow:r,download:t=>U(r,s,t),onClose:()=>h(!1)})]})}export{ee as ReviewScreen};
@@ -0,0 +1 @@
1
+ import{h as $,p as le,y as ie,e as y,aD as U,aE as se,j as e,aq as I,I as F,a as b,B as P,aF as oe,M as de,c as C,d as w,S as z,aG as ce,H as ue,aH as Q,V as me,aI as O,aJ as pe,aK as D,x as V,w as Y,D as X,q as Z,f as _,z as xe,aL as he}from"./index-B3niUZnk.js";import{R as h}from"./react-DfGhg7ZW.js";import{L as ge}from"./live-fPTkukus.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const J=10,G=a=>String(a).padStart(2,"0"),L=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"medium",timeStyle:"short"}):"—",K=a=>{const l={name:(a==null?void 0:a.name)??"",prompt:(a==null?void 0:a.prompt)??"",enabled:(a==null?void 0:a.enabled)??!1,kind:"lanjutan",time:"07:00",weekday:1,everyHours:6,expr:(a==null?void 0:a.expr)??"0 7 * * *",agent:(a==null?void 0:a.agent)??"",model:(a==null?void 0:a.model)??"",effort:(a==null?void 0:a.effort)??""},r=a?pe(a.expr):{kind:"harian",hour:7,minute:0};if(!r)return l;if(r.kind==="tiap-n-jam")return{...l,kind:r.kind,everyHours:r.everyHours,time:`00:${G(r.minute)}`};const t=`${G(r.hour)}:${G(r.minute)}`;return r.kind==="mingguan"?{...l,kind:r.kind,time:t,weekday:r.weekday}:{...l,kind:r.kind,time:t}},be=a=>{if(a.kind==="lanjutan")return a.expr.trim();const[l,r]=a.time.split(":").map(Number);switch(a.kind){case"harian":return D({kind:"harian",hour:l,minute:r});case"hari-kerja":return D({kind:"hari-kerja",hour:l,minute:r});case"mingguan":return D({kind:"mingguan",hour:l,minute:r,weekday:a.weekday});case"tiap-n-jam":return D({kind:"tiap-n-jam",everyHours:a.everyHours,minute:r})}},fe={launched:"ok",queued:"neutral",skipped:"warn",failed:"err"},ve={launched:"berjalan",queued:"menunggu",skipped:"dilewati",failed:"gagal"};function je({cronId:a}){const[l,r]=h.useState([]),[t,x]=h.useState(0),[u,f]=$("scheduler","cronRunsPage",1,V);h.useEffect(()=>{let d=!0;return y.listCronRuns(a,{page:u,limit:J}).then(i=>{d&&(r(i.items),x(i.total))}).catch(()=>{d&&(r([]),x(0))}),()=>{d=!1}},[a,u]);const c=X(t,u,J);return t===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada eksekusi."}):e.jsxs(e.Fragment,{children:[l.map(d=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",marginBottom:6},children:[e.jsx(P,{tone:fe[d.status]??"neutral",size:"sm",children:ve[d.status]??d.status}),e.jsxs("span",{style:{flex:1,minWidth:0,fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:["jatuh tempo ",L(d.dueAt),d.startedAt?` · mulai ${L(d.startedAt)}`:"",d.sessionId?` · sesi ${d.sessionId}`:"",d.manual?" · uji coba":"",d.note?` · ${d.note}`:""]})]},d.id)),e.jsx(Y,{page:c.page,pageCount:c.pageCount,total:t,from:c.from,to:c.to,onPage:f,unit:"run"})]})}function ye({projects:a,onProjectChanged:l,onToast:r}){var T;const[t,x]=$("scheduler","cronProject",((T=a[0])==null?void 0:T.id)??"",le),[u,f]=h.useState([]),[c,d]=h.useState(void 0),[i,s]=h.useState(K()),[m,j]=$("scheduler","cronOpenRuns",null,ie),[g,k]=h.useState(!1),N=a.find(n=>n.id===t),S=h.useCallback(()=>{if(!t){f([]);return}y.listCrons({projectId:t,page:1,limit:100}).then(n=>f(n.items)).catch(()=>f([]))},[t]);h.useEffect(()=>{S()},[S]);const o=n=>{d(n??null),s(K(n))},v=be(i),R=U(v)?se(v,new Date):null,M=async()=>{var n;if(!U(v)){r("Cron expression tak sah","err","x-circle");return}k(!0);try{c?await y.patchCron(c.id,{name:i.name,expr:v,prompt:i.prompt,enabled:i.enabled,agent:i.agent||null,model:i.model||null,effort:i.effort||null}):await y.createCron({project:t,name:i.name,expr:v,prompt:i.prompt,enabled:i.enabled,agent:i.agent||void 0,model:i.model||void 0,effort:i.effort||void 0}),r("Cron tersimpan","ok","save"),d(void 0),S()}catch(p){r(((n=p.detail)==null?void 0:n.error)??"Gagal menyimpan cron","err","x-circle")}finally{k(!1)}},ae=async n=>{var p;k(!0);try{await y.runCronNow(n),r("Uji coba diantrekan — sesi terbuka di tick berikutnya","ok","play")}catch(re){r(((p=re.detail)==null?void 0:p.error)??"Gagal menjalankan cron","err","x-circle")}finally{k(!1),S()}},te=async n=>{k(!0);try{await y.deleteCron(n),r("Cron dihapus","ok","trash")}catch{r("Gagal menghapus cron","err","x-circle")}finally{k(!1),S()}},ne=async()=>{if(t)try{await y.updateProject(t,{schedulerOptIn:!0}),await l(t),r("Project di-opt-in","ok")}catch{r("Gagal mengubah opt-in","err","x-circle")}},W=i.agent||"claude";return e.jsxs(I,{eyebrow:"scheduler · cronjob",title:"Pengecekan rutin per project",actions:e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(z,{value:t,"aria-label":"Project",onChange:n=>x(n.target.value),options:a.map(n=>({value:n.id,label:n.name}))}),e.jsx(b,{size:"sm",leftIcon:"plus",disabled:!t,onClick:()=>o(),children:"Cron baru"})]}),children:[N&&!N.schedulerOptIn&&e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,marginBottom:12,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-sunken)"},children:[e.jsx(F,{name:"alert-triangle",size:16,color:"var(--clay-500)"}),e.jsx("span",{style:{flex:1,fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:"Project ini belum di-opt-in scheduler — cron-nya tak akan pernah dijalankan."}),e.jsx(b,{size:"sm",leftIcon:"check",onClick:()=>void ne(),children:"Aktifkan scheduler di project ini"})]}),u.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada cron di project ini."}):u.map(n=>e.jsxs("div",{style:{padding:"10px 12px",marginBottom:6,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:n.name}),e.jsx(P,{tone:n.enabled?"ok":"neutral",size:"sm",children:n.enabled?"aktif":"nonaktif"}),e.jsx("span",{style:{flex:1}}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"play",disabled:g,onClick:()=>void ae(n.id),children:"Jalankan sekarang"}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"list",onClick:()=>j(m===n.id?null:n.id),children:"Riwayat"}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:()=>o(n),children:"Ubah"}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"trash",disabled:g,onClick:()=>void te(n.id),children:"Hapus"})]}),e.jsxs("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[oe(n.expr)," · terakhir ",L(n.lastRunAt)," · berikutnya ",L(n.nextRunAt)]}),m===n.id&&e.jsx("div",{style:{marginTop:10},children:e.jsx(je,{cronId:n.id})})]},n.id)),e.jsxs(de,{open:c!==void 0,title:c?"Ubah cron":"Cron baru",eyebrow:"scheduler",onClose:()=>d(void 0),width:620,footer:e.jsxs("div",{style:{display:"flex",gap:8,justifyContent:"flex-end"},children:[e.jsx(b,{size:"sm",variant:"ghost",onClick:()=>d(void 0),children:"Batal"}),e.jsx(b,{size:"sm",leftIcon:"save",disabled:g,onClick:()=>void M(),children:"Simpan"})]}),children:[e.jsx(C,{label:"Nama cron",children:e.jsx(w,{"aria-label":"Nama cron",placeholder:"Cek error produksi pagi",value:i.name,onChange:n=>s(p=>({...p,name:n.target.value}))})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0,1fr))",gap:10},children:[e.jsx(C,{label:"Preset jadwal",children:e.jsx(z,{"aria-label":"Preset jadwal",value:i.kind,onChange:n=>s(p=>({...p,kind:n.target.value})),options:[{value:"harian",label:"Setiap hari"},{value:"hari-kerja",label:"Hari kerja"},{value:"mingguan",label:"Mingguan"},{value:"tiap-n-jam",label:"Tiap N jam"},{value:"lanjutan",label:"Lanjutan (cron expression)"}]})}),i.kind!=="lanjutan"&&e.jsx(C,{label:i.kind==="tiap-n-jam"?"Menit (dari jam)":"Jam",children:e.jsx(w,{type:"time","aria-label":"Jam",value:i.time,onChange:n=>s(p=>({...p,time:n.target.value}))})}),i.kind==="mingguan"&&e.jsx(C,{label:"Hari",children:e.jsx(z,{"aria-label":"Hari",value:String(i.weekday),onChange:n=>s(p=>({...p,weekday:Number(n.target.value)})),options:ce.map((n,p)=>({value:String(p),label:n}))})}),i.kind==="tiap-n-jam"&&e.jsx(C,{label:"Tiap berapa jam",children:e.jsx(w,{type:"number",min:1,max:23,"aria-label":"Tiap berapa jam",placeholder:"mis. 6",value:String(i.everyHours),onChange:n=>s(p=>({...p,everyHours:Math.min(23,Math.max(1,Number(n.target.value)||1))}))})})]}),i.kind==="lanjutan"&&e.jsx(C,{label:"Cron expression",hint:"Lima field: menit jam tanggal bulan hari-pekan — zona waktu server.",children:e.jsx(w,{"aria-label":"Cron expression",placeholder:"0 7 * * 1-5",value:i.expr,onChange:n=>s(p=>({...p,expr:n.target.value}))})}),e.jsx("div",{"data-testid":"cron-next-preview",style:{marginBottom:14,fontSize:"var(--text-xs)",color:R?"var(--text-muted)":"var(--clay-500)"},children:R?`Jalan berikutnya: ${L(R.toISOString())} (waktu lokal)`:"Jadwal tak sah — tak ada jalan berikutnya"}),e.jsx(C,{label:"Prompt",hint:"Instruksi bebas untuk agen. Temuan sebaiknya difilekan sebagai backlog lewat POST /api/specs.",children:e.jsx(ue,{"aria-label":"Prompt",rows:6,placeholder:"mis. Periksa error 5xx sejak kemarin, lalu filekan temuannya sebagai QA finding.",value:i.prompt,onChange:n=>s(p=>({...p,prompt:n.target.value}))})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0,1fr))",gap:10},children:[e.jsx(C,{label:"Runtime",children:e.jsx(z,{"aria-label":"Runtime",value:i.agent,onChange:n=>s(p=>({...p,agent:n.target.value,model:"",effort:""})),options:[{value:"",label:"Warisi default sesi"},{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}]})}),e.jsx(C,{label:"Model",children:e.jsx(z,{"aria-label":"Model",value:i.model,disabled:!i.agent,onChange:n=>s(p=>({...p,model:n.target.value,effort:""})),options:[{value:"",label:"Warisi"},...Q(W).map(n=>({value:n.id,label:n.label}))]})}),e.jsx(C,{label:"Effort",children:e.jsx(z,{"aria-label":"Effort",value:i.effort,disabled:!i.agent,onChange:n=>s(p=>({...p,effort:n.target.value})),options:[{value:"",label:"Warisi"},...me(W,i.model||Q(W)[0].id).map(n=>({value:n,label:n}))]})})]}),e.jsx(O,{label:"Aktif",checked:i.enabled,onChange:n=>s(p=>({...p,enabled:n}))})]})]})}const q=5e3,H=10;function ee(a,l=Date.now()){if(!a)return"—";const r=Math.max(0,l-new Date(a).getTime()),t=Math.floor(r/6e4);if(t<1)return"baru saja";if(t<60)return`${t}m`;const x=Math.floor(t/60);return x<24?`${x}j`:`${Math.floor(x/24)}h`}function ke(a,l=Date.now()){if(!a)return"—";const r=new Date(a).getTime()-l;if(r<=0)return"jatuh tempo";const t=Math.ceil(r/6e4);return t<60?`${t}m lagi`:`${Math.ceil(t/60)}j lagi`}const Ce={tinggi:"err",sedang:"warn",rendah:"neutral"};function B(a,l){var r;return((r=l.find(t=>t.id===a))==null?void 0:r.title)??a}function Se({s:a}){return e.jsxs("div",{style:{padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",display:"flex",flexDirection:"column",gap:6,flex:1,minWidth:180},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:a.id}),e.jsx(P,{tone:a.enabled?"ok":"neutral",size:"sm",children:a.enabled?"aktif":"nonaktif"})]}),e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["tiap ",a.everyMin,"m"]}),e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:["terakhir ",ee(a.lastRunAt)," · berikutnya ",ke(a.nextRunAt)]})]})}function A({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function we({q:a,backlog:l,onCancel:r,busy:t}){return e.jsxs(A,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:B(a.specId,l)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source,a.note?` · ${a.note}`:""]})]}),e.jsx(P,{tone:Ce[a.priority]??"neutral",size:"sm",children:a.priority}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:t,onClick:()=>r(a.id),children:"Batalkan"})]})}function Ie({q:a,backlog:l,onRequeue:r,busy:t}){return e.jsxs(A,{children:[e.jsx(F,{name:"ban",size:16,color:"var(--text-subtle)"}),e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:B(a.specId,l)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source," · ",a.note??"dibatalkan"]})]}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",disabled:t,onClick:()=>r(a.id),children:"Antre lagi"})]})}function ze({s:a,backlog:l,onGotoTerminal:r}){return e.jsxs(A,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:B(a.specId,l)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId,a.flow?` · ${a.flow}`:""]})]}),a.decision&&e.jsx(P,{tone:"warn",icon:"bell",size:"sm",children:"menunggu keputusan"}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>r(a.id),children:"Buka terminal"})]})}function Pe({q:a,backlog:l,onToast:r}){const t=xe(a.specId);return e.jsxs(A,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:B(a.specId,l)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source," · ",a.launchedAt?`selesai ${ee(a.launchedAt)}`:a.note??"tak diluncurkan",a.sessionId?` · hanoman/${a.sessionId}`:""]})]}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(t,"_blank","noreferrer"),children:"Buka review"}),e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var x;(x=navigator.clipboard)==null||x.writeText(t),r("Link review disalin","ok","copy")},children:"Salin"})]})}function Ae({q:a,backlog:l}){return e.jsxs(A,{children:[e.jsx(F,{name:"x-circle",size:16,color:"var(--clay-500)"}),e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:B(a.specId,l)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.note??"gagal tanpa alasan tercatat"]})]})]})}function Re({title:a,count:l,empty:r,children:t}){return e.jsx(I,{eyebrow:"scheduler",title:`${a}${l?` · ${l}`:""}`,children:l===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:r}):t})}function E({title:a,status:l,count:r,empty:t,render:x}){const[u,f]=h.useState([]),[c,d]=h.useState(0),[i,s]=$("scheduler",`queue-${l}-page`,1,V),m=h.useCallback(()=>{let g=!0;return y.getSchedulerQueue({status:l,page:i,limit:H}).then(k=>{g&&(f(k.items),d(k.total))}).catch(()=>{g&&(f([]),d(0))}),()=>{g=!1}},[l,i]);h.useEffect(()=>m(),[m]),Z({topic:"schedulerQueue",params:{status:l,page:i,limit:H},apply:g=>{f(g.data.items),d(g.data.total)},refetch:()=>{m()},pollMs:q});const j=X(c,i,H);return e.jsx(I,{eyebrow:"scheduler",title:`${a}${r?` · ${r}`:""}`,children:r===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:t}):e.jsxs(e.Fragment,{children:[u.map(g=>x(g)),e.jsx(Y,{page:j.page,pageCount:j.pageCount,total:c,from:j.from,to:j.to,onPage:s,unit:"item"})]})})}function Me({cfg:a,cap:l,liveCount:r,onWrite:t,busy:x}){const u=!a.enabled,f=u?"neutral":a.paused?"warn":"ok",c=u?"berhenti":a.paused?"dijeda":"aktif";return e.jsx(I,{eyebrow:"scheduler · rem darurat",title:"Kendali",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(P,{tone:f,children:c}),e.jsxs("span",{style:{fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[r," / ",l," sesi hidup"]}),e.jsx(ge,{}),e.jsx("span",{style:{flex:1}}),a.enabled&&e.jsx(b,{size:"sm",variant:"secondary",leftIcon:a.paused?"play":"pause",disabled:x,onClick:()=>t({...a,paused:!a.paused}),children:a.paused?"Lanjutkan":"Pause"}),a.enabled?e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"square",disabled:x,onClick:()=>t({...a,enabled:!1}),children:"Stop"}):e.jsx(b,{size:"sm",leftIcon:"play",disabled:x,onClick:()=>t({...a,enabled:!0}),children:"Aktifkan"})]})})}function Le({status:a}){return e.jsx(I,{eyebrow:"host · peluncuran agen",title:"Gerbang peluncuran",children:e.jsxs("div",{"aria-label":"Status gerbang peluncuran",style:{fontSize:"var(--text-sm)",color:"var(--text-muted)",lineHeight:1.6},children:[e.jsxs("div",{children:["Gerbang ",a.enabled?"aktif":"nonaktif"," · ",a.liveCount," sesi hidup · ",a.liveAgentCount," agen terstruktur · cap ",a.maxConcurrent]}),e.jsxs("div",{children:["Load per core: ",a.loadStatus==="available"&&a.loadPerCore!==null?a.loadPerCore.toFixed(2):"tidak tersedia",a.loadStatus==="unsupported"?" (tidak didukung platform)":""," · ambang ",a.maxLoadPerCore]}),e.jsxs("div",{children:["Memori tersedia: ",a.memStatus==="available"&&a.memAvailablePct!==null?`${a.memAvailablePct.toFixed(0)}%`:"tidak tersedia"," · ambang ",a.minMemAvailablePct,"%"]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",marginTop:6},children:"Berlaku juga saat scheduler berhenti. Terminal dan shell tetap bisa dibuka; keduanya ikut mengisi cap."})]})})}function Be({cfg:a,onWrite:l,busy:r}){const[t,x]=h.useState(a);h.useEffect(()=>{x(a)},[a]);const u=(s,m)=>x(j=>({...j,sources:{...j.sources,[s]:{...j.sources[s],...m}}})),f=(s,m=1)=>Math.max(m,Number(s)||m),c=t.launchGuard??he.launchGuard,d=Number.isFinite(c.maxLoadPerCore)&&c.maxLoadPerCore>0,i=Number.isFinite(c.minMemAvailablePct)&&c.minMemAvailablePct>=0&&c.minMemAvailablePct<=100;return e.jsxs(I,{eyebrow:"scheduler · setelan",title:"Konfigurasi",actions:e.jsx(b,{size:"sm",leftIcon:"save",disabled:r||!d||!i,onClick:()=>l({...t,launchGuard:c}),children:"Simpan setelan"}),children:[e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(2, minmax(0,1fr))",gap:14},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Cap concurrent"}),e.jsx(w,{type:"number",min:1,value:String(t.maxConcurrent),"aria-label":"Cap concurrent",placeholder:"6",onChange:s=>x(m=>({...m,maxConcurrent:f(s.target.value)}))})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Autonomy"}),e.jsx(z,{value:t.autonomy,"aria-label":"Autonomy",onChange:s=>x(m=>({...m,autonomy:s.target.value})),options:[{value:"butuh-keputusan",label:"butuh-keputusan"},{value:"full-control",label:"full-control"}]})]})]}),e.jsxs("div",{style:{marginTop:14,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(O,{label:"Gerbang peluncuran",checked:c.enabled,onChange:s=>x(m=>({...m,launchGuard:{...c,enabled:s}}))}),e.jsx("p",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",lineHeight:1.5},children:"Membatasi peluncuran agen menurut cap sesi, beban host, dan memori tersedia, termasuk peluncuran manual. Mematikannya melewati ketiga pemeriksaan. Terpisah dari sakelar scheduler dan source."}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Ambang load per core"}),e.jsx(w,{type:"number",min:0,step:"any",value:String(c.maxLoadPerCore),"aria-label":"Ambang load per core","aria-invalid":!d,placeholder:"2.5",onChange:s=>x(m=>({...m,launchGuard:{...c,maxLoadPerCore:Number(s.target.value)}}))}),!d&&e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--clay-500)"},children:"Isi angka lebih besar dari nol."})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4,marginTop:10},children:[e.jsx("span",{className:"hn-eyebrow",children:"Ambang memori tersedia minimum (%)"}),e.jsx(w,{type:"number",min:0,max:100,step:"any",value:String(c.minMemAvailablePct),"aria-label":"Ambang memori tersedia minimum","aria-invalid":!i,placeholder:"15",onChange:s=>x(m=>({...m,launchGuard:{...c,minMemAvailablePct:Number(s.target.value)}}))}),!i&&e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--clay-500)"},children:"Isi angka 0–100."})]})]}),e.jsx("div",{style:{marginTop:14,display:"flex",flexDirection:"column",gap:10},children:["backlog","triase"].map(s=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap",padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(O,{label:s,checked:t.sources[s].enabled,onChange:m=>u(s,{enabled:m})}),e.jsx("span",{style:{flex:1}}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["tiap",e.jsx(w,{type:"number",min:1,style:{width:84},"aria-label":`cadence ${s}`,placeholder:"30",value:String(t.sources[s].everyMin),onChange:m=>u(s,{everyMin:f(m.target.value)})}),"menit"]})]},s))})]})}function Ne({projects:a,onToggle:l,busyId:r}){return e.jsxs(I,{eyebrow:"scheduler · opt-in project",title:"Project yang diizinkan",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Scheduler hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>e.jsxs(A,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),e.jsx(P,{tone:t.schedulerOptIn?"ok":"neutral",size:"sm",children:t.schedulerOptIn?"opt-in":"mati"}),t.schedulerOptIn?e.jsx(b,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:r===t.id,onClick:()=>l(t.id,!1),children:"Cabut opt-in"}):e.jsx(b,{size:"sm",leftIcon:"check",disabled:r===t.id,onClick:()=>l(t.id,!0),children:"Opt-in"})]},t.id))]})}function He({projects:a,backlog:l,onProjectChanged:r,onToast:t,onGotoTerminal:x}){const[u,f]=h.useState(null),[c,d]=h.useState("loading"),[i,s]=h.useState(!1),[m,j]=h.useState(null),g=h.useCallback((o=!1)=>{o||d("loading"),y.getSchedulerState().then(v=>{f(v),d("ready")}).catch(()=>{o||d("error")})},[]);h.useEffect(()=>{g()},[g]),Z({topic:"schedulerState",params:{},apply:o=>{f(o.state),d("ready")},refetch:()=>g(!0),pollMs:q});const k=h.useCallback(async o=>{s(!0);try{await y.putSchedulerConfig(o),t("Setelan scheduler tersimpan","ok","save"),g(!0)}catch{t("Gagal menyimpan setelan","err","x-circle")}finally{s(!1)}},[g,t]),N=h.useCallback(async(o,v)=>{j(o);try{await y.updateProject(o,{schedulerOptIn:v}),await r(o),t(v?"Project di-opt-in":"Opt-in dicabut","ok")}catch{t("Gagal mengubah opt-in","err","x-circle")}finally{j(null)}},[r,t]),S=h.useCallback(async(o,v)=>{j(o);try{v==="cancel"?(await y.cancelSchedulerQueueItem(o),t("Item antrean dibatalkan","ok","ban")):(await y.requeueSchedulerQueueItem(o),t("Item dikembalikan ke antrean","ok","rotate-ccw"))}catch(R){const M=R.detail;t((M==null?void 0:M.error)??"Gagal mengubah item antrean","err","x-circle")}finally{j(null),g(!0)}},[g,t]);return c==="loading"?e.jsx(_,{kind:"loading"}):c==="error"||!u?e.jsx(_,{kind:"error",hint:"Gagal memuat state scheduler.",action:()=>g(),actionLabel:"Coba lagi"}):e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(Me,{cfg:u.config,cap:u.cap,liveCount:u.liveCount,onWrite:k,busy:i}),u.admission&&e.jsx(Le,{status:u.admission}),e.jsx(I,{eyebrow:"scheduler · observabilitas",title:"Status per source",children:e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:u.sources.map(o=>e.jsx(Se,{s:o},o.id))})}),e.jsx(ye,{projects:a,onProjectChanged:r,onToast:t}),e.jsx(E,{title:"Antrean",status:"queued",count:u.queueCounts.queued,empty:"Antrean kosong.",render:o=>e.jsx(we,{q:o,backlog:l,onCancel:v=>void S(v,"cancel"),busy:m===o.id},o.id)}),e.jsx(E,{title:"Dibatalkan",status:"canceled",count:u.queueCounts.canceled,empty:"Tak ada item yang dibatalkan.",render:o=>e.jsx(Ie,{q:o,backlog:l,onRequeue:v=>void S(v,"requeue"),busy:m===o.id},o.id)}),e.jsx(Re,{title:"Sesi berjalan",count:u.sessions.length,empty:"Tak ada sesi scheduler berjalan.",children:u.sessions.map(o=>e.jsx(ze,{s:o,backlog:l,onGotoTerminal:x},o.id))}),e.jsx(E,{title:"Selesai (done)",status:"done",count:u.queueCounts.done,empty:"Belum ada hasil selesai.",render:o=>e.jsx(Pe,{q:o,backlog:l,onToast:t},o.id)}),e.jsx(E,{title:"Gagal",status:"failed",count:u.queueCounts.failed,empty:"Tak ada sesi gagal.",render:o=>e.jsx(Ae,{q:o,backlog:l},o.id)}),e.jsx(Be,{cfg:u.config,onWrite:k,busy:i}),e.jsx(Ne,{projects:a,onToggle:N,busyId:m})]})}export{He as SchedulerScreen};
@@ -1,4 +1,4 @@
1
- import{aP as za,aQ as Oa,aR as Pa,aS as Ba,aT as Ia,aU as Ma,aV as La,aW as Da,aX as Ha,aY as _a,aZ as Na,a_ as Ra,a$ as Fa,b0 as $a,b1 as Wa,e as f,j as e,aq as C,c as ee,d as Y,ar as me,a as y,f as V,am as Ga,aI as N,B as ne,I as Fe,N as ue,b2 as Ua,C as ba,b3 as ka,b4 as Ne,b5 as xa,b6 as Ta,b7 as Oe,b8 as Xe,b9 as Ka,ba as ta,bb as Ja,bc as Va,bd as Ya,A as qa,be as Xa,bf as Qa,bg as Ve,bh as Za,V as et,S as L,Y as te,Z as fa,u as We,bi as at,bj as tt,h as nt,a8 as it,bk as lt,p as st,bl as rt,O as ja,bm as Se,bn as $e,bo as dt,bp as ot,bq as ct,br as ut,bs as ya,bt as va,bu as Re,bv as Sa,bw as gt,bx as ht,aL as mt,by as Ae,bz as na,H as pt,bA as ia,bB as la,bC as bt,a0 as Ye,bD as wa,bE as kt,W as xt,X as ft,bF as jt,bG as yt}from"./index-CCJTT5hd.js";import{R as o}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as vt}from"./DocPreviewModal-CZ4rZ_h-.js";import"./xterm-3VOAfa_q.js";const St=[...za,...Oa,...Pa,...Ba,...Ia,...Ma,...La,...Da,...Ha,..._a,...Na,...Ra,...Fa,...$a,...Wa],wt=1;function Ct(){const[a,n]=o.useState(null),[i,r]=o.useState([]),[t,g]=o.useState(""),[d,h]=o.useState(""),[j,u]=o.useState([]),[c,k]=o.useState(null),z=o.useCallback(()=>f.listClientAccounts().then(x=>n(x.items)).catch(()=>n([])),[]);o.useEffect(()=>{z(),f.listProjects().then(x=>r(x.items.map(O=>({id:O.id,name:O.name})))).catch(()=>r([]))},[z]);const R=async()=>{k(null);try{await f.createClientAccount({email:t,password:d,projects:j}),g(""),h(""),u([]),await z()}catch{k("Gagal membuat akun — periksa email (mungkin sudah dipakai) dan panjang password.")}},F=async(x,O)=>{await f.updateClientAccount(x,O),await z()},E=async x=>{await f.deleteClientAccount(x),await z()},m=(x,O,K)=>K?[...x,O]:x.filter(U=>U!==O);return e.jsxs(e.Fragment,{children:[e.jsxs(C,{eyebrow:"akses",title:"Buat akun klien",children:[e.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:14,lineHeight:1.5},children:["Akun klien melihat ",e.jsx("b",{children:"daftar backlog"})," dan ",e.jsx("b",{children:"tiket help desk"})," project yang dipilih — baca-saja, tanpa terminal, dokumen internal, maupun setelan. Ia tak pernah melihat dashboard operator."]}),e.jsx(ee,{label:"Email klien",children:e.jsx(Y,{"aria-label":"Email klien",placeholder:"mis. budi@tokomekar.co.id",value:t,onChange:x=>g(x.target.value)})}),e.jsx(ee,{label:"Password awal",hint:"Minimal 8 karakter. Sampaikan lewat kanal yang aman — klien bisa menggantinya sendiri.",children:e.jsx(Y,{"aria-label":"Password awal",type:"password",placeholder:"mis. kunci-tokomekar-2026",value:d,onChange:x=>h(x.target.value)})}),e.jsx(ee,{label:"Project yang boleh dilihat",children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:14},children:i.map(x=>e.jsx(me,{"aria-label":`Beri akses ${x.name}`,label:x.name,checked:j.includes(x.id),onChange:O=>u(K=>m(K,x.id,O))},x.id))})}),c&&e.jsx("div",{style:{color:"var(--status-err)",fontSize:"var(--text-sm)",marginBottom:10},children:c}),e.jsx(y,{size:"sm",leftIcon:"user-plus",onClick:R,disabled:!t||d.length<8,children:"Buat akun"})]}),e.jsx(C,{eyebrow:"akses",title:"Akun klien",children:a===null?e.jsx(V,{kind:"loading",title:"Memuat…"}):a.length===0?e.jsx(V,{kind:"empty",icon:"users",title:"Belum ada akun klien",hint:"Buat akun di atas, lalu pilih project yang boleh ia lihat."}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:4},children:a.map(x=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap",padding:"12px 0",borderBottom:"1px solid var(--border-hair)"},children:[e.jsx("span",{style:{fontWeight:500,color:"var(--text-strong)"},children:x.email}),e.jsx(Ga,{status:x.disabled?"stopped":"done",size:"sm",children:x.disabled?"nonaktif":"aktif"}),e.jsx("div",{style:{flex:1,minWidth:240,display:"flex",flexWrap:"wrap",gap:14},children:i.map(O=>e.jsx(me,{"aria-label":`${x.email} · ${O.name}`,label:O.name,checked:x.projects.includes(O.id),onChange:K=>void F(x.id,{projects:m(x.projects,O.id,K)})},O.id))}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void F(x.id,{disabled:!x.disabled}),children:x.disabled?"Aktifkan":"Nonaktifkan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void E(x.id),children:"Hapus"})]},x.id))})})]})}const Te=["sessions:read","backlog:read","ide:read"],sa=[{cap:"sessions:write",label:"Tulis terminal",desc:"Ketik ke terminal, steer, interrupt, jawab & ambil alih dialog."},{cap:"sessions:spawn",label:"Mulai sesi",desc:"Membuka sesi agen BARU di mesin ini atas perintah hub — eksekusi agen di mesin ini. Hub tak bisa memaksa melewati gerbang beban."},{cap:"backlog:write",label:"Tandai selesai",desc:"Hanya menandai backlog selesai; suntingan backlog lain tetap tertutup untuk hub."}],ra=[{lane:"event",label:"event",desc:"Lahir/tutup sesi, perubahan grant — lajur audit lokal (default nyala)."},{lane:"server",label:"server",desc:"console.* proses server ini, disadap & diredaksi sebelum dikirim."},{lane:"transcript",label:"transcript",desc:"Transkrip sesi terminal yang sudah ditutup."}],At={off:"mati",connecting:"menyambung",open:"tersambung",backoff:"mencoba lagi",unsupported:"hub tak mendukung",rejected:"ditolak hub"},Et={off:"neutral",connecting:"neutral",open:"ok",backoff:"warn",unsupported:"warn",rejected:"warn"};function De({title:a,desc:n,children:i,last:r}){return e.jsxs("div",{className:"hn-setting-row",style:{display:"flex",alignItems:"center",gap:16,padding:"14px 0",borderBottom:r?"none":"1px solid var(--border-hair)"},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"var(--text-strong)"},children:a}),e.jsx("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginTop:3,lineHeight:1.5},children:n})]}),e.jsx("div",{className:"hn-setting-control",style:{flex:"0 0 auto"},children:i})]})}function zt({onToast:a}){const[n,i]=o.useState(null),[r,t]=o.useState(!1),[g,d]=o.useState(!1);if(o.useEffect(()=>{f.getRemoteControl().then(i).catch(()=>t(!0))},[]),!n)return e.jsx(C,{eyebrow:"kendali",title:"Kendali jarak jauh dari hub",children:r?e.jsx("div",{style:{fontSize:13,color:"var(--text-muted)"},children:"Gagal memuat grant kendali jarak jauh."}):e.jsx(V,{kind:"loading",compact:!0,title:"Memuat grant…"})});const{enabled:h,capabilities:j}=n.control,u=m=>j.includes(m),c=(...m)=>[...new Set(m.flat())],k=async(m,x)=>{d(!0);try{i(await f.putRemoteControl({control:{enabled:m,capabilities:x}})),a==null||a(m?"Grant kendali jarak jauh disimpan":"Kendali jarak jauh dimatikan","ok","check")}catch{a==null||a("Gagal menyimpan grant kendali jarak jauh","err","x-circle")}finally{d(!1)}},z=m=>k(m,m&&j.length===0?Te:j),R=m=>k(h,m?c(j,Te):[]),F=(m,x)=>k(h,x?c(j,Te,[m]):j.filter(O=>O!==m)),E=async(m,x)=>{d(!0);try{i(await f.putRemoteControl({logs:{...n.logs,[m]:x}})),a==null||a(x?`Lajur ${m} mulai dikirim ke hub`:`Lajur ${m} berhenti dikirim`,"ok","check")}catch{a==null||a("Gagal menyimpan lajur log","err","x-circle")}finally{d(!1)}};return e.jsxs(e.Fragment,{children:[e.jsxs(C,{eyebrow:"kendali",title:"Kendali jarak jauh dari hub",children:[e.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Mengizinkan operator ",e.jsx("b",{children:"hub"})," tempat mesin ini tersinkron bertindak di mesin ini lewat route yang sama dengan dashboard lokal. Default mati dan hanya bisa dinyalakan dari mesin ini — hub tak bisa menyalakannya sendiri."]}),e.jsx(De,{title:"Izinkan kendali jarak jauh",desc:"Membuka socket relay ke hub. Mati = tak ada jalur perintah dari hub sama sekali.",children:e.jsx(N,{checked:h,disabled:g,onChange:m=>void z(m),"aria-label":"Izinkan kendali jarak jauh"})}),e.jsx(De,{title:"Lihat",desc:"Daftar sesi, fase, dialog, dokumen & review sesi, IDE baca-saja.",children:e.jsx(N,{checked:u("sessions:read"),disabled:g||!h,onChange:m=>void R(m),"aria-label":"Lihat"})}),sa.map((m,x)=>e.jsx(De,{title:m.label,desc:m.desc,last:x===sa.length-1,children:e.jsx(N,{checked:u(m.cap),disabled:g||!h,onChange:O=>void F(m.cap,O),"aria-label":m.label})},m.cap))]}),e.jsxs(C,{eyebrow:"kendali",title:"Lajur log ke hub",children:[e.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Mengirim baris dari mesin ini ke ",e.jsx("code",{children:"POST /sync/logs"})," di hub — lepas dari grant kendali jarak jauh di atas. Tiap lajur bisa dinyalakan/dimatikan sendiri-sendiri, langsung berlaku tanpa restart."]}),ra.map((m,x)=>e.jsx(De,{title:m.label,desc:m.desc,last:x===ra.length-1,children:e.jsx(N,{checked:n.logs[m.lane],disabled:g,onChange:O=>void E(m.lane,O),"aria-label":m.label})},m.lane))]}),e.jsx(C,{eyebrow:"kendali",title:"Status relay",children:e.jsxs("div",{"data-testid":"relay-status",style:{display:"flex",gap:10,alignItems:"center",flexWrap:"wrap",fontSize:13},children:[e.jsx(ne,{tone:Et[n.relay.state],children:At[n.relay.state]}),e.jsx("span",{style:{color:"var(--text-muted)",overflowWrap:"anywhere"},children:n.relay.hubOrigin??"mesin ini tak tersambung ke hub"}),n.relay.lastClose&&e.jsxs("span",{style:{color:"var(--text-muted)"},children:["tutup terakhir ",n.relay.lastClose.code,n.relay.lastClose.reason?` · ${n.relay.lastClose.reason}`:""]})]})}),e.jsx(C,{eyebrow:"kendali",title:"Audit aksi hub di mesin ini",children:n.audit.length===0?e.jsx("div",{style:{fontSize:13,color:"var(--text-subtle)",padding:"8px 0"},children:"Belum ada aksi dari hub."}):n.audit.map(m=>e.jsxs("div",{"data-testid":"remote-audit-row",style:{fontSize:12.5,padding:"8px 0",borderBottom:"1px solid var(--border-hair)",overflowWrap:"anywhere"},children:[e.jsx("b",{children:m.kind})," · ",m.msg," · ",e.jsx("span",{style:{color:"var(--text-muted)"},children:new Date(m.ts).toLocaleString("id-ID")})]},m.id))})]})}const Ot={name:"",url:"",events:["*"],enabled:!0,allowPrivate:!1},Pt=ka.map(a=>({entity:a.entity,label:a.label,types:Ne.filter(n=>n.entity===a.entity).map(n=>n.type)})),da=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"short",timeStyle:"medium"}):"—",ce={fontSize:12.5,color:"var(--text-muted)",lineHeight:1.5},Ke={fontFamily:"var(--font-mono)",fontSize:12};function Bt({e:a}){return a.enabled?e.jsx(ne,{tone:"ok",children:"aktif"}):a.disabledAt?e.jsx(ne,{tone:"err",children:"dinonaktifkan otomatis"}):e.jsx(ne,{children:"nonaktif"})}function It({onToast:a,onOpenDocs:n}={}){const[i,r]=o.useState(null),[t,g]=o.useState(!1),[d,h]=o.useState(null),[j,u]=o.useState(null),[c,k]=o.useState(!1),[z,R]=o.useState({}),[F,E]=o.useState(null),[m,x]=o.useState([]),[O,K]=o.useState(null),U=o.useCallback(async()=>{try{r((await f.listWebhooks()).endpoints),g(!1)}catch{g(!0)}},[]);o.useEffect(()=>{U()},[U]);const ge=async s=>{E(s);try{x((await f.listWebhookDeliveries(s)).items)}catch{x([])}},pe=async()=>{if(d){k(!0);try{if(d.id)await f.updateWebhook(d.id,{name:d.name,url:d.url,events:d.events,enabled:d.enabled,allowPrivate:d.allowPrivate}),a==null||a("Endpoint webhook diperbarui");else{const s=await f.createWebhook({name:d.name,url:d.url,events:d.events,enabled:d.enabled,allowPrivate:d.allowPrivate});u(s.secret??null),a==null||a("Endpoint webhook dibuat")}h(null),await U()}catch(s){a==null||a(`Gagal menyimpan: ${s.message}`,"err")}finally{k(!1)}}},ie=async s=>{k(!0);try{const w=await f.updateWebhook(s,{rotateSecret:!0});u(w.secret??null),await U()}catch(w){a==null||a(`Gagal merotasi secret: ${w.message}`,"err")}finally{k(!1)}},we=async(s,w)=>{try{await f.updateWebhook(s.id,{enabled:w}),await U()}catch(M){a==null||a(`Gagal mengubah status: ${M.message}`,"err")}},le=async s=>{k(!0);try{const w=await f.testWebhook(s);R(M=>({...M,[s]:w})),await U()}catch(w){R(M=>({...M,[s]:{ok:!1,httpStatus:null,durationMs:0,error:w.message}}))}finally{k(!1)}},ae=async()=>{if(O)try{await f.deleteWebhook(O.id),a==null||a("Endpoint webhook dihapus"),await U()}catch(s){a==null||a(`Gagal menghapus: ${s.message}`,"err")}finally{K(null)}},se=async s=>{try{await f.retryWebhookDelivery(s),F&&await ge(F),await U()}catch(w){a==null||a(`Gagal antre ulang: ${w.message}`,"err")}},b=(s,w)=>h(M=>M&&{...M,events:w?[...new Set([...M.events.filter(_=>_!=="*"),...s])]:M.events.filter(_=>_!=="*"&&!s.includes(_))}),I=(d==null?void 0:d.events.includes("*"))??!1;return e.jsxs(e.Fragment,{children:[e.jsxs(C,{eyebrow:"integrasi",title:"Webhook keluar",children:[e.jsxs("div",{style:{...ce,marginBottom:12},children:["hanoman mengirim ",e.jsx("b",{children:"HTTP POST"})," bertanda tangan ke endpoint yang Anda daftarkan setiap kali sesuatu berubah — backlog dibuat atau berpindah stage, sesi mulai dan selesai, putusan lead terbit, tiket masuk, notifikasi. Pengiriman berjalan di antrean: penerima yang lambat atau mati ",e.jsx("b",{children:"tidak"})," memperlambat hanoman."]}),e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:16},children:[e.jsxs(y,{size:"sm",onClick:()=>{h({...Ot}),u(null)},children:[e.jsx(Fe,{name:"plus",size:14})," Tambah endpoint"]}),e.jsxs(y,{size:"sm",variant:"ghost",onClick:n,children:[e.jsx(Fe,{name:"book-open",size:14})," Dokumentasi webhook"]})]}),t?e.jsx(V,{kind:"error",compact:!0,title:"Gagal memuat endpoint webhook",hint:"Coba muat ulang.",action:()=>void U(),actionLabel:"Coba lagi"}):i===null?e.jsx("div",{style:ce,children:"Memuat…"}):i.length===0?e.jsx(V,{kind:"empty",compact:!0,title:"Belum ada endpoint webhook",hint:"Daftarkan URL penerima pertama untuk mulai berlangganan peristiwa hanoman."}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:10},children:i.map(s=>e.jsxs("div",{"data-testid":`webhook-${s.id}`,style:{border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx("div",{style:{fontWeight:600},children:s.name}),e.jsx(Bt,{e:s}),s.pending>0?e.jsxs(ne,{children:[s.pending," mengantre"]}):null,e.jsxs("div",{style:{marginLeft:"auto",display:"flex",gap:6,alignItems:"center"},children:[e.jsx(N,{checked:s.enabled,"aria-label":`Aktifkan ${s.name}`,onChange:w=>void we(s,w)}),e.jsx(y,{size:"sm",variant:"ghost",disabled:c,onClick:()=>void le(s.id),children:"Test"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void ge(s.id),children:"Riwayat"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{u(null),h({id:s.id,name:s.name,url:s.url,events:s.events,enabled:s.enabled,allowPrivate:s.allowPrivate})},children:"Ubah"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>K(s),children:"Hapus"})]})]}),e.jsx("div",{style:{...Ke,color:"var(--text-muted)",marginTop:6},children:s.url}),e.jsxs("div",{style:{...ce,marginTop:6},children:["Peristiwa: ",e.jsx("code",{children:s.events.join(", ")})," · secret …",s.secretHint," ·"," ","sukses terakhir ",da(s.lastSuccessAt),s.failureStreak>0?` · ${s.failureStreak} gagal beruntun`:""]}),s.disabledReason?e.jsx("div",{style:{...ce,marginTop:6,color:"var(--status-err-tint)"},children:s.disabledReason}):null,z[s.id]?e.jsx("div",{style:{...ce,marginTop:6},children:z[s.id].ok?`Test berhasil — HTTP ${z[s.id].httpStatus} · ${z[s.id].durationMs} ms`:`Test gagal — ${z[s.id].error}`}):null]},s.id))})]}),j?e.jsxs(C,{eyebrow:"secret",title:"Salin sekarang — secret tak ditampilkan lagi",children:[e.jsx(ue,{tone:"brass",children:e.jsx("div",{style:{...Ke,wordBreak:"break-all"},children:j})}),e.jsxs("div",{style:{display:"flex",gap:8,marginTop:10},children:[e.jsx(y,{size:"sm",onClick:()=>{var s;return void((s=navigator.clipboard)==null?void 0:s.writeText(j))},children:"Salin secret"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>u(null),children:"Tutup"})]})]}):null,d?e.jsx(C,{eyebrow:d.id?"ubah":"tambah",title:d.id?"Ubah endpoint":"Endpoint baru",children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsx(ee,{label:"Nama",children:e.jsx(Y,{value:d.name,placeholder:"mis. Dashboard internal",onChange:s=>h({...d,name:s.target.value})})}),e.jsx(ee,{label:"URL tujuan",children:e.jsx(Y,{value:d.url,placeholder:"https://contoh.id/hanoman-webhook",onChange:s=>h({...d,url:s.target.value})})}),e.jsxs("div",{children:[e.jsx("div",{style:{fontWeight:600,fontSize:13,marginBottom:6},children:"Peristiwa yang dikirim"}),e.jsx(me,{checked:I,label:"Semua peristiwa",onChange:s=>h({...d,events:s?["*"]:[]})}),I?null:e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[Pt.map(s=>e.jsxs("div",{children:[e.jsx(me,{checked:s.types.every(w=>d.events.includes(w)),label:s.label,onChange:w=>b(s.types,w)}),e.jsx("div",{style:{paddingLeft:22,display:"flex",flexWrap:"wrap",gap:10},children:s.types.map(w=>e.jsx(me,{checked:d.events.includes(w),label:w,onChange:M=>h({...d,events:M?[...new Set([...d.events.filter(_=>_!=="*"),w])]:d.events.filter(_=>_!==w&&_!=="*")})},w))})]},s.entity)),e.jsxs("div",{style:ce,children:[e.jsx("code",{children:Ua})," selalu terkirim saat tombol Test ditekan, apa pun langganannya."]})]})]}),e.jsx(me,{checked:d.allowPrivate,label:"Izinkan alamat internal / loopback",onChange:s=>h({...d,allowPrivate:s})}),e.jsx("div",{style:ce,children:"Biarkan mati kecuali penerima memang berjalan di mesin/jaringan yang sama. Menyalakannya membuka jalan ke layanan internal yang tak pernah dimaksudkan terekspos."}),e.jsx(me,{checked:d.enabled,label:"Aktif",onChange:s=>h({...d,enabled:s})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(y,{size:"sm",disabled:c||!d.name||!d.url||d.events.length===0,onClick:()=>void pe(),children:"Simpan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>h(null),children:"Batal"}),d.id?e.jsx(y,{size:"sm",variant:"ghost",disabled:c,onClick:()=>void ie(d.id),children:"Rotasi secret"}):null]})]})}):null,F?e.jsxs(C,{eyebrow:"riwayat",title:"Riwayat pengiriman",children:[e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:8},children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>E(null),children:"Tutup riwayat"})}),m.length===0?e.jsx("div",{style:ce,children:"Belum ada pengiriman."}):e.jsx("div",{className:"hn-local-overflow",style:{overflowX:"auto"},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12.5},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{textAlign:"left",color:"var(--text-muted)"},children:[e.jsx("th",{style:{padding:"6px 8px"},children:"Waktu"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Jenis"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Status"}),e.jsx("th",{style:{padding:"6px 8px"},children:"HTTP"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Percobaan"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Galat"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:m.map(s=>e.jsxs("tr",{style:{borderTop:"1px solid var(--border-hair)"},children:[e.jsx("td",{style:{padding:"6px 8px",whiteSpace:"nowrap"},children:da(s.createdAt)}),e.jsx("td",{style:{padding:"6px 8px",...Ke},children:s.eventType}),e.jsx("td",{style:{padding:"6px 8px"},children:s.status}),e.jsx("td",{style:{padding:"6px 8px"},children:s.httpStatus??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:`${s.attempt} / ${s.maxAttempts}`}),e.jsx("td",{style:{padding:"6px 8px",color:"var(--text-muted)"},children:s.error??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:s.status==="failed"||s.status==="dropped"?e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void se(s.id),children:"Antre ulang"}):null})]},s.id))})]})})]}):null,e.jsx(ba,{open:!!O,title:"Hapus endpoint webhook?",message:O?`"${O.name}" beserta seluruh riwayat pengirimannya akan dihapus.`:"",confirmLabel:"Hapus",onCancel:()=>K(null),onConfirm:()=>void ae()})]})}const J={fontSize:13,color:"var(--text-muted)",lineHeight:1.6},Mt={fontFamily:"var(--font-mono)",fontSize:12,whiteSpace:"pre",overflowX:"auto",background:"var(--bone-200)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:12,margin:0};function Je({text:a,label:n="Salin"}){const[i,r]=o.useState(!1);return e.jsxs("div",{style:{position:"relative"},children:[e.jsx("pre",{style:Mt,children:a}),e.jsx("div",{style:{marginTop:6},children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(a),r(!0),setTimeout(()=>r(!1),1500)},children:i?"Tersalin":n})})]})}const Lt=`// Node.js (Express) — verifikasi tanda tangan webhook hanoman
1
+ import{aP as za,aQ as Oa,aR as Pa,aS as Ba,aT as Ia,aU as Ma,aV as La,aW as Da,aX as Ha,aY as _a,aZ as Na,a_ as Ra,a$ as Fa,b0 as $a,b1 as Wa,e as f,j as e,aq as C,c as ee,d as Y,ar as me,a as y,f as V,am as Ga,aI as N,B as ne,I as Fe,N as ue,b2 as Ua,C as ba,b3 as ka,b4 as Ne,b5 as xa,b6 as Ta,b7 as Oe,b8 as Xe,b9 as Ka,ba as ta,bb as Ja,bc as Va,bd as Ya,A as qa,be as Xa,bf as Qa,bg as Ve,bh as Za,V as et,S as L,Y as te,Z as fa,u as We,bi as at,bj as tt,h as nt,a8 as it,bk as lt,p as st,bl as rt,O as ja,bm as Se,bn as $e,bo as dt,bp as ot,bq as ct,br as ut,bs as ya,bt as va,bu as Re,bv as Sa,bw as gt,bx as ht,aL as mt,by as Ae,bz as na,H as pt,bA as ia,bB as la,bC as bt,a0 as Ye,bD as wa,bE as kt,W as xt,X as ft,bF as jt,bG as yt}from"./index-B3niUZnk.js";import{R as o}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as vt}from"./DocPreviewModal-CIDz4ZzG.js";import"./xterm-3VOAfa_q.js";const St=[...za,...Oa,...Pa,...Ba,...Ia,...Ma,...La,...Da,...Ha,..._a,...Na,...Ra,...Fa,...$a,...Wa],wt=1;function Ct(){const[a,n]=o.useState(null),[i,r]=o.useState([]),[t,g]=o.useState(""),[d,h]=o.useState(""),[j,u]=o.useState([]),[c,k]=o.useState(null),z=o.useCallback(()=>f.listClientAccounts().then(x=>n(x.items)).catch(()=>n([])),[]);o.useEffect(()=>{z(),f.listProjects().then(x=>r(x.items.map(O=>({id:O.id,name:O.name})))).catch(()=>r([]))},[z]);const R=async()=>{k(null);try{await f.createClientAccount({email:t,password:d,projects:j}),g(""),h(""),u([]),await z()}catch{k("Gagal membuat akun — periksa email (mungkin sudah dipakai) dan panjang password.")}},F=async(x,O)=>{await f.updateClientAccount(x,O),await z()},E=async x=>{await f.deleteClientAccount(x),await z()},m=(x,O,K)=>K?[...x,O]:x.filter(U=>U!==O);return e.jsxs(e.Fragment,{children:[e.jsxs(C,{eyebrow:"akses",title:"Buat akun klien",children:[e.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:14,lineHeight:1.5},children:["Akun klien melihat ",e.jsx("b",{children:"daftar backlog"})," dan ",e.jsx("b",{children:"tiket help desk"})," project yang dipilih — baca-saja, tanpa terminal, dokumen internal, maupun setelan. Ia tak pernah melihat dashboard operator."]}),e.jsx(ee,{label:"Email klien",children:e.jsx(Y,{"aria-label":"Email klien",placeholder:"mis. budi@tokomekar.co.id",value:t,onChange:x=>g(x.target.value)})}),e.jsx(ee,{label:"Password awal",hint:"Minimal 8 karakter. Sampaikan lewat kanal yang aman — klien bisa menggantinya sendiri.",children:e.jsx(Y,{"aria-label":"Password awal",type:"password",placeholder:"mis. kunci-tokomekar-2026",value:d,onChange:x=>h(x.target.value)})}),e.jsx(ee,{label:"Project yang boleh dilihat",children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:14},children:i.map(x=>e.jsx(me,{"aria-label":`Beri akses ${x.name}`,label:x.name,checked:j.includes(x.id),onChange:O=>u(K=>m(K,x.id,O))},x.id))})}),c&&e.jsx("div",{style:{color:"var(--status-err)",fontSize:"var(--text-sm)",marginBottom:10},children:c}),e.jsx(y,{size:"sm",leftIcon:"user-plus",onClick:R,disabled:!t||d.length<8,children:"Buat akun"})]}),e.jsx(C,{eyebrow:"akses",title:"Akun klien",children:a===null?e.jsx(V,{kind:"loading",title:"Memuat…"}):a.length===0?e.jsx(V,{kind:"empty",icon:"users",title:"Belum ada akun klien",hint:"Buat akun di atas, lalu pilih project yang boleh ia lihat."}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:4},children:a.map(x=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap",padding:"12px 0",borderBottom:"1px solid var(--border-hair)"},children:[e.jsx("span",{style:{fontWeight:500,color:"var(--text-strong)"},children:x.email}),e.jsx(Ga,{status:x.disabled?"stopped":"done",size:"sm",children:x.disabled?"nonaktif":"aktif"}),e.jsx("div",{style:{flex:1,minWidth:240,display:"flex",flexWrap:"wrap",gap:14},children:i.map(O=>e.jsx(me,{"aria-label":`${x.email} · ${O.name}`,label:O.name,checked:x.projects.includes(O.id),onChange:K=>void F(x.id,{projects:m(x.projects,O.id,K)})},O.id))}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void F(x.id,{disabled:!x.disabled}),children:x.disabled?"Aktifkan":"Nonaktifkan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void E(x.id),children:"Hapus"})]},x.id))})})]})}const Te=["sessions:read","backlog:read","ide:read"],sa=[{cap:"sessions:write",label:"Tulis terminal",desc:"Ketik ke terminal, steer, interrupt, jawab & ambil alih dialog."},{cap:"sessions:spawn",label:"Mulai sesi",desc:"Membuka sesi agen BARU di mesin ini atas perintah hub — eksekusi agen di mesin ini. Hub tak bisa memaksa melewati gerbang beban."},{cap:"backlog:write",label:"Tandai selesai",desc:"Hanya menandai backlog selesai; suntingan backlog lain tetap tertutup untuk hub."}],ra=[{lane:"event",label:"event",desc:"Lahir/tutup sesi, perubahan grant — lajur audit lokal (default nyala)."},{lane:"server",label:"server",desc:"console.* proses server ini, disadap & diredaksi sebelum dikirim."},{lane:"transcript",label:"transcript",desc:"Transkrip sesi terminal yang sudah ditutup."}],At={off:"mati",connecting:"menyambung",open:"tersambung",backoff:"mencoba lagi",unsupported:"hub tak mendukung",rejected:"ditolak hub"},Et={off:"neutral",connecting:"neutral",open:"ok",backoff:"warn",unsupported:"warn",rejected:"warn"};function De({title:a,desc:n,children:i,last:r}){return e.jsxs("div",{className:"hn-setting-row",style:{display:"flex",alignItems:"center",gap:16,padding:"14px 0",borderBottom:r?"none":"1px solid var(--border-hair)"},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"var(--text-strong)"},children:a}),e.jsx("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginTop:3,lineHeight:1.5},children:n})]}),e.jsx("div",{className:"hn-setting-control",style:{flex:"0 0 auto"},children:i})]})}function zt({onToast:a}){const[n,i]=o.useState(null),[r,t]=o.useState(!1),[g,d]=o.useState(!1);if(o.useEffect(()=>{f.getRemoteControl().then(i).catch(()=>t(!0))},[]),!n)return e.jsx(C,{eyebrow:"kendali",title:"Kendali jarak jauh dari hub",children:r?e.jsx("div",{style:{fontSize:13,color:"var(--text-muted)"},children:"Gagal memuat grant kendali jarak jauh."}):e.jsx(V,{kind:"loading",compact:!0,title:"Memuat grant…"})});const{enabled:h,capabilities:j}=n.control,u=m=>j.includes(m),c=(...m)=>[...new Set(m.flat())],k=async(m,x)=>{d(!0);try{i(await f.putRemoteControl({control:{enabled:m,capabilities:x}})),a==null||a(m?"Grant kendali jarak jauh disimpan":"Kendali jarak jauh dimatikan","ok","check")}catch{a==null||a("Gagal menyimpan grant kendali jarak jauh","err","x-circle")}finally{d(!1)}},z=m=>k(m,m&&j.length===0?Te:j),R=m=>k(h,m?c(j,Te):[]),F=(m,x)=>k(h,x?c(j,Te,[m]):j.filter(O=>O!==m)),E=async(m,x)=>{d(!0);try{i(await f.putRemoteControl({logs:{...n.logs,[m]:x}})),a==null||a(x?`Lajur ${m} mulai dikirim ke hub`:`Lajur ${m} berhenti dikirim`,"ok","check")}catch{a==null||a("Gagal menyimpan lajur log","err","x-circle")}finally{d(!1)}};return e.jsxs(e.Fragment,{children:[e.jsxs(C,{eyebrow:"kendali",title:"Kendali jarak jauh dari hub",children:[e.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Mengizinkan operator ",e.jsx("b",{children:"hub"})," tempat mesin ini tersinkron bertindak di mesin ini lewat route yang sama dengan dashboard lokal. Default mati dan hanya bisa dinyalakan dari mesin ini — hub tak bisa menyalakannya sendiri."]}),e.jsx(De,{title:"Izinkan kendali jarak jauh",desc:"Membuka socket relay ke hub. Mati = tak ada jalur perintah dari hub sama sekali.",children:e.jsx(N,{checked:h,disabled:g,onChange:m=>void z(m),"aria-label":"Izinkan kendali jarak jauh"})}),e.jsx(De,{title:"Lihat",desc:"Daftar sesi, fase, dialog, dokumen & review sesi, IDE baca-saja.",children:e.jsx(N,{checked:u("sessions:read"),disabled:g||!h,onChange:m=>void R(m),"aria-label":"Lihat"})}),sa.map((m,x)=>e.jsx(De,{title:m.label,desc:m.desc,last:x===sa.length-1,children:e.jsx(N,{checked:u(m.cap),disabled:g||!h,onChange:O=>void F(m.cap,O),"aria-label":m.label})},m.cap))]}),e.jsxs(C,{eyebrow:"kendali",title:"Lajur log ke hub",children:[e.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Mengirim baris dari mesin ini ke ",e.jsx("code",{children:"POST /sync/logs"})," di hub — lepas dari grant kendali jarak jauh di atas. Tiap lajur bisa dinyalakan/dimatikan sendiri-sendiri, langsung berlaku tanpa restart."]}),ra.map((m,x)=>e.jsx(De,{title:m.label,desc:m.desc,last:x===ra.length-1,children:e.jsx(N,{checked:n.logs[m.lane],disabled:g,onChange:O=>void E(m.lane,O),"aria-label":m.label})},m.lane))]}),e.jsx(C,{eyebrow:"kendali",title:"Status relay",children:e.jsxs("div",{"data-testid":"relay-status",style:{display:"flex",gap:10,alignItems:"center",flexWrap:"wrap",fontSize:13},children:[e.jsx(ne,{tone:Et[n.relay.state],children:At[n.relay.state]}),e.jsx("span",{style:{color:"var(--text-muted)",overflowWrap:"anywhere"},children:n.relay.hubOrigin??"mesin ini tak tersambung ke hub"}),n.relay.lastClose&&e.jsxs("span",{style:{color:"var(--text-muted)"},children:["tutup terakhir ",n.relay.lastClose.code,n.relay.lastClose.reason?` · ${n.relay.lastClose.reason}`:""]})]})}),e.jsx(C,{eyebrow:"kendali",title:"Audit aksi hub di mesin ini",children:n.audit.length===0?e.jsx("div",{style:{fontSize:13,color:"var(--text-subtle)",padding:"8px 0"},children:"Belum ada aksi dari hub."}):n.audit.map(m=>e.jsxs("div",{"data-testid":"remote-audit-row",style:{fontSize:12.5,padding:"8px 0",borderBottom:"1px solid var(--border-hair)",overflowWrap:"anywhere"},children:[e.jsx("b",{children:m.kind})," · ",m.msg," · ",e.jsx("span",{style:{color:"var(--text-muted)"},children:new Date(m.ts).toLocaleString("id-ID")})]},m.id))})]})}const Ot={name:"",url:"",events:["*"],enabled:!0,allowPrivate:!1},Pt=ka.map(a=>({entity:a.entity,label:a.label,types:Ne.filter(n=>n.entity===a.entity).map(n=>n.type)})),da=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"short",timeStyle:"medium"}):"—",ce={fontSize:12.5,color:"var(--text-muted)",lineHeight:1.5},Ke={fontFamily:"var(--font-mono)",fontSize:12};function Bt({e:a}){return a.enabled?e.jsx(ne,{tone:"ok",children:"aktif"}):a.disabledAt?e.jsx(ne,{tone:"err",children:"dinonaktifkan otomatis"}):e.jsx(ne,{children:"nonaktif"})}function It({onToast:a,onOpenDocs:n}={}){const[i,r]=o.useState(null),[t,g]=o.useState(!1),[d,h]=o.useState(null),[j,u]=o.useState(null),[c,k]=o.useState(!1),[z,R]=o.useState({}),[F,E]=o.useState(null),[m,x]=o.useState([]),[O,K]=o.useState(null),U=o.useCallback(async()=>{try{r((await f.listWebhooks()).endpoints),g(!1)}catch{g(!0)}},[]);o.useEffect(()=>{U()},[U]);const ge=async s=>{E(s);try{x((await f.listWebhookDeliveries(s)).items)}catch{x([])}},pe=async()=>{if(d){k(!0);try{if(d.id)await f.updateWebhook(d.id,{name:d.name,url:d.url,events:d.events,enabled:d.enabled,allowPrivate:d.allowPrivate}),a==null||a("Endpoint webhook diperbarui");else{const s=await f.createWebhook({name:d.name,url:d.url,events:d.events,enabled:d.enabled,allowPrivate:d.allowPrivate});u(s.secret??null),a==null||a("Endpoint webhook dibuat")}h(null),await U()}catch(s){a==null||a(`Gagal menyimpan: ${s.message}`,"err")}finally{k(!1)}}},ie=async s=>{k(!0);try{const w=await f.updateWebhook(s,{rotateSecret:!0});u(w.secret??null),await U()}catch(w){a==null||a(`Gagal merotasi secret: ${w.message}`,"err")}finally{k(!1)}},we=async(s,w)=>{try{await f.updateWebhook(s.id,{enabled:w}),await U()}catch(M){a==null||a(`Gagal mengubah status: ${M.message}`,"err")}},le=async s=>{k(!0);try{const w=await f.testWebhook(s);R(M=>({...M,[s]:w})),await U()}catch(w){R(M=>({...M,[s]:{ok:!1,httpStatus:null,durationMs:0,error:w.message}}))}finally{k(!1)}},ae=async()=>{if(O)try{await f.deleteWebhook(O.id),a==null||a("Endpoint webhook dihapus"),await U()}catch(s){a==null||a(`Gagal menghapus: ${s.message}`,"err")}finally{K(null)}},se=async s=>{try{await f.retryWebhookDelivery(s),F&&await ge(F),await U()}catch(w){a==null||a(`Gagal antre ulang: ${w.message}`,"err")}},b=(s,w)=>h(M=>M&&{...M,events:w?[...new Set([...M.events.filter(_=>_!=="*"),...s])]:M.events.filter(_=>_!=="*"&&!s.includes(_))}),I=(d==null?void 0:d.events.includes("*"))??!1;return e.jsxs(e.Fragment,{children:[e.jsxs(C,{eyebrow:"integrasi",title:"Webhook keluar",children:[e.jsxs("div",{style:{...ce,marginBottom:12},children:["hanoman mengirim ",e.jsx("b",{children:"HTTP POST"})," bertanda tangan ke endpoint yang Anda daftarkan setiap kali sesuatu berubah — backlog dibuat atau berpindah stage, sesi mulai dan selesai, putusan lead terbit, tiket masuk, notifikasi. Pengiriman berjalan di antrean: penerima yang lambat atau mati ",e.jsx("b",{children:"tidak"})," memperlambat hanoman."]}),e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:16},children:[e.jsxs(y,{size:"sm",onClick:()=>{h({...Ot}),u(null)},children:[e.jsx(Fe,{name:"plus",size:14})," Tambah endpoint"]}),e.jsxs(y,{size:"sm",variant:"ghost",onClick:n,children:[e.jsx(Fe,{name:"book-open",size:14})," Dokumentasi webhook"]})]}),t?e.jsx(V,{kind:"error",compact:!0,title:"Gagal memuat endpoint webhook",hint:"Coba muat ulang.",action:()=>void U(),actionLabel:"Coba lagi"}):i===null?e.jsx("div",{style:ce,children:"Memuat…"}):i.length===0?e.jsx(V,{kind:"empty",compact:!0,title:"Belum ada endpoint webhook",hint:"Daftarkan URL penerima pertama untuk mulai berlangganan peristiwa hanoman."}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:10},children:i.map(s=>e.jsxs("div",{"data-testid":`webhook-${s.id}`,style:{border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx("div",{style:{fontWeight:600},children:s.name}),e.jsx(Bt,{e:s}),s.pending>0?e.jsxs(ne,{children:[s.pending," mengantre"]}):null,e.jsxs("div",{style:{marginLeft:"auto",display:"flex",gap:6,alignItems:"center"},children:[e.jsx(N,{checked:s.enabled,"aria-label":`Aktifkan ${s.name}`,onChange:w=>void we(s,w)}),e.jsx(y,{size:"sm",variant:"ghost",disabled:c,onClick:()=>void le(s.id),children:"Test"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void ge(s.id),children:"Riwayat"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{u(null),h({id:s.id,name:s.name,url:s.url,events:s.events,enabled:s.enabled,allowPrivate:s.allowPrivate})},children:"Ubah"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>K(s),children:"Hapus"})]})]}),e.jsx("div",{style:{...Ke,color:"var(--text-muted)",marginTop:6},children:s.url}),e.jsxs("div",{style:{...ce,marginTop:6},children:["Peristiwa: ",e.jsx("code",{children:s.events.join(", ")})," · secret …",s.secretHint," ·"," ","sukses terakhir ",da(s.lastSuccessAt),s.failureStreak>0?` · ${s.failureStreak} gagal beruntun`:""]}),s.disabledReason?e.jsx("div",{style:{...ce,marginTop:6,color:"var(--status-err-tint)"},children:s.disabledReason}):null,z[s.id]?e.jsx("div",{style:{...ce,marginTop:6},children:z[s.id].ok?`Test berhasil — HTTP ${z[s.id].httpStatus} · ${z[s.id].durationMs} ms`:`Test gagal — ${z[s.id].error}`}):null]},s.id))})]}),j?e.jsxs(C,{eyebrow:"secret",title:"Salin sekarang — secret tak ditampilkan lagi",children:[e.jsx(ue,{tone:"brass",children:e.jsx("div",{style:{...Ke,wordBreak:"break-all"},children:j})}),e.jsxs("div",{style:{display:"flex",gap:8,marginTop:10},children:[e.jsx(y,{size:"sm",onClick:()=>{var s;return void((s=navigator.clipboard)==null?void 0:s.writeText(j))},children:"Salin secret"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>u(null),children:"Tutup"})]})]}):null,d?e.jsx(C,{eyebrow:d.id?"ubah":"tambah",title:d.id?"Ubah endpoint":"Endpoint baru",children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsx(ee,{label:"Nama",children:e.jsx(Y,{value:d.name,placeholder:"mis. Dashboard internal",onChange:s=>h({...d,name:s.target.value})})}),e.jsx(ee,{label:"URL tujuan",children:e.jsx(Y,{value:d.url,placeholder:"https://contoh.id/hanoman-webhook",onChange:s=>h({...d,url:s.target.value})})}),e.jsxs("div",{children:[e.jsx("div",{style:{fontWeight:600,fontSize:13,marginBottom:6},children:"Peristiwa yang dikirim"}),e.jsx(me,{checked:I,label:"Semua peristiwa",onChange:s=>h({...d,events:s?["*"]:[]})}),I?null:e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[Pt.map(s=>e.jsxs("div",{children:[e.jsx(me,{checked:s.types.every(w=>d.events.includes(w)),label:s.label,onChange:w=>b(s.types,w)}),e.jsx("div",{style:{paddingLeft:22,display:"flex",flexWrap:"wrap",gap:10},children:s.types.map(w=>e.jsx(me,{checked:d.events.includes(w),label:w,onChange:M=>h({...d,events:M?[...new Set([...d.events.filter(_=>_!=="*"),w])]:d.events.filter(_=>_!==w&&_!=="*")})},w))})]},s.entity)),e.jsxs("div",{style:ce,children:[e.jsx("code",{children:Ua})," selalu terkirim saat tombol Test ditekan, apa pun langganannya."]})]})]}),e.jsx(me,{checked:d.allowPrivate,label:"Izinkan alamat internal / loopback",onChange:s=>h({...d,allowPrivate:s})}),e.jsx("div",{style:ce,children:"Biarkan mati kecuali penerima memang berjalan di mesin/jaringan yang sama. Menyalakannya membuka jalan ke layanan internal yang tak pernah dimaksudkan terekspos."}),e.jsx(me,{checked:d.enabled,label:"Aktif",onChange:s=>h({...d,enabled:s})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(y,{size:"sm",disabled:c||!d.name||!d.url||d.events.length===0,onClick:()=>void pe(),children:"Simpan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>h(null),children:"Batal"}),d.id?e.jsx(y,{size:"sm",variant:"ghost",disabled:c,onClick:()=>void ie(d.id),children:"Rotasi secret"}):null]})]})}):null,F?e.jsxs(C,{eyebrow:"riwayat",title:"Riwayat pengiriman",children:[e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:8},children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>E(null),children:"Tutup riwayat"})}),m.length===0?e.jsx("div",{style:ce,children:"Belum ada pengiriman."}):e.jsx("div",{className:"hn-local-overflow",style:{overflowX:"auto"},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12.5},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{textAlign:"left",color:"var(--text-muted)"},children:[e.jsx("th",{style:{padding:"6px 8px"},children:"Waktu"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Jenis"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Status"}),e.jsx("th",{style:{padding:"6px 8px"},children:"HTTP"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Percobaan"}),e.jsx("th",{style:{padding:"6px 8px"},children:"Galat"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:m.map(s=>e.jsxs("tr",{style:{borderTop:"1px solid var(--border-hair)"},children:[e.jsx("td",{style:{padding:"6px 8px",whiteSpace:"nowrap"},children:da(s.createdAt)}),e.jsx("td",{style:{padding:"6px 8px",...Ke},children:s.eventType}),e.jsx("td",{style:{padding:"6px 8px"},children:s.status}),e.jsx("td",{style:{padding:"6px 8px"},children:s.httpStatus??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:`${s.attempt} / ${s.maxAttempts}`}),e.jsx("td",{style:{padding:"6px 8px",color:"var(--text-muted)"},children:s.error??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:s.status==="failed"||s.status==="dropped"?e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void se(s.id),children:"Antre ulang"}):null})]},s.id))})]})})]}):null,e.jsx(ba,{open:!!O,title:"Hapus endpoint webhook?",message:O?`"${O.name}" beserta seluruh riwayat pengirimannya akan dihapus.`:"",confirmLabel:"Hapus",onCancel:()=>K(null),onConfirm:()=>void ae()})]})}const J={fontSize:13,color:"var(--text-muted)",lineHeight:1.6},Mt={fontFamily:"var(--font-mono)",fontSize:12,whiteSpace:"pre",overflowX:"auto",background:"var(--bone-200)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:12,margin:0};function Je({text:a,label:n="Salin"}){const[i,r]=o.useState(!1);return e.jsxs("div",{style:{position:"relative"},children:[e.jsx("pre",{style:Mt,children:a}),e.jsx("div",{style:{marginTop:6},children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(a),r(!0),setTimeout(()=>r(!1),1500)},children:i?"Tersalin":n})})]})}const Lt=`// Node.js (Express) — verifikasi tanda tangan webhook hanoman
2
2
  import express from "express";
3
3
  import { createHmac, timingSafeEqual } from "node:crypto";
4
4
 
@@ -1 +1 @@
1
- import{T as Ae,j as t,F as G,L as lt,B as ae,I as X,a as B,S as M,u as Ue,M as xe,c as $,d as O,H as ot,e as w,P as Te,E as dt,s as ct,f as H,g as de,h as A,o as we,k as ut,l as mt,m as pt,R as gt,n as ht,p as ce,q as ft}from"./index-CCJTT5hd.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as xt}from"./live-Jy46oHWQ.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const bt={backlog:"Backlog",doing:"Dikerjakan",review:"Review",done:"Selesai"},K=Ae.map(e=>({key:e,label:bt[e]})),vt=()=>Object.fromEntries(Ae.map(e=>[e,[]])),pe=(e,a)=>e!==a,He=e=>e.length===0?0:e.reduce((a,n)=>n.order>a?n.order:a,-1/0)+1;function yt(e,a,n,r){if(!pe(n,r))return null;const l=e[n].find(g=>g.id===a);if(!l)return null;const o={status:r,order:He(e[r])},d={...e};return d[n]=e[n].filter(g=>g.id!==a),d[r]=[...e[r],{...l,...o}],{board:d,patch:o}}function ue(e,a){const n={...e};return n[a.status]=e[a.status].map(r=>r.id===a.id?a:r),n}const De=e=>e?e.slice(0,10):"",Ee=e=>/^\d{4}-\d{2}-\d{2}$/.test(e)?`${e}T12:00:00.000Z`:null,F=864e5,ee=e=>Math.floor(e/F)*F,Me=e=>{if(!e)return null;const a=new Date(e).getTime();return Number.isFinite(a)?a:null};function Y(e){const a=Me(e.startDate),n=Me(e.dueDate);if(a===null&&n===null)return null;const r=a??n,l=n??a;return{start:ee(Math.min(r,l)),end:ee(Math.max(r,l))+F,invalid:l<r}}const jt=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),Be=e=>e?jt.format(new Date(e)):null;function Q(e){const a=Be(e.startDate),n=Be(e.dueDate);return a&&n?`${a} → ${n}`:n?`→ ${n}`:a}const Le=["day","week","month"],Ke={day:{cell:34,minTicks:14},week:{cell:56,minTicks:8},month:{cell:84,minTicks:6}},kt=e=>Ke[e].cell,St=120,It=(e,a)=>{const n=ee(e);if(a==="day")return n;if(a==="week")return n-(new Date(n).getUTCDay()+6)%7*F;const r=new Date(n);return Date.UTC(r.getUTCFullYear(),r.getUTCMonth(),1)},Ct=(e,a)=>{if(a==="day")return e+F;if(a==="week")return e+7*F;const n=new Date(e);return Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,1)},Tt=new Intl.DateTimeFormat("id-ID",{day:"numeric",timeZone:"UTC"}),$e=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),wt=new Intl.DateTimeFormat("id-ID",{month:"short",timeZone:"UTC"}),Dt=new Intl.DateTimeFormat("id-ID",{month:"short",year:"2-digit",timeZone:"UTC"}),Et=(e,a)=>{const n=new Date(e);return a==="day"?n.getUTCDate()===1:a==="week"?n.getUTCDate()<=7:n.getUTCMonth()===0},Mt=(e,a,n)=>{const r=new Date(e);return a==="day"?(n?$e:Tt).format(r):a==="week"?$e.format(r):(n?Dt:wt).format(r)};function Ge(e,a,n){const r=ee(n);let l=r,o=r+F;for(const c of e)c.start<l&&(l=c.start),c.end>o&&(o=c.end);const d=It(l,a),{minTicks:g}=Ke[a],u=[];let i=d;for(;u.length<St&&(i<o||u.length<g);){const c=Et(i,a);u.push({start:i,label:Mt(i,a,c),major:c}),i=Ct(i,a)}return{from:d,to:i,zoom:a,ticks:u}}function Ye(e,a){const n=a.to-a.from;if(n<=0||e.end<=a.from||e.start>=a.to)return null;const r=Math.max(e.start,a.from),l=Math.min(e.end,a.to);return{left:(r-a.from)/n*100,width:(l-r)/n*100,clippedStart:e.start<a.from,clippedEnd:e.end>a.to,invalid:e.invalid}}function ge(e,a){const n=Y(e);return n?Ye(n,a):null}function Bt(e){let a=1/0,n=-1/0,r=!1;for(const l of e){const o=Y(l);o&&(o.start<a&&(a=o.start),o.end>n&&(n=o.end),o.invalid&&(r=!0))}return a===1/0?null:{start:a,end:n,invalid:r}}function Lt(e,a){const n=ee(a);return n<e.from||n>=e.to?null:(n-e.from)/(e.to-e.from)*100}function $t(e,a){const n=[],r=[],l=[];for(const o of e){const d=Y(o);if(!d){r.push(o);continue}const g=ge(o,a);if(!g){l.push(o);continue}n.push({task:o,geometry:g,start:d.start})}return n.sort((o,d)=>o.start-d.start||o.task.title.localeCompare(d.task.title,"id")||o.task.id.localeCompare(d.task.id)),{rows:n.map(({task:o,geometry:d})=>({task:o,geometry:d})),unscheduled:r,outside:l}}const ze=(e,a)=>e.title.localeCompare(a.title,"id")||e.id.localeCompare(a.id);function zt(e,a,n){const r=Symbol("no-project"),l=new Map;for(const u of e){const i=u.projectId??r,c=l.get(i);c?c.tasks.push(u):l.set(i,{projectId:u.projectId,tasks:[u]})}const o=[...l.values()].map(({projectId:u,tasks:i})=>{const c=Bt(i),p=[],v=[];for(const x of i){const h=Y(x);h?p.push({task:x,start:h.start}):v.push(x)}return p.sort((x,h)=>x.start-h.start||ze(x.task,h.task)),v.sort(ze),{projectId:u,span:c,geometry:c?Ye(c,a):null,tasks:[...p.map(x=>x.task),...v]}}),d=u=>u.geometry?0:u.span?1:2,g=u=>u.projectId===null?[1,""]:[0,u.projectId];return o.sort((u,i)=>{const[c,p]=g(u),[v,x]=g(i);return d(u)-d(i)||(u.span&&i.span?u.span.start-i.span.start:0)||n(u.projectId).localeCompare(n(i.projectId),"id")||c-v||p.localeCompare(x)}),o}const Ot={tinggi:"err",sedang:"neutral",rendah:"neutral"};function Rt({task:e,members:a,dragging:n,onDragStart:r,onDragEnd:l,onOpen:o,onMove:d,onAssign:g,onEscalate:u,onUnlink:i}){var v;const c=((v=a.find(x=>x.id===e.memberId))==null?void 0:v.name)??"belum ditugaskan",p=Q(e);return t.jsxs("div",{draggable:!0,"data-testid":`team-card-${e.id}`,onDragStart:x=>{x.dataTransfer.effectAllowed="move",x.dataTransfer.setData("text/plain",e.id),r()},onDragEnd:l,style:{flex:"0 0 auto",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",padding:10,boxShadow:"var(--shadow-xs)",cursor:"grab",opacity:n?.4:1},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6},children:[t.jsx(ae,{tone:Ot[e.priority]??"neutral",size:"sm",variant:e.priority==="tinggi"?"soft":"outline",children:e.priority}),t.jsx("span",{style:{flex:1}}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.projectId??"tanpa project"})]}),t.jsx("button",{type:"button",onClick:()=>o(e),style:{display:"block",width:"100%",textAlign:"left",border:"none",background:"none",padding:0,cursor:"pointer",fontFamily:"var(--font-ui)",fontSize:13,fontWeight:"var(--weight-medium)",color:"var(--text-strong)",lineHeight:1.35},children:e.title}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:6,flexWrap:"wrap",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[t.jsx(X,{name:"user",size:12,color:"var(--text-subtle)"}),t.jsx("span",{children:c}),p&&t.jsxs(t.Fragment,{children:[t.jsx("span",{"aria-hidden":"true",children:"·"}),t.jsx("span",{children:p})]})]}),t.jsx("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:6,flexWrap:"wrap"},children:e.specId?t.jsxs(t.Fragment,{children:[t.jsx(ae,{tone:e.spec?"ok":"warn",size:"sm",icon:e.spec?"link":"unlink",children:e.spec?`${e.spec.id} · ${e.spec.stage}`:"tautan putus"}),t.jsx(B,{size:"sm",variant:"ghost",leftIcon:"unlink","aria-label":`Lepas tautan: ${e.title}`,onClick:()=>i(e),children:"Lepas tautan"})]}):t.jsx(B,{size:"sm",variant:"ghost",leftIcon:"git-branch","aria-label":`Eskalasi ke backlog: ${e.title}`,onClick:()=>u(e),children:"Eskalasi"})}),t.jsxs("div",{style:{display:"flex",gap:6,marginTop:8},children:[t.jsx(M,{size:"sm",value:e.status,"aria-label":`Pindah kolom: ${e.title}`,onChange:x=>d(e,x.target.value),options:K.map(x=>({value:x.key,label:x.label})),style:{flex:1,minWidth:0}}),t.jsx(M,{size:"sm",value:e.memberId??"","aria-label":`Tugaskan: ${e.title}`,onChange:x=>g(e,x.target.value||null),options:[{value:"",label:"Belum ditugaskan"},...a.map(x=>({value:x.id,label:x.name}))],style:{flex:1,minWidth:0}})]})]})}function Pt({board:e,totals:a,columns:n,members:r,onMove:l,onAssign:o,onOpen:d,onEscalate:g,onUnlink:u}){const[i,c]=m.useState(null),[p,v]=m.useState(null),x=h=>{i&&pe(i.from,h)&&l(i.task,h),c(null),v(null)};return t.jsx("div",{"data-testid":"team-board",className:"hn-board-local-overflow",style:{flex:"1 1 auto",minHeight:0,display:"flex",gap:10,overflowX:"auto",overflowY:"hidden",alignItems:"stretch",paddingBottom:4},children:n.map(h=>{const y=e[h.key],f=!!i&&pe(i.from,h.key),k=f&&p===h.key,L=Math.max(0,(a[h.key]??0)-y.length);return t.jsxs("div",{"data-testid":`team-col-${h.key}`,onDragOver:S=>{f&&(S.preventDefault(),S.dataTransfer.dropEffect="move",v(h.key))},onDragLeave:()=>v(S=>S===h.key?null:S),onDrop:S=>{S.preventDefault(),x(h.key)},style:{flex:"0 0 244px",display:"flex",flexDirection:"column",minHeight:0,padding:10,borderRadius:"var(--radius-lg)",background:k?"var(--brass-100)":"var(--bone-100)",border:`1px ${f?"dashed":"solid"} ${k?"var(--brass-500)":"var(--border-hair)"}`,opacity:i&&!f?.5:1,transition:"var(--transition-fast)"},children:[t.jsxs("div",{style:{...G,display:"flex",alignItems:"center",gap:6,marginBottom:8},children:[t.jsx("span",{className:"hn-eyebrow",children:h.label}),t.jsx("span",{style:{flex:1}}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)"},children:y.length})]}),t.jsx("div",{style:{...lt,display:"flex",flexDirection:"column",gap:8},children:y.map(S=>t.jsx(Rt,{task:S,members:r,dragging:(i==null?void 0:i.task.id)===S.id,onDragStart:()=>c({task:S,from:h.key}),onDragEnd:()=>{c(null),v(null)},onOpen:d,onMove:l,onAssign:o,onEscalate:g,onUnlink:u},S.id))}),L>0&&t.jsxs("div",{style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:["menampilkan ",y.length," dari ",a[h.key]," — persempit penyaring"]})]},h.key)})})}const U=232,he=34,me=6,_t={brass:{bg:"var(--brass-300)",border:"var(--brass-500)"},err:{bg:"var(--status-err-tint)",border:"var(--status-err)"},muted:{bg:"var(--bone-300)",border:"var(--border-strong)"},envelope:{bg:"var(--bone-200)",border:"var(--border-hair)"}},Oe={position:"sticky",left:0,zIndex:1,flex:`0 0 ${U}px`,width:U,boxSizing:"border-box",padding:"5px 10px",minWidth:0,background:"var(--surface-card)",borderRight:"1px solid var(--border-hair)"},V={overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"};function Nt({spec:e}){const a=e.geometry,n=_t[e.tone];return t.jsxs("button",{type:"button","data-testid":`timeline-bar-${e.key}`,"data-tone":e.tone,"data-invalid":a.invalid?"true":"false","data-clipped-start":a.clippedStart?"true":"false","data-clipped-end":a.clippedEnd?"true":"false",title:e.title,"aria-label":e.title,onClick:e.onClick,style:{position:"absolute",top:me,height:he-me*2,left:`${a.left}%`,width:`${a.width}%`,minWidth:3,minHeight:he-me*2,display:"flex",alignItems:"center",padding:0,overflow:"hidden",background:n.bg,border:`1px solid ${n.border}`,borderTopLeftRadius:a.clippedStart?0:"var(--radius-sm)",borderBottomLeftRadius:a.clippedStart?0:"var(--radius-sm)",borderTopRightRadius:a.clippedEnd?0:"var(--radius-sm)",borderBottomRightRadius:a.clippedEnd?0:"var(--radius-sm)",cursor:e.onClick?"pointer":"default"},children:[a.clippedStart&&t.jsx(X,{name:"chevron-left",size:11,color:n.border}),t.jsx("span",{style:{flex:1}}),a.clippedEnd&&t.jsx(X,{name:"chevron-right",size:11,color:n.border})]})}function Ze({window:e,rows:a,today:n,emptyHint:r,testId:l,labelHead:o}){const d=kt(e.zoom),g=e.ticks.length*d,u=Lt(e,n),i={position:"relative",width:g,height:he,flex:`0 0 ${g}px`,backgroundImage:`repeating-linear-gradient(to right, var(--border-hair) 0 1px, transparent 1px ${d}px)`};return t.jsx("div",{"data-testid":l??"team-timeline",className:"hn-timeline-scroll",style:{flex:"1 1 auto",minHeight:0,minWidth:0,maxWidth:"100%",overflowX:"auto",overflowY:"auto"},children:t.jsxs("div",{"data-testid":"timeline-canvas",style:{position:"relative",minWidth:U+g,width:U+g},children:[t.jsxs("div",{style:{display:"flex",position:"sticky",top:0,zIndex:2,background:"var(--bone-100)",borderBottom:"1px solid var(--border-hair)"},children:[t.jsx("div",{style:{...Oe,zIndex:3,background:"var(--bone-100)"},children:t.jsx("span",{className:"hn-eyebrow",children:o??"Tugas"})}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:`repeat(${e.ticks.length}, ${d}px)`,width:g,flex:`0 0 ${g}px`},children:e.ticks.map(c=>t.jsx("div",{"data-testid":"timeline-tick",style:{borderLeft:`1px solid ${c.major?"var(--border-strong)":"var(--border-hair)"}`,padding:"5px 4px",fontFamily:"var(--font-mono)",fontSize:10,...V,color:c.major?"var(--text-body)":"var(--text-subtle)"},children:c.label},c.start))})]}),a.length===0?t.jsx("div",{"data-testid":"timeline-empty",style:{position:"sticky",left:0,width:U,padding:"18px 10px",fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:r??"Tak ada yang bisa dihamparkan di jendela ini."}):a.map(c=>t.jsxs("div",{"data-testid":`timeline-row-${c.key}`,style:{display:"flex",borderBottom:"1px solid var(--border-hair)"},children:[t.jsxs("div",{style:Oe,children:[t.jsx("div",{style:{...V,fontSize:12,fontWeight:"var(--weight-medium)",color:"var(--text-strong)"},children:c.label}),c.meta&&t.jsx("div",{style:{...V,fontSize:10,color:"var(--text-subtle)"},children:c.meta})]}),t.jsx("div",{style:i,children:c.bars.map(p=>t.jsx(Nt,{spec:p},p.key))})]},c.key)),u!==null&&t.jsx("div",{"data-testid":"timeline-today","aria-hidden":"true",style:{position:"absolute",top:0,bottom:0,width:2,pointerEvents:"none",left:U+u/100*g,background:"var(--brass-500)",opacity:.5}})]})})}function Re({testId:e,icon:a,title:n,hint:r,tasks:l,onOpen:o}){return l.length===0?null:t.jsxs("div",{"data-testid":e,style:{...G,marginTop:10,padding:10,background:"var(--bone-100)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-lg)"},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6,flexWrap:"wrap"},children:[t.jsx(X,{name:a,size:13,color:"var(--text-subtle)"}),t.jsxs("span",{className:"hn-eyebrow",children:[n," · ",l.length]}),r&&t.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:r})]}),t.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:6},children:l.map(d=>t.jsx("button",{type:"button",onClick:()=>o(d),style:{padding:"3px 10px",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-pill)",fontFamily:"var(--font-ui)",fontSize:12,color:"var(--text-body)",cursor:"pointer"},children:d.title},d.id))})]})}function Ft({tasks:e,members:a,zoom:n,today:r,hidden:l,onOpen:o}){const d=m.useMemo(()=>{const p=e.map(Y).filter(v=>v!==null);return Ge(p,n,r)},[e,n,r]),{rows:g,unscheduled:u,outside:i}=m.useMemo(()=>$t(e,d),[e,d]),c=m.useMemo(()=>g.map(({task:p,geometry:v})=>{var f;const x=((f=a.find(k=>k.id===p.memberId))==null?void 0:f.name)??"belum ditugaskan",h=Q(p),y=[v.invalid?"tenggat mendahului mulai":null,v.clippedStart||v.clippedEnd?"melewati tepi jendela":null].filter(Boolean);return{key:p.id,label:p.title,meta:h?`${x} · ${h}`:x,bars:[{key:p.id,geometry:v,tone:v.invalid?"err":p.status==="done"?"muted":"brass",title:[p.title,h,...y].filter(Boolean).join(" · "),onClick:()=>o(p)}]}}),[g,a,o]);return t.jsxs(t.Fragment,{children:[t.jsx(Ze,{window:d,rows:c,today:r,emptyHint:"Belum ada tugas bertanggal — isi mulai atau tenggat di kartunya."}),l>0&&t.jsxs("div",{"data-testid":"timeline-truncated",style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:[l," tugas tak termuat karena plafon 200 per kolom — persempit penyaring"]}),t.jsx(Re,{testId:"timeline-unscheduled",icon:"calendar-off",title:"Belum dijadwalkan",tasks:u,onOpen:o}),t.jsx(Re,{testId:"timeline-outside",icon:"chevrons-left-right",title:"Di luar jendela",hint:"pilih zoom yang lebih lebar",tasks:i,onOpen:o})]})}const Wt="__none__",At=16,Pe=(e,a)=>a.invalid?"err":e.status==="done"?"muted":"brass",_e=(e,a,n)=>[e.title,n,a.invalid?"tenggat mendahului mulai":null,a.clippedStart||a.clippedEnd?"melewati tepi jendela":null].filter(Boolean).join(" · ");function Ut({testId:e,open:a,name:n,count:r,onClick:l}){return t.jsxs("button",{type:"button",onClick:l,"data-testid":e,"aria-expanded":a,style:{display:"flex",alignItems:"center",gap:5,width:"100%",padding:0,background:"none",border:"none",cursor:"pointer",textAlign:"left",minHeight:0,fontFamily:"var(--font-ui)",fontSize:12,fontWeight:"var(--weight-medium)",color:"var(--text-strong)"},children:[t.jsx(X,{name:a?"chevron-down":"chevron-right",size:12,color:"var(--text-subtle)"}),t.jsx("span",{style:{...V,flex:1},children:n}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:10,color:"var(--text-subtle)"},children:r})]})}function Ht({tasks:e,projects:a,members:n,zoom:r,today:l,hidden:o,expanded:d,onToggle:g,onOpen:u}){const i=m.useMemo(()=>{const h=e.map(Y).filter(y=>y!==null);return Ge(h,r,l)},[e,r,l]),c=m.useCallback(h=>{var y;return h===null?"Tanpa project":((y=a.find(f=>f.id===h))==null?void 0:y.name)??h},[a]),p=m.useMemo(()=>zt(e,i,c),[e,i,c]),v=m.useMemo(()=>new Set(d),[d]),x=m.useMemo(()=>{var y;const h=[];for(const f of p){const k=f.projectId??Wt,L=v.has(k),S=c(f.projectId),b=f.geometry?Q({startDate:new Date(f.span.start).toISOString(),dueDate:new Date(f.span.end-1).toISOString()}):f.span?"di luar jendela · pilih zoom yang lebih lebar":"belum dijadwalkan",D=[];if(f.geometry){D.push({key:`span:${k}`,geometry:f.geometry,tone:f.geometry.invalid?"err":"envelope",title:`${S} · ${b??""}`.trim(),onClick:()=>g(k)});for(const C of f.tasks){const E=ge(C,i);E&&D.push({key:`seg:${C.id}`,geometry:E,tone:Pe(C,E),title:_e(C,E,Q(C)),onClick:()=>u(C)})}}if(h.push({key:`p:${k}`,meta:b,bars:D,label:t.jsx(Ut,{testId:`expand-${k}`,open:L,name:S,count:f.tasks.length,onClick:()=>g(k)})}),!!L)for(const C of f.tasks){const E=ge(C,i),j=((y=n.find(_=>_.id===C.memberId))==null?void 0:y.name)??"belum ditugaskan",P=Q(C);h.push({key:`t:${C.id}`,label:t.jsx("span",{style:{...V,display:"block",paddingLeft:At},children:C.title}),meta:P?`${j} · ${P}`:j,bars:E?[{key:`t:${C.id}`,geometry:E,tone:Pe(C,E),title:_e(C,E,P),onClick:()=>u(C)}]:[]})}}return h},[p,v,c,i,n,g,u]);return t.jsxs(t.Fragment,{children:[t.jsx(Ze,{window:i,rows:x,today:l,testId:"team-projects",labelHead:"Project",emptyHint:"Belum ada project bertanggal — isi mulai atau tenggat di kartunya."}),o>0&&t.jsxs("div",{"data-testid":"projects-truncated",style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:[o," tugas tak termuat karena plafon 200 per kolom — amplop project bisa lebih pendek dari rentang sebenarnya; persempit kolom, anggota, atau pencarian"]})]})}const fe={tinggi:"Tinggi",sedang:"Sedang",rendah:"Rendah"},Kt=Object.keys(fe).map(e=>({value:e,label:fe[e]})),Ne=(e,a)=>({title:(e==null?void 0:e.title)??"",detail:(e==null?void 0:e.detail)??"",projectId:e?e.projectId??"":a??"",status:(e==null?void 0:e.status)??"backlog",priority:e&&e.priority in fe?e.priority:"sedang",memberId:(e==null?void 0:e.memberId)??"",startDate:De((e==null?void 0:e.startDate)??null),dueDate:De((e==null?void 0:e.dueDate)??null)});function Gt({open:e,task:a,projects:n,members:r,defaultProjectId:l,orderFor:o,onClose:d,onSaved:g,onToast:u}){const[i,c]=m.useState(()=>Ne(a,l)),[p,v]=m.useState(!1),{confirm:x,dialog:h}=Ue(),y=`${e?"1":"0"}:${(a==null?void 0:a.id)??""}`,f=m.useRef(y);if(f.current!==y&&(f.current=y,e&&c(Ne(a,l))),!e)return null;const k=b=>c(D=>({...D,...b}));async function L(){if(!i.title.trim()){u("Judul tugas wajib diisi","err","x-circle");return}v(!0);const b=!a||a.status!==i.status,D={title:i.title.trim(),detail:i.detail.trim()||null,projectId:i.projectId||null,status:i.status,priority:i.priority,memberId:i.memberId||null,startDate:Ee(i.startDate),dueDate:Ee(i.dueDate),...b?{order:o(i.status)}:{}};try{a?await w.patchTask(a.id,D):await w.createTask(D),u(a?"Tugas diperbarui":"Tugas dibuat","ok","check"),g(),d()}catch{u("Gagal menyimpan tugas","err","x-circle")}finally{v(!1)}}async function S(){a&&await x({title:`Hapus "${a.title}"?`,message:"Kartu ini hilang dari papan di semua device yang tersinkron.",confirmLabel:"Hapus tugas",tone:"danger",icon:"trash-2",run:()=>w.deleteTask(a.id)})&&(u("Tugas dihapus","ok","trash-2"),g(),d())}return t.jsxs(t.Fragment,{children:[t.jsxs(xe,{open:e,onClose:d,icon:"clipboard-list",eyebrow:"Papan tim",title:a?"Ubah tugas":"Tugas baru",footer:t.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[a&&t.jsx(B,{variant:"ghost",leftIcon:"trash-2",onClick:S,disabled:p,children:"Hapus"}),t.jsx("span",{style:{flex:1}}),t.jsx(B,{variant:"secondary",onClick:d,disabled:p,children:"Batal"}),t.jsx(B,{onClick:L,loading:p,children:a?"Simpan":"Buat tugas"})]}),children:[t.jsx($,{label:"Judul",children:t.jsx(O,{value:i.title,"aria-label":"Judul tugas",placeholder:"mis. Rapikan halaman harga",onChange:b=>k({title:b.target.value}),style:{width:"100%"}})}),t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[t.jsx($,{label:"Project",children:t.jsx(M,{value:i.projectId,"aria-label":"Project tugas",onChange:b=>k({projectId:b.target.value}),options:[{value:"",label:"Tanpa project"},...n.map(b=>({value:b.id,label:b.name}))]})}),t.jsx($,{label:"Kolom",children:t.jsx(M,{value:i.status,"aria-label":"Kolom tugas",onChange:b=>k({status:b.target.value}),options:K.map(b=>({value:b.key,label:b.label}))})}),t.jsx($,{label:"Prioritas",children:t.jsx(M,{value:i.priority,"aria-label":"Prioritas tugas",onChange:b=>k({priority:b.target.value}),options:Kt})})]}),t.jsx($,{label:"Ditugaskan ke",children:t.jsx(M,{value:i.memberId,"aria-label":"Anggota tugas",onChange:b=>k({memberId:b.target.value}),options:[{value:"",label:"Belum ditugaskan"},...r.map(b=>({value:b.id,label:b.role?`${b.name} · ${b.role}`:b.name}))],style:{width:"100%"}})}),t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[t.jsx($,{label:"Mulai",children:t.jsx(O,{type:"date",value:i.startDate,"aria-label":"Tanggal mulai",onChange:b=>k({startDate:b.target.value})})}),t.jsx($,{label:"Tenggat",children:t.jsx(O,{type:"date",value:i.dueDate,"aria-label":"Tanggal tenggat",onChange:b=>k({dueDate:b.target.value})})})]}),t.jsx($,{label:"Detail",hint:"Opsional — konteks yang tak muat di judul.",children:t.jsx(ot,{value:i.detail,"aria-label":"Detail tugas",rows:4,placeholder:"mis. tunggu aset dari klien, deadline ikut jadwal kampanye",onChange:b=>k({detail:b.target.value})})})]}),h]})}const Yt=dt.map(e=>({value:e,label:ct(e).label}));function Zt({task:e,projects:a,onClose:n,onDone:r,onToast:l}){const[o,d]=m.useState("brief"),[g,u]=m.useState(()=>Te.some(f=>f.value===e.priority)?e.priority:"sedang"),[i,c]=m.useState(""),[p,v]=m.useState(!1),x=e.projectId===null,h=e.projectId??i;async function y(){if(!(!h||p)){v(!0);try{const f=await w.escalateTask(e.id,{source:o,priority:g,...e.projectId?{}:{projectId:i}});l(f.created?`Dieskalasi jadi ${f.spec.id}`:`Sudah tertaut ke ${f.spec.id}`,"ok","link"),r(f.task),n()}catch{l("Gagal mengeskalasi kartu","err","x-circle")}finally{v(!1)}}}return t.jsxs(xe,{open:!0,onClose:p?void 0:n,icon:"git-branch",eyebrow:"Papan tim",title:"Eskalasi ke backlog",footer:t.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[t.jsx("span",{style:{flex:1}}),t.jsx(B,{variant:"secondary",onClick:n,disabled:p,children:"Batal"}),t.jsx(B,{onClick:y,loading:p,disabled:!h,leftIcon:"git-branch",children:"Eskalasi"})]}),children:[t.jsxs("div",{style:{fontSize:13.5,color:"var(--text-strong)",lineHeight:1.55,marginBottom:14},children:["Kartu ",t.jsx("strong",{children:e.title})," tetap di papan. Yang lahir adalah backlog item baru yang bisa dikerjakan sesi agen, dan kartu ini menampilkan stage-nya."]}),x&&t.jsxs($,{label:"Project",children:[t.jsx(M,{"aria-label":"Project",value:i,style:{width:"100%"},onChange:f=>c(f.target.value),options:[{value:"",label:"Pilih project…"},...a.map(f=>({value:f.id,label:f.name}))]}),t.jsx("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:"Nomor SPEC diambil dari repo project, jadi kartu tanpa project belum bisa dieskalasi."})]}),t.jsx($,{label:"Source",children:t.jsx(M,{"aria-label":"Source",value:o,style:{width:"100%"},onChange:f=>d(f.target.value),options:Yt})}),t.jsx($,{label:"Prioritas",children:t.jsx(M,{"aria-label":"Prioritas",value:g,style:{width:"100%"},onChange:f=>u(f.target.value),options:Te})})]})}function qt({m:e,busy:a,onSave:n,onToggle:r,onDelete:l}){const[o,d]=m.useState(!1),[g,u]=m.useState(e.name),[i,c]=m.useState(e.role??"");return o?t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:8,padding:"12px 14px",marginBottom:8,border:"1px solid var(--border-strong)",borderRadius:"var(--radius-md)",background:"var(--surface-card)"},children:[t.jsx(O,{size:"sm",value:g,"aria-label":`Nama ${e.name}`,placeholder:"mis. Dena Meidina",onChange:p=>u(p.target.value)}),t.jsx(O,{size:"sm",value:i,"aria-label":`Peran ${e.name}`,placeholder:"mis. desainer",onChange:p=>c(p.target.value)}),t.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[e.email," — ganti email berarti hapus lalu buat baru."]}),t.jsxs("div",{style:{display:"flex",gap:8},children:[t.jsx(B,{size:"sm",disabled:a,onClick:()=>{n(e.id,{name:g.trim(),role:i.trim()||null}),d(!1)},children:"Simpan"}),t.jsx(B,{size:"sm",variant:"ghost",onClick:()=>d(!1),children:"Batal"})]})]}):t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",marginBottom:8,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",opacity:e.active?1:.6},children:[t.jsxs("span",{style:{flex:1,minWidth:0},children:[t.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{fontWeight:"var(--weight-semibold)",color:"var(--text-strong)"},children:e.name}),e.role&&t.jsx(ae,{tone:"neutral",size:"sm",children:e.role}),!e.active&&t.jsx(ae,{tone:"warn",size:"sm",children:"nonaktif"})]}),t.jsx("span",{style:{display:"block",fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2},children:e.email})]}),t.jsx(de,{icon:"pencil",label:`Ubah ${e.name}`,size:"sm",onClick:()=>d(!0)}),t.jsx(de,{icon:e.active?"user-minus":"user-check",size:"sm",label:`${e.active?"Nonaktifkan":"Aktifkan"} ${e.name}`,onClick:()=>r(e)}),t.jsx(de,{icon:"trash-2",label:`Hapus ${e.name}`,size:"sm",onClick:()=>l(e)})]})}function Jt({open:e,onClose:a,onChanged:n,onToast:r}){const[l,o]=m.useState([]),[d,g]=m.useState("loading"),[u,i]=m.useState(!1),[c,p]=m.useState(""),[v,x]=m.useState(""),[h,y]=m.useState(""),{confirm:f,dialog:k}=Ue(),L=m.useRef(n);L.current=n;const S=m.useCallback(()=>{g("loading"),w.listMembers().then(j=>{o(j.items),g("ready"),L.current(j.items)}).catch(()=>g("error"))},[]);if(m.useEffect(()=>{e&&S()},[e,S]),!e)return null;async function b(){if(!c.trim()||!v.trim()){r("Nama & email wajib diisi","err","x-circle");return}i(!0);try{await w.createMember({name:c.trim(),email:v.trim(),role:h.trim()||null}),p(""),x(""),y(""),r("Anggota ditambahkan","ok","user-plus"),S()}catch{r("Gagal menambah anggota — email mungkin sudah terdaftar","err","x-circle")}finally{i(!1)}}async function D(j,P){i(!0);try{await w.patchMember(j,P),S()}catch{r("Gagal menyimpan anggota","err","x-circle")}finally{i(!1)}}async function C(j){i(!0);try{await w.patchMember(j.id,{active:!j.active}),S()}catch{r("Gagal mengubah status anggota","err","x-circle")}finally{i(!1)}}async function E(j){await f({title:`Hapus ${j.name} dari direktori?`,message:"Tugasnya tidak ikut terhapus — kartu yang ditugaskan padanya jadi 'belum ditugaskan'.",confirmLabel:"Hapus anggota",tone:"danger",icon:"trash-2",run:()=>w.deleteMember(j.id)})&&(r("Anggota dihapus","ok","trash-2"),S())}return t.jsxs(t.Fragment,{children:[t.jsxs(xe,{open:e,onClose:a,icon:"users",eyebrow:"Papan tim",title:"Anggota",width:620,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap",alignItems:"flex-end",marginBottom:16,paddingBottom:16,borderBottom:"1px solid var(--border-hair)"},children:[t.jsx(O,{size:"sm",value:c,"aria-label":"Nama anggota baru",placeholder:"Nama",onChange:j=>p(j.target.value),style:{flex:"1 1 140px"}}),t.jsx(O,{size:"sm",value:v,"aria-label":"Email anggota baru",placeholder:"email@nafanesia.id",onChange:j=>x(j.target.value),style:{flex:"1 1 180px"}}),t.jsx(O,{size:"sm",value:h,"aria-label":"Peran anggota baru",placeholder:"Peran (opsional)",onChange:j=>y(j.target.value),style:{flex:"1 1 130px"}}),t.jsx(B,{size:"sm",leftIcon:"user-plus",onClick:b,loading:u,children:"Tambah anggota"})]}),d==="loading"?t.jsx(H,{kind:"loading",compact:!0}):d==="error"?t.jsx(H,{kind:"error",compact:!0,hint:"Gagal memuat anggota.",action:S,actionLabel:"Coba lagi"}):l.length===0?t.jsx(H,{kind:"empty",compact:!0,icon:"users",title:"Belum ada anggota",hint:"Tambahkan orang di atas agar kartu papan bisa ditugaskan."}):l.map(j=>t.jsx(qt,{m:j,busy:u,onSave:D,onToggle:C,onDelete:E},j.id))]}),k]})}const Qt=5e3,Fe=200,Vt=400,We=[{value:"board",label:"Papan",icon:"kanban"},{value:"timeline",label:"Linimasa",icon:"gantt-chart"},{value:"projects",label:"Lintas project",icon:"layers"}],Xt={day:"Hari",week:"Minggu",month:"Bulan"},ea=()=>Object.fromEntries(K.map(e=>[e.key,0]));function ta({status:e,params:a,onData:n,refetch:r}){return ft({topic:"tasks",params:{...a,status:e},apply:l=>n(e,l.data.items,l.data.total),refetch:r,pollMs:Qt}),null}function la({projects:e,projectFilter:a,onProjectFilter:n,onToast:r}){const[l,o]=m.useState(vt),[d,g]=m.useState(ea),[u,i]=m.useState([]),[c,p]=m.useState("loading"),[v,x]=m.useState(!1),[h,y]=m.useState(null),[f,k]=m.useState(!1),[L,S]=m.useState(!1),[b,D]=m.useState(null),[C,E]=A("team","view","board",we(...We.map(s=>s.value))),[j,P]=A("team","q","",ce),[_,qe]=A("team","col","all",ce),[Z,Je]=A("team","member","all",ce),[ne,Qe]=A("team","zoom","week",we(...Le)),[Ve,be]=A("team","expanded",[],ht),Xe=m.useCallback(s=>{be(I=>I.includes(s)?I.filter(T=>T!==s):[...I,s])},[be]),ve=C==="timeline",N=C==="projects",ye=m.useRef(Date.now()).current,R=m.useMemo(()=>_==="all"?K:K.filter(s=>s.key===_),[_]),ie=R.map(s=>s.key).join(","),je=[a!=="all"&&!N,_!=="all",Z!=="all",j.trim()!==""].filter(Boolean).length,re=N||a==="all"?void 0:a,W=m.useMemo(()=>({projectId:re,memberId:Z==="all"?void 0:Z,q:j.trim()||void 0}),[re,Z,j]),te=m.useRef(!1),q=m.useCallback((s=!1)=>{!s&&!te.current&&p("loading");const I=ie?ie.split(","):[];Promise.all(I.map(T=>w.listTasks({...W,status:T,page:1,limit:Fe}))).then(T=>{o(z=>{const J={...z};return I.forEach((le,oe)=>{J[le]=T[oe].items}),J}),g(z=>{const J={...z};return I.forEach((le,oe)=>{J[le]=T[oe].total}),J}),te.current=!0,x(!1),p("ready")}).catch(()=>{if(!te.current){p("error");return}x(!0)})},[W,ie]);m.useEffect(()=>{q()},[q]);const ke=m.useCallback(()=>{w.listMembers().then(s=>i(s.items)).catch(()=>{})},[]);m.useEffect(()=>{ke()},[ke]);const[Se,et]=m.useState(()=>j.trim());m.useEffect(()=>{const s=setTimeout(()=>et(j.trim()),Vt);return()=>clearTimeout(s)},[j]);const tt=m.useCallback((s,I,T)=>{o(z=>({...z,[s]:I})),g(z=>({...z,[s]:T})),te.current=!0,x(!1),p("ready")},[]),at=m.useMemo(()=>({projectId:W.projectId,memberId:W.memberId,q:Se||void 0,page:1,limit:Fe}),[W.projectId,W.memberId,Se]),se=m.useCallback(()=>q(!0),[q]);async function nt(s,I){const T=yt(l,s.id,s.status,I);if(!T)return;const z=l;o(T.board);try{await w.patchTask(s.id,T.patch)}catch{o(z),r("Gagal memindahkan tugas","err","x-circle")}}async function it(s,I){const T=l;o(ue(l,{...s,memberId:I}));try{await w.patchTask(s.id,{memberId:I})}catch{o(T),r("Gagal menugaskan","err","x-circle")}}async function rt(s){const I=l;o(ue(l,{...s,specId:null,spec:null}));try{await w.unlinkTaskSpec(s.id),r("Tautan backlog dilepas","ok","unlink")}catch{o(I),r("Gagal melepas tautan","err","x-circle")}}const st=R.every(s=>l[s.key].length===0),Ie=m.useMemo(()=>R.flatMap(s=>l[s.key]),[l,R]),Ce=R.reduce((s,I)=>s+Math.max(0,(d[I.key]??0)-l[I.key].length),0);return t.jsxs("div",{style:ut,children:[t.jsxs("div",{className:"hn-team-controls",role:"region","aria-label":"Kontrol papan tim",style:{...G,marginBottom:18},children:[t.jsxs("div",{className:"hn-team-topline",style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,flexWrap:"wrap",marginBottom:12},children:[t.jsx(mt,{variant:"pill",value:C,onChange:E,tabs:We,"aria-label":"Mode tampilan"}),t.jsxs("div",{className:"hn-team-view-actions",style:{display:"flex",alignItems:"center",gap:10},children:[t.jsx(B,{size:"sm",leftIcon:"plus",onClick:()=>{y(null),k(!0)},children:"Tugas baru"}),t.jsx(B,{size:"sm",variant:"secondary",leftIcon:"users",onClick:()=>S(!0),children:"Anggota"}),t.jsx(pt,{onDone:se,onToast:r}),t.jsx(gt,{screen:"team",active:je,onReset:N?void 0:()=>n("all")}),t.jsxs("span",{className:"hn-eyebrow",role:"status",style:v?{color:"var(--amber-600)"}:void 0,title:v?"Server tak menjawab saat menyegarkan — angka ini dari muatan terakhir yang berhasil":void 0,children:[R.reduce((s,I)=>s+(d[I.key]??0),0)," tugas",v?" · basi":""]}),t.jsx(xt,{})]})]}),t.jsxs("div",{className:"hn-team-filters",style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[t.jsx(O,{size:"sm",leftIcon:"search","aria-label":"Cari tugas",value:j,placeholder:"mis. halaman harga atau deploy",onChange:s=>P(s.target.value),style:{flex:"1 1 220px"}}),t.jsx(M,{size:"sm","aria-label":"Filter project",value:a,disabled:N,onChange:s=>n(s.target.value),options:[{value:"all",label:"Semua project"},...e.map(s=>({value:s.id,label:s.name}))]}),N&&t.jsx("span",{"data-testid":"project-filter-note",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:"Mode ini melintasi semua project"}),t.jsx(M,{size:"sm","aria-label":"Filter kolom",value:_,onChange:s=>qe(s.target.value),options:[{value:"all",label:"Semua kolom"},...K.map(s=>({value:s.key,label:s.label}))]}),t.jsx(M,{size:"sm","aria-label":"Filter anggota",value:Z,onChange:s=>Je(s.target.value),options:[{value:"all",label:"Semua anggota"},...u.map(s=>({value:s.id,label:s.name}))]}),(ve||N)&&t.jsx(M,{size:"sm","aria-label":"Zoom linimasa",value:ne,onChange:s=>Qe(s.target.value),options:Le.map(s=>({value:s,label:Xt[s]}))})]})]}),R.map(s=>t.jsx(ta,{status:s.key,params:at,onData:tt,refetch:se},s.key)),c==="loading"?t.jsx(H,{kind:"loading"}):c==="error"?t.jsx(H,{kind:"error",hint:"Gagal memuat papan tim.",action:()=>q(),actionLabel:"Coba lagi"}):st&&je===0?t.jsx(H,{kind:"empty",icon:"users",title:"Papan tim masih kosong",hint:"Catat pekerjaan manusia di sekitar sesi agen — desain, meeting klien, deploy, nego.",action:()=>{y(null),k(!0)},actionLabel:"Tugas baru",actionIcon:"plus"}):N?t.jsx(Ht,{tasks:Ie,projects:e,members:u,zoom:ne,today:ye,hidden:Ce,expanded:Ve,onToggle:Xe,onOpen:s=>{y(s),k(!0)}}):ve?t.jsx(Ft,{tasks:Ie,members:u,zoom:ne,today:ye,hidden:Ce,onOpen:s=>{y(s),k(!0)}}):t.jsx(Pt,{board:l,totals:d,columns:R,members:u,onMove:nt,onAssign:it,onEscalate:D,onUnlink:rt,onOpen:s=>{y(s),k(!0)}}),t.jsx(Gt,{open:f,task:h,projects:e,members:u,defaultProjectId:re??null,orderFor:s=>He(l[s]),onClose:()=>{k(!1),y(null)},onSaved:se,onToast:r}),b&&t.jsx(Zt,{task:b,projects:e,onClose:()=>D(null),onDone:s=>o(I=>ue(I,s)),onToast:r}),t.jsx(Jt,{open:L,onClose:()=>S(!1),onChanged:i,onToast:r})]})}export{We as TEAM_VIEWS,la as TeamScreen};
1
+ import{T as Ae,j as t,F as G,L as lt,B as ae,I as X,a as B,S as M,u as Ue,M as xe,c as $,d as O,H as ot,e as w,P as Te,E as dt,s as ct,f as H,g as de,h as A,o as we,k as ut,l as mt,m as pt,R as gt,n as ht,p as ce,q as ft}from"./index-B3niUZnk.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as xt}from"./live-fPTkukus.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const bt={backlog:"Backlog",doing:"Dikerjakan",review:"Review",done:"Selesai"},K=Ae.map(e=>({key:e,label:bt[e]})),vt=()=>Object.fromEntries(Ae.map(e=>[e,[]])),pe=(e,a)=>e!==a,He=e=>e.length===0?0:e.reduce((a,n)=>n.order>a?n.order:a,-1/0)+1;function yt(e,a,n,r){if(!pe(n,r))return null;const l=e[n].find(g=>g.id===a);if(!l)return null;const o={status:r,order:He(e[r])},d={...e};return d[n]=e[n].filter(g=>g.id!==a),d[r]=[...e[r],{...l,...o}],{board:d,patch:o}}function ue(e,a){const n={...e};return n[a.status]=e[a.status].map(r=>r.id===a.id?a:r),n}const De=e=>e?e.slice(0,10):"",Ee=e=>/^\d{4}-\d{2}-\d{2}$/.test(e)?`${e}T12:00:00.000Z`:null,F=864e5,ee=e=>Math.floor(e/F)*F,Me=e=>{if(!e)return null;const a=new Date(e).getTime();return Number.isFinite(a)?a:null};function Y(e){const a=Me(e.startDate),n=Me(e.dueDate);if(a===null&&n===null)return null;const r=a??n,l=n??a;return{start:ee(Math.min(r,l)),end:ee(Math.max(r,l))+F,invalid:l<r}}const jt=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),Be=e=>e?jt.format(new Date(e)):null;function Q(e){const a=Be(e.startDate),n=Be(e.dueDate);return a&&n?`${a} → ${n}`:n?`→ ${n}`:a}const Le=["day","week","month"],Ke={day:{cell:34,minTicks:14},week:{cell:56,minTicks:8},month:{cell:84,minTicks:6}},kt=e=>Ke[e].cell,St=120,It=(e,a)=>{const n=ee(e);if(a==="day")return n;if(a==="week")return n-(new Date(n).getUTCDay()+6)%7*F;const r=new Date(n);return Date.UTC(r.getUTCFullYear(),r.getUTCMonth(),1)},Ct=(e,a)=>{if(a==="day")return e+F;if(a==="week")return e+7*F;const n=new Date(e);return Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,1)},Tt=new Intl.DateTimeFormat("id-ID",{day:"numeric",timeZone:"UTC"}),$e=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),wt=new Intl.DateTimeFormat("id-ID",{month:"short",timeZone:"UTC"}),Dt=new Intl.DateTimeFormat("id-ID",{month:"short",year:"2-digit",timeZone:"UTC"}),Et=(e,a)=>{const n=new Date(e);return a==="day"?n.getUTCDate()===1:a==="week"?n.getUTCDate()<=7:n.getUTCMonth()===0},Mt=(e,a,n)=>{const r=new Date(e);return a==="day"?(n?$e:Tt).format(r):a==="week"?$e.format(r):(n?Dt:wt).format(r)};function Ge(e,a,n){const r=ee(n);let l=r,o=r+F;for(const c of e)c.start<l&&(l=c.start),c.end>o&&(o=c.end);const d=It(l,a),{minTicks:g}=Ke[a],u=[];let i=d;for(;u.length<St&&(i<o||u.length<g);){const c=Et(i,a);u.push({start:i,label:Mt(i,a,c),major:c}),i=Ct(i,a)}return{from:d,to:i,zoom:a,ticks:u}}function Ye(e,a){const n=a.to-a.from;if(n<=0||e.end<=a.from||e.start>=a.to)return null;const r=Math.max(e.start,a.from),l=Math.min(e.end,a.to);return{left:(r-a.from)/n*100,width:(l-r)/n*100,clippedStart:e.start<a.from,clippedEnd:e.end>a.to,invalid:e.invalid}}function ge(e,a){const n=Y(e);return n?Ye(n,a):null}function Bt(e){let a=1/0,n=-1/0,r=!1;for(const l of e){const o=Y(l);o&&(o.start<a&&(a=o.start),o.end>n&&(n=o.end),o.invalid&&(r=!0))}return a===1/0?null:{start:a,end:n,invalid:r}}function Lt(e,a){const n=ee(a);return n<e.from||n>=e.to?null:(n-e.from)/(e.to-e.from)*100}function $t(e,a){const n=[],r=[],l=[];for(const o of e){const d=Y(o);if(!d){r.push(o);continue}const g=ge(o,a);if(!g){l.push(o);continue}n.push({task:o,geometry:g,start:d.start})}return n.sort((o,d)=>o.start-d.start||o.task.title.localeCompare(d.task.title,"id")||o.task.id.localeCompare(d.task.id)),{rows:n.map(({task:o,geometry:d})=>({task:o,geometry:d})),unscheduled:r,outside:l}}const ze=(e,a)=>e.title.localeCompare(a.title,"id")||e.id.localeCompare(a.id);function zt(e,a,n){const r=Symbol("no-project"),l=new Map;for(const u of e){const i=u.projectId??r,c=l.get(i);c?c.tasks.push(u):l.set(i,{projectId:u.projectId,tasks:[u]})}const o=[...l.values()].map(({projectId:u,tasks:i})=>{const c=Bt(i),p=[],v=[];for(const x of i){const h=Y(x);h?p.push({task:x,start:h.start}):v.push(x)}return p.sort((x,h)=>x.start-h.start||ze(x.task,h.task)),v.sort(ze),{projectId:u,span:c,geometry:c?Ye(c,a):null,tasks:[...p.map(x=>x.task),...v]}}),d=u=>u.geometry?0:u.span?1:2,g=u=>u.projectId===null?[1,""]:[0,u.projectId];return o.sort((u,i)=>{const[c,p]=g(u),[v,x]=g(i);return d(u)-d(i)||(u.span&&i.span?u.span.start-i.span.start:0)||n(u.projectId).localeCompare(n(i.projectId),"id")||c-v||p.localeCompare(x)}),o}const Ot={tinggi:"err",sedang:"neutral",rendah:"neutral"};function Rt({task:e,members:a,dragging:n,onDragStart:r,onDragEnd:l,onOpen:o,onMove:d,onAssign:g,onEscalate:u,onUnlink:i}){var v;const c=((v=a.find(x=>x.id===e.memberId))==null?void 0:v.name)??"belum ditugaskan",p=Q(e);return t.jsxs("div",{draggable:!0,"data-testid":`team-card-${e.id}`,onDragStart:x=>{x.dataTransfer.effectAllowed="move",x.dataTransfer.setData("text/plain",e.id),r()},onDragEnd:l,style:{flex:"0 0 auto",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",padding:10,boxShadow:"var(--shadow-xs)",cursor:"grab",opacity:n?.4:1},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6},children:[t.jsx(ae,{tone:Ot[e.priority]??"neutral",size:"sm",variant:e.priority==="tinggi"?"soft":"outline",children:e.priority}),t.jsx("span",{style:{flex:1}}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.projectId??"tanpa project"})]}),t.jsx("button",{type:"button",onClick:()=>o(e),style:{display:"block",width:"100%",textAlign:"left",border:"none",background:"none",padding:0,cursor:"pointer",fontFamily:"var(--font-ui)",fontSize:13,fontWeight:"var(--weight-medium)",color:"var(--text-strong)",lineHeight:1.35},children:e.title}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:6,flexWrap:"wrap",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[t.jsx(X,{name:"user",size:12,color:"var(--text-subtle)"}),t.jsx("span",{children:c}),p&&t.jsxs(t.Fragment,{children:[t.jsx("span",{"aria-hidden":"true",children:"·"}),t.jsx("span",{children:p})]})]}),t.jsx("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:6,flexWrap:"wrap"},children:e.specId?t.jsxs(t.Fragment,{children:[t.jsx(ae,{tone:e.spec?"ok":"warn",size:"sm",icon:e.spec?"link":"unlink",children:e.spec?`${e.spec.id} · ${e.spec.stage}`:"tautan putus"}),t.jsx(B,{size:"sm",variant:"ghost",leftIcon:"unlink","aria-label":`Lepas tautan: ${e.title}`,onClick:()=>i(e),children:"Lepas tautan"})]}):t.jsx(B,{size:"sm",variant:"ghost",leftIcon:"git-branch","aria-label":`Eskalasi ke backlog: ${e.title}`,onClick:()=>u(e),children:"Eskalasi"})}),t.jsxs("div",{style:{display:"flex",gap:6,marginTop:8},children:[t.jsx(M,{size:"sm",value:e.status,"aria-label":`Pindah kolom: ${e.title}`,onChange:x=>d(e,x.target.value),options:K.map(x=>({value:x.key,label:x.label})),style:{flex:1,minWidth:0}}),t.jsx(M,{size:"sm",value:e.memberId??"","aria-label":`Tugaskan: ${e.title}`,onChange:x=>g(e,x.target.value||null),options:[{value:"",label:"Belum ditugaskan"},...a.map(x=>({value:x.id,label:x.name}))],style:{flex:1,minWidth:0}})]})]})}function Pt({board:e,totals:a,columns:n,members:r,onMove:l,onAssign:o,onOpen:d,onEscalate:g,onUnlink:u}){const[i,c]=m.useState(null),[p,v]=m.useState(null),x=h=>{i&&pe(i.from,h)&&l(i.task,h),c(null),v(null)};return t.jsx("div",{"data-testid":"team-board",className:"hn-board-local-overflow",style:{flex:"1 1 auto",minHeight:0,display:"flex",gap:10,overflowX:"auto",overflowY:"hidden",alignItems:"stretch",paddingBottom:4},children:n.map(h=>{const y=e[h.key],f=!!i&&pe(i.from,h.key),k=f&&p===h.key,L=Math.max(0,(a[h.key]??0)-y.length);return t.jsxs("div",{"data-testid":`team-col-${h.key}`,onDragOver:S=>{f&&(S.preventDefault(),S.dataTransfer.dropEffect="move",v(h.key))},onDragLeave:()=>v(S=>S===h.key?null:S),onDrop:S=>{S.preventDefault(),x(h.key)},style:{flex:"0 0 244px",display:"flex",flexDirection:"column",minHeight:0,padding:10,borderRadius:"var(--radius-lg)",background:k?"var(--brass-100)":"var(--bone-100)",border:`1px ${f?"dashed":"solid"} ${k?"var(--brass-500)":"var(--border-hair)"}`,opacity:i&&!f?.5:1,transition:"var(--transition-fast)"},children:[t.jsxs("div",{style:{...G,display:"flex",alignItems:"center",gap:6,marginBottom:8},children:[t.jsx("span",{className:"hn-eyebrow",children:h.label}),t.jsx("span",{style:{flex:1}}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)"},children:y.length})]}),t.jsx("div",{style:{...lt,display:"flex",flexDirection:"column",gap:8},children:y.map(S=>t.jsx(Rt,{task:S,members:r,dragging:(i==null?void 0:i.task.id)===S.id,onDragStart:()=>c({task:S,from:h.key}),onDragEnd:()=>{c(null),v(null)},onOpen:d,onMove:l,onAssign:o,onEscalate:g,onUnlink:u},S.id))}),L>0&&t.jsxs("div",{style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:["menampilkan ",y.length," dari ",a[h.key]," — persempit penyaring"]})]},h.key)})})}const U=232,he=34,me=6,_t={brass:{bg:"var(--brass-300)",border:"var(--brass-500)"},err:{bg:"var(--status-err-tint)",border:"var(--status-err)"},muted:{bg:"var(--bone-300)",border:"var(--border-strong)"},envelope:{bg:"var(--bone-200)",border:"var(--border-hair)"}},Oe={position:"sticky",left:0,zIndex:1,flex:`0 0 ${U}px`,width:U,boxSizing:"border-box",padding:"5px 10px",minWidth:0,background:"var(--surface-card)",borderRight:"1px solid var(--border-hair)"},V={overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"};function Nt({spec:e}){const a=e.geometry,n=_t[e.tone];return t.jsxs("button",{type:"button","data-testid":`timeline-bar-${e.key}`,"data-tone":e.tone,"data-invalid":a.invalid?"true":"false","data-clipped-start":a.clippedStart?"true":"false","data-clipped-end":a.clippedEnd?"true":"false",title:e.title,"aria-label":e.title,onClick:e.onClick,style:{position:"absolute",top:me,height:he-me*2,left:`${a.left}%`,width:`${a.width}%`,minWidth:3,minHeight:he-me*2,display:"flex",alignItems:"center",padding:0,overflow:"hidden",background:n.bg,border:`1px solid ${n.border}`,borderTopLeftRadius:a.clippedStart?0:"var(--radius-sm)",borderBottomLeftRadius:a.clippedStart?0:"var(--radius-sm)",borderTopRightRadius:a.clippedEnd?0:"var(--radius-sm)",borderBottomRightRadius:a.clippedEnd?0:"var(--radius-sm)",cursor:e.onClick?"pointer":"default"},children:[a.clippedStart&&t.jsx(X,{name:"chevron-left",size:11,color:n.border}),t.jsx("span",{style:{flex:1}}),a.clippedEnd&&t.jsx(X,{name:"chevron-right",size:11,color:n.border})]})}function Ze({window:e,rows:a,today:n,emptyHint:r,testId:l,labelHead:o}){const d=kt(e.zoom),g=e.ticks.length*d,u=Lt(e,n),i={position:"relative",width:g,height:he,flex:`0 0 ${g}px`,backgroundImage:`repeating-linear-gradient(to right, var(--border-hair) 0 1px, transparent 1px ${d}px)`};return t.jsx("div",{"data-testid":l??"team-timeline",className:"hn-timeline-scroll",style:{flex:"1 1 auto",minHeight:0,minWidth:0,maxWidth:"100%",overflowX:"auto",overflowY:"auto"},children:t.jsxs("div",{"data-testid":"timeline-canvas",style:{position:"relative",minWidth:U+g,width:U+g},children:[t.jsxs("div",{style:{display:"flex",position:"sticky",top:0,zIndex:2,background:"var(--bone-100)",borderBottom:"1px solid var(--border-hair)"},children:[t.jsx("div",{style:{...Oe,zIndex:3,background:"var(--bone-100)"},children:t.jsx("span",{className:"hn-eyebrow",children:o??"Tugas"})}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:`repeat(${e.ticks.length}, ${d}px)`,width:g,flex:`0 0 ${g}px`},children:e.ticks.map(c=>t.jsx("div",{"data-testid":"timeline-tick",style:{borderLeft:`1px solid ${c.major?"var(--border-strong)":"var(--border-hair)"}`,padding:"5px 4px",fontFamily:"var(--font-mono)",fontSize:10,...V,color:c.major?"var(--text-body)":"var(--text-subtle)"},children:c.label},c.start))})]}),a.length===0?t.jsx("div",{"data-testid":"timeline-empty",style:{position:"sticky",left:0,width:U,padding:"18px 10px",fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:r??"Tak ada yang bisa dihamparkan di jendela ini."}):a.map(c=>t.jsxs("div",{"data-testid":`timeline-row-${c.key}`,style:{display:"flex",borderBottom:"1px solid var(--border-hair)"},children:[t.jsxs("div",{style:Oe,children:[t.jsx("div",{style:{...V,fontSize:12,fontWeight:"var(--weight-medium)",color:"var(--text-strong)"},children:c.label}),c.meta&&t.jsx("div",{style:{...V,fontSize:10,color:"var(--text-subtle)"},children:c.meta})]}),t.jsx("div",{style:i,children:c.bars.map(p=>t.jsx(Nt,{spec:p},p.key))})]},c.key)),u!==null&&t.jsx("div",{"data-testid":"timeline-today","aria-hidden":"true",style:{position:"absolute",top:0,bottom:0,width:2,pointerEvents:"none",left:U+u/100*g,background:"var(--brass-500)",opacity:.5}})]})})}function Re({testId:e,icon:a,title:n,hint:r,tasks:l,onOpen:o}){return l.length===0?null:t.jsxs("div",{"data-testid":e,style:{...G,marginTop:10,padding:10,background:"var(--bone-100)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-lg)"},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6,flexWrap:"wrap"},children:[t.jsx(X,{name:a,size:13,color:"var(--text-subtle)"}),t.jsxs("span",{className:"hn-eyebrow",children:[n," · ",l.length]}),r&&t.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:r})]}),t.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:6},children:l.map(d=>t.jsx("button",{type:"button",onClick:()=>o(d),style:{padding:"3px 10px",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-pill)",fontFamily:"var(--font-ui)",fontSize:12,color:"var(--text-body)",cursor:"pointer"},children:d.title},d.id))})]})}function Ft({tasks:e,members:a,zoom:n,today:r,hidden:l,onOpen:o}){const d=m.useMemo(()=>{const p=e.map(Y).filter(v=>v!==null);return Ge(p,n,r)},[e,n,r]),{rows:g,unscheduled:u,outside:i}=m.useMemo(()=>$t(e,d),[e,d]),c=m.useMemo(()=>g.map(({task:p,geometry:v})=>{var f;const x=((f=a.find(k=>k.id===p.memberId))==null?void 0:f.name)??"belum ditugaskan",h=Q(p),y=[v.invalid?"tenggat mendahului mulai":null,v.clippedStart||v.clippedEnd?"melewati tepi jendela":null].filter(Boolean);return{key:p.id,label:p.title,meta:h?`${x} · ${h}`:x,bars:[{key:p.id,geometry:v,tone:v.invalid?"err":p.status==="done"?"muted":"brass",title:[p.title,h,...y].filter(Boolean).join(" · "),onClick:()=>o(p)}]}}),[g,a,o]);return t.jsxs(t.Fragment,{children:[t.jsx(Ze,{window:d,rows:c,today:r,emptyHint:"Belum ada tugas bertanggal — isi mulai atau tenggat di kartunya."}),l>0&&t.jsxs("div",{"data-testid":"timeline-truncated",style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:[l," tugas tak termuat karena plafon 200 per kolom — persempit penyaring"]}),t.jsx(Re,{testId:"timeline-unscheduled",icon:"calendar-off",title:"Belum dijadwalkan",tasks:u,onOpen:o}),t.jsx(Re,{testId:"timeline-outside",icon:"chevrons-left-right",title:"Di luar jendela",hint:"pilih zoom yang lebih lebar",tasks:i,onOpen:o})]})}const Wt="__none__",At=16,Pe=(e,a)=>a.invalid?"err":e.status==="done"?"muted":"brass",_e=(e,a,n)=>[e.title,n,a.invalid?"tenggat mendahului mulai":null,a.clippedStart||a.clippedEnd?"melewati tepi jendela":null].filter(Boolean).join(" · ");function Ut({testId:e,open:a,name:n,count:r,onClick:l}){return t.jsxs("button",{type:"button",onClick:l,"data-testid":e,"aria-expanded":a,style:{display:"flex",alignItems:"center",gap:5,width:"100%",padding:0,background:"none",border:"none",cursor:"pointer",textAlign:"left",minHeight:0,fontFamily:"var(--font-ui)",fontSize:12,fontWeight:"var(--weight-medium)",color:"var(--text-strong)"},children:[t.jsx(X,{name:a?"chevron-down":"chevron-right",size:12,color:"var(--text-subtle)"}),t.jsx("span",{style:{...V,flex:1},children:n}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:10,color:"var(--text-subtle)"},children:r})]})}function Ht({tasks:e,projects:a,members:n,zoom:r,today:l,hidden:o,expanded:d,onToggle:g,onOpen:u}){const i=m.useMemo(()=>{const h=e.map(Y).filter(y=>y!==null);return Ge(h,r,l)},[e,r,l]),c=m.useCallback(h=>{var y;return h===null?"Tanpa project":((y=a.find(f=>f.id===h))==null?void 0:y.name)??h},[a]),p=m.useMemo(()=>zt(e,i,c),[e,i,c]),v=m.useMemo(()=>new Set(d),[d]),x=m.useMemo(()=>{var y;const h=[];for(const f of p){const k=f.projectId??Wt,L=v.has(k),S=c(f.projectId),b=f.geometry?Q({startDate:new Date(f.span.start).toISOString(),dueDate:new Date(f.span.end-1).toISOString()}):f.span?"di luar jendela · pilih zoom yang lebih lebar":"belum dijadwalkan",D=[];if(f.geometry){D.push({key:`span:${k}`,geometry:f.geometry,tone:f.geometry.invalid?"err":"envelope",title:`${S} · ${b??""}`.trim(),onClick:()=>g(k)});for(const C of f.tasks){const E=ge(C,i);E&&D.push({key:`seg:${C.id}`,geometry:E,tone:Pe(C,E),title:_e(C,E,Q(C)),onClick:()=>u(C)})}}if(h.push({key:`p:${k}`,meta:b,bars:D,label:t.jsx(Ut,{testId:`expand-${k}`,open:L,name:S,count:f.tasks.length,onClick:()=>g(k)})}),!!L)for(const C of f.tasks){const E=ge(C,i),j=((y=n.find(_=>_.id===C.memberId))==null?void 0:y.name)??"belum ditugaskan",P=Q(C);h.push({key:`t:${C.id}`,label:t.jsx("span",{style:{...V,display:"block",paddingLeft:At},children:C.title}),meta:P?`${j} · ${P}`:j,bars:E?[{key:`t:${C.id}`,geometry:E,tone:Pe(C,E),title:_e(C,E,P),onClick:()=>u(C)}]:[]})}}return h},[p,v,c,i,n,g,u]);return t.jsxs(t.Fragment,{children:[t.jsx(Ze,{window:i,rows:x,today:l,testId:"team-projects",labelHead:"Project",emptyHint:"Belum ada project bertanggal — isi mulai atau tenggat di kartunya."}),o>0&&t.jsxs("div",{"data-testid":"projects-truncated",style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:[o," tugas tak termuat karena plafon 200 per kolom — amplop project bisa lebih pendek dari rentang sebenarnya; persempit kolom, anggota, atau pencarian"]})]})}const fe={tinggi:"Tinggi",sedang:"Sedang",rendah:"Rendah"},Kt=Object.keys(fe).map(e=>({value:e,label:fe[e]})),Ne=(e,a)=>({title:(e==null?void 0:e.title)??"",detail:(e==null?void 0:e.detail)??"",projectId:e?e.projectId??"":a??"",status:(e==null?void 0:e.status)??"backlog",priority:e&&e.priority in fe?e.priority:"sedang",memberId:(e==null?void 0:e.memberId)??"",startDate:De((e==null?void 0:e.startDate)??null),dueDate:De((e==null?void 0:e.dueDate)??null)});function Gt({open:e,task:a,projects:n,members:r,defaultProjectId:l,orderFor:o,onClose:d,onSaved:g,onToast:u}){const[i,c]=m.useState(()=>Ne(a,l)),[p,v]=m.useState(!1),{confirm:x,dialog:h}=Ue(),y=`${e?"1":"0"}:${(a==null?void 0:a.id)??""}`,f=m.useRef(y);if(f.current!==y&&(f.current=y,e&&c(Ne(a,l))),!e)return null;const k=b=>c(D=>({...D,...b}));async function L(){if(!i.title.trim()){u("Judul tugas wajib diisi","err","x-circle");return}v(!0);const b=!a||a.status!==i.status,D={title:i.title.trim(),detail:i.detail.trim()||null,projectId:i.projectId||null,status:i.status,priority:i.priority,memberId:i.memberId||null,startDate:Ee(i.startDate),dueDate:Ee(i.dueDate),...b?{order:o(i.status)}:{}};try{a?await w.patchTask(a.id,D):await w.createTask(D),u(a?"Tugas diperbarui":"Tugas dibuat","ok","check"),g(),d()}catch{u("Gagal menyimpan tugas","err","x-circle")}finally{v(!1)}}async function S(){a&&await x({title:`Hapus "${a.title}"?`,message:"Kartu ini hilang dari papan di semua device yang tersinkron.",confirmLabel:"Hapus tugas",tone:"danger",icon:"trash-2",run:()=>w.deleteTask(a.id)})&&(u("Tugas dihapus","ok","trash-2"),g(),d())}return t.jsxs(t.Fragment,{children:[t.jsxs(xe,{open:e,onClose:d,icon:"clipboard-list",eyebrow:"Papan tim",title:a?"Ubah tugas":"Tugas baru",footer:t.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[a&&t.jsx(B,{variant:"ghost",leftIcon:"trash-2",onClick:S,disabled:p,children:"Hapus"}),t.jsx("span",{style:{flex:1}}),t.jsx(B,{variant:"secondary",onClick:d,disabled:p,children:"Batal"}),t.jsx(B,{onClick:L,loading:p,children:a?"Simpan":"Buat tugas"})]}),children:[t.jsx($,{label:"Judul",children:t.jsx(O,{value:i.title,"aria-label":"Judul tugas",placeholder:"mis. Rapikan halaman harga",onChange:b=>k({title:b.target.value}),style:{width:"100%"}})}),t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[t.jsx($,{label:"Project",children:t.jsx(M,{value:i.projectId,"aria-label":"Project tugas",onChange:b=>k({projectId:b.target.value}),options:[{value:"",label:"Tanpa project"},...n.map(b=>({value:b.id,label:b.name}))]})}),t.jsx($,{label:"Kolom",children:t.jsx(M,{value:i.status,"aria-label":"Kolom tugas",onChange:b=>k({status:b.target.value}),options:K.map(b=>({value:b.key,label:b.label}))})}),t.jsx($,{label:"Prioritas",children:t.jsx(M,{value:i.priority,"aria-label":"Prioritas tugas",onChange:b=>k({priority:b.target.value}),options:Kt})})]}),t.jsx($,{label:"Ditugaskan ke",children:t.jsx(M,{value:i.memberId,"aria-label":"Anggota tugas",onChange:b=>k({memberId:b.target.value}),options:[{value:"",label:"Belum ditugaskan"},...r.map(b=>({value:b.id,label:b.role?`${b.name} · ${b.role}`:b.name}))],style:{width:"100%"}})}),t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[t.jsx($,{label:"Mulai",children:t.jsx(O,{type:"date",value:i.startDate,"aria-label":"Tanggal mulai",onChange:b=>k({startDate:b.target.value})})}),t.jsx($,{label:"Tenggat",children:t.jsx(O,{type:"date",value:i.dueDate,"aria-label":"Tanggal tenggat",onChange:b=>k({dueDate:b.target.value})})})]}),t.jsx($,{label:"Detail",hint:"Opsional — konteks yang tak muat di judul.",children:t.jsx(ot,{value:i.detail,"aria-label":"Detail tugas",rows:4,placeholder:"mis. tunggu aset dari klien, deadline ikut jadwal kampanye",onChange:b=>k({detail:b.target.value})})})]}),h]})}const Yt=dt.map(e=>({value:e,label:ct(e).label}));function Zt({task:e,projects:a,onClose:n,onDone:r,onToast:l}){const[o,d]=m.useState("brief"),[g,u]=m.useState(()=>Te.some(f=>f.value===e.priority)?e.priority:"sedang"),[i,c]=m.useState(""),[p,v]=m.useState(!1),x=e.projectId===null,h=e.projectId??i;async function y(){if(!(!h||p)){v(!0);try{const f=await w.escalateTask(e.id,{source:o,priority:g,...e.projectId?{}:{projectId:i}});l(f.created?`Dieskalasi jadi ${f.spec.id}`:`Sudah tertaut ke ${f.spec.id}`,"ok","link"),r(f.task),n()}catch{l("Gagal mengeskalasi kartu","err","x-circle")}finally{v(!1)}}}return t.jsxs(xe,{open:!0,onClose:p?void 0:n,icon:"git-branch",eyebrow:"Papan tim",title:"Eskalasi ke backlog",footer:t.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[t.jsx("span",{style:{flex:1}}),t.jsx(B,{variant:"secondary",onClick:n,disabled:p,children:"Batal"}),t.jsx(B,{onClick:y,loading:p,disabled:!h,leftIcon:"git-branch",children:"Eskalasi"})]}),children:[t.jsxs("div",{style:{fontSize:13.5,color:"var(--text-strong)",lineHeight:1.55,marginBottom:14},children:["Kartu ",t.jsx("strong",{children:e.title})," tetap di papan. Yang lahir adalah backlog item baru yang bisa dikerjakan sesi agen, dan kartu ini menampilkan stage-nya."]}),x&&t.jsxs($,{label:"Project",children:[t.jsx(M,{"aria-label":"Project",value:i,style:{width:"100%"},onChange:f=>c(f.target.value),options:[{value:"",label:"Pilih project…"},...a.map(f=>({value:f.id,label:f.name}))]}),t.jsx("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:"Nomor SPEC diambil dari repo project, jadi kartu tanpa project belum bisa dieskalasi."})]}),t.jsx($,{label:"Source",children:t.jsx(M,{"aria-label":"Source",value:o,style:{width:"100%"},onChange:f=>d(f.target.value),options:Yt})}),t.jsx($,{label:"Prioritas",children:t.jsx(M,{"aria-label":"Prioritas",value:g,style:{width:"100%"},onChange:f=>u(f.target.value),options:Te})})]})}function qt({m:e,busy:a,onSave:n,onToggle:r,onDelete:l}){const[o,d]=m.useState(!1),[g,u]=m.useState(e.name),[i,c]=m.useState(e.role??"");return o?t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:8,padding:"12px 14px",marginBottom:8,border:"1px solid var(--border-strong)",borderRadius:"var(--radius-md)",background:"var(--surface-card)"},children:[t.jsx(O,{size:"sm",value:g,"aria-label":`Nama ${e.name}`,placeholder:"mis. Dena Meidina",onChange:p=>u(p.target.value)}),t.jsx(O,{size:"sm",value:i,"aria-label":`Peran ${e.name}`,placeholder:"mis. desainer",onChange:p=>c(p.target.value)}),t.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[e.email," — ganti email berarti hapus lalu buat baru."]}),t.jsxs("div",{style:{display:"flex",gap:8},children:[t.jsx(B,{size:"sm",disabled:a,onClick:()=>{n(e.id,{name:g.trim(),role:i.trim()||null}),d(!1)},children:"Simpan"}),t.jsx(B,{size:"sm",variant:"ghost",onClick:()=>d(!1),children:"Batal"})]})]}):t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",marginBottom:8,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",opacity:e.active?1:.6},children:[t.jsxs("span",{style:{flex:1,minWidth:0},children:[t.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{fontWeight:"var(--weight-semibold)",color:"var(--text-strong)"},children:e.name}),e.role&&t.jsx(ae,{tone:"neutral",size:"sm",children:e.role}),!e.active&&t.jsx(ae,{tone:"warn",size:"sm",children:"nonaktif"})]}),t.jsx("span",{style:{display:"block",fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2},children:e.email})]}),t.jsx(de,{icon:"pencil",label:`Ubah ${e.name}`,size:"sm",onClick:()=>d(!0)}),t.jsx(de,{icon:e.active?"user-minus":"user-check",size:"sm",label:`${e.active?"Nonaktifkan":"Aktifkan"} ${e.name}`,onClick:()=>r(e)}),t.jsx(de,{icon:"trash-2",label:`Hapus ${e.name}`,size:"sm",onClick:()=>l(e)})]})}function Jt({open:e,onClose:a,onChanged:n,onToast:r}){const[l,o]=m.useState([]),[d,g]=m.useState("loading"),[u,i]=m.useState(!1),[c,p]=m.useState(""),[v,x]=m.useState(""),[h,y]=m.useState(""),{confirm:f,dialog:k}=Ue(),L=m.useRef(n);L.current=n;const S=m.useCallback(()=>{g("loading"),w.listMembers().then(j=>{o(j.items),g("ready"),L.current(j.items)}).catch(()=>g("error"))},[]);if(m.useEffect(()=>{e&&S()},[e,S]),!e)return null;async function b(){if(!c.trim()||!v.trim()){r("Nama & email wajib diisi","err","x-circle");return}i(!0);try{await w.createMember({name:c.trim(),email:v.trim(),role:h.trim()||null}),p(""),x(""),y(""),r("Anggota ditambahkan","ok","user-plus"),S()}catch{r("Gagal menambah anggota — email mungkin sudah terdaftar","err","x-circle")}finally{i(!1)}}async function D(j,P){i(!0);try{await w.patchMember(j,P),S()}catch{r("Gagal menyimpan anggota","err","x-circle")}finally{i(!1)}}async function C(j){i(!0);try{await w.patchMember(j.id,{active:!j.active}),S()}catch{r("Gagal mengubah status anggota","err","x-circle")}finally{i(!1)}}async function E(j){await f({title:`Hapus ${j.name} dari direktori?`,message:"Tugasnya tidak ikut terhapus — kartu yang ditugaskan padanya jadi 'belum ditugaskan'.",confirmLabel:"Hapus anggota",tone:"danger",icon:"trash-2",run:()=>w.deleteMember(j.id)})&&(r("Anggota dihapus","ok","trash-2"),S())}return t.jsxs(t.Fragment,{children:[t.jsxs(xe,{open:e,onClose:a,icon:"users",eyebrow:"Papan tim",title:"Anggota",width:620,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap",alignItems:"flex-end",marginBottom:16,paddingBottom:16,borderBottom:"1px solid var(--border-hair)"},children:[t.jsx(O,{size:"sm",value:c,"aria-label":"Nama anggota baru",placeholder:"Nama",onChange:j=>p(j.target.value),style:{flex:"1 1 140px"}}),t.jsx(O,{size:"sm",value:v,"aria-label":"Email anggota baru",placeholder:"email@nafanesia.id",onChange:j=>x(j.target.value),style:{flex:"1 1 180px"}}),t.jsx(O,{size:"sm",value:h,"aria-label":"Peran anggota baru",placeholder:"Peran (opsional)",onChange:j=>y(j.target.value),style:{flex:"1 1 130px"}}),t.jsx(B,{size:"sm",leftIcon:"user-plus",onClick:b,loading:u,children:"Tambah anggota"})]}),d==="loading"?t.jsx(H,{kind:"loading",compact:!0}):d==="error"?t.jsx(H,{kind:"error",compact:!0,hint:"Gagal memuat anggota.",action:S,actionLabel:"Coba lagi"}):l.length===0?t.jsx(H,{kind:"empty",compact:!0,icon:"users",title:"Belum ada anggota",hint:"Tambahkan orang di atas agar kartu papan bisa ditugaskan."}):l.map(j=>t.jsx(qt,{m:j,busy:u,onSave:D,onToggle:C,onDelete:E},j.id))]}),k]})}const Qt=5e3,Fe=200,Vt=400,We=[{value:"board",label:"Papan",icon:"kanban"},{value:"timeline",label:"Linimasa",icon:"gantt-chart"},{value:"projects",label:"Lintas project",icon:"layers"}],Xt={day:"Hari",week:"Minggu",month:"Bulan"},ea=()=>Object.fromEntries(K.map(e=>[e.key,0]));function ta({status:e,params:a,onData:n,refetch:r}){return ft({topic:"tasks",params:{...a,status:e},apply:l=>n(e,l.data.items,l.data.total),refetch:r,pollMs:Qt}),null}function la({projects:e,projectFilter:a,onProjectFilter:n,onToast:r}){const[l,o]=m.useState(vt),[d,g]=m.useState(ea),[u,i]=m.useState([]),[c,p]=m.useState("loading"),[v,x]=m.useState(!1),[h,y]=m.useState(null),[f,k]=m.useState(!1),[L,S]=m.useState(!1),[b,D]=m.useState(null),[C,E]=A("team","view","board",we(...We.map(s=>s.value))),[j,P]=A("team","q","",ce),[_,qe]=A("team","col","all",ce),[Z,Je]=A("team","member","all",ce),[ne,Qe]=A("team","zoom","week",we(...Le)),[Ve,be]=A("team","expanded",[],ht),Xe=m.useCallback(s=>{be(I=>I.includes(s)?I.filter(T=>T!==s):[...I,s])},[be]),ve=C==="timeline",N=C==="projects",ye=m.useRef(Date.now()).current,R=m.useMemo(()=>_==="all"?K:K.filter(s=>s.key===_),[_]),ie=R.map(s=>s.key).join(","),je=[a!=="all"&&!N,_!=="all",Z!=="all",j.trim()!==""].filter(Boolean).length,re=N||a==="all"?void 0:a,W=m.useMemo(()=>({projectId:re,memberId:Z==="all"?void 0:Z,q:j.trim()||void 0}),[re,Z,j]),te=m.useRef(!1),q=m.useCallback((s=!1)=>{!s&&!te.current&&p("loading");const I=ie?ie.split(","):[];Promise.all(I.map(T=>w.listTasks({...W,status:T,page:1,limit:Fe}))).then(T=>{o(z=>{const J={...z};return I.forEach((le,oe)=>{J[le]=T[oe].items}),J}),g(z=>{const J={...z};return I.forEach((le,oe)=>{J[le]=T[oe].total}),J}),te.current=!0,x(!1),p("ready")}).catch(()=>{if(!te.current){p("error");return}x(!0)})},[W,ie]);m.useEffect(()=>{q()},[q]);const ke=m.useCallback(()=>{w.listMembers().then(s=>i(s.items)).catch(()=>{})},[]);m.useEffect(()=>{ke()},[ke]);const[Se,et]=m.useState(()=>j.trim());m.useEffect(()=>{const s=setTimeout(()=>et(j.trim()),Vt);return()=>clearTimeout(s)},[j]);const tt=m.useCallback((s,I,T)=>{o(z=>({...z,[s]:I})),g(z=>({...z,[s]:T})),te.current=!0,x(!1),p("ready")},[]),at=m.useMemo(()=>({projectId:W.projectId,memberId:W.memberId,q:Se||void 0,page:1,limit:Fe}),[W.projectId,W.memberId,Se]),se=m.useCallback(()=>q(!0),[q]);async function nt(s,I){const T=yt(l,s.id,s.status,I);if(!T)return;const z=l;o(T.board);try{await w.patchTask(s.id,T.patch)}catch{o(z),r("Gagal memindahkan tugas","err","x-circle")}}async function it(s,I){const T=l;o(ue(l,{...s,memberId:I}));try{await w.patchTask(s.id,{memberId:I})}catch{o(T),r("Gagal menugaskan","err","x-circle")}}async function rt(s){const I=l;o(ue(l,{...s,specId:null,spec:null}));try{await w.unlinkTaskSpec(s.id),r("Tautan backlog dilepas","ok","unlink")}catch{o(I),r("Gagal melepas tautan","err","x-circle")}}const st=R.every(s=>l[s.key].length===0),Ie=m.useMemo(()=>R.flatMap(s=>l[s.key]),[l,R]),Ce=R.reduce((s,I)=>s+Math.max(0,(d[I.key]??0)-l[I.key].length),0);return t.jsxs("div",{style:ut,children:[t.jsxs("div",{className:"hn-team-controls",role:"region","aria-label":"Kontrol papan tim",style:{...G,marginBottom:18},children:[t.jsxs("div",{className:"hn-team-topline",style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,flexWrap:"wrap",marginBottom:12},children:[t.jsx(mt,{variant:"pill",value:C,onChange:E,tabs:We,"aria-label":"Mode tampilan"}),t.jsxs("div",{className:"hn-team-view-actions",style:{display:"flex",alignItems:"center",gap:10},children:[t.jsx(B,{size:"sm",leftIcon:"plus",onClick:()=>{y(null),k(!0)},children:"Tugas baru"}),t.jsx(B,{size:"sm",variant:"secondary",leftIcon:"users",onClick:()=>S(!0),children:"Anggota"}),t.jsx(pt,{onDone:se,onToast:r}),t.jsx(gt,{screen:"team",active:je,onReset:N?void 0:()=>n("all")}),t.jsxs("span",{className:"hn-eyebrow",role:"status",style:v?{color:"var(--amber-600)"}:void 0,title:v?"Server tak menjawab saat menyegarkan — angka ini dari muatan terakhir yang berhasil":void 0,children:[R.reduce((s,I)=>s+(d[I.key]??0),0)," tugas",v?" · basi":""]}),t.jsx(xt,{})]})]}),t.jsxs("div",{className:"hn-team-filters",style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[t.jsx(O,{size:"sm",leftIcon:"search","aria-label":"Cari tugas",value:j,placeholder:"mis. halaman harga atau deploy",onChange:s=>P(s.target.value),style:{flex:"1 1 220px"}}),t.jsx(M,{size:"sm","aria-label":"Filter project",value:a,disabled:N,onChange:s=>n(s.target.value),options:[{value:"all",label:"Semua project"},...e.map(s=>({value:s.id,label:s.name}))]}),N&&t.jsx("span",{"data-testid":"project-filter-note",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:"Mode ini melintasi semua project"}),t.jsx(M,{size:"sm","aria-label":"Filter kolom",value:_,onChange:s=>qe(s.target.value),options:[{value:"all",label:"Semua kolom"},...K.map(s=>({value:s.key,label:s.label}))]}),t.jsx(M,{size:"sm","aria-label":"Filter anggota",value:Z,onChange:s=>Je(s.target.value),options:[{value:"all",label:"Semua anggota"},...u.map(s=>({value:s.id,label:s.name}))]}),(ve||N)&&t.jsx(M,{size:"sm","aria-label":"Zoom linimasa",value:ne,onChange:s=>Qe(s.target.value),options:Le.map(s=>({value:s,label:Xt[s]}))})]})]}),R.map(s=>t.jsx(ta,{status:s.key,params:at,onData:tt,refetch:se},s.key)),c==="loading"?t.jsx(H,{kind:"loading"}):c==="error"?t.jsx(H,{kind:"error",hint:"Gagal memuat papan tim.",action:()=>q(),actionLabel:"Coba lagi"}):st&&je===0?t.jsx(H,{kind:"empty",icon:"users",title:"Papan tim masih kosong",hint:"Catat pekerjaan manusia di sekitar sesi agen — desain, meeting klien, deploy, nego.",action:()=>{y(null),k(!0)},actionLabel:"Tugas baru",actionIcon:"plus"}):N?t.jsx(Ht,{tasks:Ie,projects:e,members:u,zoom:ne,today:ye,hidden:Ce,expanded:Ve,onToggle:Xe,onOpen:s=>{y(s),k(!0)}}):ve?t.jsx(Ft,{tasks:Ie,members:u,zoom:ne,today:ye,hidden:Ce,onOpen:s=>{y(s),k(!0)}}):t.jsx(Pt,{board:l,totals:d,columns:R,members:u,onMove:nt,onAssign:it,onEscalate:D,onUnlink:rt,onOpen:s=>{y(s),k(!0)}}),t.jsx(Gt,{open:f,task:h,projects:e,members:u,defaultProjectId:re??null,orderFor:s=>He(l[s]),onClose:()=>{k(!1),y(null)},onSaved:se,onToast:r}),b&&t.jsx(Zt,{task:b,projects:e,onClose:()=>D(null),onDone:s=>o(I=>ue(I,s)),onToast:r}),t.jsx(Jt,{open:L,onClose:()=>S(!1),onChanged:i,onToast:r})]})}export{We as TEAM_VIEWS,la as TeamScreen};