hanoman 0.3.1 → 0.3.2

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 (28) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +415 -74
  3. package/dist/server.js +1848 -1108
  4. package/package.json +1 -1
  5. package/prisma/migrations/20260905120000_agent_evidence_identity/migration.sql +3 -0
  6. package/prisma/schema.prisma +2 -0
  7. package/web/assets/{ChangelogScreen-C3S2gIAp.js → ChangelogScreen-D_-RmJkz.js} +1 -1
  8. package/web/assets/{DalangHanomanScreen-Bf7WEGnw.js → DalangHanomanScreen-pVfnLx9z.js} +1 -1
  9. package/web/assets/{DocPreviewModal-DsAfvavy.js → DocPreviewModal-ZFjISCL0.js} +1 -1
  10. package/web/assets/{DocsWorkspace-BLRgm3tN.js → DocsWorkspace-Vp_vik3v.js} +1 -1
  11. package/web/assets/IdeScreen-DQSRs3fr.js +2 -0
  12. package/web/assets/{LeadScreen-Cko3FBrm.js → LeadScreen-Bv5LiudD.js} +1 -1
  13. package/web/assets/{ReviewScreen-5Kh6qQJn.js → ReviewScreen-Cime4Tci.js} +1 -1
  14. package/web/assets/SchedulerScreen-DKmRNbTs.js +1 -0
  15. package/web/assets/{SettingsScreen-D7LNmEUW.js → SettingsScreen-Bh8XhyVQ.js} +1 -1
  16. package/web/assets/{TeamScreen-VU3NfDdm.js → TeamScreen-5ugoXsOv.js} +1 -1
  17. package/web/assets/TerminalScreen-DsAn5dlH.js +9 -0
  18. package/web/assets/{TriageScreen-BxAGZi09.js → TriageScreen-BajACF5K.js} +1 -1
  19. package/web/assets/{VpsScreen-Xq65JDcT.js → VpsScreen-C7muNRX5.js} +1 -1
  20. package/web/assets/{diff-view-BNI0kLEC.js → diff-view-CsZPBznT.js} +1 -1
  21. package/web/assets/index-DI7G_sit.js +923 -0
  22. package/web/assets/live-DVDstDzi.js +1 -0
  23. package/web/index.html +1 -1
  24. package/web/assets/IdeScreen-CI0YYC3D.js +0 -2
  25. package/web/assets/SchedulerScreen-C4Qftb2o.js +0 -1
  26. package/web/assets/TerminalScreen-uPBkCPTD.js +0 -9
  27. package/web/assets/index-j_iWjqt5.js +0 -915
  28. package/web/assets/live-BkauBLCS.js +0 -1
@@ -1,4 +1,4 @@
1
- import{aw as pa,ax as ka,ay as ba,az as xa,aA as fa,aB as ja,aC as ya,aD as va,aE as Sa,aF as wa,aG as Ca,aH as Aa,aI as Ea,aJ as za,aK as Pa,e as f,j as e,ad as C,c as ee,d as V,ae as he,a as m,f as Y,a8 as Ba,I as Le,B as re,aq as J,N as ue,aL as Oa,C as la,aM as sa,aN as De,aO as ra,aP as Ia,aQ as Ee,aR as Ke,aS as Ma,aT as Ye,aU as Da,aV as Ha,aW as La,A as _a,u as Ne,aX as Na,aY as Fa,aZ as Ra,h as Wa,a3 as $a,a_ as Ga,S as D,p as Ua,a$ as Ka,O as da,b0 as ye,b1 as _e,b2 as oa,b3 as ca,b4 as He,b5 as ua,b6 as Ta,b7 as Ja,b8 as Va,Y as se,b9 as Ce,ba as qe,H as Ya,bb as Xe,bc as Qe,bd as qa,a0 as Ue,Z as Xa,be as Qa,W as Za,X as et,bf as We}from"./index-j_iWjqt5.js";import{R as l}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as at}from"./DocPreviewModal-DsAfvavy.js";const tt=[...pa,...ka,...ba,...xa,...fa,...ja,...ya,...va,...Sa,...wa,...Ca,...Aa,...Ea,...za,...Pa],nt=1;function it(){const[a,d]=l.useState(null),[r,u]=l.useState([]),[k,i]=l.useState(""),[s,p]=l.useState(""),[A,o]=l.useState([]),[g,x]=l.useState(null),E=l.useCallback(()=>f.listClientAccounts().then(v=>d(v.items)).catch(()=>d([])),[]);l.useEffect(()=>{E(),f.listProjects().then(v=>u(v.items.map(I=>({id:I.id,name:I.name})))).catch(()=>u([]))},[E]);const R=async()=>{x(null);try{await f.createClientAccount({email:k,password:s,projects:A}),i(""),p(""),o([]),await E()}catch{x("Gagal membuat akun — periksa email (mungkin sudah dipakai) dan panjang password.")}},W=async(v,I)=>{await f.updateClientAccount(v,I),await E()},w=async v=>{await f.deleteClientAccount(v),await E()},z=(v,I,K)=>K?[...v,I]:v.filter($=>$!==I);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(V,{"aria-label":"Email klien",placeholder:"mis. budi@tokomekar.co.id",value:k,onChange:v=>i(v.target.value)})}),e.jsx(ee,{label:"Password awal",hint:"Minimal 8 karakter. Sampaikan lewat kanal yang aman — klien bisa menggantinya sendiri.",children:e.jsx(V,{"aria-label":"Password awal",type:"password",placeholder:"mis. kunci-tokomekar-2026",value:s,onChange:v=>p(v.target.value)})}),e.jsx(ee,{label:"Project yang boleh dilihat",children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:14},children:r.map(v=>e.jsx(he,{"aria-label":`Beri akses ${v.name}`,label:v.name,checked:A.includes(v.id),onChange:I=>o(K=>z(K,v.id,I))},v.id))})}),g&&e.jsx("div",{style:{color:"var(--status-err)",fontSize:"var(--text-sm)",marginBottom:10},children:g}),e.jsx(m,{size:"sm",leftIcon:"user-plus",onClick:R,disabled:!k||s.length<8,children:"Buat akun"})]}),e.jsx(C,{eyebrow:"akses",title:"Akun klien",children:a===null?e.jsx(Y,{kind:"loading",title:"Memuat…"}):a.length===0?e.jsx(Y,{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(v=>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:v.email}),e.jsx(Ba,{status:v.disabled?"stopped":"done",size:"sm",children:v.disabled?"nonaktif":"aktif"}),e.jsx("div",{style:{flex:1,minWidth:240,display:"flex",flexWrap:"wrap",gap:14},children:r.map(I=>e.jsx(he,{"aria-label":`${v.email} · ${I.name}`,label:I.name,checked:v.projects.includes(I.id),onChange:K=>void W(v.id,{projects:z(v.projects,I.id,K)})},I.id))}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void W(v.id,{disabled:!v.disabled}),children:v.disabled?"Aktifkan":"Nonaktifkan"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void w(v.id),children:"Hapus"})]},v.id))})})]})}const lt={name:"",url:"",events:["*"],enabled:!0,allowPrivate:!1},st=sa.map(a=>({entity:a.entity,label:a.label,types:De.filter(d=>d.entity===a.entity).map(d=>d.type)})),Ze=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"short",timeStyle:"medium"}):"—",ce={fontSize:12.5,color:"var(--text-muted)",lineHeight:1.5},$e={fontFamily:"var(--font-mono)",fontSize:12};function rt({e:a}){return a.enabled?e.jsx(re,{tone:"ok",children:"aktif"}):a.disabledAt?e.jsx(re,{tone:"err",children:"dinonaktifkan otomatis"}):e.jsx(re,{children:"nonaktif"})}function dt({onToast:a,onOpenDocs:d}={}){const[r,u]=l.useState(null),[k,i]=l.useState(!1),[s,p]=l.useState(null),[A,o]=l.useState(null),[g,x]=l.useState(!1),[E,R]=l.useState({}),[W,w]=l.useState(null),[z,v]=l.useState([]),[I,K]=l.useState(null),$=l.useCallback(async()=>{try{u((await f.listWebhooks()).endpoints),i(!1)}catch{i(!0)}},[]);l.useEffect(()=>{$()},[$]);const ge=async n=>{w(n);try{v((await f.listWebhookDeliveries(n)).items)}catch{v([])}},me=async()=>{if(s){x(!0);try{if(s.id)await f.updateWebhook(s.id,{name:s.name,url:s.url,events:s.events,enabled:s.enabled,allowPrivate:s.allowPrivate}),a==null||a("Endpoint webhook diperbarui");else{const n=await f.createWebhook({name:s.name,url:s.url,events:s.events,enabled:s.enabled,allowPrivate:s.allowPrivate});o(n.secret??null),a==null||a("Endpoint webhook dibuat")}p(null),await $()}catch(n){a==null||a(`Gagal menyimpan: ${n.message}`,"err")}finally{x(!1)}}},te=async n=>{x(!0);try{const j=await f.updateWebhook(n,{rotateSecret:!0});o(j.secret??null),await $()}catch(j){a==null||a(`Gagal merotasi secret: ${j.message}`,"err")}finally{x(!1)}},ve=async(n,j)=>{try{await f.updateWebhook(n.id,{enabled:j}),await $()}catch(M){a==null||a(`Gagal mengubah status: ${M.message}`,"err")}},ne=async n=>{x(!0);try{const j=await f.testWebhook(n);R(M=>({...M,[n]:j})),await $()}catch(j){R(M=>({...M,[n]:{ok:!1,httpStatus:null,durationMs:0,error:j.message}}))}finally{x(!1)}},ae=async()=>{if(I)try{await f.deleteWebhook(I.id),a==null||a("Endpoint webhook dihapus"),await $()}catch(n){a==null||a(`Gagal menghapus: ${n.message}`,"err")}finally{K(null)}},ie=async n=>{try{await f.retryWebhookDelivery(n),W&&await ge(W),await $()}catch(j){a==null||a(`Gagal antre ulang: ${j.message}`,"err")}},h=(n,j)=>p(M=>M&&{...M,events:j?[...new Set([...M.events.filter(_=>_!=="*"),...n])]:M.events.filter(_=>_!=="*"&&!n.includes(_))}),O=(s==null?void 0:s.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(m,{size:"sm",onClick:()=>{p({...lt}),o(null)},children:[e.jsx(Le,{name:"plus",size:14})," Tambah endpoint"]}),e.jsxs(m,{size:"sm",variant:"ghost",onClick:d,children:[e.jsx(Le,{name:"book-open",size:14})," Dokumentasi webhook"]})]}),k?e.jsx(Y,{kind:"error",compact:!0,title:"Gagal memuat endpoint webhook",hint:"Coba muat ulang.",action:()=>void $(),actionLabel:"Coba lagi"}):r===null?e.jsx("div",{style:ce,children:"Memuat…"}):r.length===0?e.jsx(Y,{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:r.map(n=>e.jsxs("div",{"data-testid":`webhook-${n.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:n.name}),e.jsx(rt,{e:n}),n.pending>0?e.jsxs(re,{children:[n.pending," mengantre"]}):null,e.jsxs("div",{style:{marginLeft:"auto",display:"flex",gap:6,alignItems:"center"},children:[e.jsx(J,{checked:n.enabled,"aria-label":`Aktifkan ${n.name}`,onChange:j=>void ve(n,j)}),e.jsx(m,{size:"sm",variant:"ghost",disabled:g,onClick:()=>void ne(n.id),children:"Test"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void ge(n.id),children:"Riwayat"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>{o(null),p({id:n.id,name:n.name,url:n.url,events:n.events,enabled:n.enabled,allowPrivate:n.allowPrivate})},children:"Ubah"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>K(n),children:"Hapus"})]})]}),e.jsx("div",{style:{...$e,color:"var(--text-muted)",marginTop:6},children:n.url}),e.jsxs("div",{style:{...ce,marginTop:6},children:["Peristiwa: ",e.jsx("code",{children:n.events.join(", ")})," · secret …",n.secretHint," ·"," ","sukses terakhir ",Ze(n.lastSuccessAt),n.failureStreak>0?` · ${n.failureStreak} gagal beruntun`:""]}),n.disabledReason?e.jsx("div",{style:{...ce,marginTop:6,color:"var(--status-err-tint)"},children:n.disabledReason}):null,E[n.id]?e.jsx("div",{style:{...ce,marginTop:6},children:E[n.id].ok?`Test berhasil — HTTP ${E[n.id].httpStatus} · ${E[n.id].durationMs} ms`:`Test gagal — ${E[n.id].error}`}):null]},n.id))})]}),A?e.jsxs(C,{eyebrow:"secret",title:"Salin sekarang — secret tak ditampilkan lagi",children:[e.jsx(ue,{tone:"brass",children:e.jsx("div",{style:{...$e,wordBreak:"break-all"},children:A})}),e.jsxs("div",{style:{display:"flex",gap:8,marginTop:10},children:[e.jsx(m,{size:"sm",onClick:()=>{var n;return void((n=navigator.clipboard)==null?void 0:n.writeText(A))},children:"Salin secret"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>o(null),children:"Tutup"})]})]}):null,s?e.jsx(C,{eyebrow:s.id?"ubah":"tambah",title:s.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(V,{value:s.name,placeholder:"mis. Dashboard internal",onChange:n=>p({...s,name:n.target.value})})}),e.jsx(ee,{label:"URL tujuan",children:e.jsx(V,{value:s.url,placeholder:"https://contoh.id/hanoman-webhook",onChange:n=>p({...s,url:n.target.value})})}),e.jsxs("div",{children:[e.jsx("div",{style:{fontWeight:600,fontSize:13,marginBottom:6},children:"Peristiwa yang dikirim"}),e.jsx(he,{checked:O,label:"Semua peristiwa",onChange:n=>p({...s,events:n?["*"]:[]})}),O?null:e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[st.map(n=>e.jsxs("div",{children:[e.jsx(he,{checked:n.types.every(j=>s.events.includes(j)),label:n.label,onChange:j=>h(n.types,j)}),e.jsx("div",{style:{paddingLeft:22,display:"flex",flexWrap:"wrap",gap:10},children:n.types.map(j=>e.jsx(he,{checked:s.events.includes(j),label:j,onChange:M=>p({...s,events:M?[...new Set([...s.events.filter(_=>_!=="*"),j])]:s.events.filter(_=>_!==j&&_!=="*")})},j))})]},n.entity)),e.jsxs("div",{style:ce,children:[e.jsx("code",{children:Oa})," selalu terkirim saat tombol Test ditekan, apa pun langganannya."]})]})]}),e.jsx(he,{checked:s.allowPrivate,label:"Izinkan alamat internal / loopback",onChange:n=>p({...s,allowPrivate:n})}),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(he,{checked:s.enabled,label:"Aktif",onChange:n=>p({...s,enabled:n})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(m,{size:"sm",disabled:g||!s.name||!s.url||s.events.length===0,onClick:()=>void me(),children:"Simpan"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>p(null),children:"Batal"}),s.id?e.jsx(m,{size:"sm",variant:"ghost",disabled:g,onClick:()=>void te(s.id),children:"Rotasi secret"}):null]})]})}):null,W?e.jsxs(C,{eyebrow:"riwayat",title:"Riwayat pengiriman",children:[e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:8},children:e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>w(null),children:"Tutup riwayat"})}),z.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:z.map(n=>e.jsxs("tr",{style:{borderTop:"1px solid var(--border-hair)"},children:[e.jsx("td",{style:{padding:"6px 8px",whiteSpace:"nowrap"},children:Ze(n.createdAt)}),e.jsx("td",{style:{padding:"6px 8px",...$e},children:n.eventType}),e.jsx("td",{style:{padding:"6px 8px"},children:n.status}),e.jsx("td",{style:{padding:"6px 8px"},children:n.httpStatus??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:`${n.attempt} / ${n.maxAttempts}`}),e.jsx("td",{style:{padding:"6px 8px",color:"var(--text-muted)"},children:n.error??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:n.status==="failed"||n.status==="dropped"?e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void ie(n.id),children:"Antre ulang"}):null})]},n.id))})]})})]}):null,e.jsx(la,{open:!!I,title:"Hapus endpoint webhook?",message:I?`"${I.name}" beserta seluruh riwayat pengirimannya akan dihapus.`:"",confirmLabel:"Hapus",onCancel:()=>K(null),onConfirm:()=>void ae()})]})}const T={fontSize:13,color:"var(--text-muted)",lineHeight:1.6},ot={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 Ge({text:a,label:d="Salin"}){const[r,u]=l.useState(!1);return e.jsxs("div",{style:{position:"relative"},children:[e.jsx("pre",{style:ot,children:a}),e.jsx("div",{style:{marginTop:6},children:e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>{var k;(k=navigator.clipboard)==null||k.writeText(a),u(!0),setTimeout(()=>u(!1),1500)},children:r?"Tersalin":d})})]})}const ct=`// Node.js (Express) — verifikasi tanda tangan webhook hanoman
1
+ import{ay as pa,az as ka,aA as ba,aB as xa,aC as fa,aD as ja,aE as ya,aF as va,aG as Sa,aH as wa,aI as Ca,aJ as Aa,aK as Ea,aL as za,aM as Pa,e as f,j as e,ae as C,c as ee,d as V,af as he,a as m,f as Y,a9 as Ba,I as Le,B as re,ar as J,N as ue,aN as Oa,C as la,aO as sa,aP as De,aQ as ra,aR as Ia,aS as Ee,aT as Ke,aU as Ma,aV as Ye,aW as Da,aX as Ha,aY as La,A as _a,u as Ne,aZ as Na,a_ as Fa,a$ as Ra,h as Wa,a4 as $a,b0 as Ga,S as D,p as Ua,b1 as Ka,O as da,b2 as ye,b3 as _e,b4 as oa,b5 as ca,b6 as He,b7 as ua,b8 as Ta,b9 as Ja,au as Va,Y as se,ba as Ce,bb as qe,H as Ya,bc as Xe,bd as Qe,be as qa,a0 as Ue,Z as Xa,bf as Qa,W as Za,X as et,bg as We}from"./index-DI7G_sit.js";import{R as l}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as at}from"./DocPreviewModal-ZFjISCL0.js";const tt=[...pa,...ka,...ba,...xa,...fa,...ja,...ya,...va,...Sa,...wa,...Ca,...Aa,...Ea,...za,...Pa],nt=1;function it(){const[a,d]=l.useState(null),[r,u]=l.useState([]),[k,i]=l.useState(""),[s,p]=l.useState(""),[A,o]=l.useState([]),[g,x]=l.useState(null),E=l.useCallback(()=>f.listClientAccounts().then(v=>d(v.items)).catch(()=>d([])),[]);l.useEffect(()=>{E(),f.listProjects().then(v=>u(v.items.map(I=>({id:I.id,name:I.name})))).catch(()=>u([]))},[E]);const R=async()=>{x(null);try{await f.createClientAccount({email:k,password:s,projects:A}),i(""),p(""),o([]),await E()}catch{x("Gagal membuat akun — periksa email (mungkin sudah dipakai) dan panjang password.")}},W=async(v,I)=>{await f.updateClientAccount(v,I),await E()},w=async v=>{await f.deleteClientAccount(v),await E()},z=(v,I,K)=>K?[...v,I]:v.filter($=>$!==I);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(V,{"aria-label":"Email klien",placeholder:"mis. budi@tokomekar.co.id",value:k,onChange:v=>i(v.target.value)})}),e.jsx(ee,{label:"Password awal",hint:"Minimal 8 karakter. Sampaikan lewat kanal yang aman — klien bisa menggantinya sendiri.",children:e.jsx(V,{"aria-label":"Password awal",type:"password",placeholder:"mis. kunci-tokomekar-2026",value:s,onChange:v=>p(v.target.value)})}),e.jsx(ee,{label:"Project yang boleh dilihat",children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:14},children:r.map(v=>e.jsx(he,{"aria-label":`Beri akses ${v.name}`,label:v.name,checked:A.includes(v.id),onChange:I=>o(K=>z(K,v.id,I))},v.id))})}),g&&e.jsx("div",{style:{color:"var(--status-err)",fontSize:"var(--text-sm)",marginBottom:10},children:g}),e.jsx(m,{size:"sm",leftIcon:"user-plus",onClick:R,disabled:!k||s.length<8,children:"Buat akun"})]}),e.jsx(C,{eyebrow:"akses",title:"Akun klien",children:a===null?e.jsx(Y,{kind:"loading",title:"Memuat…"}):a.length===0?e.jsx(Y,{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(v=>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:v.email}),e.jsx(Ba,{status:v.disabled?"stopped":"done",size:"sm",children:v.disabled?"nonaktif":"aktif"}),e.jsx("div",{style:{flex:1,minWidth:240,display:"flex",flexWrap:"wrap",gap:14},children:r.map(I=>e.jsx(he,{"aria-label":`${v.email} · ${I.name}`,label:I.name,checked:v.projects.includes(I.id),onChange:K=>void W(v.id,{projects:z(v.projects,I.id,K)})},I.id))}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void W(v.id,{disabled:!v.disabled}),children:v.disabled?"Aktifkan":"Nonaktifkan"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void w(v.id),children:"Hapus"})]},v.id))})})]})}const lt={name:"",url:"",events:["*"],enabled:!0,allowPrivate:!1},st=sa.map(a=>({entity:a.entity,label:a.label,types:De.filter(d=>d.entity===a.entity).map(d=>d.type)})),Ze=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"short",timeStyle:"medium"}):"—",ce={fontSize:12.5,color:"var(--text-muted)",lineHeight:1.5},$e={fontFamily:"var(--font-mono)",fontSize:12};function rt({e:a}){return a.enabled?e.jsx(re,{tone:"ok",children:"aktif"}):a.disabledAt?e.jsx(re,{tone:"err",children:"dinonaktifkan otomatis"}):e.jsx(re,{children:"nonaktif"})}function dt({onToast:a,onOpenDocs:d}={}){const[r,u]=l.useState(null),[k,i]=l.useState(!1),[s,p]=l.useState(null),[A,o]=l.useState(null),[g,x]=l.useState(!1),[E,R]=l.useState({}),[W,w]=l.useState(null),[z,v]=l.useState([]),[I,K]=l.useState(null),$=l.useCallback(async()=>{try{u((await f.listWebhooks()).endpoints),i(!1)}catch{i(!0)}},[]);l.useEffect(()=>{$()},[$]);const ge=async n=>{w(n);try{v((await f.listWebhookDeliveries(n)).items)}catch{v([])}},me=async()=>{if(s){x(!0);try{if(s.id)await f.updateWebhook(s.id,{name:s.name,url:s.url,events:s.events,enabled:s.enabled,allowPrivate:s.allowPrivate}),a==null||a("Endpoint webhook diperbarui");else{const n=await f.createWebhook({name:s.name,url:s.url,events:s.events,enabled:s.enabled,allowPrivate:s.allowPrivate});o(n.secret??null),a==null||a("Endpoint webhook dibuat")}p(null),await $()}catch(n){a==null||a(`Gagal menyimpan: ${n.message}`,"err")}finally{x(!1)}}},te=async n=>{x(!0);try{const j=await f.updateWebhook(n,{rotateSecret:!0});o(j.secret??null),await $()}catch(j){a==null||a(`Gagal merotasi secret: ${j.message}`,"err")}finally{x(!1)}},ve=async(n,j)=>{try{await f.updateWebhook(n.id,{enabled:j}),await $()}catch(M){a==null||a(`Gagal mengubah status: ${M.message}`,"err")}},ne=async n=>{x(!0);try{const j=await f.testWebhook(n);R(M=>({...M,[n]:j})),await $()}catch(j){R(M=>({...M,[n]:{ok:!1,httpStatus:null,durationMs:0,error:j.message}}))}finally{x(!1)}},ae=async()=>{if(I)try{await f.deleteWebhook(I.id),a==null||a("Endpoint webhook dihapus"),await $()}catch(n){a==null||a(`Gagal menghapus: ${n.message}`,"err")}finally{K(null)}},ie=async n=>{try{await f.retryWebhookDelivery(n),W&&await ge(W),await $()}catch(j){a==null||a(`Gagal antre ulang: ${j.message}`,"err")}},h=(n,j)=>p(M=>M&&{...M,events:j?[...new Set([...M.events.filter(_=>_!=="*"),...n])]:M.events.filter(_=>_!=="*"&&!n.includes(_))}),O=(s==null?void 0:s.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(m,{size:"sm",onClick:()=>{p({...lt}),o(null)},children:[e.jsx(Le,{name:"plus",size:14})," Tambah endpoint"]}),e.jsxs(m,{size:"sm",variant:"ghost",onClick:d,children:[e.jsx(Le,{name:"book-open",size:14})," Dokumentasi webhook"]})]}),k?e.jsx(Y,{kind:"error",compact:!0,title:"Gagal memuat endpoint webhook",hint:"Coba muat ulang.",action:()=>void $(),actionLabel:"Coba lagi"}):r===null?e.jsx("div",{style:ce,children:"Memuat…"}):r.length===0?e.jsx(Y,{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:r.map(n=>e.jsxs("div",{"data-testid":`webhook-${n.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:n.name}),e.jsx(rt,{e:n}),n.pending>0?e.jsxs(re,{children:[n.pending," mengantre"]}):null,e.jsxs("div",{style:{marginLeft:"auto",display:"flex",gap:6,alignItems:"center"},children:[e.jsx(J,{checked:n.enabled,"aria-label":`Aktifkan ${n.name}`,onChange:j=>void ve(n,j)}),e.jsx(m,{size:"sm",variant:"ghost",disabled:g,onClick:()=>void ne(n.id),children:"Test"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void ge(n.id),children:"Riwayat"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>{o(null),p({id:n.id,name:n.name,url:n.url,events:n.events,enabled:n.enabled,allowPrivate:n.allowPrivate})},children:"Ubah"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>K(n),children:"Hapus"})]})]}),e.jsx("div",{style:{...$e,color:"var(--text-muted)",marginTop:6},children:n.url}),e.jsxs("div",{style:{...ce,marginTop:6},children:["Peristiwa: ",e.jsx("code",{children:n.events.join(", ")})," · secret …",n.secretHint," ·"," ","sukses terakhir ",Ze(n.lastSuccessAt),n.failureStreak>0?` · ${n.failureStreak} gagal beruntun`:""]}),n.disabledReason?e.jsx("div",{style:{...ce,marginTop:6,color:"var(--status-err-tint)"},children:n.disabledReason}):null,E[n.id]?e.jsx("div",{style:{...ce,marginTop:6},children:E[n.id].ok?`Test berhasil — HTTP ${E[n.id].httpStatus} · ${E[n.id].durationMs} ms`:`Test gagal — ${E[n.id].error}`}):null]},n.id))})]}),A?e.jsxs(C,{eyebrow:"secret",title:"Salin sekarang — secret tak ditampilkan lagi",children:[e.jsx(ue,{tone:"brass",children:e.jsx("div",{style:{...$e,wordBreak:"break-all"},children:A})}),e.jsxs("div",{style:{display:"flex",gap:8,marginTop:10},children:[e.jsx(m,{size:"sm",onClick:()=>{var n;return void((n=navigator.clipboard)==null?void 0:n.writeText(A))},children:"Salin secret"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>o(null),children:"Tutup"})]})]}):null,s?e.jsx(C,{eyebrow:s.id?"ubah":"tambah",title:s.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(V,{value:s.name,placeholder:"mis. Dashboard internal",onChange:n=>p({...s,name:n.target.value})})}),e.jsx(ee,{label:"URL tujuan",children:e.jsx(V,{value:s.url,placeholder:"https://contoh.id/hanoman-webhook",onChange:n=>p({...s,url:n.target.value})})}),e.jsxs("div",{children:[e.jsx("div",{style:{fontWeight:600,fontSize:13,marginBottom:6},children:"Peristiwa yang dikirim"}),e.jsx(he,{checked:O,label:"Semua peristiwa",onChange:n=>p({...s,events:n?["*"]:[]})}),O?null:e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[st.map(n=>e.jsxs("div",{children:[e.jsx(he,{checked:n.types.every(j=>s.events.includes(j)),label:n.label,onChange:j=>h(n.types,j)}),e.jsx("div",{style:{paddingLeft:22,display:"flex",flexWrap:"wrap",gap:10},children:n.types.map(j=>e.jsx(he,{checked:s.events.includes(j),label:j,onChange:M=>p({...s,events:M?[...new Set([...s.events.filter(_=>_!=="*"),j])]:s.events.filter(_=>_!==j&&_!=="*")})},j))})]},n.entity)),e.jsxs("div",{style:ce,children:[e.jsx("code",{children:Oa})," selalu terkirim saat tombol Test ditekan, apa pun langganannya."]})]})]}),e.jsx(he,{checked:s.allowPrivate,label:"Izinkan alamat internal / loopback",onChange:n=>p({...s,allowPrivate:n})}),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(he,{checked:s.enabled,label:"Aktif",onChange:n=>p({...s,enabled:n})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(m,{size:"sm",disabled:g||!s.name||!s.url||s.events.length===0,onClick:()=>void me(),children:"Simpan"}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>p(null),children:"Batal"}),s.id?e.jsx(m,{size:"sm",variant:"ghost",disabled:g,onClick:()=>void te(s.id),children:"Rotasi secret"}):null]})]})}):null,W?e.jsxs(C,{eyebrow:"riwayat",title:"Riwayat pengiriman",children:[e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:8},children:e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>w(null),children:"Tutup riwayat"})}),z.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:z.map(n=>e.jsxs("tr",{style:{borderTop:"1px solid var(--border-hair)"},children:[e.jsx("td",{style:{padding:"6px 8px",whiteSpace:"nowrap"},children:Ze(n.createdAt)}),e.jsx("td",{style:{padding:"6px 8px",...$e},children:n.eventType}),e.jsx("td",{style:{padding:"6px 8px"},children:n.status}),e.jsx("td",{style:{padding:"6px 8px"},children:n.httpStatus??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:`${n.attempt} / ${n.maxAttempts}`}),e.jsx("td",{style:{padding:"6px 8px",color:"var(--text-muted)"},children:n.error??"—"}),e.jsx("td",{style:{padding:"6px 8px"},children:n.status==="failed"||n.status==="dropped"?e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>void ie(n.id),children:"Antre ulang"}):null})]},n.id))})]})})]}):null,e.jsx(la,{open:!!I,title:"Hapus endpoint webhook?",message:I?`"${I.name}" beserta seluruh riwayat pengirimannya akan dihapus.`:"",confirmLabel:"Hapus",onCancel:()=>K(null),onConfirm:()=>void ae()})]})}const T={fontSize:13,color:"var(--text-muted)",lineHeight:1.6},ot={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 Ge({text:a,label:d="Salin"}){const[r,u]=l.useState(!1);return e.jsxs("div",{style:{position:"relative"},children:[e.jsx("pre",{style:ot,children:a}),e.jsx("div",{style:{marginTop:6},children:e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>{var k;(k=navigator.clipboard)==null||k.writeText(a),u(!0),setTimeout(()=>u(!1),1500)},children:r?"Tersalin":d})})]})}const ct=`// 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-j_iWjqt5.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as xt}from"./live-BkauBLCS.js";import"./markdown-CWEY34jk.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 sa({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,sa 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-DI7G_sit.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as xt}from"./live-DVDstDzi.js";import"./markdown-CWEY34jk.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 sa({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,sa as TeamScreen};
@@ -0,0 +1,9 @@
1
+ import{j as t,d as it,e as _,A as Xt,M as Be,S as pe,G as Vt,J as At,f as st,B as tt,I as ve,w as Jt,D as Qt,a as re,K as Zt,N as en,O as mt,Q as ht,c as Xe,U as tn,V as nn,W as rn,X as an,Y as sn,Z as on,_ as $e,$ as zt,a0 as ot,a1 as ln,h as Ne,a2 as Lt,a3 as cn,a4 as un,a5 as dn,g as Ve,a6 as Nt,l as pn,x as fn,a7 as Je,p as mn,a8 as hn,a9 as De,aa as gn,ab as gt,ac as xn,ad as bn}from"./index-DI7G_sit.js";import{R as l,r as H}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as vn,o as yn}from"./xterm-3VOAfa_q.js";function lt(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const kn=new RegExp(["\\x1b\\[[?>][0-9;]*c","\\x1b\\[\\??[0-9]+;[0-9]+R","\\x1b\\[\\??[0-9;]*n","\\x1b\\[\\??[0-9;]*\\$y","\\x1b\\][0-9][0-9;]*;[^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)","\\x1bP[0-9]*[$+>][a-z|][^\\x1b]*\\x1b\\\\"].join("|"),"g"),jn=e=>e.length>0&&e.replace(kn,"")==="";function wn(e,n){if(e.type!=="keydown")return null;const a=e.key.toLowerCase();return e.metaKey||e.ctrlKey&&e.shiftKey?a==="c"?n?"copy":null:a==="v"?"paste":null:null}const Sn=new Set(["image/png","image/jpeg","image/webp"]);function xt(e){return(e!=null&&e.files?Array.from(e.files):[]).filter(a=>Sn.has(a.type))}function Cn(e){return e!=null&&e.types?Array.from(e.types).includes("Files"):!1}const In=96,En=50,Rn=2,Tn=2;function An(e,n,a){if(!Number.isFinite(e)||e<=0)return n;const i=a+Rn,s=Math.floor((e-In-En-Tn*i)/i);return s>=n?n:Math.max(0,s-1)}const zn=/enter to select/i,Ln=/to navigate/i,Nn=/^\s*[❯>*]?\s*(\d)\.\s/;function Dn(e,n){var s;const a=e.join(`
2
+ `);if(!zn.test(a)||!Ln.test(a))return null;const i=e[n];return i?((s=Nn.exec(i))==null?void 0:s[1])??null:null}const Dt=10,Bt=24,ct=13,Bn=15;function nt(e){return Number.isFinite(e)?Math.min(Bt,Math.max(Dt,Math.round(e))):ct}const $n=[{id:"esc",label:"Esc",seq:"\x1B",aria:"Kirim Escape ke terminal"},{id:"tab",label:"Tab",seq:" ",aria:"Kirim Tab ke terminal"},{id:"up",label:"↑",seq:"\x1B[A",aria:"Kirim panah atas ke terminal"},{id:"down",label:"↓",seq:"\x1B[B",aria:"Kirim panah bawah ke terminal"},{id:"left",label:"←",seq:"\x1B[D",aria:"Kirim panah kiri ke terminal"},{id:"right",label:"→",seq:"\x1B[C",aria:"Kirim panah kanan ke terminal"},{id:"enter",label:"Enter",seq:"\r",aria:"Kirim Enter ke terminal"}],Mn=/[\x00-\x1f\x7f]/;function ut(e){return!e||Mn.test(e)?"control":[...e].length>1?"bulk":"text"}function $t(e){return e?`\x1B[4m${e}\x1B[24m`:""}function Ue(e){return e>0?`\x1B[${e}D\x1B[K`:""}const Fn=500,Pn=5e3,On=64,Wn=2;function Mt(){return{pending:"",since:null,altScreen:!1,suspendedUntil:0,typed:"",unechoed:"",gen:0,parsed:0}}const _n=e=>e.gen!==e.parsed;function Kn(e,n){return{...e,altScreen:n}}const Hn=/(password|passphrase|pass|pin)\s*(?:for\s+\S+\s*)?:\s*$/i;function qn(e){return Hn.test(e)}function Ft(e,n,a,i,s){return!s||!a.deliverable||e.altScreen||i<e.suspendedUntil||ut(n)!=="text"||a.cursorX+Wn+1>a.cols||a.line.slice(a.cursorX).trim().length>0?!1:!qn(a.line.trimEnd())}function Gn(e,n){for(let a=n.length;a>0;a-=1)if(e.endsWith(n.slice(0,a)))return a;return 0}function Un(e,n,a,i,s){const u=ut(n);if(u==="text"&&_n(e)&&s&&a.deliverable&&!e.altScreen&&i>=e.suspendedUntil)return e.unechoed.length>=On?{state:e,write:""}:{state:{...e,unechoed:e.unechoed+n,typed:""},write:"",deferred:!0};if(!Ft(e,n,a,i,s)){const h=i<e.suspendedUntil&&u==="text"?(e.typed+n).slice(-32):"";return h===e.typed&&!e.unechoed?{state:e,write:""}:{state:{...e,typed:h,unechoed:""},write:""}}return{state:{...e,pending:e.pending+n,unechoed:e.unechoed+n,since:null,typed:""},write:$t(n)}}function Yn(e,n){if(!n)return!1;const a=n.slice(-Math.min(2,n.length));return e.endsWith(a)}function Xn(e,n,a){return a>=e.suspendedUntil?e.typed?{...e,typed:""}:e:Yn(n,e.typed)?{...e,suspendedUntil:0,typed:""}:e}function Vn(e,n,a){return{state:{...e,pending:"",since:null,gen:e.gen+1},write:Ue(e.pending.length)+n}}function Jn(e,n,a,i,s){if(n!==e.gen)return{state:e,write:""};const u=a.line.slice(0,a.cursorX),v=Xn({...e,parsed:n},u,i);if(!v.unechoed)return{state:v,write:""};const h=v.unechoed.slice(Gn(u,v.unechoed));if(!h)return{state:{...v,unechoed:""},write:""};const I=Zn({...v,pending:""},h,a,i,s);return I.write?{state:{...I.state,unechoed:h},write:I.write}:{state:{...v,pending:"",unechoed:""},write:""}}function Qn(e,n){return!e.pending||e.since!==null?e:{...e,since:n}}function Zn(e,n,a,i,s){if(!n)return{state:e,write:""};const u=[...n];for(let v=0;v<u.length;v+=1){const h={...a,cursorX:a.cursorX+v};if(!Ft({...e},u[v],h,i,s))return{state:e,write:""}}return{state:{...e,pending:n,since:null},write:$t(n)}}function er(e,n){return!e.pending||e.since===null||n<e.since+Fn?{state:e,write:"",missed:!1}:{state:{...e,pending:"",since:null,suspendedUntil:n+Pn,typed:"",unechoed:""},write:Ue(e.pending.length),missed:!0}}function bt(e){const n=((e==null?void 0:e.gen)??0)+1;return{...Mt(),gen:n,parsed:n}}const tr=16;function nr(e){let n="",a;const i=()=>{if(a&&(clearTimeout(a),a=void 0),!n)return;const s=n;n="",e(s)};return{push(s,u){if(!u||ut(s)!=="text"){i(),s&&e(s);return}n+=s,a||(a=setTimeout(i,tr))},flush:i,dispose(){i()}}}const rr=250,ar=512,ir={"\x1B":"\\e","\r":"\\r","\n":"\\n"," ":"\\t","\b":"\\b","":"\\x7f"};function vt(e){let n="";for(const a of e){const i=ir[a];if(i){n+=i;continue}const s=a.codePointAt(0);n+=s<32||s===127?`\\x${s.toString(16).padStart(2,"0")}`:a}return n}function sr(e){const n=e.batchMs??rr,a=e.max??ar;let i=null,s=[],u,v=!1;const h=()=>{if(u&&(clearTimeout(u),u=void 0),!s.length)return;const I=s;s=[],e.send(I)};return{record(I,T,g){if(v)return;const b=e.now();i===null&&(i=b);const D={t:b-i,k:I,v:T};g!==void 0&&(D.n=g),s.push(D),s.length>a&&(s=s.slice(s.length-a)),u||(u=setTimeout(h,n))},flush:h,dispose(){h(),v=!0}}}const or="",lr=350,cr=1e3;function dt(){return{text:"",sentPrefix:""}}function ur(e,n){const a=[...e],i=[...n];let s=0;for(;s<a.length&&s<i.length&&a[s]===i[s];)s+=1;return s}function pt(e,n){const a=ur(e,n);return or.repeat([...e].length-a)+[...n].slice(a).join("")}function dr(e,n){return{...e,text:n}}function pr(e){return{state:{...e,sentPrefix:e.text},send:pt(e.sentPrefix,e.text)}}function fr(e){return{state:dt(),send:pt(e.sentPrefix,e.text)+"\r"}}function mr(e){return{state:dt(),send:pt(e.sentPrefix,e.text)}}function hr(e,n){return n.held?{kind:"held",text:"tertahan — Kirim di atas"}:n.n>0?{kind:"queued",text:`diantre ${n.n}`}:e==="open"?{kind:"sent",text:"terkirim"}:null}function gr({sessionId:e,send:n,external:a,linkState:i,queue:s}){const[u,v]=l.useState(""),h=l.useRef(dt()),I=l.useRef(n);I.current=n;const T=l.useRef(void 0),g=l.useRef(void 0),b=()=>{clearTimeout(T.current),T.current=void 0,clearTimeout(g.current),g.current=void 0},D=C=>{b(),h.current=C.state,C.send&&I.current(C.send)},z=()=>D(pr(h.current));a.current=()=>{D(mr(h.current)),v("")},l.useEffect(()=>()=>{a.current=()=>{}},[a]),l.useEffect(()=>b,[]);const E=C=>{h.current=dr(h.current,C),v(C),clearTimeout(T.current),T.current=setTimeout(z,lr),g.current||(g.current=setTimeout(z,cr))},k=()=>{D(fr(h.current)),v("")},f=hr(i,s);return t.jsxs("div",{className:"hn-terminal-composer",children:[t.jsx(it,{size:"lg",mono:!0,value:u,"data-testid":"terminal-composer","aria-label":`Ketik untuk sesi ${e}`,placeholder:"mis. pnpm vitest --run",autoCapitalize:"off",autoCorrect:"off",spellCheck:!1,autoComplete:"off",enterKeyHint:"send",style:{flex:"1 1 160px",minWidth:0},onChange:C=>E(C.target.value),onBlur:()=>z(),onKeyDown:C=>{C.key!=="Enter"||C.nativeEvent.isComposing||(C.preventDefault(),k())}}),f&&t.jsx("span",{"data-testid":"terminal-composer-status",className:`hn-terminal-composer-status hn-terminal-composer-status--${f.kind}`,children:f.text})]})}const Pt=[500,1e3,2e3,4e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3],yt=Pt.length,xr=4096,br=/[\r\n]/;function Ot({sessionId:e,onExit:n,onPhases:a,fontSize:i=ct,showKeys:s=!1,predict:u=!0,diag:v=!1}){const h=l.useRef(null),I=l.useRef(i);I.current=i;const T=l.useRef(u);T.current=u;const g=l.useRef(v);g.current=v;const b=l.useRef(null),D=l.useRef(n);D.current=n;const z=l.useRef(a);z.current=a;const[E,k]=l.useState({state:"connecting"}),[f,C]=l.useState({n:0,held:!1,full:!1}),S=l.useRef(()=>{}),y=l.useRef(()=>{}),P=l.useRef(()=>{}),j=l.useRef(()=>{}),B=l.useRef(()=>{}),d=l.useRef(()=>{});return l.useEffect(()=>{const c=h.current;if(!c)return;const N=getComputedStyle(document.documentElement),M=(p,R)=>N.getPropertyValue(p).trim()||R,x=new vn({fontFamily:M("--font-mono","monospace"),fontSize:nt(I.current),cursorBlink:!0,macOptionClickForcesSelection:!0,theme:{background:M("--term-bg","#1c1810"),foreground:M("--term-fg","#e9e0cd")}}),G=new yn;x.loadAddon(G),x.open(c);const U=()=>{const p=c.getBoundingClientRect();return p.width>0&&p.height>0?p:null};U()&&G.fit();let L,Y=!1,ae=0,ie,X=!1;const le=p=>{(L==null?void 0:L.readyState)===WebSocket.OPEN&&L.send(JSON.stringify(p))};b.current={term:x,fit:G,send:le};const Q=sr({now:()=>Date.now(),send:p=>le({t:"diag",ev:p})}),Z=(p,R,r)=>{g.current&&Q.record(p,R,r)};let V="",J=!1,ee=!1,se=0,ce=0,fe=!1;const ue=new Map,K=p=>{if(se+=1,ce+=1,g.current){if(ue.size>256)for(const R of[...ue.keys()].slice(0,128))ue.delete(R);ue.set(se,Date.now())}le({t:"in",d:p,seq:se})},O=()=>C({n:V.length,held:J,full:ee}),Fe=p=>{if(!J&&!V&&(L==null?void 0:L.readyState)===WebSocket.OPEN){K(p);return}if(!(fe||jn(p))){if(V.length+p.length>xr){ee=!0,O();return}V+=p,O()}};let w=Mt();const q=nr(Fe),ye=p=>q.push(p,!1);y.current=ye;const te=p=>{B.current(),ye(p)};d.current=te;const de=()=>{var R;const p=x.buffer.active;return{cursorX:p.cursorX,cols:x.cols,deliverable:!fe&&!ee,line:((R=p.getLine(p.viewportY+p.cursorY))==null?void 0:R.translateToString(!0))??""}},ke=()=>{ce===0&&(L==null?void 0:L.readyState)===WebSocket.OPEN&&(w=Qn(w,Date.now()))},je=()=>{if(!V||(L==null?void 0:L.readyState)!==WebSocket.OPEN){O();return}const p=V;V="",ee=!1,O(),K(p)},Ye=()=>{if(q.flush(),!V){O();return}if(br.test(V)){J=!0,O();return}je()};P.current=()=>{J=!1,je()},j.current=()=>{V="",J=!1,ee=!1,O()};const Ae=p=>{B.current();const R=w.pending.length>0;Z("data",vt(p));const r=de(),o=Un(w,p,r,Date.now(),T.current);w=o.state,o.write?x.write(o.write):o.deferred?Z("pred","tangguh: frame server in flight"):Z("pred",`tolak cx=${r.cursorX}/${r.cols} alt=${w.altScreen?1:0} deliverable=${r.deliverable?1:0} suspend=${Math.max(0,w.suspendedUntil-Date.now())}`),q.push(p,R||o.write.length>0||o.deferred===!0)},Se=setInterval(()=>{const p=er(w,Date.now());w=p.state,p.write&&x.write(p.write)},100),me=()=>{_.issueWsTicket(`terminal:${e}`).then(({ticket:p})=>{if(Y)return;const R=location.protocol==="https:"?"wss:":"ws:",r=new WebSocket(`${R}//${location.host}${Xt.terminalWs(e)}`,[`hanoman-ticket.${p}`]);L=r,r.onopen=()=>{ae=0,se=0,ce=0;const o=Ue(w.pending.length);o&&x.write(o),w=bt(w),k({state:"open"}),U()&&((typeof window.matchMedia!="function"||window.matchMedia("(hover: hover) and (pointer: fine)").matches)&&x.focus(),le({t:"resize",cols:x.cols,rows:x.rows})),Ye()},r.onmessage=o=>{var A;const m=JSON.parse(o.data);if(m.t==="data"){const F=Vn(w,m.d??"");w=F.state;const oe=w.gen;x.write(F.write,()=>{if(Y)return;const ne=Jn(w,oe,de(),Date.now(),T.current);w=ne.state,ne.write&&x.write(ne.write),ke()}),ke()}else if(m.t==="ack"){if(ce=Math.max(0,ce-1),typeof m.seq=="number"){const F=ue.get(m.seq);F!==void 0&&(ue.delete(m.seq),Z("ack",String(m.seq),Date.now()-F))}ke()}else m.t==="phase"?(A=z.current)==null||A.call(z,m.phases??[],m.complete===!0):m.t==="alt"?w=Kn(w,m.on===!0):m.t==="exit"&&(X=!0,x.write(`\r
3
+ \x1B[33m— sesi berakhir (exit ${m.code}) —\x1B[0m\r
4
+ `),D.current(m.code??0))},r.onclose=o=>{if(!(Y||X)){if(o.code===4004){fe=!0;const m=Ue(w.pending.length);m&&x.write(m),w=bt(w),V="",J=!1,ee=!1,O(),k({state:"gone"});return}Pe()}},r.onerror=()=>{}}).catch(()=>{Y||(x.write(`\r
5
+ \x1B[31mWebSocket admission gagal\x1B[0m\r
6
+ `),Pe())})},Pe=()=>{if(ae>=yt){k({state:"lost"});return}const p=Pt[ae];ae+=1,k({state:"retrying",attempt:ae}),ie=setTimeout(me,p)};S.current=()=>{Y||(clearTimeout(ie),ae=0,k({state:"retrying",attempt:1}),me())},me(),x.attachCustomKeyEventHandler(p=>{var r,o;const R=wn(p,x.hasSelection());return R==="copy"?((r=navigator.clipboard)==null||r.writeText(x.getSelection()),!1):R==="paste"?((o=navigator.clipboard)==null||o.readText().then(m=>{m&&te(m)}),!1):!0}),x.attachCustomWheelEventHandler(p=>{if(!p.shiftKey)return!0;const R=U();if(!R||x.rows<=0)return!0;const r=R.height/x.rows,o=Math.trunc(p.deltaY/r)||Math.sign(p.deltaY);return o&&x.scrollLines(o),!1});const Oe=x.onData(Ae),$=x.textarea,ze=p=>Z("key",p.key,p.keyCode),he=p=>Z("comp",`${p.type}:${vt(p.data??"")}`);$==null||$.addEventListener("keydown",ze),$==null||$.addEventListener("compositionstart",he),$==null||$.addEventListener("compositionupdate",he),$==null||$.addEventListener("compositionend",he);let ge=null,xe=0,Ce=!1;const we=()=>{ge=null,xe=0,Ce=!1},We=p=>{if(p.touches.length!==1){we();return}ge=p.touches[0].clientY,xe=0,Ce=!1},_e=p=>{if(ge===null||p.touches.length!==1){we();return}const R=U();if(!R||x.rows<=0)return;const r=p.touches[0].clientY;xe+=ge-r,ge=r;const o=R.height/x.rows,m=Math.trunc(xe/o);m!==0&&(x.scrollLines(m),xe-=m*o,Ce=!0),p.preventDefault()},Ke=p=>{var ne,Ee;const R=ge!==null&&!Ce,r=((Ee=(ne=p.changedTouches)==null?void 0:ne[0])==null?void 0:Ee.clientY)??ge;if(we(),!R||r===null||r===void 0)return;const o=U();if(!o||x.rows<=0)return;const m=Math.floor((r-o.top)/(o.height/x.rows)),A=x.buffer.active,F=Array.from({length:x.rows},(Hr,Yt)=>{var ft;return((ft=A.getLine(A.viewportY+Yt))==null?void 0:ft.translateToString(!0))??""}),oe=Dn(F,m);oe&&te(oe)},Ie=async p=>{for(const R of p)try{const{path:r}=await _.uploadTerminalAttachment(e,R);te(`${r} `)}catch(r){x.write(`\r
7
+ \x1B[31mlampiran gagal: ${r.message}\x1B[0m\r
8
+ `)}},W=p=>{const R=xt(p.clipboardData);R.length&&(p.preventDefault(),Ie(R))},Le=p=>{Cn(p.dataTransfer)&&p.preventDefault()},He=p=>{const R=xt(p.dataTransfer);R.length&&(p.preventDefault(),Ie(R))};c.addEventListener("paste",W),c.addEventListener("dragover",Le),c.addEventListener("drop",He),c.addEventListener("touchstart",We,{passive:!0}),c.addEventListener("touchmove",_e,{passive:!1}),c.addEventListener("touchend",Ke,{passive:!0}),c.addEventListener("touchcancel",we,{passive:!0});const qe=new ResizeObserver(p=>{var r;const R=((r=p[0])==null?void 0:r.contentRect)??c.getBoundingClientRect();R.width<=0||R.height<=0||(G.fit(),le({t:"resize",cols:x.cols,rows:x.rows}))});return qe.observe(c),()=>{Y=!0,clearTimeout(ie),S.current=()=>{},y.current=()=>{},d.current=()=>{},P.current=()=>{},j.current=()=>{},b.current=null,c.removeEventListener("paste",W),c.removeEventListener("dragover",Le),c.removeEventListener("drop",He),c.removeEventListener("touchstart",We),c.removeEventListener("touchmove",_e),c.removeEventListener("touchend",Ke),c.removeEventListener("touchcancel",we),qe.disconnect(),clearInterval(Se),q.dispose(),Q.dispose(),$==null||$.removeEventListener("keydown",ze),$==null||$.removeEventListener("compositionstart",he),$==null||$.removeEventListener("compositionupdate",he),$==null||$.removeEventListener("compositionend",he),Oe.dispose(),L==null||L.close(),x.dispose()}},[e]),l.useEffect(()=>{const c=b.current,N=h.current;if(!c||!N)return;const M=nt(i);if(c.term.options.fontSize===M)return;c.term.options.fontSize=M;const x=N.getBoundingClientRect();x.width<=0||x.height<=0||(c.fit.fit(),c.send({t:"resize",cols:c.term.cols,rows:c.term.rows}))},[i]),l.useEffect(()=>{const c=b.current,N=h.current;if(!c||!N)return;const M=N.getBoundingClientRect();M.width<=0||M.height<=0||(c.fit.fit(),c.send({t:"resize",cols:c.term.cols,rows:c.term.rows}))},[s]),t.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[(E.state!=="open"&&E.state!=="connecting"||f.held||f.full)&&t.jsxs("div",{"data-testid":"terminal-link",style:{display:"flex",alignItems:"center",gap:8,flex:"0 0 auto",flexWrap:"wrap",padding:"3px 8px",fontFamily:"var(--font-mono)",fontSize:11,background:E.state==="retrying"||f.held?"var(--status-warn-tint)":"var(--status-err-tint)",color:"var(--text-body)"},children:[E.state==="retrying"&&t.jsxs("span",{children:["menyambung ulang… (",E.attempt,"/",yt,")"]}),E.state==="gone"&&t.jsx("span",{children:"sesi tidak ditemukan di tmux"}),E.state==="lost"&&t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"terputus"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>S.current(),children:"Sambungkan lagi"})]}),f.n>0&&!f.held&&t.jsxs("span",{"data-testid":"terminal-queue",children:[f.n," ketikan diantre"]}),f.held&&t.jsxs(t.Fragment,{children:[t.jsxs("span",{"data-testid":"terminal-held",children:[f.n," ketikan tertahan — belum dikirim"]}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>P.current(),children:"Kirim"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>j.current(),children:"Buang"})]}),f.full&&t.jsx("span",{"data-testid":"terminal-queue-full",children:"antrean penuh"})]}),t.jsx("div",{ref:h,"data-testid":"terminal-host",style:{flex:1,minHeight:0,width:"100%",background:"var(--term-bg)",padding:8,borderRadius:"var(--radius-sm)",touchAction:"pan-x pinch-zoom",overscrollBehavior:"contain"}}),s&&t.jsx(gr,{sessionId:e,send:c=>y.current(c),external:B,linkState:E.state,queue:f}),s&&t.jsx(vr,{onKey:c=>d.current(c)})]})}function vr({onKey:e}){return t.jsx("div",{className:"hn-terminal-keys",role:"group","aria-label":"Tombol terminal",children:$n.map(n=>t.jsx("button",{type:"button",className:"hn-terminal-key","aria-label":n.aria,title:n.aria,onClick:()=>e(n.seq),children:n.label},n.id))})}const kt=20;function yr(e,n){if(!n)return"—";const a=new Date(n).getTime()-new Date(e).getTime();if(!Number.isFinite(a)||a<0)return"—";const i=Math.round(a/1e3);if(i<60)return`${i} dtk`;const s=Math.round(i/60);return s<60?`${s} mnt`:`${Math.floor(s/60)} jam ${s%60} mnt`}function kr(e){switch(lt(e)){case"running":return{label:"berjalan",tone:"neutral"};case"interrupted":return{label:"terputus",tone:"warn"};case"failed":return{label:`exit ${e.exitCode}`,tone:"err"};default:return{label:"selesai",tone:"ok"}}}const Wt=e=>lt(e)==="interrupted"?"—":yr(e.startedAt,e.endedAt),_t=e=>At[e]??e;function jr({projects:e,onClose:n,onRestart:a}){const[i,s]=l.useState([]),[u,v]=l.useState(0),[h,I]=l.useState(1),[T,g]=l.useState(!1),[b,D]=l.useState(""),[z,E]=l.useState(""),[k,f]=l.useState(""),[C,S]=l.useState(""),[y,P]=l.useState(null);l.useEffect(()=>{const d=setTimeout(()=>S(k.trim()),250);return()=>clearTimeout(d)},[k]),l.useEffect(()=>{I(1)},[b,z,C]),l.useEffect(()=>{let d=!0;return g(!0),_.listSessionHistory({projectId:b||void 0,kind:z||void 0,q:C||void 0,page:h,limit:kt}).then(c=>{d&&(v(c.total),s(c.items))}).catch(()=>{d&&(s([]),v(0))}).finally(()=>{d&&g(!1)}),()=>{d=!1}},[b,z,C,h]);const j=Qt(u,h,kt),B=d=>{var c;return((c=e.find(N=>N.id===d))==null?void 0:c.name)??d};return t.jsxs(Be,{open:!0,title:"Riwayat sesi",icon:"history",onClose:n,width:900,children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(it,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:k,onChange:d=>f(d.target.value),style:{flex:"1 1 200px"}}),t.jsx(pe,{size:"sm","aria-label":"Filter project",value:b,onChange:d=>D(d.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(d=>({value:d.id,label:d.name})))}),t.jsx(pe,{size:"sm","aria-label":"Filter jenis",value:z,onChange:d=>E(d.target.value),options:[{value:"",label:"Semua jenis"}].concat(Vt.map(d=>({value:d,label:At[d]})))})]}),i.length===0&&!T?t.jsx(st,{kind:"empty",icon:"history",title:"Belum ada riwayat sesi",hint:"Riwayat terisi sendiri saat sesi terminal dibuka lalu ditutup — termasuk sesi backlog, terminal biasa, dan sesi project-level."}):t.jsxs("div",{style:{display:"flex",flexDirection:"column",maxHeight:"60vh",overflowY:"auto"},children:[i.map(d=>{const c=kr(d);return t.jsx("button",{onClick:()=>P(d),style:{cursor:"pointer",display:"block",width:"100%",flex:"0 0 auto",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:"9px 8px",border:"none",borderBottom:"1px solid var(--border-hair)"},children:t.jsxs("span",{className:"hn-dense-row hn-picker-row",style:{display:"flex",alignItems:"center",gap:10,width:"100%"},children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)",flex:"0 0 132px"},children:new Date(d.startedAt).toLocaleString("id-ID")}),t.jsx(tt,{size:"sm",tone:"neutral",children:_t(d.kind)}),t.jsx("span",{className:"hn-picker-title",style:{flex:1,minWidth:0,fontSize:13,color:"var(--text-strong)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.title??d.specId??B(d.projectId)}),d.transcriptBytes!==null&&t.jsx(ve,{name:"file-text",size:12,color:"var(--text-subtle)"}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-muted)",flex:"0 0 72px"},children:Wt(d)}),t.jsx(tt,{size:"sm",tone:c.tone,children:c.label})]})},d.id)}),T&&t.jsx("div",{style:{padding:"10px 8px",textAlign:"center",fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),t.jsx(Jt,{page:j.page,pageCount:j.pageCount,total:u,from:j.from,to:j.to,onPage:I,unit:"sesi"}),y&&t.jsx(wr,{row:y,projectName:B(y.projectId),onBack:()=>P(null),onRestart:a})]})}function wr({row:e,projectName:n,onBack:a,onRestart:i}){const[s,u]=l.useState(null),[v,h]=l.useState("idle");l.useEffect(()=>{if(e.transcriptBytes===null){h("none"),u(null);return}let g=!0;return h("loading"),_.sessionTranscript(e.id).then(b=>{g&&(u(b.text),h("idle"))}).catch(()=>{g&&(u(null),h("error"))}),()=>{g=!1}},[e.id,e.transcriptBytes]);const I=lt(e)==="interrupted",T=[["Project",n],["Sesi",e.sessionId],["Jenis",_t(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[I?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...I&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",Wt(e)],["Direktori",e.cwd]];return e.specId&&T.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&T.push(["Branch",e.branch]),t.jsxs(Be,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:a,width:1e3,children:[t.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",marginBottom:10},children:[t.jsx(re,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:a,children:"Kembali"}),t.jsx("div",{style:{flex:1}}),s&&t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>{var g;return void((g=navigator.clipboard)==null?void 0:g.writeText(s))},children:"Salin transkrip"}),Zt(e.kind)&&t.jsx(re,{size:"sm",leftIcon:"play",onClick:()=>i(e),children:"Mulai lagi"})]}),I&&t.jsxs(en,{tone:"warn",title:"Sesi terputus — hasilnya tak diketahui",style:{marginBottom:12},children:["Panenya sudah lenyap saat hanoman menyala lagi (reboot, ",t.jsx("code",{children:"tmux kill-server"}),", atau host mati), jadi sesi ini tak meninggalkan exit code dan transkripnya kemungkinan besar tak sempat diambil — capture berjalan tepat sebelum pane dibunuh, dan di jalur ini sudah tak ada pane untuk dibaca. Periksa worktree & branch sesi ini sebelum menganggapnya selesai, lalu mulai lagi bila pekerjaannya belum tuntas."]}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"4px 12px",marginBottom:12,fontSize:12},children:T.map(([g,b])=>t.jsxs(l.Fragment,{children:[t.jsx("span",{style:{color:"var(--text-subtle)"},children:g}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",color:"var(--text-body)",wordBreak:"break-all"},children:b})]},g))}),v==="loading"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:"memuat transkrip…"}),v==="none"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:I?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),v==="error"&&t.jsx("div",{style:{fontSize:12,color:"var(--clay-600)"},children:"Transkrip tak terbaca lagi di server."}),s!==null&&t.jsx("pre",{style:{maxHeight:"52vh",overflow:"auto",margin:0,padding:10,background:"var(--bone-200)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",fontFamily:"var(--font-mono)",fontSize:11,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:s})]})}function Sr({open:e,projectId:n,projectName:a,onClose:i,onCreated:s}){var P;const[u,v]=l.useState("claude"),[h,I]=l.useState("claude-opus-5"),[T,g]=l.useState("xhigh"),[b,D]=l.useState({claude:{model:"claude-opus-5",effort:"xhigh"},codex:{...mt}}),[z,E]=l.useState(!1),[k,f]=l.useState(null);l.useEffect(()=>{e&&(_.getSettings().then(j=>{const B={claude:{model:j.model,effort:j.effort},codex:{...mt,...j.codex??{}}},d=j.agent==="codex"?"codex":"claude",c=ht(B,d);D(B),v(d),I(c.model),g(c.effort)}).catch(()=>{}),_.getCodexVersion().then(j=>f(j.version)).catch(()=>{}))},[e]);const C=j=>{v(j);const B=ht(b,j);I(B.model),g(B.effort)},S=j=>{I(j),g(B=>u==="codex"?sn(j,B):on(j,B))};async function y(){E(!0);try{const{id:j}=await _.createTerminal(n,{agent:u,model:h,effort:T});s(j),i()}catch{}finally{E(!1)}}return t.jsxs(Be,{open:e,onClose:i,icon:"plus",eyebrow:a,title:"Sesi baru",footer:t.jsxs(t.Fragment,{children:[t.jsx(re,{variant:"ghost",onClick:i,children:"Batal"}),t.jsx(re,{leftIcon:"play",disabled:z,onClick:()=>void y(),children:"Buka sesi"})]}),children:[t.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Runtime untuk sesi ini. Default dari setelan global; ubah bila perlu. Sesi lahir dengan pilihan ini untuk seluruh hidupnya — ",t.jsx("code",{children:"/model"})," di terminal tetap bisa mengubahnya."]}),t.jsx(Xe,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:t.jsx(pe,{"aria-label":"Agen",value:u,style:{width:"100%"},options:[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}],onChange:j=>C(j.target.value)})}),t.jsx(Xe,{label:"Model",children:t.jsx(pe,{"aria-label":"Model",value:h,style:{width:"100%"},options:tn(u).map(j=>({value:j.id,label:j.label})),onChange:j=>S(j.target.value)})}),t.jsx(Xe,{label:"Effort",children:t.jsx(pe,{"aria-label":"Effort",value:T,style:{width:"100%"},options:nn(u,h).map(j=>({value:j,label:j})),onChange:j=>g(j.target.value)})}),u==="codex"&&rn(h,k)&&t.jsxs("div",{"data-testid":"codex-version-note",style:{fontSize:12,lineHeight:1.5,marginBottom:12,padding:"8px 10px",borderRadius:8,background:"var(--warn-bg, #fdf6e3)",color:"var(--text-muted)"},children:["Codex CLI terpasang ",t.jsx("b",{children:k}),", sedangkan ",t.jsx("b",{children:h})," butuh ",t.jsx("b",{children:(P=an(h))==null?void 0:P.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}const Cr=()=>({rows:1,cols:1,cells:[null]}),jt=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)]});function wt(e){const n=e.cols+1,a=[];for(let i=0;i<e.rows;i++)for(let s=0;s<n;s++)a.push(s<e.cols?e.cells[i*e.cols+s]??null:null);return{rows:e.rows,cols:n,cells:a}}function St(e,n){if(e.rows===1||n<0||n>=e.rows)return e;const a=[...e.cells];return a.splice(n*e.cols,e.cols),{...e,rows:e.rows-1,cells:a}}function Ct(e,n){if(e.cols===1||n<0||n>=e.cols)return e;const a=e.cols-1,i=[];for(let s=0;s<e.rows;s++)for(let u=0;u<e.cols;u++)u!==n&&i.push(e.cells[s*e.cols+u]??null);return{rows:e.rows,cols:a,cells:i}}function rt(e,n,a){if(n<0||n>=e.cells.length)return e;const i=e.cells.map(s=>a!==null&&s===a?null:s);return i[n]=a,{...e,cells:i}}const Ir=(e,n)=>({...e,cells:e.cells.map(a=>a&&n.has(a)?a:null)}),Kt=e=>({id:crypto.randomUUID(),name:e,layout:Cr()});function It(){const e=Kt("Utama");return{groups:[e],active:e.id}}const Me=e=>e.groups.find(n=>n.id===e.active)??e.groups[0];function Er(e,n){const a=Kt(n);return{groups:[...e.groups,a],active:a.id}}const Rr=(e,n,a)=>({...e,groups:e.groups.map(i=>i.id===n?{...i,name:a}:i)});function Tr(e,n){if(e.groups.length===1)return e;const a=e.groups.filter(i=>i.id!==n);return a.length===e.groups.length?e:{groups:a,active:e.active===n?a[0].id:e.active}}const Ar=(e,n)=>e.groups.some(a=>a.id===n)?{...e,active:n}:e;function be(e,n){const a=Me(e);return{...e,groups:e.groups.map(i=>i.id===a.id?{...i,layout:n(i.layout)}:i)}}function at(e,n,a){const i=Me(e),s=a===null?e.groups:e.groups.map(u=>u.id===i.id?u:{...u,layout:rt(u.layout,u.layout.cells.indexOf(a),null)});return{...e,groups:s.map(u=>u.id===i.id?{...u,layout:rt(u.layout,n,a)}:u)}}function Re(e,n){const a=Me(e).layout.cells.indexOf(null);return a===-1?e:at(e,a,n)}const zr=(e,n)=>({...e,groups:e.groups.map(a=>({...a,layout:rt(a.layout,a.layout.cells.indexOf(n),null)}))}),Et=e=>new Set(e.groups.flatMap(n=>n.layout.cells.filter(a=>a!==null))),Rt=(e,n)=>({...e,groups:e.groups.map(a=>({...a,layout:Ir(a.layout,n)}))}),Ht="hanoman.terminal.workspace",qt="hanoman.terminal.layout",Te=e=>$e.parse({version:1,groups:e.groups});function Ge(e,n){const a=e.groups,i=n&&a.some(s=>s.id===n)?n:a[0].id;return{groups:a,active:i}}function Lr(e){try{const n=JSON.parse(e);if(!n||typeof n!="object")return null;const a=n,i=$e.parse({version:1,groups:a.groups});return{workspace:i,active:typeof a.active=="string"&&i.groups.some(s=>s.id===a.active)?a.active:i.groups[0].id}}catch{return null}}function Nr(){try{const e=localStorage.getItem(Ht);if(e)return Lr(e);const n=localStorage.getItem(qt);if(!n)return null;const a=JSON.parse(n),i={id:crypto.randomUUID(),name:"Utama",layout:a};return{workspace:$e.parse({version:1,groups:[i]}),active:i.id}}catch{return null}}function Qe(){try{localStorage.removeItem(Ht),localStorage.removeItem(qt)}catch{}}const Gt=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function Dr(e){try{const n=localStorage.getItem(Gt(e));if(!n)return null;const a=JSON.parse(n),i=$e.parse(a.workspace);if(!Number.isInteger(a.revision)||(a.revision??-1)<0)return null;const s=typeof a.active=="string"&&i.groups.some(u=>u.id===a.active)?a.active:i.groups[0].id;return{workspace:i,revision:a.revision,active:s}}catch{return null}}function Ze(e,n){try{const a=$e.parse(n.workspace);if(!Number.isInteger(n.revision)||n.revision<0)return;const i=a.groups.some(s=>s.id===n.active)?n.active:a.groups[0].id;localStorage.setItem(Gt(e),JSON.stringify({workspace:a,revision:n.revision,active:i}))}catch{}}function et(e){if(!(e instanceof ot)||e.status!==409)return null;const n=e.detail;if((n==null?void 0:n.code)!=="revision-conflict")return null;const a=ln.safeParse(n.current);return a.success?a.data:null}function Br(e){const n=H.useRef(null);n.current||(n.current=It());const[a,i]=H.useState(n.current),[s,u]=H.useState("loading"),[v,h]=H.useState(null),[I,T]=H.useState(!1),g=H.useRef(a),b=H.useRef(0),D=H.useRef(!1),z=H.useRef(Promise.resolve()),E=H.useRef(0),k=H.useCallback(d=>{g.current=d,i(d)},[]),f=H.useCallback(d=>{D.current=d,T(d)},[]),C=H.useCallback(d=>{const c=z.current.then(d,d);return z.current=c.then(()=>{},()=>{}),c},[]),S=H.useCallback((d,c="ready",N=null,M=g.current.active)=>{const x=d.workspace?Ge(d.workspace,M):It();b.current=d.revision,k(x),u(c),h(N),f(!0),d.workspace&&Ze(e,{workspace:d.workspace,revision:d.revision,active:x.active})},[k,f,e]),y=H.useCallback(d=>{const c=Dr(e);c&&(b.current=c.revision,k(Ge(c.workspace,c.active))),f(!1),u("recovering"),h(d instanceof Error?d.message:"Layout server belum tersambung")},[k,f,e]),P=H.useCallback(()=>C(async()=>{try{S(await _.getTerminalWorkspace())}catch(d){y(d)}}),[S,C,y]);H.useEffect(()=>{const d=++E.current;return u("loading"),h(null),f(!1),C(async()=>{try{const c=await _.getTerminalWorkspace();if(d!==E.current)return;if(c.workspace){S(c),Qe();return}const N=Nr();if(!N){S(c);return}try{const M=await _.putTerminalWorkspace({baseRevision:c.revision,workspace:N.workspace});if(d!==E.current)return;k(Ge(M.workspace,N.active)),b.current=M.revision,Ze(e,{workspace:M.workspace,revision:M.revision,active:N.active}),Qe(),u("ready"),h(null),f(!0)}catch(M){const x=et(M);x!=null&&x.workspace?(S(x,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),Qe()):y(M)}}catch(c){d===E.current&&y(c)}}),()=>{E.current+=1}},[S,C,y,k,f,e]),H.useEffect(()=>{const d=()=>{P()},c=()=>{document.visibilityState==="visible"&&P()};return window.addEventListener("focus",d),document.addEventListener("visibilitychange",c),()=>{window.removeEventListener("focus",d),document.removeEventListener("visibilitychange",c)}},[P]);const j=H.useCallback(d=>C(async()=>{if(!D.current)return!1;const c=d(g.current);let N,M;try{N=Te(c),M=Te(g.current)}catch{return u("conflict"),h("Layout tidak valid dan tidak disimpan"),!1}if(zt(N,M))return!0;try{return S(await _.putTerminalWorkspace({baseRevision:b.current,workspace:N}),"ready",null,c.active),!0}catch(x){const G=et(x);if(!(G!=null&&G.workspace))return y(x),!1;const U=d(Ge(G.workspace,g.current.active));try{const L=await _.putTerminalWorkspace({baseRevision:G.revision,workspace:Te(U)});return S(L,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",U.active),!0}catch(L){if(!et(L)&&!(L instanceof ot&&L.status===409))return y(L),!1;try{S(await _.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(Y){y(Y)}return!1}}}),[S,C,y]),B=H.useCallback(d=>{const c=Ar(g.current,d);k(c);const N=Te(c);Ze(e,{workspace:N,revision:b.current,active:c.active})},[k,e]);return{workspace:a,status:s,message:v,writable:I,mutate:j,setActive:B,refresh:P}}function Xr({userId:e="test-user",projects:n,backlog:a=[],focusSession:i,onOpenReview:s,onOpenSessionReview:u,titleOf:v,onIntegrate:h,onIntegrateSession:I,specOf:T}){var R;const[g,b]=l.useState([]),[D,z]=l.useState([]),E=Br(e),{workspace:k,status:f,message:C,writable:S,mutate:y,setActive:P,refresh:j}=E,[B,d]=Ne("terminal","project",((R=n[0])==null?void 0:R.id)??"",mn),c=Lt(),[N,M]=Ne("terminal","fontSize",c?Bn:ct,fn),[x,G]=Ne("terminal","keys",c,Je),[U,L]=Ne("terminal","predict",!0,Je),[Y,ae]=Ne("terminal","diag",!1,Je),ie=r=>M(o=>nt(o+r)),[X,le]=l.useState(!1),[Q,Z]=l.useState(null),[V,J]=l.useState(!1),[ee,se]=l.useState(null),[ce,fe]=l.useState(!1),[ue,K]=l.useState(!1),O=cn(),w=un()==="mobile",[q,ye]=l.useState(0),[te,de]=l.useState(null),ke=l.useRef(null),[je,Ye]=l.useState(!1);l.useEffect(()=>{_.listTerminals().then(r=>{b(r),Ye(!0)}).catch(()=>{})},[]),l.useEffect(()=>dn(r=>{r.t==="sessions"?b(r.sessions):r.t==="cleanups"&&z(r.cleanups)}),[]),l.useEffect(()=>{if(!je||!S)return;const r=new Set(g.map(m=>m.id)),o=Rt(k,r);zt(Te(o),Te(k))||y(m=>Rt(m,r))},[y,g,je,S,k]),l.useEffect(()=>{if(!i){ke.current=null;return}!je||ke.current===i||g.some(r=>r.id===i&&!r.exited)&&(ke.current=i,de(i))},[i,g,je]),l.useEffect(()=>{if(!te)return;const r=k.groups.find(o=>o.layout.cells.includes(te));if(r){r.id!==k.active&&P(r.id);return}S&&y(o=>{if(Et(o).has(te))return o;const m=Re(o,te);return m!==o||!w?m:at(o,q,te)})},[q,w,y,te,P,S,k]),l.useEffect(()=>{Q&&!g.some(r=>r.id===Q)&&Z(null)},[Q,g]);const Ae=D.filter(r=>r.error),Se=r=>g.find(o=>o.id===r)??null,me=r=>{var o;return((o=n.find(m=>m.id===r))==null?void 0:o.name)??r};function Pe(r){b(o=>o.some(m=>m.id===r)?o:[...o,{id:r,projectId:B,cwd:"",exited:!1}]),y(o=>Re(o,r)),de(r)}async function Oe(){if(!B)return;const{id:r}=await _.createShell(B);b(o=>[...o,{id:r,projectId:B,cwd:"",exited:!1}]),y(o=>Re(o,r)),de(r)}async function $(r,o){const m=bn(r.source);try{const{id:A}=await _.startSession({spec:r.id,flow:m,...o?{force:o}:{}});b(F=>F.some(oe=>oe.id===A)?F:[...F,{id:A,projectId:r.projectId,specId:r.id,flow:m,cwd:"",exited:!1}]),y(F=>Re(F,A)),de(A),J(!1),se(null)}catch(A){if(O.offerRetry(A,r.id,oe=>$(r,oe)))return;const F=A instanceof ot&&(A.status===400||A.status===422);se(`${r.id} · gagal mulai${F?" · project belum punya repoDir":""}`)}}async function ze(r,o){try{const m=r.specId?await _.startSession({spec:r.specId,flow:r.flow??"feature",...o?{force:o}:{}}):r.kind==="shell"?await _.createShell(r.projectId):r.kind==="terminal"?await _.createTerminal(r.projectId,{agent:r.agent==="codex"?"codex":"claude",...r.model?{model:r.model}:{},...r.effort?{effort:r.effort}:{}}):await(o?_.createTerminalFlow(r.projectId,r.kind,{force:o}):_.createTerminalFlow(r.projectId,r.kind));b(A=>A.some(F=>F.id===m.id)?A:[...A,{id:m.id,projectId:r.projectId,specId:r.specId??void 0,cwd:"",exited:!1}]),y(A=>Re(A,m.id)),de(m.id),K(!1)}catch(m){if((r.specId||r.kind!=="shell"&&r.kind!=="terminal")&&O.offerRetry(m,`${r.projectId} · ${r.title??r.specId??r.kind}`,A=>ze(r,A)))return}}const he=new Set(g.filter(r=>r.specId&&!r.exited).map(r=>r.specId)),ge=a.filter(r=>r.stage!=="done"&&!he.has(r.id));function xe(r){b(o=>o.filter(m=>m.id!==r)),_.deleteTerminal(r).catch(()=>{})}const Ce=l.useCallback((r,o)=>{b(m=>m.map(A=>A.id===r?{...A,exited:!0,exitCode:o}:A))},[]),we=(r,o)=>{ye(r),y(m=>at(m,r,o))},We=r=>{de(r),y(o=>Re(o,r))},_e=r=>{y(o=>zr(o,r))},Ke=Et(k),Ie=g.filter(r=>!Ke.has(r.id)),W=Me(k).layout;l.useEffect(()=>{if(!te)return;const r=W.cells.indexOf(te);r<0||(ye(r),de(null))},[W.cells,te]),l.useEffect(()=>{q>=W.cells.length&&ye(Math.max(0,W.cells.length-1))},[q,W.cells.length]);const Le=W.rows===1&&W.cols===1&&!W.cells[0]&&g.length===0,He=t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:10,marginBottom:10},children:[t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Ukuran teks terminal"}),t.jsx(Ve,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:N<=Dt,onClick:()=>ie(-1)}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,minWidth:44,textAlign:"center"},children:[N,"px"]}),t.jsx(Ve,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:N>=Bt,onClick:()=>ie(1)})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Papan tombol layar (Esc · panah · Enter)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":x,onClick:()=>G(r=>!r),children:x?"Sembunyikan":"Tampilkan"})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Ketik responsif (huruf tampil sebelum echo server)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":U,"aria-label":`${U?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>L(r=>!r),children:U?"Matikan":"Nyalakan"})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Rekam jalur ketik (diagnostik — merekam setiap tombol)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":Y,"aria-label":`${Y?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>ae(r=>!r),children:Y?"Matikan":"Nyalakan"})]}),w&&t.jsx(pe,{size:"sm","aria-label":"Project sesi baru",value:B,onChange:r=>d(r.target.value),options:n.map(r=>({value:r.id,label:r.name}))})]}),qe=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{se(null),J(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>K(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>void Oe()},{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!S,onSelect:()=>void y(r=>be(r,wt))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!S,onSelect:()=>void y(r=>be(r,jt))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!S||W.cols===1,onSelect:()=>void y(r=>be(r,o=>Ct(o,q%o.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!S||W.rows===1,onSelect:()=>void y(r=>be(r,o=>St(o,Math.floor(q/o.cols))))}],p={display:"flex",flexDirection:"column",gap:X?8:12,...X?{position:"fixed",inset:0,zIndex:100,background:"var(--surface-page)",paddingTop:"max(12px, var(--safe-top))",paddingRight:"max(12px, var(--safe-right))",paddingBottom:"max(12px, var(--safe-bottom))",paddingLeft:"max(12px, var(--safe-left))"}:{flex:"1 1 0",minHeight:640}};return t.jsxs("div",{"data-testid":"terminal-root",style:p,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexDirection:X?"row":"column",alignItems:X?"center":"stretch"},children:[t.jsx(Mr,{compact:X,ws:k,writable:S,onSelect:P,onAdd:()=>void y(r=>Er(r,`Grup ${r.groups.length+1}`)),onRename:(r,o)=>void y(m=>Rr(m,r,o)),onRemove:r=>void y(o=>Tr(o,r))}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",...X?{flex:1,minWidth:0}:{}},children:[!w&&t.jsxs(t.Fragment,{children:[t.jsx(re,{size:"sm",variant:"ghost",disabled:!S,onClick:()=>void y(r=>be(r,wt)),children:"+ Kolom"}),t.jsx(re,{size:"sm",variant:"ghost",disabled:!S,onClick:()=>void y(r=>be(r,jt)),children:"+ Baris"})]}),t.jsx("div",{style:{flex:1,minWidth:0}}),f!=="ready"&&t.jsx("span",{"data-testid":"terminal-workspace-status",title:C??void 0,style:{fontSize:12,color:f==="conflict"?"var(--status-warn)":"var(--text-muted)"},children:f==="loading"?"Memuat layout server…":f==="recovering"?t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Layout server belum tersambung"})," ",t.jsx("button",{type:"button",onClick:()=>void j(),children:"Retry"})]}):C??"Layout berubah di perangkat lain"}),D.length>0&&t.jsx("span",{"data-testid":"worktree-cleanups",title:D.map(r=>`${r.sessionId}${r.error?` — ${r.error}`:""}`).join(`
9
+ `),style:{fontSize:12,color:Ae.length?"var(--status-err)":"var(--text-muted)"},children:Ae.length?`${Ae.length} worktree gagal dibersihkan`:`membersihkan ${D.length} worktree…`}),!w&&t.jsxs(t.Fragment,{children:[t.jsx(pe,{size:"sm",value:B,onChange:r=>d(r.target.value),options:n.map(r=>({value:r.id,label:r.name}))}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"inbox",onClick:()=>{se(null),J(!0)},children:"Ambil backlog"}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"history",title:"Riwayat sesi yang sudah berlalu — buka kembali atau baca transkripnya",onClick:()=>K(!0),children:"Riwayat"}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"terminal",title:"Buka shell tmux tanpa Claude di project terpilih — jalankan command di project",onClick:()=>void Oe(),children:"Terminal biasa"})]}),t.jsx(re,{size:"sm",leftIcon:"plus",onClick:()=>fe(!0),children:"Sesi baru"}),t.jsx(Nt,{label:w?"Aksi terminal lain":"Tampilan terminal",items:w?qe:[],children:He}),t.jsx(Ve,{size:"sm",icon:X?"minimize-2":"maximize-2",label:X?"Keluar layar penuh":"Layar penuh","aria-pressed":X,onClick:()=>le(r=>!r)})]})]}),Ie.length>0&&t.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",alignItems:"center"},children:[t.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Belum di grid:"}),Ie.map(r=>t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6,padding:"4px 8px",borderRadius:"var(--radius-sm)",background:"var(--bone-200)",border:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("button",{className:"hn-terminal-unplaced-action",disabled:!S,onClick:()=>We(r.id),title:"Taruh di sel kosong pertama grup ini",style:{all:"unset",cursor:"pointer"},children:[r.specId??me(r.projectId)," · ",r.id.slice(0,6)]}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${r.id}`,onClick:()=>void xe(r.id),children:"×"})]},r.id))]}),w&&!Le&&t.jsx("div",{className:"hn-stack-mobile",style:{display:"flex",alignItems:"center",gap:8},children:t.jsx(pn,{"aria-label":"Panel terminal",variant:"pill",value:String(q),onChange:r=>ye(Number(r)),tabs:W.cells.map((r,o)=>({value:String(o),label:`Panel ${o+1}${r?` · ${r.slice(0,6)}`:" · kosong"}`}))})}),Le?t.jsx(st,{kind:"empty",icon:"terminal",title:"Belum ada sesi terminal",hint:"Pilih project lalu buka sesi — 'Sesi baru' menjalankan claude --dangerously-skip-permissions di direktori project; 'Terminal biasa' membuka shell tmux polos untuk menjalankan command."}):t.jsxs("div",{style:{flex:1,minHeight:0,display:"grid",gap:8,gridTemplateColumns:w?"minmax(0, 1fr)":`18px repeat(${W.cols}, minmax(0, 1fr))`,gridTemplateRows:w?"minmax(0, 1fr)":`16px repeat(${W.rows}, minmax(0, 1fr))`},children:[!w&&t.jsx("div",{}),!w&&Array.from({length:W.cols},(r,o)=>t.jsx(Tt,{label:`Tutup kolom ${o+1}`,disabled:!S||W.cols===1,onClick:()=>void y(m=>be(m,A=>Ct(A,o)))},`col-${o}`)),Array.from({length:W.rows},(r,o)=>t.jsxs(l.Fragment,{children:[!w&&t.jsx(Tt,{label:`Tutup baris ${o+1}`,disabled:!S||W.rows===1,onClick:()=>void y(m=>be(m,A=>St(A,o)))}),Array.from({length:W.cols},(m,A)=>{const F=o*W.cols+A,oe=W.cells[F]??null,ne=oe?Se(oe):null;return t.jsx("div",{"data-terminal-cell-index":F,"aria-hidden":w&&q!==F?"true":"false",style:{minHeight:0,minWidth:0,display:w&&q!==F?"none":"flex",flexDirection:"column",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:ne?t.jsx(Wr,{session:ne,nameOf:me,onClose:()=>void xe(ne.id),canArrange:S,onDetach:()=>_e(ne.id),onExit:Ee=>Ce(ne.id,Ee),onReview:s,onSessionReview:u,titleOf:v,onIntegrate:h,onIntegrateSession:I,specOf:T,fontSize:N,showKeys:x,predict:U,diag:Y,fullscreen:Q===ne.id,onFullscreen:()=>Z(ne.id)}):t.jsx(Kr,{disabled:!S,unplaced:Ie,nameOf:me,onPick:Ee=>we(F,Ee)})},oe??`empty-${F}`)})]},`row-${o}`))]}),V&&t.jsx($r,{seed:ge,activeIds:he,error:ee,onPick:r=>void $(r),onClose:()=>J(!1)}),ce&&t.jsx(Sr,{open:!0,projectId:B,projectName:me(B),onClose:()=>fe(!1),onCreated:Pe}),ue&&t.jsx(jr,{projects:n,onClose:()=>K(!1),onRestart:r=>void ze(r)}),O.dialog,Q&&Se(Q)&&t.jsx(_r,{session:Se(Q),label:Ut(Se(Q),me,v),fontSize:N,showKeys:x,predict:U,diag:Y,onClose:()=>Z(null)})]})}function Ut(e,n,a){const i=n(e.projectId),s=e.specId?a==null?void 0:a(e.specId):void 0;return e.specId?`${i} · ${e.specId}${s?` · ${s}`:""}`:e.id.startsWith("xaudit-")?`${i} · audit lintas`:i}function $r({seed:e,activeIds:n,error:a,onPick:i,onClose:s}){const[u,v]=l.useState(""),[h,I]=l.useState("all"),[T,g]=l.useState("all"),[b,D]=l.useState(e),[z,E]=l.useState("");l.useEffect(()=>{const f=setTimeout(()=>E(u.trim()),250);return()=>clearTimeout(f)},[u]),l.useEffect(()=>{var S,y;let f=!0;const C=(y=(S=_).listSpecs)==null?void 0:y.call(S,{startable:!0,q:z||void 0,stage:h==="all"?void 0:h,priority:T==="all"?void 0:T});return C==null||C.then(P=>{f&&D(P.items)}).catch(()=>{}),()=>{f=!1}},[z,h,T]);const k=b.filter(f=>!n.has(f.id));return t.jsxs(Be,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:s,width:760,children:[a&&t.jsx("div",{style:{marginBottom:10,padding:"8px 10px",borderRadius:"var(--radius-sm)",background:"var(--clay-100)",color:"var(--clay-600)",fontSize:12},children:a}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(it,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:u,onChange:f=>v(f.target.value),style:{flex:"1 1 220px"}}),t.jsx(pe,{size:"sm","aria-label":"Filter stage",value:h,onChange:f=>I(f.target.value),options:[{value:"all",label:"Semua stage"}].concat(xn.filter(f=>f.key!=="done").map(f=>({value:f.key,label:f.label})))}),t.jsx(pe,{size:"sm","aria-label":"Filter prioritas",value:T,onChange:f=>g(f.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),k.length===0?t.jsx(st,{kind:"empty",icon:"inbox",title:"Tak ada backlog untuk diambil",hint:"Semua item sudah selesai/aktif atau tak cocok filter — buat brief baru di halaman Backlog."}):t.jsx("div",{style:{display:"flex",flexDirection:"column",maxHeight:"62vh",overflowY:"auto"},children:k.map(f=>t.jsx("button",{onClick:()=>i(f),style:{cursor:"pointer",display:"block",width:"100%",flex:"0 0 auto",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:"9px 8px",border:"none",borderBottom:"1px solid var(--border-hair)"},children:t.jsxs("span",{className:"hn-dense-row hn-picker-row",style:{display:"flex",alignItems:"center",gap:10,width:"100%"},children:[t.jsx(ve,{name:f.source==="qa"?"bug":f.source==="audit"?"search":"lightbulb",size:14,color:f.source==="qa"?"var(--clay-500)":f.source==="audit"?"var(--wind-600)":"var(--brass-500)"}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-subtle)",flex:"0 0 78px"},children:f.id}),t.jsx("span",{className:"hn-picker-title",style:{flex:1,minWidth:0,fontSize:13,color:"var(--text-strong)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:f.title}),t.jsx(tt,{tone:f.priority==="tinggi"?"err":"neutral",size:"sm",children:f.priority}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,flex:"0 1 auto",minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--text-muted)"},children:f.projectId})]})},f.id))})]})}function Mr({ws:e,compact:n=!1,writable:a,onSelect:i,onAdd:s,onRename:u,onRemove:v}){const[h,I]=l.useState(null),T=Me(e),g=e.groups.length===1;return t.jsxs("div",{role:"tablist","aria-label":"Grup terminal",style:{display:"flex",alignItems:"center",gap:4,flexWrap:"wrap",...n?{}:{borderBottom:"1px solid var(--border-hair)",paddingBottom:4}},children:[e.groups.map((b,D)=>{const z=b.id===T.id;return h===b.id?t.jsx(Fr,{initial:b.name,onCommit:E=>{E.trim()&&u(b.id,E.trim()),I(null)},onCancel:()=>I(null)},b.id):t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"3px 6px",borderRadius:"var(--radius-sm)",fontSize:12,background:z?"var(--bone-200)":"transparent",border:`1px solid ${z?"var(--border-hair)":"transparent"}`},children:[t.jsx("button",{className:"hn-terminal-group-control",role:"tab","aria-selected":z,tabIndex:z?0:-1,onClick:()=>i(b.id),onKeyDown:E=>{var f,C;let k=null;E.key==="ArrowRight"?k=(D+1)%e.groups.length:E.key==="ArrowLeft"?k=(D-1+e.groups.length)%e.groups.length:E.key==="Home"?k=0:E.key==="End"&&(k=e.groups.length-1),k!==null&&(E.preventDefault(),i(e.groups[k].id),(C=(f=E.currentTarget.closest('[role="tablist"]'))==null?void 0:f.querySelectorAll('[role="tab"]')[k])==null||C.focus())},style:{border:0,padding:0,background:"transparent",font:"inherit",cursor:"pointer",color:z?"var(--text-strong)":"var(--text-muted)"},children:b.name}),z&&a&&t.jsxs(t.Fragment,{children:[t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Ganti nama grup ${b.name}`,title:"Ganti nama",onClick:()=>I(b.id),style:{border:0,padding:0,background:"transparent",cursor:"pointer",color:"var(--text-subtle)",fontSize:10},children:"✎"}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Hapus grup ${b.name}`,title:g?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:g,onClick:()=>v(b.id),style:{border:0,padding:0,background:"transparent",cursor:g?"not-allowed":"pointer",color:"var(--text-subtle)",opacity:g?.35:1},children:"×"})]})]},b.id)}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":"Grup baru",title:"Grup baru",disabled:!a,onClick:s,style:{border:0,background:"transparent",cursor:"pointer",padding:"3px 8px",color:"var(--text-subtle)",fontSize:12},children:"+"})]})}function Tt({label:e,disabled:n,onClick:a}){return t.jsx("button",{type:"button","aria-label":e,title:n?"Grid tak boleh menyusut ke nol":e,disabled:n,onClick:a,style:{all:"unset",display:"grid",placeItems:"center",fontSize:11,lineHeight:1,color:"var(--text-subtle)",opacity:n?.3:1,cursor:n?"not-allowed":"pointer"},children:"×"})}function Fr({initial:e,onCommit:n,onCancel:a}){const[i,s]=l.useState(e);return t.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:i,placeholder:"mis. Rilis",onChange:u=>s(u.target.value),onBlur:()=>n(i),onKeyDown:u=>{u.key==="Enter"?n(i):u.key==="Escape"&&a()},style:{width:100,padding:"3px 6px",fontSize:12,fontFamily:"var(--font-ui)",border:"1px solid var(--border-strong)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",color:"var(--text-strong)"}})}const Pr={done:"var(--brass)",active:"var(--text-strong)",skipped:"var(--text-subtle)",pending:"var(--text-subtle)"};function Or({phases:e}){return e!=null&&e.length?t.jsx("div",{style:{display:"flex",alignItems:"center",gap:8,padding:"3px 8px",flex:"0 0 auto",borderBottom:"1px solid var(--border-hair)",fontSize:10,fontFamily:"var(--font-mono)"},children:e.map(n=>t.jsx("span",{"data-state":n.state,title:n.state,style:{color:Pr[n.state],fontWeight:n.state==="active"?600:400,textDecoration:n.state==="skipped"?"line-through":"none",opacity:n.state==="pending"?.5:1},children:n.name},n.name))}):null}function Wr({session:e,nameOf:n,onClose:a,canArrange:i,onDetach:s,onExit:u,onReview:v,onSessionReview:h,titleOf:I,onIntegrate:T,onIntegrateSession:g,specOf:b,fontSize:D,showKeys:z,predict:E,diag:k,fullscreen:f,onFullscreen:C}){const[S,y]=l.useState(null),P=l.useRef(null),[j,B]=l.useState(Number.POSITIVE_INFINITY),d=Lt();l.useEffect(()=>{const K=P.current;if(!K||typeof ResizeObserver!="function")return;const O=new ResizeObserver(Fe=>{var q;const w=((q=Fe[0])==null?void 0:q.contentRect.width)??K.getBoundingClientRect().width;w>0&&B(w)});return O.observe(K),()=>O.disconnect()},[]);const[c,N]=l.useState(!1),M=l.useCallback((K,O)=>{y(K),N(O)},[]),[x,G]=l.useState(!1),[U,L]=l.useState(!1),[Y,ae]=l.useState(!1),ie=e.specId?b==null?void 0:b(e.specId):void 0,X=!e.specId&&!!e.branch,le=Ut(e,n,I),Q=!e.exited&&!!e.decision,Z=!e.exited&&!!e.deciding,V=Q||Z,J=e.exited&&!!e.exitCode,ee=!e.exited&&c,se=J?null:e.exited||ee?"PST-005":V?"PST-004":"PST-003",ce=[...e.specId?[{key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>G(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>G(!0),"aria-label":`Lihat dokumen sesi ${e.id}`,title:"Lihat dokumen (audit/spec/plan)",children:t.jsx(ve,{name:"file-text",size:12})},"docs")}]:[],...e.specId&&v?[{key:"review",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree)",onSelect:()=>v(e.specId),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>v(e.specId),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree)",children:t.jsx(ve,{name:"git-compare",size:12})},"review")}]:[],...X&&h?[{key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>h(e.id,le),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>h(e.id,le),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree sesi)",children:t.jsx(ve,{name:"git-compare",size:12})},"review-session")}]:[],...ie&&T?[{key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",onSelect:()=>L(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>L(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch spec",children:t.jsx(ve,{name:"git-merge",size:12})},"integrate")}]:[],...X&&g?[{key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>ae(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>ae(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch sesi",children:t.jsx(ve,{name:"git-merge",size:12})},"integrate-session")}]:[],{key:"detach",label:"Lepas dari grid",icon:"unlink",disabled:!i,title:"Lepas dari grid (sesi tetap hidup)",onSelect:s,render:t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:s,disabled:!i,title:"Lepas dari grid (sesi tetap hidup)",children:"lepas"},"detach")}],fe=An(j,ce.length,d?44:28),ue=ce.slice(fe);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:P,className:"hn-terminal-cell-header",style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",flex:"0 0 auto",background:J?"var(--status-err-tint)":e.exited||ee?"var(--status-ok-tint)":V?"var(--status-warn-tint)":"var(--bone-200)",borderBottom:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11,color:e.exited?"var(--text-muted)":"var(--text-body)"},children:[se&&t.jsx(hn,{id:se,decorative:!0,style:{width:34,flex:"0 0 auto",borderRadius:"var(--radius-sm)"}}),t.jsxs("span",{style:{flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:[le," · ",e.id.slice(0,6)]}),e.exited&&(J?t.jsx(De,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):t.jsx(De,{status:"done",size:"sm",children:"Selesai"})),ee&&t.jsx(De,{status:"done",size:"sm",children:"Selesai"}),Z&&!ee&&t.jsx(De,{status:"running",size:"sm",children:"Lead memutuskan"}),Q&&!Z&&!ee&&t.jsx(De,{status:"awaiting",size:"sm"}),t.jsxs("span",{className:"hn-terminal-actions",children:[ce.slice(0,fe).map(K=>K.render),ue.length>0&&t.jsx(Nt,{label:`Aksi lain sesi ${e.id}`,items:ue.map(({render:K,...O})=>O)}),t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:C,title:"Layar penuh — fokus 1 terminal","aria-label":`Layar penuh sesi ${e.id}`,children:t.jsx(ve,{name:"fullscreen",size:12})}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,onClick:a,children:"×"})]})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0,opacity:e.exited?.6:1},children:[t.jsx(Or,{phases:S}),t.jsx("div",{style:{flex:1,minHeight:0},children:f?t.jsx("div",{style:{height:"100%",display:"grid",placeItems:"center",padding:12,color:"var(--text-subtle)",fontSize:12,textAlign:"center"},children:"Terbuka di layar penuh"}):t.jsx(Ot,{sessionId:e.id,onExit:u,onPhases:M,fontSize:D,showKeys:z,predict:E,diag:k},e.id)})]}),x&&e.specId&&t.jsx(gn,{specId:e.specId,onClose:()=>G(!1)}),U&&ie&&T&&t.jsx(gt,{projectId:ie.projectId,ownBranch:`hanoman/${ie.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:ie.id,onClose:()=>L(!1),onIntegrate:(K,O)=>{L(!1),T(ie,K,O)}}),Y&&X&&g&&t.jsx(gt,{projectId:e.projectId,ownBranch:e.branch,eyebrow:e.id.slice(0,16),onClose:()=>ae(!1),onIntegrate:(K,O)=>{ae(!1),g(e,K,O)}})]})}function _r({session:e,label:n,fontSize:a,showKeys:i,predict:s,diag:u,onClose:v}){return t.jsx(Be,{open:!0,icon:"terminal",title:n,onClose:v,closeOnEscape:!1,width:1600,children:t.jsx("div",{style:{height:"min(72vh, calc(100dvh - 180px))",minHeight:0,display:"flex",flexDirection:"column",opacity:e.exited?.6:1},children:t.jsx(Ot,{sessionId:e.id,onExit:()=>{},fontSize:a,showKeys:i,predict:s,diag:u},e.id)})})}function Kr({unplaced:e,nameOf:n,onPick:a,disabled:i}){return t.jsx("div",{style:{flex:1,display:"grid",placeItems:"center",padding:12},children:t.jsx(pe,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:i||!e.length,onChange:s=>s.target.value&&a(s.target.value),options:[{value:"",label:e.length?"Pilih sesi…":"tidak ada sesi bebas"}].concat(e.map(s=>({value:s.id,label:`${s.specId??n(s.projectId)} · ${s.id.slice(0,6)}`})))})})}export{Or as PhaseStrip,Xr as TerminalScreen};
@@ -1 +1 @@
1
- import{e as y,j as e,a as d,f as T,B as C,h as H,o as V,r as Y,t as X,q as Z,S as F,d as U,m as ee,R as te,v as ae,w as ie,p as A,x as se,I as le,y as ne,u as re,c as W,H as oe,z as O,A as q,C as ce,D as de}from"./index-j_iWjqt5.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as ue}from"./live-BkauBLCS.js";import"./markdown-CWEY34jk.js";function pe(s,c){return s==="rejected"?"Ditutup":s!=="accepted"?"Sedang ditinjau":c==="done"?"Selesai":c==="executing"?"Sedang dikerjakan":"Diterima"}const he=5e3,$=20,me=400;function M({total:s,page:c,onPage:j,unit:p="tiket"}){const n=de(s,c,$);return e.jsx(ie,{page:n.page,pageCount:n.pageCount,total:s,from:n.from,to:n.to,onPage:j,unit:p})}function Q(s,c=Date.now()){const j=Math.max(0,c-new Date(s).getTime()),p=Math.floor(j/6e4);if(p<1)return"baru saja";if(p<60)return`${p}m`;const n=Math.floor(p/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const K={new:"warn",accepted:"ok",rejected:"neutral"},J={new:"belum ditinjau",accepted:"diterima",rejected:"ditutup"};function ge({t:s,onOpen:c}){return e.jsxs("button",{onClick:()=>c(s.id),className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:12,width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",cursor:"pointer",marginBottom:8},children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",s.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:s.category}),e.jsx(C,{tone:K[s.status]??"neutral",size:"sm",children:J[s.status]??s.status})]}),e.jsx("span",{style:{display:"block",color:"var(--text-body)",fontSize:"var(--text-sm)",marginTop:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2,display:"block"},children:[s.projectId," · ",s.reporterEmail," · ",Q(s.createdAt)," lalu",s.attachmentCount>0?` · ${s.attachmentCount} lampiran`:""]})]}),s.specId&&e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",s.specId]}),e.jsx(le,{name:"chevron-right",size:16,color:"var(--text-subtle)"})]})}function xe({id:s,onBack:c,onAccepted:j,onDeleted:p,onToast:n}){var R;const[i,k]=l.useState(null),[h,z]=l.useState("loading"),[m,u]=l.useState(!1),[g,x]=l.useState("sedang"),[P,b]=l.useState(!1),[f,B]=l.useState(!1),{confirm:v,dialog:S}=re(),[r,I]=l.useState({title:"",detail:"",category:"bug",status:"new"}),w=l.useCallback(()=>{y.getTicket(s).then(t=>{k(t),z("ready")}).catch(()=>z("error"))},[s]);if(l.useEffect(()=>{w()},[w]),h==="loading")return e.jsx(T,{kind:"loading"});if(h==="error"||!i)return e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:w,actionLabel:"Coba lagi"});async function L(){u(!0);try{const t=await y.acceptTicket(s,g);j(t.spec,!!t.alreadyPromoted)}catch{n("Gagal menerima tiket","err","x-circle")}finally{u(!1)}}async function E(){if(await v({title:`Tolak & tutup tiket #${i.number}?`,message:`"${i.title}" ditutup tanpa membuat backlog item.`,confirmLabel:"Tolak tiket",icon:"x-circle"})){u(!0);try{await y.rejectTicket(s),k({...i,status:"rejected"}),n("Tiket ditutup","ok","check")}catch{n("Gagal menolak tiket","err","x-circle")}finally{u(!1)}}}async function a(){u(!0);try{const t=await y.unlinkTicket(s);k({...i,specId:t.specId,spec:null,status:t.status}),n("Tautan backlog dilepas","ok","unlink")}catch{n("Gagal melepas tautan","err","x-circle")}finally{u(!1)}}function o(){I({title:i.title,detail:i.detail,category:i.category,status:i.status}),b(!0)}async function D(){u(!0);try{const t=await y.editTicket(s,{title:r.title,detail:r.detail,category:r.category,status:r.status});k(t),b(!1),n("Tiket diperbarui","ok")}catch{n("Gagal menyimpan","err","x-circle")}finally{u(!1)}}async function N(){u(!0);try{await y.deleteTicket(s),n("Tiket dihapus","ok","trash-2"),p()}catch{n("Gagal menghapus","err","x-circle"),u(!1)}}if(P)return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>b(!1),disabled:m,children:"Batal"}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"primary",leftIcon:"check",onClick:D,disabled:m,children:"Simpan"})]}),e.jsx(W,{label:"Judul",children:e.jsx(U,{value:r.title,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:t=>I({...r,title:t.target.value})})}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[e.jsx(W,{label:"Kategori",children:e.jsx(F,{value:r.category,onChange:t=>I({...r,category:t.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(W,{label:"Status",children:e.jsx(F,{value:r.status,onChange:t=>I({...r,status:t.target.value}),options:[{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]})})]}),e.jsx(W,{label:"Detail keluhan",children:e.jsx(oe,{value:r.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:t=>I({...r,detail:t.target.value})})})]});const _=i.status!=="new";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:c,children:"Kembali"}),e.jsx(C,{tone:K[i.status]??"neutral",children:J[i.status]??i.status}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:o,disabled:m,children:"Ubah"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:()=>B(!0),disabled:m,children:"Hapus"}),i.publicStatusUrl&&e.jsxs(e.Fragment,{children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"share-2",onClick:()=>window.open(i.publicStatusUrl,"_blank","noreferrer"),children:"Buka status publik"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"link-2",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(i.publicStatusUrl),n("Link publik disalin","ok","copy")},children:"Salin link publik"})]}),i.specId?e.jsxs(e.Fragment,{children:[e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",i.specId]}),e.jsx(C,{tone:"neutral",size:"sm",children:pe(i.status,(R=i.spec)==null?void 0:R.stage)}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(O(i.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(O(i.specId)),n("Link backlog disalin","ok","copy")},children:"Salin link"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"unlink",onClick:a,disabled:m,children:"Lepas tautan"})]}):!_&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:g,onChange:t=>x(t.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]}),e.jsx(d,{size:"sm",leftIcon:"arrow-up-right",onClick:L,disabled:m,children:"Terima → backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"ban",onClick:E,disabled:m,children:"Tolak"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",i.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:i.category})]}),e.jsx("div",{style:{fontWeight:600,fontSize:"var(--text-lg)",color:"var(--text-strong)",marginTop:4},children:i.title})]}),e.jsxs("div",{style:{display:"flex",gap:18,flexWrap:"wrap",fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[e.jsxs("span",{children:["pelapor: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.reporterEmail})]}),e.jsxs("span",{children:["project: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.projectId})]}),e.jsxs("span",{children:["masuk: ",Q(i.createdAt)," lalu"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Detail keluhan"}),e.jsx("div",{style:{whiteSpace:"pre-wrap",color:"var(--text-body)",fontSize:"var(--text-sm)",lineHeight:1.55},children:i.detail})]}),i.attachments.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Lampiran"}),e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:i.attachments.map(t=>e.jsx("a",{href:q.ticketAttachment(i.id,t.id),target:"_blank",rel:"noreferrer",style:{display:"block",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:e.jsx("img",{src:q.ticketAttachment(i.id,t.id),alt:t.filename,style:{display:"block",maxWidth:180,maxHeight:140,objectFit:"cover"}})},t.id))})]}),e.jsx(ce,{open:f,title:"Hapus tiket?",eyebrow:`#${i.number}`,message:`Tiket "${i.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:m,onCancel:()=>B(!1),onConfirm:N}),S]})}function fe({projectId:s,onAccepted:c}){const[j,p]=l.useState([]),[n,i]=l.useState("loading"),[k,h]=l.useState(!1),[z,m]=l.useState(null),[u,g]=l.useState(null),[x,P]=l.useState([]),[b,f]=l.useState(0),[B,v]=l.useState(1),S=l.useCallback(async()=>{try{const a=await y.listGithubIssues(s,{page:B,limit:$});p(a.items),f(a.total),i("ready")}catch{i("error")}},[s,B]);l.useEffect(()=>{S()},[S]);const r=a=>{var D;const o=(D=a.detail)==null?void 0:D.error;return typeof o=="string"?o:a.message};async function I(){h(!0),g(null),m(null);try{const a=await y.pullGithubIssues(s);m(`${a.repo}: ${a.created} baru, ${a.updated} diperbarui`+(a.skippedPullRequests?` · ${a.skippedPullRequests} pull request dilewati`:"")),await S()}catch(a){g(r(a))}finally{h(!1)}}async function w(){h(!0),g(null);try{const a=await y.acceptGithubIssues(x,void 0);P([]),c==null||c(a.created),await S()}catch(a){g(r(a))}finally{h(!1)}}async function L(a){h(!0),g(null);try{await y.rejectGithubIssue(a),await S()}catch(o){g(r(o))}finally{h(!1)}}const E=a=>P(o=>o.includes(a)?o.filter(D=>D!==a):[...o,a]);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",onClick:I,disabled:k,children:"Tarik issue"}),e.jsxs(d,{size:"sm",variant:"primary",onClick:w,disabled:k||x.length===0,children:["Terima terpilih",x.length?` (${x.length})`:""]}),z&&e.jsx("span",{style:{fontSize:12,color:"var(--text-muted)"},children:z})]}),u&&e.jsx("div",{role:"alert",style:{fontSize:12,color:"var(--danger, #b00)"},children:u}),n==="loading"?e.jsx(T,{kind:"loading"}):n==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat daftar issue.",action:()=>void S(),actionLabel:"Coba lagi"}):j.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada issue tertarik",hint:"Tekan “Tarik issue” untuk menariknya dari repo GitHub project ini."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{overflowY:"auto",minHeight:0},children:j.map(a=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",gap:8,alignItems:"baseline",padding:"8px 0",borderBottom:"1px solid var(--border-hair)"},children:[a.status==="new"&&e.jsx("input",{type:"checkbox","aria-label":`Pilih issue ${a.number}`,checked:x.includes(a.id),onChange:()=>E(a.id)}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:["#",a.number]}),e.jsx("a",{href:a.url,target:"_blank",rel:"noreferrer",style:{flex:1,minWidth:0},children:a.title}),e.jsxs("span",{style:{fontSize:12,color:"var(--text-muted)"},children:["@",a.authorLogin]}),a.labels.map(o=>e.jsx(C,{children:o},o)),a.status==="rejected"&&e.jsx(C,{tone:"neutral",children:"ditutup"}),a.specId&&e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12},children:a.specId}),a.status==="new"&&e.jsx(d,{size:"sm",variant:"ghost",onClick:()=>L(a.id),disabled:k,children:"Tolak"})]},a.id))}),e.jsx(M,{total:b,page:B,onPage:v,unit:"issue"})]})]})}function ve({projects:s,onAccepted:c,onToast:j}){const[p,n]=l.useState([]),[i,k]=l.useState(0),[h,z]=H("triage","page",1,se),[m,u]=l.useState(0),[g,x]=l.useState("loading"),[P,b]=H("triage","openId",null,ne),[f,B]=H("triage","project","",A),[v,S]=H("triage","status","",A),[r,I]=H("triage","q","",A),[w,L]=H("triage","tab","tiket",V("tiket","issue")),E=[f!=="",v!=="",r.trim()!==""].filter(Boolean).length,a=Y("triage","scroll",p.length>0),o=l.useCallback((t=!1)=>{t||x("loading"),y.listTickets({project:f||void 0,status:v||void 0,q:r||void 0,page:String(h),limit:String($)}).then(G=>{n(G.items),k(G.total),u(G.unreviewed),x("ready")}).catch(()=>{t||x("error")})},[f,v,r,h]);l.useEffect(()=>{o()},[o]),X(JSON.stringify([f,v,r]),()=>z(1));const[D,N]=l.useState(r);l.useEffect(()=>{const t=setTimeout(()=>N(r),me);return()=>clearTimeout(t)},[r]),Z({topic:"tickets",params:{project:f||void 0,status:v||void 0,q:D||void 0,page:h,limit:$},apply:t=>{n(t.data.items),k(t.data.total),u(t.data.unreviewed),x("ready")},refetch:()=>o(!0),pollMs:he});const _=e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:f?e.jsx(fe,{projectId:f,onAccepted:t=>t.forEach(G=>c(G,!1))}):e.jsx(T,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring di atas."})}),R=e.jsx("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0},children:g==="loading"?e.jsx(T,{kind:"loading"}):g==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:()=>o(),actionLabel:"Coba lagi"}):p.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{ref:a,"data-testid":"triage-scroll",style:{overflowY:"auto",minHeight:0,flex:"1 1 auto"},children:p.map(t=>e.jsx(ge,{t,onOpen:b},t.id))}),e.jsx(M,{total:i,page:h,onPage:z})]})});return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14,minHeight:0,flex:1},children:[e.jsxs("div",{className:"hn-wrap-mobile",style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(d,{size:"sm",variant:w==="tiket"?"primary":"ghost",onClick:()=>L("tiket"),children:"Tiket Help Center"}),e.jsx(d,{size:"sm",variant:w==="issue"?"primary":"ghost",onClick:()=>L("issue"),children:"Issue GitHub"})]}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap",alignItems:"center"},children:[e.jsx(F,{size:"sm",value:f,"aria-label":"Project triase",onChange:t=>B(t.target.value),options:[{value:"",label:"Semua project"},...s.map(t=>({value:t.id,label:t.name}))]}),w==="tiket"&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:v,"aria-label":"Status tiket",onChange:t=>S(t.target.value),options:[{value:"",label:"Semua status"},{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]}),e.jsx(U,{size:"sm",value:r,"aria-label":"Cari tiket",onChange:t=>I(t.target.value),placeholder:"mis. gagal login atau budi@contoh.id",style:{flex:1,minWidth:160}}),m>0&&e.jsxs(C,{tone:"warn",children:[m," belum ditinjau"]}),e.jsx(ee,{onDone:()=>o(!0),onToast:j}),e.jsx(te,{screen:"triage",active:E}),e.jsx(ue,{})]})]}),w==="issue"?_:e.jsx(ae,{ariaLabel:"Panel triase",active:P?"detail":"list",onActiveChange:t=>{t==="list"&&b(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:R,className:"hn-panel-flex"},...P?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:e.jsx(xe,{id:P,onBack:()=>{b(null),o(!0)},onAccepted:c,onDeleted:()=>{b(null),o(!0)},onToast:j})}]:[]]})]})}export{fe as GithubIssuesPanel,ve as TriageScreen};
1
+ import{e as y,j as e,a as d,f as T,B as C,h as H,o as V,r as Y,t as X,q as Z,S as F,d as U,m as ee,R as te,v as ae,w as ie,p as A,x as se,I as le,y as ne,u as re,c as W,H as oe,z as O,A as q,C as ce,D as de}from"./index-DI7G_sit.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as ue}from"./live-DVDstDzi.js";import"./markdown-CWEY34jk.js";function pe(s,c){return s==="rejected"?"Ditutup":s!=="accepted"?"Sedang ditinjau":c==="done"?"Selesai":c==="executing"?"Sedang dikerjakan":"Diterima"}const he=5e3,$=20,me=400;function M({total:s,page:c,onPage:j,unit:p="tiket"}){const n=de(s,c,$);return e.jsx(ie,{page:n.page,pageCount:n.pageCount,total:s,from:n.from,to:n.to,onPage:j,unit:p})}function Q(s,c=Date.now()){const j=Math.max(0,c-new Date(s).getTime()),p=Math.floor(j/6e4);if(p<1)return"baru saja";if(p<60)return`${p}m`;const n=Math.floor(p/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const K={new:"warn",accepted:"ok",rejected:"neutral"},J={new:"belum ditinjau",accepted:"diterima",rejected:"ditutup"};function ge({t:s,onOpen:c}){return e.jsxs("button",{onClick:()=>c(s.id),className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:12,width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",cursor:"pointer",marginBottom:8},children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",s.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:s.category}),e.jsx(C,{tone:K[s.status]??"neutral",size:"sm",children:J[s.status]??s.status})]}),e.jsx("span",{style:{display:"block",color:"var(--text-body)",fontSize:"var(--text-sm)",marginTop:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2,display:"block"},children:[s.projectId," · ",s.reporterEmail," · ",Q(s.createdAt)," lalu",s.attachmentCount>0?` · ${s.attachmentCount} lampiran`:""]})]}),s.specId&&e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",s.specId]}),e.jsx(le,{name:"chevron-right",size:16,color:"var(--text-subtle)"})]})}function xe({id:s,onBack:c,onAccepted:j,onDeleted:p,onToast:n}){var R;const[i,k]=l.useState(null),[h,z]=l.useState("loading"),[m,u]=l.useState(!1),[g,x]=l.useState("sedang"),[P,b]=l.useState(!1),[f,B]=l.useState(!1),{confirm:v,dialog:S}=re(),[r,I]=l.useState({title:"",detail:"",category:"bug",status:"new"}),w=l.useCallback(()=>{y.getTicket(s).then(t=>{k(t),z("ready")}).catch(()=>z("error"))},[s]);if(l.useEffect(()=>{w()},[w]),h==="loading")return e.jsx(T,{kind:"loading"});if(h==="error"||!i)return e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:w,actionLabel:"Coba lagi"});async function L(){u(!0);try{const t=await y.acceptTicket(s,g);j(t.spec,!!t.alreadyPromoted)}catch{n("Gagal menerima tiket","err","x-circle")}finally{u(!1)}}async function E(){if(await v({title:`Tolak & tutup tiket #${i.number}?`,message:`"${i.title}" ditutup tanpa membuat backlog item.`,confirmLabel:"Tolak tiket",icon:"x-circle"})){u(!0);try{await y.rejectTicket(s),k({...i,status:"rejected"}),n("Tiket ditutup","ok","check")}catch{n("Gagal menolak tiket","err","x-circle")}finally{u(!1)}}}async function a(){u(!0);try{const t=await y.unlinkTicket(s);k({...i,specId:t.specId,spec:null,status:t.status}),n("Tautan backlog dilepas","ok","unlink")}catch{n("Gagal melepas tautan","err","x-circle")}finally{u(!1)}}function o(){I({title:i.title,detail:i.detail,category:i.category,status:i.status}),b(!0)}async function D(){u(!0);try{const t=await y.editTicket(s,{title:r.title,detail:r.detail,category:r.category,status:r.status});k(t),b(!1),n("Tiket diperbarui","ok")}catch{n("Gagal menyimpan","err","x-circle")}finally{u(!1)}}async function N(){u(!0);try{await y.deleteTicket(s),n("Tiket dihapus","ok","trash-2"),p()}catch{n("Gagal menghapus","err","x-circle"),u(!1)}}if(P)return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>b(!1),disabled:m,children:"Batal"}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"primary",leftIcon:"check",onClick:D,disabled:m,children:"Simpan"})]}),e.jsx(W,{label:"Judul",children:e.jsx(U,{value:r.title,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:t=>I({...r,title:t.target.value})})}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[e.jsx(W,{label:"Kategori",children:e.jsx(F,{value:r.category,onChange:t=>I({...r,category:t.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(W,{label:"Status",children:e.jsx(F,{value:r.status,onChange:t=>I({...r,status:t.target.value}),options:[{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]})})]}),e.jsx(W,{label:"Detail keluhan",children:e.jsx(oe,{value:r.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:t=>I({...r,detail:t.target.value})})})]});const _=i.status!=="new";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:c,children:"Kembali"}),e.jsx(C,{tone:K[i.status]??"neutral",children:J[i.status]??i.status}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:o,disabled:m,children:"Ubah"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:()=>B(!0),disabled:m,children:"Hapus"}),i.publicStatusUrl&&e.jsxs(e.Fragment,{children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"share-2",onClick:()=>window.open(i.publicStatusUrl,"_blank","noreferrer"),children:"Buka status publik"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"link-2",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(i.publicStatusUrl),n("Link publik disalin","ok","copy")},children:"Salin link publik"})]}),i.specId?e.jsxs(e.Fragment,{children:[e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",i.specId]}),e.jsx(C,{tone:"neutral",size:"sm",children:pe(i.status,(R=i.spec)==null?void 0:R.stage)}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(O(i.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(O(i.specId)),n("Link backlog disalin","ok","copy")},children:"Salin link"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"unlink",onClick:a,disabled:m,children:"Lepas tautan"})]}):!_&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:g,onChange:t=>x(t.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]}),e.jsx(d,{size:"sm",leftIcon:"arrow-up-right",onClick:L,disabled:m,children:"Terima → backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"ban",onClick:E,disabled:m,children:"Tolak"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",i.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:i.category})]}),e.jsx("div",{style:{fontWeight:600,fontSize:"var(--text-lg)",color:"var(--text-strong)",marginTop:4},children:i.title})]}),e.jsxs("div",{style:{display:"flex",gap:18,flexWrap:"wrap",fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[e.jsxs("span",{children:["pelapor: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.reporterEmail})]}),e.jsxs("span",{children:["project: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.projectId})]}),e.jsxs("span",{children:["masuk: ",Q(i.createdAt)," lalu"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Detail keluhan"}),e.jsx("div",{style:{whiteSpace:"pre-wrap",color:"var(--text-body)",fontSize:"var(--text-sm)",lineHeight:1.55},children:i.detail})]}),i.attachments.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Lampiran"}),e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:i.attachments.map(t=>e.jsx("a",{href:q.ticketAttachment(i.id,t.id),target:"_blank",rel:"noreferrer",style:{display:"block",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:e.jsx("img",{src:q.ticketAttachment(i.id,t.id),alt:t.filename,style:{display:"block",maxWidth:180,maxHeight:140,objectFit:"cover"}})},t.id))})]}),e.jsx(ce,{open:f,title:"Hapus tiket?",eyebrow:`#${i.number}`,message:`Tiket "${i.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:m,onCancel:()=>B(!1),onConfirm:N}),S]})}function fe({projectId:s,onAccepted:c}){const[j,p]=l.useState([]),[n,i]=l.useState("loading"),[k,h]=l.useState(!1),[z,m]=l.useState(null),[u,g]=l.useState(null),[x,P]=l.useState([]),[b,f]=l.useState(0),[B,v]=l.useState(1),S=l.useCallback(async()=>{try{const a=await y.listGithubIssues(s,{page:B,limit:$});p(a.items),f(a.total),i("ready")}catch{i("error")}},[s,B]);l.useEffect(()=>{S()},[S]);const r=a=>{var D;const o=(D=a.detail)==null?void 0:D.error;return typeof o=="string"?o:a.message};async function I(){h(!0),g(null),m(null);try{const a=await y.pullGithubIssues(s);m(`${a.repo}: ${a.created} baru, ${a.updated} diperbarui`+(a.skippedPullRequests?` · ${a.skippedPullRequests} pull request dilewati`:"")),await S()}catch(a){g(r(a))}finally{h(!1)}}async function w(){h(!0),g(null);try{const a=await y.acceptGithubIssues(x,void 0);P([]),c==null||c(a.created),await S()}catch(a){g(r(a))}finally{h(!1)}}async function L(a){h(!0),g(null);try{await y.rejectGithubIssue(a),await S()}catch(o){g(r(o))}finally{h(!1)}}const E=a=>P(o=>o.includes(a)?o.filter(D=>D!==a):[...o,a]);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",onClick:I,disabled:k,children:"Tarik issue"}),e.jsxs(d,{size:"sm",variant:"primary",onClick:w,disabled:k||x.length===0,children:["Terima terpilih",x.length?` (${x.length})`:""]}),z&&e.jsx("span",{style:{fontSize:12,color:"var(--text-muted)"},children:z})]}),u&&e.jsx("div",{role:"alert",style:{fontSize:12,color:"var(--danger, #b00)"},children:u}),n==="loading"?e.jsx(T,{kind:"loading"}):n==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat daftar issue.",action:()=>void S(),actionLabel:"Coba lagi"}):j.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada issue tertarik",hint:"Tekan “Tarik issue” untuk menariknya dari repo GitHub project ini."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{overflowY:"auto",minHeight:0},children:j.map(a=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",gap:8,alignItems:"baseline",padding:"8px 0",borderBottom:"1px solid var(--border-hair)"},children:[a.status==="new"&&e.jsx("input",{type:"checkbox","aria-label":`Pilih issue ${a.number}`,checked:x.includes(a.id),onChange:()=>E(a.id)}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:["#",a.number]}),e.jsx("a",{href:a.url,target:"_blank",rel:"noreferrer",style:{flex:1,minWidth:0},children:a.title}),e.jsxs("span",{style:{fontSize:12,color:"var(--text-muted)"},children:["@",a.authorLogin]}),a.labels.map(o=>e.jsx(C,{children:o},o)),a.status==="rejected"&&e.jsx(C,{tone:"neutral",children:"ditutup"}),a.specId&&e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12},children:a.specId}),a.status==="new"&&e.jsx(d,{size:"sm",variant:"ghost",onClick:()=>L(a.id),disabled:k,children:"Tolak"})]},a.id))}),e.jsx(M,{total:b,page:B,onPage:v,unit:"issue"})]})]})}function ve({projects:s,onAccepted:c,onToast:j}){const[p,n]=l.useState([]),[i,k]=l.useState(0),[h,z]=H("triage","page",1,se),[m,u]=l.useState(0),[g,x]=l.useState("loading"),[P,b]=H("triage","openId",null,ne),[f,B]=H("triage","project","",A),[v,S]=H("triage","status","",A),[r,I]=H("triage","q","",A),[w,L]=H("triage","tab","tiket",V("tiket","issue")),E=[f!=="",v!=="",r.trim()!==""].filter(Boolean).length,a=Y("triage","scroll",p.length>0),o=l.useCallback((t=!1)=>{t||x("loading"),y.listTickets({project:f||void 0,status:v||void 0,q:r||void 0,page:String(h),limit:String($)}).then(G=>{n(G.items),k(G.total),u(G.unreviewed),x("ready")}).catch(()=>{t||x("error")})},[f,v,r,h]);l.useEffect(()=>{o()},[o]),X(JSON.stringify([f,v,r]),()=>z(1));const[D,N]=l.useState(r);l.useEffect(()=>{const t=setTimeout(()=>N(r),me);return()=>clearTimeout(t)},[r]),Z({topic:"tickets",params:{project:f||void 0,status:v||void 0,q:D||void 0,page:h,limit:$},apply:t=>{n(t.data.items),k(t.data.total),u(t.data.unreviewed),x("ready")},refetch:()=>o(!0),pollMs:he});const _=e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:f?e.jsx(fe,{projectId:f,onAccepted:t=>t.forEach(G=>c(G,!1))}):e.jsx(T,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring di atas."})}),R=e.jsx("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0},children:g==="loading"?e.jsx(T,{kind:"loading"}):g==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:()=>o(),actionLabel:"Coba lagi"}):p.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{ref:a,"data-testid":"triage-scroll",style:{overflowY:"auto",minHeight:0,flex:"1 1 auto"},children:p.map(t=>e.jsx(ge,{t,onOpen:b},t.id))}),e.jsx(M,{total:i,page:h,onPage:z})]})});return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14,minHeight:0,flex:1},children:[e.jsxs("div",{className:"hn-wrap-mobile",style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(d,{size:"sm",variant:w==="tiket"?"primary":"ghost",onClick:()=>L("tiket"),children:"Tiket Help Center"}),e.jsx(d,{size:"sm",variant:w==="issue"?"primary":"ghost",onClick:()=>L("issue"),children:"Issue GitHub"})]}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap",alignItems:"center"},children:[e.jsx(F,{size:"sm",value:f,"aria-label":"Project triase",onChange:t=>B(t.target.value),options:[{value:"",label:"Semua project"},...s.map(t=>({value:t.id,label:t.name}))]}),w==="tiket"&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:v,"aria-label":"Status tiket",onChange:t=>S(t.target.value),options:[{value:"",label:"Semua status"},{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]}),e.jsx(U,{size:"sm",value:r,"aria-label":"Cari tiket",onChange:t=>I(t.target.value),placeholder:"mis. gagal login atau budi@contoh.id",style:{flex:1,minWidth:160}}),m>0&&e.jsxs(C,{tone:"warn",children:[m," belum ditinjau"]}),e.jsx(ee,{onDone:()=>o(!0),onToast:j}),e.jsx(te,{screen:"triage",active:E}),e.jsx(ue,{})]})]}),w==="issue"?_:e.jsx(ae,{ariaLabel:"Panel triase",active:P?"detail":"list",onActiveChange:t=>{t==="list"&&b(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:R,className:"hn-panel-flex"},...P?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:e.jsx(xe,{id:P,onBack:()=>{b(null),o(!0)},onAccepted:c,onDeleted:()=>{b(null),o(!0)},onToast:j})}]:[]]})]})}export{fe as GithubIssuesPanel,ve as TriageScreen};