@runfusion/fusion 0.12.0 → 0.14.0
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.
- package/README.md +13 -0
- package/dist/bin.js +1707 -610
- package/dist/client/assets/AgentDetailView-CBFUveyO.js +18 -0
- package/dist/client/assets/AgentsView-DPezXQ-U.js +522 -0
- package/dist/client/assets/{AgentsView-Bkk-uBij.css → AgentsView-V5GhlBYu.css} +1 -1
- package/dist/client/assets/ChatView-5N4-EuhD.js +1 -0
- package/dist/client/assets/{DevServerView-DQrVLbK5.js → DevServerView-Daft4YFc.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DVmy6sLM.js → DirectoryPicker-rew1y6qO.js} +1 -1
- package/dist/client/assets/{DocumentsView-DHEv-Q2a.js → DocumentsView-i72qJzwd.js} +1 -1
- package/dist/client/assets/{InsightsView-ByyY7GX7.js → InsightsView-BL5eZJ0a.js} +3 -3
- package/dist/client/assets/{MemoryView-Udiu0u8R.js → MemoryView-pl8Cdg_p.js} +2 -2
- package/dist/client/assets/{NodesView-CupS-GGc.js → NodesView-D6eJ15zc.js} +4 -4
- package/dist/client/assets/PiExtensionsManager-ExInwXWP.js +11 -0
- package/dist/client/assets/PluginManager-CYhtxHun.js +1 -0
- package/dist/client/assets/{ResearchView-BG9Feaeb.js → ResearchView-B_QPUEjB.js} +1 -1
- package/dist/client/assets/{RoadmapsView-BTJtmBnF.js → RoadmapsView-DBNLaEsK.js} +2 -2
- package/dist/client/assets/SettingsModal-1ET586M3.js +31 -0
- package/dist/client/assets/{SettingsModal-eNCZiHa6.js → SettingsModal-CL_gWmOj.js} +1 -1
- package/dist/client/assets/SettingsModal-D_AFkDJa.css +1 -0
- package/dist/client/assets/{SetupWizardModal-yf79TN1L.js → SetupWizardModal-CLkY9HFL.js} +1 -1
- package/dist/client/assets/{SkillMultiselect-DOj5vX4U.js → SkillMultiselect-B0qi32SQ.js} +1 -1
- package/dist/client/assets/{SkillsView-CgnCnikX.js → SkillsView-umVjRq6o.js} +1 -1
- package/dist/client/assets/TodoView-CFifSvrD.js +6 -0
- package/dist/client/assets/TodoView-SeO9o7km.css +1 -0
- package/dist/client/assets/{folder-open-D11gjHGK.js → folder-open-nYPrL1W3.js} +1 -1
- package/dist/client/assets/index-Bc8nfKeH.js +661 -0
- package/dist/client/assets/index-C1prPuSl.css +1 -0
- package/dist/client/assets/{list-checks-CBzPc3GA.js → list-checks-sK8xJeH_.js} +1 -1
- package/dist/client/assets/{star-BWcRk8nt.js → star-BRtXbYkB.js} +1 -1
- package/dist/client/assets/{upload-91TM4ljC.js → upload-BP60eBwN.js} +1 -1
- package/dist/client/assets/{users-BAsI___L.js → users-qSGAX2Pf.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/sw.js +6 -0
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/index.ts +127 -0
- package/dist/droid-cli/package.json +37 -0
- package/dist/droid-cli/src/__tests__/control-handler.test.ts +164 -0
- package/dist/droid-cli/src/__tests__/event-bridge.test.ts +1318 -0
- package/dist/droid-cli/src/__tests__/mcp-config.test.ts +310 -0
- package/dist/droid-cli/src/__tests__/process-manager.test.ts +818 -0
- package/dist/droid-cli/src/__tests__/prompt-builder.test.ts +1206 -0
- package/dist/droid-cli/src/__tests__/provider.test.ts +1894 -0
- package/dist/droid-cli/src/__tests__/setup-test-isolation.test.ts +32 -0
- package/dist/droid-cli/src/__tests__/setup-test-isolation.ts +14 -0
- package/dist/droid-cli/src/__tests__/stream-parser.test.ts +188 -0
- package/dist/droid-cli/src/__tests__/thinking-config.test.ts +141 -0
- package/dist/droid-cli/src/__tests__/tool-mapping.test.ts +253 -0
- package/dist/droid-cli/src/control-handler.ts +82 -0
- package/dist/droid-cli/src/event-bridge.ts +397 -0
- package/dist/droid-cli/src/mcp-config.ts +144 -0
- package/dist/droid-cli/src/mcp-schema-server.cjs +49 -0
- package/dist/droid-cli/src/process-manager.ts +358 -0
- package/dist/droid-cli/src/prompt-builder.ts +629 -0
- package/dist/droid-cli/src/provider.ts +447 -0
- package/dist/droid-cli/src/stream-parser.ts +37 -0
- package/dist/droid-cli/src/thinking-config.ts +83 -0
- package/dist/droid-cli/src/tool-mapping.ts +147 -0
- package/dist/droid-cli/src/types.ts +87 -0
- package/dist/extension.js +542 -141
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/pi-claude-cli/src/__tests__/prompt-builder.test.ts +36 -0
- package/dist/pi-claude-cli/src/prompt-builder.ts +19 -28
- package/package.json +2 -1
- package/dist/client/assets/AgentDetailView-B20ApPe1.js +0 -18
- package/dist/client/assets/AgentsView-ChN1tgQ0.js +0 -522
- package/dist/client/assets/ChatView-oPMFwmoc.js +0 -1
- package/dist/client/assets/PiExtensionsManager-DXs2xI8K.js +0 -11
- package/dist/client/assets/PluginManager-BCpiZf4_.js +0 -1
- package/dist/client/assets/SettingsModal-9HS8MnmW.css +0 -1
- package/dist/client/assets/SettingsModal-DZ_LaEhd.js +0 -31
- package/dist/client/assets/TodoView-67BMyICY.js +0 -6
- package/dist/client/assets/TodoView-C1g65hJo.css +0 -1
- package/dist/client/assets/index-BLn1R7Ob.css +0 -1
- package/dist/client/assets/index-CLAHcGnI.js +0 -656
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{as as ae,at as ne,s as ce,au as ie,av as le,aw as oe,ax as de,ay as ue,az as he,z as me,aA as be,L as ve,S as pe}from"./index-CLAHcGnI.js";import"./vendor-xterm-DzcZoU0P.js";const C={webSearch:!0,pageFetch:!0,github:!1,localDocs:!0,llmSynthesis:!0};function K(d){const r=d?.researchGlobalDefaults,o=d?.researchSettings;return{enabled:o?.enabled??d?.researchEnabled??d?.researchGlobalEnabled??!0,searchProvider:o?.searchProvider??r?.searchProvider,synthesisProvider:o?.synthesisProvider??r?.synthesisProvider,synthesisModelId:o?.synthesisModelId??r?.synthesisModelId,enabledSources:{webSearch:o?.enabledSources?.webSearch??r?.enabledSources?.webSearch??C.webSearch,pageFetch:o?.enabledSources?.pageFetch??r?.enabledSources?.pageFetch??C.pageFetch,github:o?.enabledSources?.github??r?.enabledSources?.github??C.github,localDocs:o?.enabledSources?.localDocs??r?.enabledSources?.localDocs??C.localDocs,llmSynthesis:o?.enabledSources?.llmSynthesis??r?.enabledSources?.llmSynthesis??C.llmSynthesis},limits:{maxConcurrentRuns:o?.limits?.maxConcurrentRuns??d?.researchMaxConcurrentRuns??d?.researchGlobalMaxConcurrentRuns??3,maxSourcesPerRun:o?.limits?.maxSourcesPerRun??r?.maxSourcesPerRun??d?.researchMaxSourcesPerRun??d?.researchGlobalMaxSourcesPerRun??20,maxDurationMs:o?.limits?.maxDurationMs??d?.researchDefaultTimeout??d?.researchGlobalDefaultTimeout??3e5,requestTimeoutMs:o?.limits?.requestTimeoutMs??d?.researchFetchTimeoutMs??3e4},defaultExportFormat:r?.defaultExportFormat??"markdown"}}const fe=300,xe=4e3;function ye(d){const r=d?.projectId,[o,D]=a.useState([]),[u,t]=a.useState(null),[q,y]=a.useState(null),[f,R]=a.useState({available:!0}),[w,E]=a.useState(!0),[O,P]=a.useState(null),[S,U]=a.useState(""),_=a.useRef(0),g=a.useRef(0),A=a.useRef(r);a.useEffect(()=>{A.current!==r&&(A.current=r,g.current++)},[r]);const p=a.useCallback(async(n=S)=>{const c=++_.current,i=r;P(null);try{const h=await ae({q:n||void 0,limit:100},i);if(c!==_.current||i!==r)return;D(h.runs),R(h.availability),u&&!h.runs.some(m=>m.id===u)&&(t(null),y(null))}catch(h){if(c!==_.current||i!==r)return;P(h instanceof Error?h.message:"Failed to load research runs")}finally{c===_.current&&E(!1)}},[r,S,u]),x=a.useCallback(async n=>{const c=await ne(n,r);return y(c.run),R(c.availability),c.run},[r]);return a.useEffect(()=>{E(!0);const n=window.setTimeout(()=>{p(S)},fe);return()=>window.clearTimeout(n)},[p,S]),a.useEffect(()=>{if(!u){y(null);return}x(u)},[x,u]),a.useEffect(()=>{const n=g.current,c=()=>g.current!==n,i=r?`?projectId=${encodeURIComponent(r)}`:"";let h=!0;const m=()=>{!h||c()||(p(),u&&x(u))},V=ce(`/api/events${i}`,{events:{"research:run:created":m,"research:run:updated":m,"research:run:completed":m,"research:run:failed":m,"research:run:cancelled":m},onReconnect:m}),M=window.setInterval(m,xe);return()=>{h=!1,V(),window.clearInterval(M)}},[r,p,u,x]),{runs:o,selectedRun:q,selectedRunId:u,setSelectedRunId:t,availability:f,loading:w,error:O,searchQuery:S,setSearchQuery:U,refresh:p,createRun:n=>he(n,r),cancelRun:async n=>{const c=await ue(n,r);return u===n&&y(c.run),await p(),c},retryRun:async n=>{const c=await de(n,r);return u===n&&y(c.run),await p(),c},exportRun:(n,c)=>oe(n,c,r),createTaskFromRun:(n,c)=>le(n,{title:c},r),attachRunToTask:(n,c,i)=>ie(n,{taskId:c,mode:i},r),statusCounts:o.reduce((n,c)=>(n[c.status]+=1,n),{pending:0,running:0,completed:0,failed:0,cancelled:0})}}const Se=["web-search","page-fetch","github","local-docs","llm-synthesis"],je={"web-search":"webSearch","page-fetch":"pageFetch",github:"github","local-docs":"localDocs","llm-synthesis":"llmSynthesis"},Re={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};function ke({projectId:d,addToast:r,onOpenSettings:o,readinessVersion:D=0}){const{runs:u,selectedRun:t,selectedRunId:q,setSelectedRunId:y,availability:f,loading:R,error:w,searchQuery:E,setSearchQuery:O,createRun:P,cancelRun:S,retryRun:U,exportRun:_,createTaskFromRun:g,attachRunToTask:A,statusCounts:p,refresh:x}=ye({projectId:d}),[n,c]=a.useState(""),[i,h]=a.useState(()=>K(void 0)),[m,V]=a.useState([]),[M,J]=a.useState(!1),[W,Y]=a.useState([]),[$,ee]=a.useState(""),[j,I]=a.useState(null),G=f.supportedProviders??Se,F=s=>i.enabledSources[je[s]];a.useEffect(()=>{const s=G.filter(l=>F(l));Y(l=>{const b=l.filter(v=>s.includes(v));return b.length>0?b:s})},[i.enabledSources,G]),a.useEffect(()=>{let s=!1;return Promise.all([me(d),be().catch(()=>({providers:[]}))]).then(([l,b])=>{s||(h(K(l)),V(b.providers.filter(v=>v.type==="api_key").map(v=>({id:v.id,authenticated:v.authenticated}))))}).catch(()=>{s||h(K(void 0))}),()=>{s=!0}},[d,D]);const se=a.useMemo(()=>t?t.status:"No run selected",[t]),re=a.useMemo(()=>t?t.status==="pending"?"status-dot status-dot--pending":t.status==="running"?"status-dot status-dot--connecting":t.status==="completed"?"status-dot status-dot--online":t.status==="failed"||t.status==="cancelled"?"status-dot status-dot--error":"status-dot":"status-dot",[t]),Q=f.supportedExportFormats??["markdown","json","html"],L=i.searchProvider,X=i.enabledSources.webSearch&&!L,Z=i.enabledSources.llmSynthesis&&(!i.synthesisProvider||!i.synthesisModelId),z=a.useMemo(()=>new Map(m.map(s=>[s.id,s.authenticated])),[m]),B=a.useMemo(()=>{const s=new Set;return i.enabledSources.webSearch&&L&&s.add(L),i.enabledSources.llmSynthesis&&i.synthesisProvider&&s.add(i.synthesisProvider),[...s].filter(l=>z.has(l))},[i.enabledSources.llmSynthesis,i.enabledSources.webSearch,i.synthesisProvider,L,z]).find(s=>z.get(s)!==!0),N=a.useMemo(()=>f.available?i.enabled?X||Z?{reason:"Research defaults are incomplete.",details:"Select the required provider/model defaults in Research settings.",settingsSection:"research-global"}:B?{reason:`Missing API key for ${B}.`,details:"Add provider credentials in Authentication settings.",settingsSection:"authentication"}:null:{reason:"Research is disabled for this project.",details:"Enable project research settings to create runs.",settingsSection:"research-project"}:{reason:f.reason??"Research is unavailable for this project.",details:f.setupInstructions,settingsSection:"research-project"},[f.available,f.reason,f.setupInstructions,i.enabled,B,X,Z]),T=async(s,l,b)=>{I(s);try{await l(),r?.(b,"success"),await x()}catch(v){r?.(v instanceof Error?v.message:"Action failed","error")}finally{I(null)}},H=async s=>{if(t){I(`export-${s}`);try{const l=await _(t.id,s),b=new Blob([l.content],{type:"text/plain;charset=utf-8"}),v=URL.createObjectURL(b),k=document.createElement("a");k.href=v,k.download=l.filename,document.body.appendChild(k),k.click(),k.remove(),URL.revokeObjectURL(v),r?.(`Exported ${l.filename}`,"success")}catch(l){r?.(l instanceof Error?l.message:"Export failed","error")}finally{I(null)}}},te=async()=>{if(n.trim()){J(!0);try{const s=W.filter(b=>F(b));if(s.length===0){r?.("No enabled research sources are available for this project.","error");return}const l=await P({query:n.trim(),providers:s});y(l.run.id),c(""),r?.("Research run created","success"),await x()}catch(s){r?.(s instanceof Error?s.message:"Failed to create run","error")}finally{J(!1)}}};return e.jsxs("section",{className:"research-view","aria-label":"Research view",children:[e.jsxs("header",{className:"research-view__header",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"research-view__title",children:"Research"}),e.jsx("p",{className:"research-view__subtitle",children:"Create and track research runs with cited findings."})]}),e.jsx("button",{className:"btn",type:"button",onClick:()=>void x(),children:"Refresh"})]}),N?e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:N.reason}),N.details&&e.jsx("p",{children:N.details}),e.jsxs("p",{children:["Current defaults: provider ",i.searchProvider??"(not set)",", max sources ",i.limits.maxSourcesPerRun]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:()=>void x(),children:"Refresh"}),e.jsx("button",{className:"btn btn-primary",type:"button",onClick:()=>o?.(N.settingsSection),children:"Open Settings"})]})]}):e.jsxs("div",{className:"research-view__layout",children:[e.jsxs("aside",{className:"research-view__sidebar card",children:[e.jsxs("div",{className:"research-view__form",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-query",children:"Query"}),e.jsx("textarea",{id:"research-query",className:"input research-view__textarea",value:n,onChange:s=>c(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Providers"}),e.jsx("div",{className:"research-view__providers",children:G.map(s=>e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:W.includes(s),disabled:!F(s),onChange:()=>{F(s)&&Y(l=>l.includes(s)?l.filter(b=>b!==s):[...l,s])}}),e.jsx("span",{children:Re[s]??s})]},s))})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!n.trim()||M,onClick:()=>void te(),children:[M?e.jsx(ve,{className:"animate-spin",size:14}):null,"Create Run"]})]}),e.jsxs("div",{className:"research-view__history-header form-group",children:[e.jsx("label",{htmlFor:"research-run-search",children:"Search"}),e.jsxs("div",{className:"research-view__history-search-row",children:[e.jsx(pe,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:E,onChange:s=>O(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:u.map(s=>e.jsxs("button",{type:"button",className:`research-view__history-item${q===s.id?" research-view__history-item--active":""}`,onClick:()=>y(s.id),children:[e.jsx("span",{className:"card-id",children:s.id}),e.jsx("span",{children:s.title})]},s.id))})]}),e.jsxs("div",{className:"research-view__reader card",children:[R&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!R&&w&&e.jsx("p",{"data-testid":"research-state-error",children:w}),!R&&!w&&u.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),t&&e.jsxs("div",{children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:re}),e.jsx("strong",{children:se})]}),e.jsx("h3",{className:"research-view__run-title",children:t.title}),e.jsx("p",{className:"research-view__run-query",children:t.query}),e.jsx("p",{className:"research-view__run-summary","data-testid":"research-state-results",children:t.results?.summary??"No summary yet."}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",disabled:j==="cancel",onClick:()=>void T("cancel",()=>S(t.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",disabled:j==="retry",onClick:()=>void T("retry",()=>U(t.id),"Run retried"),children:"Retry"}),Q.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:j==="export-markdown",onClick:()=>void H("markdown"),children:"Export MD"}),Q.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:j==="export-json",onClick:()=>void H("json"),children:"Export JSON"}),Q.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:j==="export-html",onClick:()=>void H("html"),children:"Export HTML"})]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn btn-primary",type:"button",disabled:j==="create-task",onClick:()=>void T("create-task",()=>g(t.id,`Research: ${t.title}`),"Task created from research"),children:"Create Task"}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-task-id",children:"Task ID"}),e.jsx("input",{id:"research-task-id",className:"input",placeholder:"Task ID",value:$,onChange:s=>ee(s.target.value)})]}),e.jsx("button",{className:"btn",type:"button",disabled:!$.trim()||j==="attach-task",onClick:()=>void T("attach-task",()=>A(t.id,$.trim(),"document"),"Attached to task"),children:"Attach to Task"})]}),t.error&&e.jsx("p",{className:"research-view__error",children:t.error}),Array.isArray(t.results?.findings)&&t.results.findings.length>0&&e.jsx("div",{className:"research-view__findings",children:t.results.findings.map(s=>e.jsxs("article",{className:"research-view__finding card",children:[e.jsx("h4",{children:s.heading}),e.jsx("p",{children:s.content})]},s.heading))}),Array.isArray(t.results?.citations)&&t.results.citations.length>0&&e.jsx("ul",{className:"research-view__citations",children:t.results.citations.map(s=>e.jsx("li",{children:e.jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:s})},s))}),t.events.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Run history"}),e.jsx("ul",{className:"research-view__events",children:t.events.map(s=>e.jsx("li",{children:s.message},s.id))})]})]}),!t&&u.length>0&&e.jsx("p",{children:"Select a run to view details."}),e.jsxs("div",{className:"research-view__stats",children:[e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Running"}),e.jsx("div",{className:"research-view__stat-value",children:p.running})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Completed"}),e.jsx("div",{className:"research-view__stat-value",children:p.completed})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Failed"}),e.jsx("div",{className:"research-view__stat-value",children:p.failed})]})]})]})]})]})}export{ke as ResearchView};
|
|
1
|
+
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{aq as ae,ar as ne,s as ce,as as ie,at as le,au as oe,av as de,aw as ue,ax as he,x as me,ay as be,L as ve,S as pe}from"./index-Bc8nfKeH.js";import"./vendor-xterm-DzcZoU0P.js";const C={webSearch:!0,pageFetch:!0,github:!1,localDocs:!0,llmSynthesis:!0};function z(d){const r=d?.researchGlobalDefaults,o=d?.researchSettings;return{enabled:o?.enabled??d?.researchEnabled??d?.researchGlobalEnabled??!0,searchProvider:o?.searchProvider??r?.searchProvider,synthesisProvider:o?.synthesisProvider??r?.synthesisProvider,synthesisModelId:o?.synthesisModelId??r?.synthesisModelId,enabledSources:{webSearch:o?.enabledSources?.webSearch??r?.enabledSources?.webSearch??C.webSearch,pageFetch:o?.enabledSources?.pageFetch??r?.enabledSources?.pageFetch??C.pageFetch,github:o?.enabledSources?.github??r?.enabledSources?.github??C.github,localDocs:o?.enabledSources?.localDocs??r?.enabledSources?.localDocs??C.localDocs,llmSynthesis:o?.enabledSources?.llmSynthesis??r?.enabledSources?.llmSynthesis??C.llmSynthesis},limits:{maxConcurrentRuns:o?.limits?.maxConcurrentRuns??d?.researchMaxConcurrentRuns??d?.researchGlobalMaxConcurrentRuns??3,maxSourcesPerRun:o?.limits?.maxSourcesPerRun??r?.maxSourcesPerRun??d?.researchMaxSourcesPerRun??d?.researchGlobalMaxSourcesPerRun??20,maxDurationMs:o?.limits?.maxDurationMs??d?.researchDefaultTimeout??d?.researchGlobalDefaultTimeout??3e5,requestTimeoutMs:o?.limits?.requestTimeoutMs??d?.researchFetchTimeoutMs??3e4},defaultExportFormat:r?.defaultExportFormat??"markdown"}}const xe=300,fe=4e3;function ye(d){const r=d?.projectId,[o,D]=a.useState([]),[u,t]=a.useState(null),[q,y]=a.useState(null),[x,R]=a.useState({available:!0}),[w,E]=a.useState(!0),[O,P]=a.useState(null),[S,U]=a.useState(""),_=a.useRef(0),g=a.useRef(0),A=a.useRef(r);a.useEffect(()=>{A.current!==r&&(A.current=r,g.current++)},[r]);const p=a.useCallback(async(n=S)=>{const c=++_.current,i=r;P(null);try{const h=await ae({q:n||void 0,limit:100},i);if(c!==_.current||i!==r)return;D(h.runs),R(h.availability),u&&!h.runs.some(m=>m.id===u)&&(t(null),y(null))}catch(h){if(c!==_.current||i!==r)return;P(h instanceof Error?h.message:"Failed to load research runs")}finally{c===_.current&&E(!1)}},[r,S,u]),f=a.useCallback(async n=>{const c=await ne(n,r);return y(c.run),R(c.availability),c.run},[r]);return a.useEffect(()=>{E(!0);const n=window.setTimeout(()=>{p(S)},xe);return()=>window.clearTimeout(n)},[p,S]),a.useEffect(()=>{if(!u){y(null);return}f(u)},[f,u]),a.useEffect(()=>{const n=g.current,c=()=>g.current!==n,i=r?`?projectId=${encodeURIComponent(r)}`:"";let h=!0;const m=()=>{!h||c()||(p(),u&&f(u))},V=ce(`/api/events${i}`,{events:{"research:run:created":m,"research:run:updated":m,"research:run:completed":m,"research:run:failed":m,"research:run:cancelled":m},onReconnect:m}),M=window.setInterval(m,fe);return()=>{h=!1,V(),window.clearInterval(M)}},[r,p,u,f]),{runs:o,selectedRun:q,selectedRunId:u,setSelectedRunId:t,availability:x,loading:w,error:O,searchQuery:S,setSearchQuery:U,refresh:p,createRun:n=>he(n,r),cancelRun:async n=>{const c=await ue(n,r);return u===n&&y(c.run),await p(),c},retryRun:async n=>{const c=await de(n,r);return u===n&&y(c.run),await p(),c},exportRun:(n,c)=>oe(n,c,r),createTaskFromRun:(n,c)=>le(n,{title:c},r),attachRunToTask:(n,c,i)=>ie(n,{taskId:c,mode:i},r),statusCounts:o.reduce((n,c)=>(n[c.status]+=1,n),{pending:0,running:0,completed:0,failed:0,cancelled:0})}}const Se=["web-search","page-fetch","github","local-docs","llm-synthesis"],je={"web-search":"webSearch","page-fetch":"pageFetch",github:"github","local-docs":"localDocs","llm-synthesis":"llmSynthesis"},Re={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};function ke({projectId:d,addToast:r,onOpenSettings:o,readinessVersion:D=0}){const{runs:u,selectedRun:t,selectedRunId:q,setSelectedRunId:y,availability:x,loading:R,error:w,searchQuery:E,setSearchQuery:O,createRun:P,cancelRun:S,retryRun:U,exportRun:_,createTaskFromRun:g,attachRunToTask:A,statusCounts:p,refresh:f}=ye({projectId:d}),[n,c]=a.useState(""),[i,h]=a.useState(()=>z(void 0)),[m,V]=a.useState([]),[M,J]=a.useState(!1),[W,Y]=a.useState([]),[$,ee]=a.useState(""),[j,I]=a.useState(null),G=x.supportedProviders??Se,F=s=>i.enabledSources[je[s]];a.useEffect(()=>{const s=G.filter(l=>F(l));Y(l=>{const b=l.filter(v=>s.includes(v));return b.length>0?b:s})},[i.enabledSources,G]),a.useEffect(()=>{let s=!1;return Promise.all([me(d),be().catch(()=>({providers:[]}))]).then(([l,b])=>{s||(h(z(l)),V(b.providers.filter(v=>v.type==="api_key").map(v=>({id:v.id,authenticated:v.authenticated}))))}).catch(()=>{s||h(z(void 0))}),()=>{s=!0}},[d,D]);const se=a.useMemo(()=>t?t.status:"No run selected",[t]),re=a.useMemo(()=>t?t.status==="pending"?"status-dot status-dot--pending":t.status==="running"?"status-dot status-dot--connecting":t.status==="completed"?"status-dot status-dot--online":t.status==="failed"||t.status==="cancelled"?"status-dot status-dot--error":"status-dot":"status-dot",[t]),Q=x.supportedExportFormats??["markdown","json","html"],L=i.searchProvider,X=i.enabledSources.webSearch&&!L,Z=i.enabledSources.llmSynthesis&&(!i.synthesisProvider||!i.synthesisModelId),B=a.useMemo(()=>new Map(m.map(s=>[s.id,s.authenticated])),[m]),H=a.useMemo(()=>{const s=new Set;return i.enabledSources.webSearch&&L&&s.add(L),i.enabledSources.llmSynthesis&&i.synthesisProvider&&s.add(i.synthesisProvider),[...s].filter(l=>B.has(l))},[i.enabledSources.llmSynthesis,i.enabledSources.webSearch,i.synthesisProvider,L,B]).find(s=>B.get(s)!==!0),N=a.useMemo(()=>x.available?i.enabled?X||Z?{reason:"Research defaults are incomplete.",details:"Select the required provider/model defaults in Research settings.",settingsSection:"research-global"}:H?{reason:`Missing API key for ${H}.`,details:"Add provider credentials in Authentication settings.",settingsSection:"authentication"}:null:{reason:"Research is disabled for this project.",details:"Enable project research settings to create runs.",settingsSection:"research-project"}:{reason:x.reason??"Research is unavailable for this project.",details:x.setupInstructions,settingsSection:"research-project"},[x.available,x.reason,x.setupInstructions,i.enabled,H,X,Z]),T=async(s,l,b)=>{I(s);try{await l(),r?.(b,"success"),await f()}catch(v){r?.(v instanceof Error?v.message:"Action failed","error")}finally{I(null)}},K=async s=>{if(t){I(`export-${s}`);try{const l=await _(t.id,s),b=new Blob([l.content],{type:"text/plain;charset=utf-8"}),v=URL.createObjectURL(b),k=document.createElement("a");k.href=v,k.download=l.filename,document.body.appendChild(k),k.click(),k.remove(),URL.revokeObjectURL(v),r?.(`Exported ${l.filename}`,"success")}catch(l){r?.(l instanceof Error?l.message:"Export failed","error")}finally{I(null)}}},te=async()=>{if(n.trim()){J(!0);try{const s=W.filter(b=>F(b));if(s.length===0){r?.("No enabled research sources are available for this project.","error");return}const l=await P({query:n.trim(),providers:s});y(l.run.id),c(""),r?.("Research run created","success"),await f()}catch(s){r?.(s instanceof Error?s.message:"Failed to create run","error")}finally{J(!1)}}};return e.jsxs("section",{className:"research-view","aria-label":"Research view",children:[e.jsxs("header",{className:"research-view__header",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"research-view__title",children:"Research"}),e.jsx("p",{className:"research-view__subtitle",children:"Create and track research runs with cited findings."})]}),e.jsx("button",{className:"btn",type:"button",onClick:()=>void f(),children:"Refresh"})]}),N?e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:N.reason}),N.details&&e.jsx("p",{children:N.details}),e.jsxs("p",{children:["Current defaults: provider ",i.searchProvider??"(not set)",", max sources ",i.limits.maxSourcesPerRun]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:()=>void f(),children:"Refresh"}),e.jsx("button",{className:"btn btn-primary",type:"button",onClick:()=>o?.(N.settingsSection),children:"Open Settings"})]})]}):e.jsxs("div",{className:"research-view__layout",children:[e.jsxs("aside",{className:"research-view__sidebar card",children:[e.jsxs("div",{className:"research-view__form",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-query",children:"Query"}),e.jsx("textarea",{id:"research-query",className:"input research-view__textarea",value:n,onChange:s=>c(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Providers"}),e.jsx("div",{className:"research-view__providers",children:G.map(s=>e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:W.includes(s),disabled:!F(s),onChange:()=>{F(s)&&Y(l=>l.includes(s)?l.filter(b=>b!==s):[...l,s])}}),e.jsx("span",{children:Re[s]??s})]},s))})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!n.trim()||M,onClick:()=>void te(),children:[M?e.jsx(ve,{className:"animate-spin",size:14}):null,"Create Run"]})]}),e.jsxs("div",{className:"research-view__history-header form-group",children:[e.jsx("label",{htmlFor:"research-run-search",children:"Search"}),e.jsxs("div",{className:"research-view__history-search-row",children:[e.jsx(pe,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:E,onChange:s=>O(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:u.map(s=>e.jsxs("button",{type:"button",className:`research-view__history-item${q===s.id?" research-view__history-item--active":""}`,onClick:()=>y(s.id),children:[e.jsx("span",{className:"card-id",children:s.id}),e.jsx("span",{children:s.title})]},s.id))})]}),e.jsxs("div",{className:"research-view__reader card",children:[R&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!R&&w&&e.jsx("p",{"data-testid":"research-state-error",children:w}),!R&&!w&&u.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),t&&e.jsxs("div",{children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:re}),e.jsx("strong",{children:se})]}),e.jsx("h3",{className:"research-view__run-title",children:t.title}),e.jsx("p",{className:"research-view__run-query",children:t.query}),e.jsx("p",{className:"research-view__run-summary","data-testid":"research-state-results",children:t.results?.summary??"No summary yet."}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",disabled:j==="cancel",onClick:()=>void T("cancel",()=>S(t.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",disabled:j==="retry",onClick:()=>void T("retry",()=>U(t.id),"Run retried"),children:"Retry"}),Q.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:j==="export-markdown",onClick:()=>void K("markdown"),children:"Export MD"}),Q.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:j==="export-json",onClick:()=>void K("json"),children:"Export JSON"}),Q.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:j==="export-html",onClick:()=>void K("html"),children:"Export HTML"})]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn btn-primary",type:"button",disabled:j==="create-task",onClick:()=>void T("create-task",()=>g(t.id,`Research: ${t.title}`),"Task created from research"),children:"Create Task"}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-task-id",children:"Task ID"}),e.jsx("input",{id:"research-task-id",className:"input",placeholder:"Task ID",value:$,onChange:s=>ee(s.target.value)})]}),e.jsx("button",{className:"btn",type:"button",disabled:!$.trim()||j==="attach-task",onClick:()=>void T("attach-task",()=>A(t.id,$.trim(),"document"),"Attached to task"),children:"Attach to Task"})]}),t.error&&e.jsx("p",{className:"research-view__error",children:t.error}),Array.isArray(t.results?.findings)&&t.results.findings.length>0&&e.jsx("div",{className:"research-view__findings",children:t.results.findings.map(s=>e.jsxs("article",{className:"research-view__finding card",children:[e.jsx("h4",{children:s.heading}),e.jsx("p",{children:s.content})]},s.heading))}),Array.isArray(t.results?.citations)&&t.results.citations.length>0&&e.jsx("ul",{className:"research-view__citations",children:t.results.citations.map(s=>e.jsx("li",{children:e.jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:s})},s))}),t.events.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Run history"}),e.jsx("ul",{className:"research-view__events",children:t.events.map(s=>e.jsx("li",{children:s.message},s.id))})]})]}),!t&&u.length>0&&e.jsx("p",{children:"Select a run to view details."}),e.jsxs("div",{className:"research-view__stats",children:[e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Running"}),e.jsx("div",{className:"research-view__stat-value",children:p.running})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Completed"}),e.jsx("div",{className:"research-view__stat-value",children:p.completed})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Failed"}),e.jsx("div",{className:"research-view__stat-value",children:p.failed})]})]})]})]})]})}export{ke as ResearchView};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Et,
|
|
1
|
+
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Et,b4 as kt,b5 as Ft,b6 as Dt,b7 as Mt,b8 as Rt,b9 as tt,ba as It,bb as $t,bc as at,bd as zt,be as At,bf as Bt,bg as Ht,bh as Ot,bi as Gt,bj as Tt,bk as Pt,w as Lt,aU as Vt,J as Ae,bl as he,X as re,aH as Fe,V as Pe,ad as Ut,aj as pt,aG as rt,aa as Kt,bm as Je,bn as Wt}from"./index-Bc8nfKeH.js";import"./vendor-xterm-DzcZoU0P.js";/**
|
|
2
2
|
* @license lucide-react v1.7.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const Yt=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],Jt=Et("loader",Yt);function qt(l){const n=l?.projectId,[v,f]=a.useState([]),[_,j]=a.useState(null),[S,m]=a.useState(null),[F,E]=a.useState([]),[C,y]=a.useState({}),[se,V]=a.useState(!1),[A,$]=a.useState(null),[De,ne]=a.useState(null),[fe,ie]=a.useState(!1),[Be,oe]=a.useState(null),[be,T]=a.useState([]),[B,P]=a.useState(!1),[X,O]=a.useState({}),[Me,le]=a.useState({}),Y=a.useRef(X),ce=a.useRef(Me),Q=a.useRef(be);Y.current=X,ce.current=Me,Q.current=be;const Re=a.useRef(n),D=a.useRef(0),Z=a.useRef(0),Oe=a.useRef(v),x=a.useRef(_),de=a.useRef(F),ve=a.useRef(C),R=a.useRef(n),xe=a.useRef(De);Oe.current=v,x.current=_,de.current=F,ve.current=C,R.current=n,xe.current=De,a.useEffect(()=>{Re.current!==n&&(Re.current=n,D.current++,j(null),m(null),E([]),y({}),ne(null),oe(null),T([]),P(!1),O({}),le({}))},[n]);const J=a.useCallback(async()=>{V(!0),$(null);try{const r=await kt(n);f(r)}catch(r){$(r instanceof Error?r:new Error("Failed to fetch roadmaps"))}finally{V(!1)}},[n]),N=a.useCallback(async r=>{try{const c=await Ft(r,n);m(c),E(c.milestones||[]);const i={};for(const s of c.milestones||[])i[s.id]=s.features||[];y(i)}catch(c){$(c instanceof Error?c:new Error("Failed to fetch roadmap"))}},[n]);a.useEffect(()=>{J()},[J]),a.useEffect(()=>{_?N(_):(m(null),E([]),y({}))},[_,N]);const He=a.useCallback(async(r,c)=>{try{const i=await Dt(r,R.current);f(s=>[...s,i]),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to create roadmap");throw c?.onError?.(s),s}},[]),we=a.useCallback(async(r,c,i)=>{try{const s=await Mt(r,c,R.current);f(d=>d.map(o=>o.id===r?s:o)),x.current===r&&m(d=>d?{...d,...s}:null),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update roadmap");throw i?.onError?.(d),d}},[]),h=a.useCallback(async(r,c)=>{try{await Rt(r,R.current),f(i=>i.filter(s=>s.id!==r)),x.current===r&&(j(null),m(null),E([]),y({})),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete roadmap");throw c?.onError?.(s),s}},[]),I=a.useCallback(r=>{j(r)},[]),je=a.useCallback(async(r,c)=>{const i=x.current;if(!i){const s=new Error("No roadmap selected");throw c?.onError?.(s),s}try{const s=await tt(i,r,R.current);E(d=>[...d,s]),y(d=>({...d,[s.id]:[]})),x.current&&N(x.current),c?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create milestone");throw c?.onError?.(d),d}},[N]),q=a.useCallback(async(r,c,i)=>{try{const s=await It(r,c,R.current);E(d=>d.map(o=>o.id===r?s:o)),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update milestone");throw i?.onError?.(d),d}},[N]),_e=a.useCallback(async(r,c)=>{try{await $t(r,R.current),E(i=>i.filter(s=>s.id!==r)),y(i=>{const s={...i};return delete s[r],s}),x.current&&N(x.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete milestone");throw c?.onError?.(s),s}},[N]),Le=a.useCallback(async(r,c,i)=>{try{const s=await at(r,c,R.current);y(d=>({...d,[r]:[...d[r]||[],s]})),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create feature");throw i?.onError?.(d),d}},[N]),M=a.useCallback(async(r,c,i)=>{try{const s=await zt(r,c,R.current);y(d=>{const o={};for(const[g,p]of Object.entries(d))o[g]=p.map(w=>w.id===r?s:w);return o}),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update feature");throw i?.onError?.(d),d}},[N]),ue=a.useCallback(async(r,c)=>{try{await At(r,R.current),y(i=>{const s={};for(const[d,o]of Object.entries(i))s[d]=o.filter(g=>g.id!==r);return s}),x.current&&N(x.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete feature");throw c?.onError?.(s),s}},[N]),H=a.useCallback(async(r,c,i)=>{const s=de.current,d=c.map(o=>s.find(g=>g.id===o)).filter(o=>o!==void 0).map((o,g)=>({...o,orderIndex:g}));E(d);try{await Bt(r,c,R.current),x.current&&N(x.current),i?.onSuccess?.()}catch(o){E(s);const g=o instanceof Error?o:new Error("Failed to reorder milestones");throw i?.onError?.(g),g}},[N]),ee=a.useCallback(async(r,c,i)=>{const s=ve.current[r]||[],d=s.map(p=>p.id);if(JSON.stringify(d)===JSON.stringify(c)){i?.onSuccess?.();return}const o=ve.current,g=c.map(p=>s.find(w=>w.id===p)).filter(p=>p!==void 0).map((p,w)=>({...p,orderIndex:w}));y(p=>({...p,[r]:g}));try{await Ot(r,c,R.current),x.current&&N(x.current),i?.onSuccess?.()}catch(p){y(o);const w=p instanceof Error?p:new Error("Failed to reorder features");throw i?.onError?.(w),w}},[N]),te=a.useCallback(async(r,c,i,s)=>{const d=ve.current;let o=null;for(const[k,K]of Object.entries(d))if(K.some(Ke=>Ke.id===r)){o=k;break}if(!o){const k=new Error("Feature not found");throw s?.onError?.(k),k}if(o===c){const k=d[o]||[],K=Math.max(0,Math.min(i,k.length-1));if(k.findIndex(We=>We.id===r)===K){s?.onSuccess?.();return}}const g=d[o]||[],p=d[c]||[],w=g.find(k=>k.id===r);if(!w){const k=new Error("Feature not found");throw s?.onError?.(k),k}const G=g.filter(k=>k.id!==r).map((k,K)=>({...k,orderIndex:K})),Ne={...w,milestoneId:c,orderIndex:i},ae=[...p];ae.splice(i,0,Ne);const Ve=ae.map((k,K)=>({...k,orderIndex:K}));y(o===c?k=>({...k,[o]:Ve}):k=>({...k,[o]:G,[c]:Ve}));try{await Ht(r,c,i,n),x.current&&N(x.current),s?.onSuccess?.()}catch(k){y(d);const K=k instanceof Error?k:new Error("Failed to move feature");throw s?.onError?.(K),K}},[N,n]);function Ie(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`draft-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}const pe=a.useCallback(async(r,c=5,i)=>{const s=x.current;if(!s){const g=new Error("No roadmap selected");throw i?.onError?.(g),g}const d=D.current,o=R.current;P(!0);try{const g=await Gt(s,r,c,o);if(D.current!==d)return;const p=g.suggestions.map(w=>({id:Ie(),title:w.title,description:w.description}));T(p),i?.onSuccess?.()}catch(g){if(D.current!==d)return;const p=g instanceof Error?g:new Error("Failed to generate suggestions");throw i?.onError?.(p),p}finally{D.current===d&&P(!1)}},[]),Ue=a.useCallback((r,c)=>{const s=Q.current.map(d=>d.id===r?{...d,...c}:d);Q.current=s,T(d=>d.map(o=>o.id===r?{...o,...c}:o))},[]),me=a.useCallback(async(r,c)=>{const i=x.current;if(!i){const p=new Error("No roadmap selected");throw c?.onError?.(p),p}const s=D.current,d=Q.current,o=d.findIndex(p=>p.id===r);if(o===-1){const p=new Error("Suggestion draft not found");throw c?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw c?.onError?.(p),p}T(p=>p.filter(w=>w.id!==r));try{if(await tt(i,{title:g.title,description:g.description},R.current),D.current!==s){T(p=>{const w=[...p];return w.splice(o,0,g),w});return}x.current&&N(x.current),c?.onSuccess?.()}catch(p){T(G=>{const Ne=[...G];return Ne.splice(o,0,g),Ne});const w=p instanceof Error?p:new Error("Failed to accept suggestion");throw c?.onError?.(w),w}},[N]),U=a.useCallback(async r=>{const c=x.current;if(!c){const o=new Error("No roadmap selected");throw r?.onError?.(o),o}const i=[...Q.current];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw r?.onError?.(o),o}T([]);const d=D.current;for(let o=0;o<i.length&&D.current===d;o++){const g=i[o];try{await tt(c,{title:g.title,description:g.description},R.current)}catch(p){const w=p instanceof Error?p:new Error("Failed to accept all suggestions");throw r?.onError?.(w),w}}D.current===d&&(x.current&&N(x.current),r?.onSuccess?.())},[N]),Je=a.useCallback(r=>ce.current[r]??!1,[]),Ge=a.useCallback(async(r,c,i)=>{const s=D.current,d=R.current;le(o=>({...o,[r]:!0}));try{const o=await Tt(r,c,d);if(D.current!==s)return;const g=o.suggestions.map(p=>({id:Ie(),title:p.title,description:p.description}));O(p=>({...p,[r]:g})),i?.onSuccess?.()}catch(o){if(D.current!==s)return;const g=o instanceof Error?o:new Error("Failed to generate feature suggestions");throw i?.onError?.(g),g}finally{D.current===s&&le(o=>({...o,[r]:!1}))}},[]),Ce=a.useCallback((r,c,i)=>{const d=(Y.current[r]||[]).map(o=>o.id===c?{...o,...i}:o);Y.current={...Y.current,[r]:d},O(o=>({...o,[r]:o[r]?.map(g=>g.id===c?{...g,...i}:g)||[]}))},[]),Te=a.useCallback(async(r,c,i)=>{const s=D.current,d=Y.current[r]||[],o=d.findIndex(p=>p.id===c);if(o===-1){const p=new Error("Suggestion draft not found");throw i?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw i?.onError?.(p),p}O(p=>({...p,[r]:p[r]?.filter(w=>w.id!==c)||[]}));try{if(await at(r,{title:g.title,description:g.description},R.current),D.current!==s){O(p=>{const G=[...p[r]||[]];return G.splice(o,0,g),{...p,[r]:G}});return}x.current&&N(x.current),i?.onSuccess?.()}catch(p){O(G=>{const ae=[...G[r]||[]];return ae.splice(o,0,g),{...G,[r]:ae}});const w=p instanceof Error?p:new Error("Failed to accept suggestion");throw i?.onError?.(w),w}},[N]),qe=a.useCallback(async(r,c)=>{const i=[...Y.current[r]||[]];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw c?.onError?.(o),o}O(o=>({...o,[r]:[]}));const d=D.current;for(let o=0;o<i.length&&D.current===d;o++){const g=i[o];try{await at(r,{title:g.title,description:g.description},R.current)}catch(p){const w=p instanceof Error?p:new Error("Failed to accept all suggestions");throw c?.onError?.(w),w}}D.current===d&&(x.current&&N(x.current),c?.onSuccess?.())},[N]),ye=a.useCallback(()=>{T([]),P(!1)},[]),Xe=a.useCallback(r=>{O(c=>{const i={...c};return delete i[r],i}),le(c=>{const i={...c};return delete i[r],i})},[]),ge=a.useCallback(async(r,c)=>{const i=++Z.current,s=n;ie(!0),oe(null);try{const d=await Pt(r,s);if(Z.current!==i||n!==s)return;ne(d),c?.onSuccess?.()}catch(d){if(Z.current!==i||n!==s)return;const o=d instanceof Error?d:new Error(String(d));oe(o),ne(null),c?.onError?.(o)}finally{Z.current===i&&ie(!1)}},[n]),$e=a.useCallback(()=>{ne(null),oe(null),ie(!1)},[]),Qe=a.useCallback(async()=>{await J(),x.current&&await N(x.current)},[J,N]);return{roadmaps:v,selectedRoadmapId:_,selectedRoadmap:S,milestones:F,featuresByMilestoneId:C,loading:se,error:A,createRoadmap:He,updateRoadmap:we,deleteRoadmap:h,selectRoadmap:I,createMilestone:je,updateMilestone:q,deleteMilestone:_e,reorderMilestones:H,createFeature:Le,updateFeature:M,deleteFeature:ue,reorderFeatures:ee,moveFeature:te,milestoneSuggestions:be,isGeneratingSuggestions:B,generateMilestoneSuggestions:pe,updateMilestoneSuggestionDraft:Ue,acceptMilestoneSuggestion:me,acceptAllMilestoneSuggestions:U,clearMilestoneSuggestions:ye,featureSuggestionsByMilestoneId:X,isGeneratingFeatureSuggestions:Je,generateFeatureSuggestions:Ge,updateFeatureSuggestionDraft:Ce,acceptFeatureSuggestion:Te,acceptAllFeatureSuggestions:qe,clearFeatureSuggestions:Xe,handoffPayload:De,isFetchingHandoff:fe,handoffError:Be,fetchHandoff:ge,clearHandoff:$e,refresh:Qe}}function Xt({isOpen:l,onClose:n,roadmapTitle:v,handoffPayload:f,isLoading:_,error:j,onFetchHandoff:S,onCopyToClipboard:m}){return l?e.jsx("div",{className:"modal-overlay open",onClick:n,role:"presentation",children:e.jsxs("div",{className:"modal modal-lg",onClick:F=>F.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"handoff-modal-title",children:[e.jsxs("div",{className:"modal-header",children:[e.jsxs("h2",{id:"handoff-modal-title",children:["Export Roadmap: ",v]}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close modal",children:e.jsx(re,{size:18})})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("p",{className:"text-muted",style:{marginBottom:"var(--space-lg)"},children:"Export roadmap data for use in mission and task planning flows. This is a read-only export — no missions or tasks will be created."}),j&&e.jsxs("div",{className:"form-error",style:{marginBottom:"var(--space-lg)"},children:["Error loading handoff data: ",j.message]}),!f&&!_&&e.jsx("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:e.jsxs("button",{className:"btn btn-primary",onClick:S,children:[e.jsx(rt,{size:16,style:{marginRight:"var(--space-sm)"}}),"Load Handoff Data"]})}),_&&e.jsxs("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:[e.jsx(Jt,{size:24,className:"spin"}),e.jsx("p",{style:{marginTop:"var(--space-md)"},children:"Loading handoff data..."})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsx("h3",{style:{marginBottom:"var(--space-sm)"},children:"Mission Planning Handoff"}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"200px",overflow:"auto"},children:JSON.stringify(f.mission,null,2)})})]}),e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsxs("h3",{style:{marginBottom:"var(--space-sm)"},children:["Feature Task Planning Handoffs (",f.features.length,")"]}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"300px",overflow:"auto"},children:JSON.stringify(f.features,null,2)})})]})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("div",{className:"modal-actions-left",children:f&&e.jsxs("button",{className:"btn btn-sm",onClick:m,children:[e.jsx(Wt,{size:14,style:{marginRight:"var(--space-xs)"}}),"Copy to Clipboard"]})}),e.jsx("div",{className:"modal-actions-right",children:e.jsx("button",{className:"btn",onClick:n,children:"Close"})})]})]})}):null}function Qt({roadmap:l,isSelected:n,onSelect:v,onEdit:f,onDelete:_,onExport:j}){const S=C=>{C.key==="Enter"&&v()},m=C=>{C.stopPropagation(),f()},F=C=>{C.stopPropagation(),_()},E=C=>{C.stopPropagation(),j()};return e.jsxs("div",{className:`roadmaps-view__sidebar-item${n?" roadmaps-view__sidebar-item--active":""}`,onClick:v,onKeyDown:S,role:"button",tabIndex:0,"aria-selected":n,"data-testid":`roadmap-item-${l.id}`,children:[e.jsxs("div",{className:"roadmaps-view__sidebar-item-content",children:[e.jsx("div",{className:"roadmaps-view__sidebar-item-title",children:l.title}),l.description&&e.jsx("div",{className:"roadmaps-view__sidebar-item-desc",children:l.description})]}),e.jsxs("div",{className:"roadmaps-view__sidebar-item-actions",onClick:m,role:"presentation",children:[e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:E,role:"button",title:"Export roadmap","aria-label":"Export roadmap","data-testid":`roadmap-export-${l.id}`,tabIndex:0,children:e.jsx(rt,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:m,role:"button",title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`roadmap-edit-${l.id}`,tabIndex:0,children:e.jsx(Fe,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:F,role:"button",title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`roadmap-delete-${l.id}`,tabIndex:0,children:e.jsx(Pe,{size:14})})]})]})}function Zt({roadmaps:l,selectedRoadmapId:n,onSelect:v,onCreate:f,onEdit:_,onDelete:j,onExport:S,showCreateForm:m,onCancelCreate:F,onSaveCreate:E}){return e.jsxs("div",{className:"roadmaps-view__mobile-list","data-testid":"roadmaps-view__mobile-list",children:[e.jsxs("div",{className:"roadmaps-view__mobile-list-header",children:[e.jsx("h2",{className:"roadmaps-view__mobile-list-title",children:"Roadmaps"}),!m&&e.jsx("button",{className:"roadmaps-view__mobile-add-btn",onClick:f,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-create-roadmap-btn",children:e.jsx(Ae,{size:18})})]}),m&&e.jsx("div",{className:"roadmaps-view__mobile-create-form",children:e.jsx(mt,{onSave:E,onCancel:F})}),l.length===0&&!m?e.jsxs("div",{className:"roadmaps-view__mobile-empty",children:[e.jsx("p",{children:"No roadmaps yet."}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Create Roadmap"})]})]}):e.jsx("div",{className:"roadmaps-view__mobile-list-items",children:l.map(C=>e.jsxs("div",{className:`roadmaps-view__mobile-item${C.id===n?" roadmaps-view__mobile-item--active":""}`,onClick:()=>v(C.id),role:"button",tabIndex:0,onKeyDown:y=>{y.key==="Enter"&&v(C.id)},"data-testid":`mobile-roadmap-item-${C.id}`,children:[e.jsxs("div",{className:"roadmaps-view__mobile-item-content",children:[e.jsx("span",{className:"roadmaps-view__mobile-item-title",children:C.title}),C.description&&e.jsx("span",{className:"roadmaps-view__mobile-item-desc",children:C.description})]}),e.jsxs("div",{className:"roadmaps-view__mobile-item-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),S(C)},title:"Export roadmap","aria-label":"Export roadmap","data-testid":`mobile-roadmap-export-${C.id}`,children:e.jsx(rt,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),_(C)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`mobile-roadmap-edit-${C.id}`,children:e.jsx(Fe,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:y=>{y.stopPropagation(),j(C.id)},title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`mobile-roadmap-delete-${C.id}`,children:e.jsx(Pe,{size:16})})]})]},C.id))})]})}function ea({roadmapTitle:l,onBack:n,onEdit:v,onDelete:f,onCreate:_}){return e.jsxs("div",{className:"roadmaps-view__mobile-header","data-testid":"roadmaps-view__mobile-header",children:[e.jsx("button",{className:"roadmaps-view__mobile-back-btn",onClick:n,title:"Back to roadmap list","aria-label":"Back to roadmap list","data-testid":"mobile-back-btn",children:e.jsx(Kt,{size:20})}),e.jsx("h2",{className:"roadmaps-view__mobile-header-title",children:l}),e.jsxs("div",{className:"roadmaps-view__mobile-header-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:_,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-header-create-btn",children:e.jsx(Ae,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:v,title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"mobile-header-edit-btn",children:e.jsx(Fe,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:f,title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"mobile-header-delete-btn",children:e.jsx(Pe,{size:18})})]})]})}function ta({milestone:l,features:n,onEditMilestone:v,onDeleteMilestone:f,onAddFeature:_,onEditFeature:j,onDeleteFeature:S,milestoneEdit:m,onStartMilestoneEdit:F,onCancelMilestoneEdit:E,onSaveMilestoneEdit:C,featureEdit:y,onStartFeatureEdit:se,onCancelFeatureEdit:V,onSaveFeatureEdit:A,projectId:$,addToast:De,isMilestoneDragging:ne,isMilestoneDropTarget:fe,milestoneDropPosition:ie,onMilestoneDragStart:Be,onMilestoneDragEnd:oe,onMilestoneDragOver:be,onMilestoneDrop:T,onMilestoneDragLeave:B,isFeatureDragging:P,isFeatureDropTarget:X,featureDropIndex:O,onFeatureDragStart:Me,onFeatureDragEnd:le,onFeatureDragOver:Y,onFeatureDrop:ce,onFeatureDragLeave:Q,onFeatureDropOnMilestone:Re,featureSuggestions:D,isGeneratingFeatureSuggestions:Z,onGenerateFeatureSuggestions:Oe,onAcceptFeatureSuggestion:x,onAcceptAllFeatureSuggestions:de,onUpdateFeatureSuggestionDraft:ve,onClearFeatureSuggestions:R}){const xe=m?.milestoneId===l.id,J=h=>{h.key==="Enter"?(h.preventDefault(),m&&C({title:m.value})):h.key==="Escape"&&E()},N=h=>{h.key==="Escape"&&E()},He=["roadmaps-view__milestone",ne?"roadmaps-view__milestone--dragging":"",fe?"roadmaps-view__milestone--drop-target":"",fe&&ie==="before"?"roadmaps-view__milestone--drop-before":"",fe&&ie==="after"?"roadmaps-view__milestone--drop-after":""].filter(Boolean).join(" "),we=["roadmaps-view__feature-list",X?"roadmaps-view__feature-list--drop-target":""].filter(Boolean).join(" ");return e.jsxs("div",{className:He,draggable:!xe,onDragStart:h=>{xe||(Be(l.id),h.dataTransfer.setData("text/plain",`milestone:${l.id}`),h.dataTransfer.effectAllowed="move")},onDragEnd:oe,onDragOver:h=>{h.dataTransfer.types.includes("text/plain")&&h.dataTransfer.types.includes("text/plain")&&(h.preventDefault(),h.dataTransfer.dropEffect="move",be(l.id))},onDrop:h=>{h.preventDefault(),h.dataTransfer.getData("text/plain")?.startsWith("feature:")||T(l.id)},onDragLeave:B,"data-testid":`milestone-card-${l.id}`,children:[e.jsx("div",{className:"roadmaps-view__milestone-header",children:xe?e.jsxs("div",{className:"roadmaps-view__inline-edit",children:[e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:m.value,onChange:()=>F(),onKeyDown:J,placeholder:"Milestone title",autoFocus:!0,"data-testid":`milestone-title-input-${l.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>C({title:m.value}),"aria-label":"Save milestone title",title:"Save",children:e.jsx(he,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:E,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(re,{size:14})})]}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:m.field==="description"?m.value:l.description||"",onChange:()=>{},onKeyDown:N,placeholder:"Milestone description (optional)",rows:2,"data-testid":`milestone-desc-input-${l.id}`})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__milestone-title-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("h3",{className:"roadmaps-view__milestone-title",children:l.title}),e.jsxs("div",{className:"roadmaps-view__milestone-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:v,title:"Edit milestone","aria-label":"Edit milestone","data-testid":`milestone-edit-${l.id}`,children:e.jsx(Fe,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:f,title:"Delete milestone","aria-label":"Delete milestone","data-testid":`milestone-delete-${l.id}`,children:e.jsx(Pe,{size:14})})]})]}),l.description&&e.jsx("p",{className:"roadmaps-view__milestone-desc",children:l.description})]})}),e.jsxs("div",{className:"roadmaps-view__milestone-actions-bar",children:[e.jsxs("button",{className:"roadmaps-view__add-feature-btn",onClick:_,title:"Add feature","aria-label":"Add feature","data-testid":`add-feature-${l.id}`,children:[e.jsx(Ae,{size:12}),e.jsx("span",{children:"Add Feature"})]}),e.jsxs("button",{className:"roadmaps-view__suggest-btn",onClick:()=>{Oe?.()},disabled:Z??!1,title:"Generate feature suggestions with AI","aria-label":"Generate feature suggestions","data-testid":`generate-features-${l.id}`,children:[e.jsx(pt,{size:12}),e.jsx("span",{children:Z?"Generating...":"AI Suggestions"})]})]}),e.jsxs("div",{className:we,onDragOver:h=>{h.preventDefault(),h.dataTransfer.dropEffect="move",h.dataTransfer.getData("text/plain")?.startsWith("feature:")&&Re()},onDrop:h=>{h.preventDefault();const I=h.dataTransfer.getData("text/plain");I?.startsWith("feature:")&&ce(I.split(":")[1],n.length)},onDragLeave:Q,children:[n.length===0?e.jsx("p",{className:"roadmaps-view__empty-features",children:"No features yet."}):n.map((h,I)=>{const je=y?.featureId===h.id,q=P(h.id),_e=M=>{M.key==="Enter"?(M.preventDefault(),y&&A({title:y.value})):M.key==="Escape"&&V()},Le=["roadmaps-view__feature-item",q?"roadmaps-view__feature-item--dragging":"",X&&O===I?"roadmaps-view__feature-item--drop-before":"",X&&O===I+1?"roadmaps-view__feature-item--drop-after":""].filter(Boolean).join(" ");return e.jsx("div",{className:Le,draggable:!je,onDragStart:M=>{je||(Me(h.id,l.id),M.dataTransfer.setData("text/plain",`feature:${h.id}`),M.dataTransfer.effectAllowed="move")},onDragEnd:le,onDragOver:M=>{if(M.preventDefault(),M.stopPropagation(),M.dataTransfer.dropEffect="move",M.dataTransfer.getData("text/plain")?.startsWith("feature:")){const H=M.currentTarget.getBoundingClientRect(),ee=H.top+H.height/2,te=M.clientY<ee?"before":"after";Y(h.id,te)}},onDrop:M=>{M.preventDefault(),M.stopPropagation();const ue=M.dataTransfer.getData("text/plain");if(ue?.startsWith("feature:")){const H=ue.split(":")[1],ee=M.currentTarget.getBoundingClientRect(),te=ee.top+ee.height/2,Ie=M.clientY<te?"before":"after";let pe=I;Ie==="after"&&(pe=I+1),ce(H,pe)}},onDragLeave:Q,"data-testid":`feature-item-${h.id}`,children:je?e.jsx("div",{className:"roadmaps-view__inline-edit roadmaps-view__inline-edit--compact",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:y.value,onChange:()=>{},onKeyDown:_e,placeholder:"Feature title",autoFocus:!0,"data-testid":`feature-title-input-${h.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>A({title:y.value}),"aria-label":"Save feature title",title:"Save",children:e.jsx(he,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:V,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(re,{size:14})})]})}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsxs("div",{className:"roadmaps-view__feature-content",children:[e.jsx("span",{className:"roadmaps-view__feature-title",children:h.title}),h.description&&e.jsx("p",{className:"roadmaps-view__feature-desc",children:h.description})]}),e.jsxs("div",{className:"roadmaps-view__feature-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>j(h.id),title:"Edit feature","aria-label":"Edit feature","data-testid":`feature-edit-${h.id}`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>S(h.id),title:"Delete feature","aria-label":"Delete feature","data-testid":`feature-delete-${h.id}`,children:e.jsx(Pe,{size:12})})]})]})},h.id)}),D&&D.length>0&&e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h4",{className:"roadmap-suggestion-title",children:"AI Feature Suggestions"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-accept-all-btn",onClick:()=>de?.(),title:"Accept all suggestions","aria-label":"Accept all","data-testid":`accept-all-features-${l.id}`,children:"Accept All"}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:()=>R?.(),title:"Clear suggestions","aria-label":"Clear","data-testid":`clear-features-${l.id}`,children:"Clear"})]})]}),e.jsx("div",{className:"roadmap-suggestion-list",children:D.map(h=>e.jsx(aa,{suggestion:h,onUpdateDraft:I=>ve?.(l.id,h.id,I),onAccept:()=>{x?.(l.id,h.id)},testIdPrefix:`feature-suggestion-${l.id}`},h.id))})]})]})]})}function aa({suggestion:l,onUpdateDraft:n,onAccept:v,testIdPrefix:f}){const[_,j]=a.useState(!1),[S,m]=a.useState(l.title),[F,E]=a.useState(l.description||""),C=()=>{m(l.title),E(l.description||""),j(!0)},y=()=>{n({title:S.trim(),description:F.trim()||void 0}),j(!1)},se=()=>{m(l.title),E(l.description||""),j(!1)},V=()=>{l.title.trim()&&v()},A=l.title.trim().length>0;return _?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:$=>m($.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:F,onChange:$=>E($.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(he,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:se,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(re,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:C,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:V,disabled:!A,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(he,{size:12})})]})]})}function ut({suggestion:l,onUpdateDraft:n,onAccept:v,testIdPrefix:f}){const[_,j]=a.useState(!1),[S,m]=a.useState(l.title),[F,E]=a.useState(l.description||""),C=()=>{m(l.title),E(l.description||""),j(!0)},y=()=>{n({title:S.trim(),description:F.trim()||void 0}),j(!1)},se=()=>{m(l.title),E(l.description||""),j(!1)},V=()=>{l.title.trim()&&v()},A=l.title.trim().length>0;return _?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:$=>m($.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:F,onChange:$=>E($.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(he,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:se,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(re,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:C,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:V,disabled:!A,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(he,{size:12})})]})]})}function mt({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form","data-testid":"create-roadmap-form",children:e.jsxs("form",{onSubmit:S,children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Roadmap title",autoFocus:!0,"data-testid":"create-roadmap-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Roadmap description (optional)",rows:2,"data-testid":"create-roadmap-description"}),e.jsxs("div",{className:"roadmaps-view__create-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__btn roadmaps-view__btn--primary",disabled:!v.trim(),"data-testid":"create-roadmap-submit",children:"Create"}),e.jsx("button",{type:"button",className:"roadmaps-view__btn",onClick:n,"data-testid":"create-roadmap-cancel",children:"Cancel"})]})]})})}function ra({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-milestone-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":"create-milestone-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-milestone-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!v.trim(),"aria-label":"Save milestone",title:"Save","data-testid":"create-milestone-submit",children:e.jsx(he,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-milestone-cancel",children:e.jsx(re,{size:14})})]})]})})}function sa({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-feature-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":"create-feature-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-feature-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!v.trim(),"aria-label":"Save feature",title:"Save","data-testid":"create-feature-submit",children:e.jsx(he,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-feature-cancel",children:e.jsx(re,{size:14})})]})]})})}function ca({projectId:l,addToast:n}){const{confirm:v}=Lt(),f=Vt()==="mobile",{roadmaps:_,selectedRoadmapId:j,selectedRoadmap:S,milestones:m,featuresByMilestoneId:F,loading:E,error:C,createRoadmap:y,updateRoadmap:se,deleteRoadmap:V,selectRoadmap:A,createMilestone:$,updateMilestone:De,deleteMilestone:ne,createFeature:fe,updateFeature:ie,deleteFeature:Be,reorderMilestones:oe,reorderFeatures:be,moveFeature:T,milestoneSuggestions:B,isGeneratingSuggestions:P,generateMilestoneSuggestions:X,updateMilestoneSuggestionDraft:O,acceptMilestoneSuggestion:Me,acceptAllMilestoneSuggestions:le,clearMilestoneSuggestions:Y,featureSuggestionsByMilestoneId:ce,isGeneratingFeatureSuggestions:Q,generateFeatureSuggestions:Re,updateFeatureSuggestionDraft:D,acceptFeatureSuggestion:Z,acceptAllFeatureSuggestions:Oe,clearFeatureSuggestions:x,handoffPayload:de,isFetchingHandoff:ve,handoffError:R,fetchHandoff:xe,clearHandoff:J}=qt({projectId:l}),[N,He]=a.useState(!1),[we,h]=a.useState(null),[I,je]=a.useState(""),[q,_e]=a.useState(""),[Le,M]=a.useState(!1),ue=a.useRef(null);a.useEffect(()=>{ue.current!==null&&ue.current!==j&&M(!1),ue.current=j},[j]);const[H,ee]=a.useState({roadmapId:null,field:null,value:""}),[te,Ie]=a.useState({milestoneId:null,field:null,value:""}),[pe,Ue]=a.useState({featureId:null,field:null,value:""}),[me,U]=a.useState({type:null,parentId:void 0,title:"",description:""}),[Je,Ge]=a.useState(!1),[Ce,Te]=a.useState({draggingId:null,dropTargetId:null,dropPosition:null}),qe=a.useCallback(t=>{Te(u=>({...u,draggingId:t}))},[]),ye=a.useCallback(()=>{Te({draggingId:null,dropTargetId:null,dropPosition:null})},[]),Xe=a.useCallback(t=>{Te(u=>u.draggingId===t?u:{...u,dropTargetId:t,dropPosition:null})},[]),[ge,$e]=a.useState({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}),Qe=a.useCallback((t,u)=>{$e(b=>({...b,draggingId:t,draggingMilestoneId:u}))},[]),r=a.useCallback(()=>{$e({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null})},[]),c=a.useCallback((t,u)=>{$e(b=>{if(b.draggingId===t)return b;const L=(F[b.draggingMilestoneId||""]||[]).findIndex(Ee=>Ee.id===t);let W;return u==="before"?W=L:W=L+1,{...b,dropTargetMilestoneId:b.draggingMilestoneId,dropTargetIndex:W,dropPosition:u}})},[F]),i=a.useCallback(()=>{$e(t=>({...t,dropTargetMilestoneId:t.draggingMilestoneId,dropTargetIndex:(F[t.draggingMilestoneId||""]||[]).length}))},[F]),s=a.useCallback(async(t,u)=>{const{draggingMilestoneId:b,dropTargetMilestoneId:z}=ge;if(!b){r();return}const L=z||b,W=F[b]||[],Ee=W.find(ke=>ke.id===t);if(!Ee){r();return}if(b!==L){if(b===L){r();return}try{await T(t,L,u,{onError:ke=>{n(`Failed to move feature: ${ke.message}`,"error")}})}catch{}}else{const ke=[...W],Nt=ke.findIndex(ze=>ze.id===t);ke.splice(Nt,1),ke.splice(u,0,Ee);const dt=ke.map(ze=>ze.id),St=W.map(ze=>ze.id);if(dt.join(",")===St.join(",")){r();return}try{await be(b,dt,{onError:ze=>{n(`Failed to reorder features: ${ze.message}`,"error")}})}catch{}}r()},[ge,F,be,T,n,r]),d=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),b=t.clientX,z=t.clientY;(b<u.left||b>u.right||z<u.top||z>u.bottom)&&$e(L=>({...L,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}))},[]),o=a.useCallback(t=>ge.draggingId===t,[ge.draggingId]),g=a.useCallback(async t=>{const{draggingId:u}=Ce;if(!u||u===t){ye();return}const b=m.map(Ee=>Ee.id),z=b.indexOf(u),L=b.indexOf(t);if(z===-1||L===-1){ye();return}const W=[...b];if(W.splice(z,1),W.splice(L,0,u),W.join(",")===b.join(",")){ye();return}try{await oe(j,W,{onError:Ee=>{n(`Failed to reorder milestones: ${Ee.message}`,"error")}})}catch{}ye()},[Ce,m,j,oe,n,ye]),p=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),b=t.clientX,z=t.clientY;(b<u.left||b>u.right||z<u.top||z>u.bottom)&&Te(L=>({...L,dropTargetId:null,dropPosition:null}))},[]),w=a.useCallback(t=>{A(t.id),ee({roadmapId:t.id,field:"title",value:t.title})},[A]),G=a.useCallback(()=>{ee({roadmapId:null,field:null,value:""})},[]),Ne=a.useCallback(async t=>{if(H.roadmapId)try{await se(H.roadmapId,t,{onError:u=>n(u.message,"error")}),G()}catch{}},[H.roadmapId,se,G,n]),ae=a.useCallback(async t=>{if(await v({title:"Delete Roadmap",message:"Delete this roadmap? This cannot be undone.",danger:!0}))try{await V(t,{onError:b=>n(b.message,"error")}),n("Roadmap deleted","success")}catch{}},[V,n,v]),Ve=a.useCallback((t,u)=>{h(t),je(u),He(!0),J()},[J]),k=a.useCallback(()=>{He(!1),h(null),je(""),J()},[J]),K=a.useCallback(()=>{we&&xe(we,{onError:t=>n(`Failed to load handoff: ${t.message}`,"error")})},[we,xe,n]),Ke=a.useCallback(()=>{if(de){const t=JSON.stringify(de,null,2);navigator.clipboard.writeText(t).then(()=>{n("Handoff data copied to clipboard","success")}).catch(()=>{n("Failed to copy to clipboard","error")})}},[de,n]),We=a.useCallback(async t=>{try{await y(t,{onError:u=>n(u.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Roadmap created","success")}catch{}},[y,n]),st=a.useCallback(t=>{Ie({milestoneId:t.id,field:"title",value:t.title})},[]),Ze=a.useCallback(()=>{Ie({milestoneId:null,field:null,value:""})},[]),gt=a.useCallback(async t=>{if(te.milestoneId)try{await De(te.milestoneId,t,{onError:u=>n(u.message,"error")}),Ze()}catch{}},[te.milestoneId,De,Ze,n]),ht=a.useCallback(async t=>{if(await v({title:"Delete Milestone",message:"Delete this milestone and all its features?",danger:!0}))try{await ne(t,{onError:b=>n(b.message,"error")}),n("Milestone deleted","success")}catch{}},[ne,n,v]),ft=a.useCallback(async t=>{try{await $(t,{onError:u=>n(u.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Milestone created","success")}catch{}},[$,n]),nt=a.useCallback((t,u,b)=>{Ue({featureId:t,field:"title",value:u})},[]),et=a.useCallback(()=>{Ue({featureId:null,field:null,value:""})},[]),bt=a.useCallback(async t=>{if(pe.featureId)try{await ie(pe.featureId,t,{onError:u=>n(u.message,"error")}),et()}catch{}},[pe.featureId,ie,et,n]),vt=a.useCallback(async t=>{if(await v({title:"Delete Feature",message:"Delete this feature?",danger:!0}))try{await Be(t,{onError:b=>n(b.message,"error")}),n("Feature deleted","success")}catch{}},[Be,n,v]),it=a.useCallback(async()=>{if(q.trim())try{await X(q,5,{onError:t=>n(t.message,"error")})}catch{}},[q,X,n]),ot=a.useCallback(async t=>{try{await Me(t,{onError:u=>n(u.message,"error")}),n("Milestone added","success")}catch{}},[Me,n]),lt=a.useCallback(async()=>{try{await le({onError:t=>n(t.message,"error")}),n(`${B.length} milestones added`,"success"),_e("")}catch{}},[le,B.length,n]),ct=a.useCallback(()=>{Y(),_e("")},[Y]),xt=a.useCallback(async t=>{try{await Re(t,{count:5},{onError:u=>n(u.message,"error")})}catch{}},[Re,n]),wt=a.useCallback(async(t,u)=>{try{await Z(t,u,{onError:b=>n(b.message,"error")}),n("Feature added","success")}catch{}},[Z,n]),jt=a.useCallback((t,u,b)=>{D(t,u,b)},[D]),_t=a.useCallback(async t=>{const u=ce[t]||[];try{await Oe(t,{onError:b=>n(b.message,"error")}),n(`${u.length} features added`,"success")}catch{}},[Oe,ce,n]),Ct=a.useCallback(t=>{x(t)},[x]),yt=a.useCallback(async(t,u)=>{try{await fe(t,u,{onError:b=>n(b.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Feature created","success")}catch{}},[fe,n]),Se=j;return E&&_.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--loading",children:e.jsx("div",{className:"roadmaps-view__loading-state",children:"Loading roadmaps..."})}):C&&_.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--error",children:e.jsxs("div",{className:"roadmaps-view__error-state",children:[e.jsx("p",{children:"Failed to load roadmaps"}),e.jsx("p",{className:"roadmaps-view__error-msg",children:C.message})]})}):e.jsxs("div",{className:"roadmaps-view",children:[f&&!Se&&e.jsx(Zt,{roadmaps:_,selectedRoadmapId:Se,onSelect:t=>A(t),onCreate:()=>Ge(!0),onEdit:w,onDelete:ae,onExport:t=>Ve(t.id,t.title),showCreateForm:Je,onCancelCreate:()=>Ge(!1),onSaveCreate:async t=>{await We(t),Ge(!1)}}),!f&&e.jsxs("aside",{className:"roadmaps-view__sidebar","aria-label":"Roadmaps",children:[e.jsxs("div",{className:"roadmaps-view__sidebar-header",children:[e.jsx("h2",{className:"roadmaps-view__sidebar-title",children:"Roadmaps"}),e.jsx("button",{className:"roadmaps-view__add-btn",onClick:()=>U({type:"roadmap",title:"",description:""}),title:"Create roadmap","aria-label":"Create roadmap","data-testid":"create-roadmap-btn",children:e.jsx(Ae,{size:16})})]}),me.type==="roadmap"&&e.jsx(mt,{onSave:We,onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})}),e.jsx("div",{className:"roadmaps-view__sidebar-list",children:_.length===0?e.jsx("p",{className:"roadmaps-view__empty-sidebar",children:"No roadmaps yet. Click + to create one."}):_.map(t=>e.jsx(Qt,{roadmap:t,isSelected:t.id===Se,onSelect:()=>A(t.id),onEdit:()=>w(t),onDelete:()=>ae(t.id),onExport:()=>Ve(t.id,t.title)},t.id))})]}),e.jsxs("main",{className:"roadmaps-view__main","aria-label":"Roadmap content",children:[f&&Se&&e.jsx(ea,{roadmapTitle:S?.title||"Untitled Roadmap",onBack:()=>A(null),onEdit:()=>{S&&w(S)},onDelete:()=>ae(Se),onCreate:()=>Ge(!0)}),Se?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"roadmaps-view__roadmap-header",children:H.roadmapId===Se?e.jsx("div",{className:"roadmaps-view__inline-edit",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input roadmaps-view__inline-input--large",value:H.value,onChange:t=>ee(u=>({...u,value:t.target.value})),onKeyDown:t=>{t.key==="Enter"?Ne({title:H.value}):t.key==="Escape"&&G()},placeholder:"Roadmap title",autoFocus:!0,"data-testid":"roadmap-title-input"}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>Ne({title:H.value}),"aria-label":"Save",title:"Save",children:e.jsx(he,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:G,"aria-label":"Cancel",title:"Cancel",children:e.jsx(re,{size:16})})]})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__roadmap-title-row",children:[e.jsx("h1",{className:"roadmaps-view__roadmap-title",children:S?.title||"Untitled Roadmap"}),e.jsxs("div",{className:"roadmaps-view__roadmap-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>{S&&w(S)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"edit-roadmap-btn",children:e.jsx(Fe,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>ae(Se),title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"delete-roadmap-btn",children:e.jsx(Pe,{size:16})})]})]}),S?.description&&e.jsx("p",{className:"roadmaps-view__roadmap-desc",children:S.description})]})}),f?Le?e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"}),e.jsx("button",{className:"roadmap-suggestion-collapse-btn",onClick:()=>M(!1),"aria-label":"Collapse suggestion panel","data-testid":"collapse-suggestion-panel-btn",children:e.jsx(Ut,{size:16})})]}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:q,onChange:t=>_e(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:P||!j,"data-testid":"goal-prompt-input",autoFocus:!0}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:it,disabled:!q.trim()||P||!j,"data-testid":"generate-suggestions-btn",children:P?"Generating...":"Generate Milestones"}),B.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:lt,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",B.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:ct,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(re,{size:14})})]})]})]}),B.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:B.map(t=>e.jsx(ut,{suggestion:t,onUpdateDraft:u=>O(t.id,u),onAccept:()=>ot(t.id),testIdPrefix:"suggestion"},t.id))})]}):e.jsx("div",{className:"roadmap-suggestion-section",children:e.jsxs("button",{className:"roadmap-suggestion-expand-btn",onClick:()=>M(!0),disabled:!j,"data-testid":"expand-suggestion-panel-btn",children:[e.jsx(pt,{size:16}),"Generate Milestone Ideas"]})}):e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsx("div",{className:"roadmap-suggestion-header",children:e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"})}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:q,onChange:t=>_e(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:P||!j,"data-testid":"goal-prompt-input"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:it,disabled:!q.trim()||P||!j,"data-testid":"generate-suggestions-btn",children:P?"Generating...":"Generate Milestones"}),B.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:lt,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",B.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:ct,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(re,{size:14})})]})]})]}),B.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:B.map(t=>e.jsx(ut,{suggestion:t,onUpdateDraft:u=>O(t.id,u),onAccept:()=>ot(t.id),testIdPrefix:"suggestion"},t.id))})]}),e.jsxs("div",{className:"roadmaps-view__milestone-lanes",children:[me.type==="milestone"&&e.jsx(ra,{onSave:ft,onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})}),m.length===0&&me.type!=="milestone"?e.jsxs("div",{className:"roadmaps-view__empty-milestones",children:[e.jsx("p",{children:"This roadmap has no milestones."}),e.jsxs("button",{className:"roadmaps-view__add-milestone-btn",onClick:()=>U({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn-empty",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]})]}):e.jsxs(e.Fragment,{children:[me.type!=="milestone"&&e.jsxs("button",{className:"roadmaps-view__add-milestone-fab",onClick:()=>U({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]}),m.map(t=>e.jsx(ta,{milestone:t,features:F[t.id]||[],onEditMilestone:()=>st(t),onDeleteMilestone:()=>ht(t.id),onAddFeature:()=>U({type:"feature",parentId:t.id,title:"",description:""}),onEditFeature:u=>{const b=F[t.id]?.find(z=>z.id===u);b&&nt(u,b.title,b.description)},onDeleteFeature:vt,milestoneEdit:te,onStartMilestoneEdit:()=>st(t),onCancelMilestoneEdit:Ze,onSaveMilestoneEdit:gt,featureEdit:pe,onStartFeatureEdit:nt,onCancelFeatureEdit:et,onSaveFeatureEdit:bt,projectId:l,addToast:n,isMilestoneDragging:Ce.draggingId===t.id,isMilestoneDropTarget:Ce.dropTargetId===t.id,milestoneDropPosition:Ce.dropTargetId===t.id?Ce.dropPosition:null,onMilestoneDragStart:qe,onMilestoneDragEnd:ye,onMilestoneDragOver:Xe,onMilestoneDrop:g,onMilestoneDragLeave:p,isFeatureDragging:o,isFeatureDropTarget:ge.dropTargetMilestoneId===t.id,featureDropIndex:ge.dropTargetMilestoneId===t.id?ge.dropTargetIndex:null,onFeatureDragStart:Qe,onFeatureDragEnd:r,onFeatureDragOver:c,onFeatureDrop:s,onFeatureDragLeave:d,onFeatureDropOnMilestone:i,featureSuggestions:ce[t.id],isGeneratingFeatureSuggestions:Q(t.id),onGenerateFeatureSuggestions:()=>xt(t.id),onAcceptFeatureSuggestion:u=>wt(t.id,u),onAcceptAllFeatureSuggestions:()=>_t(t.id),onUpdateFeatureSuggestionDraft:(u,b,z)=>jt(u,b,z),onClearFeatureSuggestions:()=>Ct(t.id)},t.id))]})]})]}):e.jsx("div",{className:"roadmaps-view__empty-main",children:e.jsx("p",{children:"Select a roadmap from the sidebar to view its milestones."})})]}),me.type==="feature"&&me.parentId&&e.jsx("div",{className:"roadmaps-view__feature-create-overlay",children:e.jsx(sa,{onSave:t=>yt(me.parentId,t),onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})})}),e.jsx(Xt,{isOpen:N,onClose:k,roadmapId:we||"",roadmapTitle:I,handoffPayload:de,isLoading:ve,error:R,onFetchHandoff:K,onCopyToClipboard:Ke})]})}export{ca as RoadmapsView};
|
|
6
|
+
*/const Jt=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],Yt=Et("loader",Jt);function qt(l){const n=l?.projectId,[v,f]=a.useState([]),[_,j]=a.useState(null),[S,m]=a.useState(null),[F,E]=a.useState([]),[C,y]=a.useState({}),[se,V]=a.useState(!1),[A,$]=a.useState(null),[De,ne]=a.useState(null),[fe,ie]=a.useState(!1),[Be,oe]=a.useState(null),[be,T]=a.useState([]),[B,P]=a.useState(!1),[X,H]=a.useState({}),[Me,le]=a.useState({}),J=a.useRef(X),ce=a.useRef(Me),Q=a.useRef(be);J.current=X,ce.current=Me,Q.current=be;const Re=a.useRef(n),D=a.useRef(0),Z=a.useRef(0),He=a.useRef(v),x=a.useRef(_),de=a.useRef(F),ve=a.useRef(C),R=a.useRef(n),xe=a.useRef(De);He.current=v,x.current=_,de.current=F,ve.current=C,R.current=n,xe.current=De,a.useEffect(()=>{Re.current!==n&&(Re.current=n,D.current++,j(null),m(null),E([]),y({}),ne(null),oe(null),T([]),P(!1),H({}),le({}))},[n]);const Y=a.useCallback(async()=>{V(!0),$(null);try{const r=await kt(n);f(r)}catch(r){$(r instanceof Error?r:new Error("Failed to fetch roadmaps"))}finally{V(!1)}},[n]),N=a.useCallback(async r=>{try{const c=await Ft(r,n);m(c),E(c.milestones||[]);const i={};for(const s of c.milestones||[])i[s.id]=s.features||[];y(i)}catch(c){$(c instanceof Error?c:new Error("Failed to fetch roadmap"))}},[n]);a.useEffect(()=>{Y()},[Y]),a.useEffect(()=>{_?N(_):(m(null),E([]),y({}))},[_,N]);const Oe=a.useCallback(async(r,c)=>{try{const i=await Dt(r,R.current);f(s=>[...s,i]),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to create roadmap");throw c?.onError?.(s),s}},[]),we=a.useCallback(async(r,c,i)=>{try{const s=await Mt(r,c,R.current);f(d=>d.map(o=>o.id===r?s:o)),x.current===r&&m(d=>d?{...d,...s}:null),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update roadmap");throw i?.onError?.(d),d}},[]),h=a.useCallback(async(r,c)=>{try{await Rt(r,R.current),f(i=>i.filter(s=>s.id!==r)),x.current===r&&(j(null),m(null),E([]),y({})),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete roadmap");throw c?.onError?.(s),s}},[]),I=a.useCallback(r=>{j(r)},[]),je=a.useCallback(async(r,c)=>{const i=x.current;if(!i){const s=new Error("No roadmap selected");throw c?.onError?.(s),s}try{const s=await tt(i,r,R.current);E(d=>[...d,s]),y(d=>({...d,[s.id]:[]})),x.current&&N(x.current),c?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create milestone");throw c?.onError?.(d),d}},[N]),q=a.useCallback(async(r,c,i)=>{try{const s=await It(r,c,R.current);E(d=>d.map(o=>o.id===r?s:o)),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update milestone");throw i?.onError?.(d),d}},[N]),_e=a.useCallback(async(r,c)=>{try{await $t(r,R.current),E(i=>i.filter(s=>s.id!==r)),y(i=>{const s={...i};return delete s[r],s}),x.current&&N(x.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete milestone");throw c?.onError?.(s),s}},[N]),Le=a.useCallback(async(r,c,i)=>{try{const s=await at(r,c,R.current);y(d=>({...d,[r]:[...d[r]||[],s]})),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create feature");throw i?.onError?.(d),d}},[N]),M=a.useCallback(async(r,c,i)=>{try{const s=await zt(r,c,R.current);y(d=>{const o={};for(const[g,p]of Object.entries(d))o[g]=p.map(w=>w.id===r?s:w);return o}),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update feature");throw i?.onError?.(d),d}},[N]),ue=a.useCallback(async(r,c)=>{try{await At(r,R.current),y(i=>{const s={};for(const[d,o]of Object.entries(i))s[d]=o.filter(g=>g.id!==r);return s}),x.current&&N(x.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete feature");throw c?.onError?.(s),s}},[N]),O=a.useCallback(async(r,c,i)=>{const s=de.current,d=c.map(o=>s.find(g=>g.id===o)).filter(o=>o!==void 0).map((o,g)=>({...o,orderIndex:g}));E(d);try{await Bt(r,c,R.current),x.current&&N(x.current),i?.onSuccess?.()}catch(o){E(s);const g=o instanceof Error?o:new Error("Failed to reorder milestones");throw i?.onError?.(g),g}},[N]),ee=a.useCallback(async(r,c,i)=>{const s=ve.current[r]||[],d=s.map(p=>p.id);if(JSON.stringify(d)===JSON.stringify(c)){i?.onSuccess?.();return}const o=ve.current,g=c.map(p=>s.find(w=>w.id===p)).filter(p=>p!==void 0).map((p,w)=>({...p,orderIndex:w}));y(p=>({...p,[r]:g}));try{await Ht(r,c,R.current),x.current&&N(x.current),i?.onSuccess?.()}catch(p){y(o);const w=p instanceof Error?p:new Error("Failed to reorder features");throw i?.onError?.(w),w}},[N]),te=a.useCallback(async(r,c,i,s)=>{const d=ve.current;let o=null;for(const[k,K]of Object.entries(d))if(K.some(Ke=>Ke.id===r)){o=k;break}if(!o){const k=new Error("Feature not found");throw s?.onError?.(k),k}if(o===c){const k=d[o]||[],K=Math.max(0,Math.min(i,k.length-1));if(k.findIndex(We=>We.id===r)===K){s?.onSuccess?.();return}}const g=d[o]||[],p=d[c]||[],w=g.find(k=>k.id===r);if(!w){const k=new Error("Feature not found");throw s?.onError?.(k),k}const G=g.filter(k=>k.id!==r).map((k,K)=>({...k,orderIndex:K})),Ne={...w,milestoneId:c,orderIndex:i},ae=[...p];ae.splice(i,0,Ne);const Ve=ae.map((k,K)=>({...k,orderIndex:K}));y(o===c?k=>({...k,[o]:Ve}):k=>({...k,[o]:G,[c]:Ve}));try{await Ot(r,c,i,n),x.current&&N(x.current),s?.onSuccess?.()}catch(k){y(d);const K=k instanceof Error?k:new Error("Failed to move feature");throw s?.onError?.(K),K}},[N,n]);function Ie(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`draft-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}const pe=a.useCallback(async(r,c=5,i)=>{const s=x.current;if(!s){const g=new Error("No roadmap selected");throw i?.onError?.(g),g}const d=D.current,o=R.current;P(!0);try{const g=await Gt(s,r,c,o);if(D.current!==d)return;const p=g.suggestions.map(w=>({id:Ie(),title:w.title,description:w.description}));T(p),i?.onSuccess?.()}catch(g){if(D.current!==d)return;const p=g instanceof Error?g:new Error("Failed to generate suggestions");throw i?.onError?.(p),p}finally{D.current===d&&P(!1)}},[]),Ue=a.useCallback((r,c)=>{const s=Q.current.map(d=>d.id===r?{...d,...c}:d);Q.current=s,T(d=>d.map(o=>o.id===r?{...o,...c}:o))},[]),me=a.useCallback(async(r,c)=>{const i=x.current;if(!i){const p=new Error("No roadmap selected");throw c?.onError?.(p),p}const s=D.current,d=Q.current,o=d.findIndex(p=>p.id===r);if(o===-1){const p=new Error("Suggestion draft not found");throw c?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw c?.onError?.(p),p}T(p=>p.filter(w=>w.id!==r));try{if(await tt(i,{title:g.title,description:g.description},R.current),D.current!==s){T(p=>{const w=[...p];return w.splice(o,0,g),w});return}x.current&&N(x.current),c?.onSuccess?.()}catch(p){T(G=>{const Ne=[...G];return Ne.splice(o,0,g),Ne});const w=p instanceof Error?p:new Error("Failed to accept suggestion");throw c?.onError?.(w),w}},[N]),U=a.useCallback(async r=>{const c=x.current;if(!c){const o=new Error("No roadmap selected");throw r?.onError?.(o),o}const i=[...Q.current];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw r?.onError?.(o),o}T([]);const d=D.current;for(let o=0;o<i.length&&D.current===d;o++){const g=i[o];try{await tt(c,{title:g.title,description:g.description},R.current)}catch(p){const w=p instanceof Error?p:new Error("Failed to accept all suggestions");throw r?.onError?.(w),w}}D.current===d&&(x.current&&N(x.current),r?.onSuccess?.())},[N]),Ye=a.useCallback(r=>ce.current[r]??!1,[]),Ge=a.useCallback(async(r,c,i)=>{const s=D.current,d=R.current;le(o=>({...o,[r]:!0}));try{const o=await Tt(r,c,d);if(D.current!==s)return;const g=o.suggestions.map(p=>({id:Ie(),title:p.title,description:p.description}));H(p=>({...p,[r]:g})),i?.onSuccess?.()}catch(o){if(D.current!==s)return;const g=o instanceof Error?o:new Error("Failed to generate feature suggestions");throw i?.onError?.(g),g}finally{D.current===s&&le(o=>({...o,[r]:!1}))}},[]),Ce=a.useCallback((r,c,i)=>{const d=(J.current[r]||[]).map(o=>o.id===c?{...o,...i}:o);J.current={...J.current,[r]:d},H(o=>({...o,[r]:o[r]?.map(g=>g.id===c?{...g,...i}:g)||[]}))},[]),Te=a.useCallback(async(r,c,i)=>{const s=D.current,d=J.current[r]||[],o=d.findIndex(p=>p.id===c);if(o===-1){const p=new Error("Suggestion draft not found");throw i?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw i?.onError?.(p),p}H(p=>({...p,[r]:p[r]?.filter(w=>w.id!==c)||[]}));try{if(await at(r,{title:g.title,description:g.description},R.current),D.current!==s){H(p=>{const G=[...p[r]||[]];return G.splice(o,0,g),{...p,[r]:G}});return}x.current&&N(x.current),i?.onSuccess?.()}catch(p){H(G=>{const ae=[...G[r]||[]];return ae.splice(o,0,g),{...G,[r]:ae}});const w=p instanceof Error?p:new Error("Failed to accept suggestion");throw i?.onError?.(w),w}},[N]),qe=a.useCallback(async(r,c)=>{const i=[...J.current[r]||[]];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw c?.onError?.(o),o}H(o=>({...o,[r]:[]}));const d=D.current;for(let o=0;o<i.length&&D.current===d;o++){const g=i[o];try{await at(r,{title:g.title,description:g.description},R.current)}catch(p){const w=p instanceof Error?p:new Error("Failed to accept all suggestions");throw c?.onError?.(w),w}}D.current===d&&(x.current&&N(x.current),c?.onSuccess?.())},[N]),ye=a.useCallback(()=>{T([]),P(!1)},[]),Xe=a.useCallback(r=>{H(c=>{const i={...c};return delete i[r],i}),le(c=>{const i={...c};return delete i[r],i})},[]),ge=a.useCallback(async(r,c)=>{const i=++Z.current,s=n;ie(!0),oe(null);try{const d=await Pt(r,s);if(Z.current!==i||n!==s)return;ne(d),c?.onSuccess?.()}catch(d){if(Z.current!==i||n!==s)return;const o=d instanceof Error?d:new Error(String(d));oe(o),ne(null),c?.onError?.(o)}finally{Z.current===i&&ie(!1)}},[n]),$e=a.useCallback(()=>{ne(null),oe(null),ie(!1)},[]),Qe=a.useCallback(async()=>{await Y(),x.current&&await N(x.current)},[Y,N]);return{roadmaps:v,selectedRoadmapId:_,selectedRoadmap:S,milestones:F,featuresByMilestoneId:C,loading:se,error:A,createRoadmap:Oe,updateRoadmap:we,deleteRoadmap:h,selectRoadmap:I,createMilestone:je,updateMilestone:q,deleteMilestone:_e,reorderMilestones:O,createFeature:Le,updateFeature:M,deleteFeature:ue,reorderFeatures:ee,moveFeature:te,milestoneSuggestions:be,isGeneratingSuggestions:B,generateMilestoneSuggestions:pe,updateMilestoneSuggestionDraft:Ue,acceptMilestoneSuggestion:me,acceptAllMilestoneSuggestions:U,clearMilestoneSuggestions:ye,featureSuggestionsByMilestoneId:X,isGeneratingFeatureSuggestions:Ye,generateFeatureSuggestions:Ge,updateFeatureSuggestionDraft:Ce,acceptFeatureSuggestion:Te,acceptAllFeatureSuggestions:qe,clearFeatureSuggestions:Xe,handoffPayload:De,isFetchingHandoff:fe,handoffError:Be,fetchHandoff:ge,clearHandoff:$e,refresh:Qe}}function Xt({isOpen:l,onClose:n,roadmapTitle:v,handoffPayload:f,isLoading:_,error:j,onFetchHandoff:S,onCopyToClipboard:m}){return l?e.jsx("div",{className:"modal-overlay open",onClick:n,role:"presentation",children:e.jsxs("div",{className:"modal modal-lg",onClick:F=>F.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"handoff-modal-title",children:[e.jsxs("div",{className:"modal-header",children:[e.jsxs("h2",{id:"handoff-modal-title",children:["Export Roadmap: ",v]}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close modal",children:e.jsx(re,{size:18})})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("p",{className:"text-muted",style:{marginBottom:"var(--space-lg)"},children:"Export roadmap data for use in mission and task planning flows. This is a read-only export — no missions or tasks will be created."}),j&&e.jsxs("div",{className:"form-error",style:{marginBottom:"var(--space-lg)"},children:["Error loading handoff data: ",j.message]}),!f&&!_&&e.jsx("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:e.jsxs("button",{className:"btn btn-primary",onClick:S,children:[e.jsx(rt,{size:16,style:{marginRight:"var(--space-sm)"}}),"Load Handoff Data"]})}),_&&e.jsxs("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:[e.jsx(Yt,{size:24,className:"spin"}),e.jsx("p",{style:{marginTop:"var(--space-md)"},children:"Loading handoff data..."})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsx("h3",{style:{marginBottom:"var(--space-sm)"},children:"Mission Planning Handoff"}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"200px",overflow:"auto"},children:JSON.stringify(f.mission,null,2)})})]}),e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsxs("h3",{style:{marginBottom:"var(--space-sm)"},children:["Feature Task Planning Handoffs (",f.features.length,")"]}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"300px",overflow:"auto"},children:JSON.stringify(f.features,null,2)})})]})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("div",{className:"modal-actions-left",children:f&&e.jsxs("button",{className:"btn btn-sm",onClick:m,children:[e.jsx(Wt,{size:14,style:{marginRight:"var(--space-xs)"}}),"Copy to Clipboard"]})}),e.jsx("div",{className:"modal-actions-right",children:e.jsx("button",{className:"btn",onClick:n,children:"Close"})})]})]})}):null}function Qt({roadmap:l,isSelected:n,onSelect:v,onEdit:f,onDelete:_,onExport:j}){const S=C=>{C.key==="Enter"&&v()},m=C=>{C.stopPropagation(),f()},F=C=>{C.stopPropagation(),_()},E=C=>{C.stopPropagation(),j()};return e.jsxs("div",{className:`roadmaps-view__sidebar-item${n?" roadmaps-view__sidebar-item--active":""}`,onClick:v,onKeyDown:S,role:"button",tabIndex:0,"aria-selected":n,"data-testid":`roadmap-item-${l.id}`,children:[e.jsxs("div",{className:"roadmaps-view__sidebar-item-content",children:[e.jsx("div",{className:"roadmaps-view__sidebar-item-title",children:l.title}),l.description&&e.jsx("div",{className:"roadmaps-view__sidebar-item-desc",children:l.description})]}),e.jsxs("div",{className:"roadmaps-view__sidebar-item-actions",onClick:m,role:"presentation",children:[e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:E,role:"button",title:"Export roadmap","aria-label":"Export roadmap","data-testid":`roadmap-export-${l.id}`,tabIndex:0,children:e.jsx(rt,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:m,role:"button",title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`roadmap-edit-${l.id}`,tabIndex:0,children:e.jsx(Fe,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:F,role:"button",title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`roadmap-delete-${l.id}`,tabIndex:0,children:e.jsx(Pe,{size:14})})]})]})}function Zt({roadmaps:l,selectedRoadmapId:n,onSelect:v,onCreate:f,onEdit:_,onDelete:j,onExport:S,showCreateForm:m,onCancelCreate:F,onSaveCreate:E}){return e.jsxs("div",{className:"roadmaps-view__mobile-list","data-testid":"roadmaps-view__mobile-list",children:[e.jsxs("div",{className:"roadmaps-view__mobile-list-header",children:[e.jsx("h2",{className:"roadmaps-view__mobile-list-title",children:"Roadmaps"}),!m&&e.jsx("button",{className:"roadmaps-view__mobile-add-btn",onClick:f,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-create-roadmap-btn",children:e.jsx(Ae,{size:18})})]}),m&&e.jsx("div",{className:"roadmaps-view__mobile-create-form",children:e.jsx(mt,{onSave:E,onCancel:F})}),l.length===0&&!m?e.jsxs("div",{className:"roadmaps-view__mobile-empty",children:[e.jsx("p",{children:"No roadmaps yet."}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Create Roadmap"})]})]}):e.jsx("div",{className:"roadmaps-view__mobile-list-items",children:l.map(C=>e.jsxs("div",{className:`roadmaps-view__mobile-item${C.id===n?" roadmaps-view__mobile-item--active":""}`,onClick:()=>v(C.id),role:"button",tabIndex:0,onKeyDown:y=>{y.key==="Enter"&&v(C.id)},"data-testid":`mobile-roadmap-item-${C.id}`,children:[e.jsxs("div",{className:"roadmaps-view__mobile-item-content",children:[e.jsx("span",{className:"roadmaps-view__mobile-item-title",children:C.title}),C.description&&e.jsx("span",{className:"roadmaps-view__mobile-item-desc",children:C.description})]}),e.jsxs("div",{className:"roadmaps-view__mobile-item-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),S(C)},title:"Export roadmap","aria-label":"Export roadmap","data-testid":`mobile-roadmap-export-${C.id}`,children:e.jsx(rt,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),_(C)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`mobile-roadmap-edit-${C.id}`,children:e.jsx(Fe,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:y=>{y.stopPropagation(),j(C.id)},title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`mobile-roadmap-delete-${C.id}`,children:e.jsx(Pe,{size:16})})]})]},C.id))})]})}function ea({roadmapTitle:l,onBack:n,onEdit:v,onDelete:f,onCreate:_}){return e.jsxs("div",{className:"roadmaps-view__mobile-header","data-testid":"roadmaps-view__mobile-header",children:[e.jsx("button",{className:"roadmaps-view__mobile-back-btn",onClick:n,title:"Back to roadmap list","aria-label":"Back to roadmap list","data-testid":"mobile-back-btn",children:e.jsx(Kt,{size:20})}),e.jsx("h2",{className:"roadmaps-view__mobile-header-title",children:l}),e.jsxs("div",{className:"roadmaps-view__mobile-header-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:_,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-header-create-btn",children:e.jsx(Ae,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:v,title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"mobile-header-edit-btn",children:e.jsx(Fe,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:f,title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"mobile-header-delete-btn",children:e.jsx(Pe,{size:18})})]})]})}function ta({milestone:l,features:n,onEditMilestone:v,onDeleteMilestone:f,onAddFeature:_,onEditFeature:j,onDeleteFeature:S,milestoneEdit:m,onStartMilestoneEdit:F,onCancelMilestoneEdit:E,onSaveMilestoneEdit:C,featureEdit:y,onStartFeatureEdit:se,onCancelFeatureEdit:V,onSaveFeatureEdit:A,projectId:$,addToast:De,isMilestoneDragging:ne,isMilestoneDropTarget:fe,milestoneDropPosition:ie,onMilestoneDragStart:Be,onMilestoneDragEnd:oe,onMilestoneDragOver:be,onMilestoneDrop:T,onMilestoneDragLeave:B,isFeatureDragging:P,isFeatureDropTarget:X,featureDropIndex:H,onFeatureDragStart:Me,onFeatureDragEnd:le,onFeatureDragOver:J,onFeatureDrop:ce,onFeatureDragLeave:Q,onFeatureDropOnMilestone:Re,featureSuggestions:D,isGeneratingFeatureSuggestions:Z,onGenerateFeatureSuggestions:He,onAcceptFeatureSuggestion:x,onAcceptAllFeatureSuggestions:de,onUpdateFeatureSuggestionDraft:ve,onClearFeatureSuggestions:R}){const xe=m?.milestoneId===l.id,Y=h=>{h.key==="Enter"?(h.preventDefault(),m&&C({title:m.value})):h.key==="Escape"&&E()},N=h=>{h.key==="Escape"&&E()},Oe=["roadmaps-view__milestone",ne?"roadmaps-view__milestone--dragging":"",fe?"roadmaps-view__milestone--drop-target":"",fe&&ie==="before"?"roadmaps-view__milestone--drop-before":"",fe&&ie==="after"?"roadmaps-view__milestone--drop-after":""].filter(Boolean).join(" "),we=["roadmaps-view__feature-list",X?"roadmaps-view__feature-list--drop-target":""].filter(Boolean).join(" ");return e.jsxs("div",{className:Oe,draggable:!xe,onDragStart:h=>{xe||(Be(l.id),h.dataTransfer.setData("text/plain",`milestone:${l.id}`),h.dataTransfer.effectAllowed="move")},onDragEnd:oe,onDragOver:h=>{h.dataTransfer.types.includes("text/plain")&&h.dataTransfer.types.includes("text/plain")&&(h.preventDefault(),h.dataTransfer.dropEffect="move",be(l.id))},onDrop:h=>{h.preventDefault(),h.dataTransfer.getData("text/plain")?.startsWith("feature:")||T(l.id)},onDragLeave:B,"data-testid":`milestone-card-${l.id}`,children:[e.jsx("div",{className:"roadmaps-view__milestone-header",children:xe?e.jsxs("div",{className:"roadmaps-view__inline-edit",children:[e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Je,{size:14})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:m.value,onChange:()=>F(),onKeyDown:Y,placeholder:"Milestone title",autoFocus:!0,"data-testid":`milestone-title-input-${l.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>C({title:m.value}),"aria-label":"Save milestone title",title:"Save",children:e.jsx(he,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:E,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(re,{size:14})})]}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:m.field==="description"?m.value:l.description||"",onChange:()=>{},onKeyDown:N,placeholder:"Milestone description (optional)",rows:2,"data-testid":`milestone-desc-input-${l.id}`})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__milestone-title-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Je,{size:14})}),e.jsx("h3",{className:"roadmaps-view__milestone-title",children:l.title}),e.jsxs("div",{className:"roadmaps-view__milestone-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:v,title:"Edit milestone","aria-label":"Edit milestone","data-testid":`milestone-edit-${l.id}`,children:e.jsx(Fe,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:f,title:"Delete milestone","aria-label":"Delete milestone","data-testid":`milestone-delete-${l.id}`,children:e.jsx(Pe,{size:14})})]})]}),l.description&&e.jsx("p",{className:"roadmaps-view__milestone-desc",children:l.description})]})}),e.jsxs("div",{className:"roadmaps-view__milestone-actions-bar",children:[e.jsxs("button",{className:"roadmaps-view__add-feature-btn",onClick:_,title:"Add feature","aria-label":"Add feature","data-testid":`add-feature-${l.id}`,children:[e.jsx(Ae,{size:12}),e.jsx("span",{children:"Add Feature"})]}),e.jsxs("button",{className:"roadmaps-view__suggest-btn",onClick:()=>{He?.()},disabled:Z??!1,title:"Generate feature suggestions with AI","aria-label":"Generate feature suggestions","data-testid":`generate-features-${l.id}`,children:[e.jsx(pt,{size:12}),e.jsx("span",{children:Z?"Generating...":"AI Suggestions"})]})]}),e.jsxs("div",{className:we,onDragOver:h=>{h.preventDefault(),h.dataTransfer.dropEffect="move",h.dataTransfer.getData("text/plain")?.startsWith("feature:")&&Re()},onDrop:h=>{h.preventDefault();const I=h.dataTransfer.getData("text/plain");I?.startsWith("feature:")&&ce(I.split(":")[1],n.length)},onDragLeave:Q,children:[n.length===0?e.jsx("p",{className:"roadmaps-view__empty-features",children:"No features yet."}):n.map((h,I)=>{const je=y?.featureId===h.id,q=P(h.id),_e=M=>{M.key==="Enter"?(M.preventDefault(),y&&A({title:y.value})):M.key==="Escape"&&V()},Le=["roadmaps-view__feature-item",q?"roadmaps-view__feature-item--dragging":"",X&&H===I?"roadmaps-view__feature-item--drop-before":"",X&&H===I+1?"roadmaps-view__feature-item--drop-after":""].filter(Boolean).join(" ");return e.jsx("div",{className:Le,draggable:!je,onDragStart:M=>{je||(Me(h.id,l.id),M.dataTransfer.setData("text/plain",`feature:${h.id}`),M.dataTransfer.effectAllowed="move")},onDragEnd:le,onDragOver:M=>{if(M.preventDefault(),M.stopPropagation(),M.dataTransfer.dropEffect="move",M.dataTransfer.getData("text/plain")?.startsWith("feature:")){const O=M.currentTarget.getBoundingClientRect(),ee=O.top+O.height/2,te=M.clientY<ee?"before":"after";J(h.id,te)}},onDrop:M=>{M.preventDefault(),M.stopPropagation();const ue=M.dataTransfer.getData("text/plain");if(ue?.startsWith("feature:")){const O=ue.split(":")[1],ee=M.currentTarget.getBoundingClientRect(),te=ee.top+ee.height/2,Ie=M.clientY<te?"before":"after";let pe=I;Ie==="after"&&(pe=I+1),ce(O,pe)}},onDragLeave:Q,"data-testid":`feature-item-${h.id}`,children:je?e.jsx("div",{className:"roadmaps-view__inline-edit roadmaps-view__inline-edit--compact",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Je,{size:12})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:y.value,onChange:()=>{},onKeyDown:_e,placeholder:"Feature title",autoFocus:!0,"data-testid":`feature-title-input-${h.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>A({title:y.value}),"aria-label":"Save feature title",title:"Save",children:e.jsx(he,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:V,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(re,{size:14})})]})}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Je,{size:12})}),e.jsxs("div",{className:"roadmaps-view__feature-content",children:[e.jsx("span",{className:"roadmaps-view__feature-title",children:h.title}),h.description&&e.jsx("p",{className:"roadmaps-view__feature-desc",children:h.description})]}),e.jsxs("div",{className:"roadmaps-view__feature-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>j(h.id),title:"Edit feature","aria-label":"Edit feature","data-testid":`feature-edit-${h.id}`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>S(h.id),title:"Delete feature","aria-label":"Delete feature","data-testid":`feature-delete-${h.id}`,children:e.jsx(Pe,{size:12})})]})]})},h.id)}),D&&D.length>0&&e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h4",{className:"roadmap-suggestion-title",children:"AI Feature Suggestions"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-accept-all-btn",onClick:()=>de?.(),title:"Accept all suggestions","aria-label":"Accept all","data-testid":`accept-all-features-${l.id}`,children:"Accept All"}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:()=>R?.(),title:"Clear suggestions","aria-label":"Clear","data-testid":`clear-features-${l.id}`,children:"Clear"})]})]}),e.jsx("div",{className:"roadmap-suggestion-list",children:D.map(h=>e.jsx(aa,{suggestion:h,onUpdateDraft:I=>ve?.(l.id,h.id,I),onAccept:()=>{x?.(l.id,h.id)},testIdPrefix:`feature-suggestion-${l.id}`},h.id))})]})]})]})}function aa({suggestion:l,onUpdateDraft:n,onAccept:v,testIdPrefix:f}){const[_,j]=a.useState(!1),[S,m]=a.useState(l.title),[F,E]=a.useState(l.description||""),C=()=>{m(l.title),E(l.description||""),j(!0)},y=()=>{n({title:S.trim(),description:F.trim()||void 0}),j(!1)},se=()=>{m(l.title),E(l.description||""),j(!1)},V=()=>{l.title.trim()&&v()},A=l.title.trim().length>0;return _?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:$=>m($.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:F,onChange:$=>E($.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(he,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:se,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(re,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:C,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:V,disabled:!A,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(he,{size:12})})]})]})}function ut({suggestion:l,onUpdateDraft:n,onAccept:v,testIdPrefix:f}){const[_,j]=a.useState(!1),[S,m]=a.useState(l.title),[F,E]=a.useState(l.description||""),C=()=>{m(l.title),E(l.description||""),j(!0)},y=()=>{n({title:S.trim(),description:F.trim()||void 0}),j(!1)},se=()=>{m(l.title),E(l.description||""),j(!1)},V=()=>{l.title.trim()&&v()},A=l.title.trim().length>0;return _?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:$=>m($.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:F,onChange:$=>E($.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(he,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:se,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(re,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:C,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:V,disabled:!A,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(he,{size:12})})]})]})}function mt({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form","data-testid":"create-roadmap-form",children:e.jsxs("form",{onSubmit:S,children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Roadmap title",autoFocus:!0,"data-testid":"create-roadmap-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Roadmap description (optional)",rows:2,"data-testid":"create-roadmap-description"}),e.jsxs("div",{className:"roadmaps-view__create-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__btn roadmaps-view__btn--primary",disabled:!v.trim(),"data-testid":"create-roadmap-submit",children:"Create"}),e.jsx("button",{type:"button",className:"roadmaps-view__btn",onClick:n,"data-testid":"create-roadmap-cancel",children:"Cancel"})]})]})})}function ra({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-milestone-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":"create-milestone-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-milestone-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!v.trim(),"aria-label":"Save milestone",title:"Save","data-testid":"create-milestone-submit",children:e.jsx(he,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-milestone-cancel",children:e.jsx(re,{size:14})})]})]})})}function sa({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-feature-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":"create-feature-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-feature-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!v.trim(),"aria-label":"Save feature",title:"Save","data-testid":"create-feature-submit",children:e.jsx(he,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-feature-cancel",children:e.jsx(re,{size:14})})]})]})})}function ca({projectId:l,addToast:n}){const{confirm:v}=Lt(),f=Vt()==="mobile",{roadmaps:_,selectedRoadmapId:j,selectedRoadmap:S,milestones:m,featuresByMilestoneId:F,loading:E,error:C,createRoadmap:y,updateRoadmap:se,deleteRoadmap:V,selectRoadmap:A,createMilestone:$,updateMilestone:De,deleteMilestone:ne,createFeature:fe,updateFeature:ie,deleteFeature:Be,reorderMilestones:oe,reorderFeatures:be,moveFeature:T,milestoneSuggestions:B,isGeneratingSuggestions:P,generateMilestoneSuggestions:X,updateMilestoneSuggestionDraft:H,acceptMilestoneSuggestion:Me,acceptAllMilestoneSuggestions:le,clearMilestoneSuggestions:J,featureSuggestionsByMilestoneId:ce,isGeneratingFeatureSuggestions:Q,generateFeatureSuggestions:Re,updateFeatureSuggestionDraft:D,acceptFeatureSuggestion:Z,acceptAllFeatureSuggestions:He,clearFeatureSuggestions:x,handoffPayload:de,isFetchingHandoff:ve,handoffError:R,fetchHandoff:xe,clearHandoff:Y}=qt({projectId:l}),[N,Oe]=a.useState(!1),[we,h]=a.useState(null),[I,je]=a.useState(""),[q,_e]=a.useState(""),[Le,M]=a.useState(!1),ue=a.useRef(null);a.useEffect(()=>{ue.current!==null&&ue.current!==j&&M(!1),ue.current=j},[j]);const[O,ee]=a.useState({roadmapId:null,field:null,value:""}),[te,Ie]=a.useState({milestoneId:null,field:null,value:""}),[pe,Ue]=a.useState({featureId:null,field:null,value:""}),[me,U]=a.useState({type:null,parentId:void 0,title:"",description:""}),[Ye,Ge]=a.useState(!1),[Ce,Te]=a.useState({draggingId:null,dropTargetId:null,dropPosition:null}),qe=a.useCallback(t=>{Te(u=>({...u,draggingId:t}))},[]),ye=a.useCallback(()=>{Te({draggingId:null,dropTargetId:null,dropPosition:null})},[]),Xe=a.useCallback(t=>{Te(u=>u.draggingId===t?u:{...u,dropTargetId:t,dropPosition:null})},[]),[ge,$e]=a.useState({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}),Qe=a.useCallback((t,u)=>{$e(b=>({...b,draggingId:t,draggingMilestoneId:u}))},[]),r=a.useCallback(()=>{$e({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null})},[]),c=a.useCallback((t,u)=>{$e(b=>{if(b.draggingId===t)return b;const L=(F[b.draggingMilestoneId||""]||[]).findIndex(Ee=>Ee.id===t);let W;return u==="before"?W=L:W=L+1,{...b,dropTargetMilestoneId:b.draggingMilestoneId,dropTargetIndex:W,dropPosition:u}})},[F]),i=a.useCallback(()=>{$e(t=>({...t,dropTargetMilestoneId:t.draggingMilestoneId,dropTargetIndex:(F[t.draggingMilestoneId||""]||[]).length}))},[F]),s=a.useCallback(async(t,u)=>{const{draggingMilestoneId:b,dropTargetMilestoneId:z}=ge;if(!b){r();return}const L=z||b,W=F[b]||[],Ee=W.find(ke=>ke.id===t);if(!Ee){r();return}if(b!==L){if(b===L){r();return}try{await T(t,L,u,{onError:ke=>{n(`Failed to move feature: ${ke.message}`,"error")}})}catch{}}else{const ke=[...W],Nt=ke.findIndex(ze=>ze.id===t);ke.splice(Nt,1),ke.splice(u,0,Ee);const dt=ke.map(ze=>ze.id),St=W.map(ze=>ze.id);if(dt.join(",")===St.join(",")){r();return}try{await be(b,dt,{onError:ze=>{n(`Failed to reorder features: ${ze.message}`,"error")}})}catch{}}r()},[ge,F,be,T,n,r]),d=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),b=t.clientX,z=t.clientY;(b<u.left||b>u.right||z<u.top||z>u.bottom)&&$e(L=>({...L,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}))},[]),o=a.useCallback(t=>ge.draggingId===t,[ge.draggingId]),g=a.useCallback(async t=>{const{draggingId:u}=Ce;if(!u||u===t){ye();return}const b=m.map(Ee=>Ee.id),z=b.indexOf(u),L=b.indexOf(t);if(z===-1||L===-1){ye();return}const W=[...b];if(W.splice(z,1),W.splice(L,0,u),W.join(",")===b.join(",")){ye();return}try{await oe(j,W,{onError:Ee=>{n(`Failed to reorder milestones: ${Ee.message}`,"error")}})}catch{}ye()},[Ce,m,j,oe,n,ye]),p=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),b=t.clientX,z=t.clientY;(b<u.left||b>u.right||z<u.top||z>u.bottom)&&Te(L=>({...L,dropTargetId:null,dropPosition:null}))},[]),w=a.useCallback(t=>{A(t.id),ee({roadmapId:t.id,field:"title",value:t.title})},[A]),G=a.useCallback(()=>{ee({roadmapId:null,field:null,value:""})},[]),Ne=a.useCallback(async t=>{if(O.roadmapId)try{await se(O.roadmapId,t,{onError:u=>n(u.message,"error")}),G()}catch{}},[O.roadmapId,se,G,n]),ae=a.useCallback(async t=>{if(await v({title:"Delete Roadmap",message:"Delete this roadmap? This cannot be undone.",danger:!0}))try{await V(t,{onError:b=>n(b.message,"error")}),n("Roadmap deleted","success")}catch{}},[V,n,v]),Ve=a.useCallback((t,u)=>{h(t),je(u),Oe(!0),Y()},[Y]),k=a.useCallback(()=>{Oe(!1),h(null),je(""),Y()},[Y]),K=a.useCallback(()=>{we&&xe(we,{onError:t=>n(`Failed to load handoff: ${t.message}`,"error")})},[we,xe,n]),Ke=a.useCallback(()=>{if(de){const t=JSON.stringify(de,null,2);navigator.clipboard.writeText(t).then(()=>{n("Handoff data copied to clipboard","success")}).catch(()=>{n("Failed to copy to clipboard","error")})}},[de,n]),We=a.useCallback(async t=>{try{await y(t,{onError:u=>n(u.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Roadmap created","success")}catch{}},[y,n]),st=a.useCallback(t=>{Ie({milestoneId:t.id,field:"title",value:t.title})},[]),Ze=a.useCallback(()=>{Ie({milestoneId:null,field:null,value:""})},[]),gt=a.useCallback(async t=>{if(te.milestoneId)try{await De(te.milestoneId,t,{onError:u=>n(u.message,"error")}),Ze()}catch{}},[te.milestoneId,De,Ze,n]),ht=a.useCallback(async t=>{if(await v({title:"Delete Milestone",message:"Delete this milestone and all its features?",danger:!0}))try{await ne(t,{onError:b=>n(b.message,"error")}),n("Milestone deleted","success")}catch{}},[ne,n,v]),ft=a.useCallback(async t=>{try{await $(t,{onError:u=>n(u.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Milestone created","success")}catch{}},[$,n]),nt=a.useCallback((t,u,b)=>{Ue({featureId:t,field:"title",value:u})},[]),et=a.useCallback(()=>{Ue({featureId:null,field:null,value:""})},[]),bt=a.useCallback(async t=>{if(pe.featureId)try{await ie(pe.featureId,t,{onError:u=>n(u.message,"error")}),et()}catch{}},[pe.featureId,ie,et,n]),vt=a.useCallback(async t=>{if(await v({title:"Delete Feature",message:"Delete this feature?",danger:!0}))try{await Be(t,{onError:b=>n(b.message,"error")}),n("Feature deleted","success")}catch{}},[Be,n,v]),it=a.useCallback(async()=>{if(q.trim())try{await X(q,5,{onError:t=>n(t.message,"error")})}catch{}},[q,X,n]),ot=a.useCallback(async t=>{try{await Me(t,{onError:u=>n(u.message,"error")}),n("Milestone added","success")}catch{}},[Me,n]),lt=a.useCallback(async()=>{try{await le({onError:t=>n(t.message,"error")}),n(`${B.length} milestones added`,"success"),_e("")}catch{}},[le,B.length,n]),ct=a.useCallback(()=>{J(),_e("")},[J]),xt=a.useCallback(async t=>{try{await Re(t,{count:5},{onError:u=>n(u.message,"error")})}catch{}},[Re,n]),wt=a.useCallback(async(t,u)=>{try{await Z(t,u,{onError:b=>n(b.message,"error")}),n("Feature added","success")}catch{}},[Z,n]),jt=a.useCallback((t,u,b)=>{D(t,u,b)},[D]),_t=a.useCallback(async t=>{const u=ce[t]||[];try{await He(t,{onError:b=>n(b.message,"error")}),n(`${u.length} features added`,"success")}catch{}},[He,ce,n]),Ct=a.useCallback(t=>{x(t)},[x]),yt=a.useCallback(async(t,u)=>{try{await fe(t,u,{onError:b=>n(b.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Feature created","success")}catch{}},[fe,n]),Se=j;return E&&_.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--loading",children:e.jsx("div",{className:"roadmaps-view__loading-state",children:"Loading roadmaps..."})}):C&&_.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--error",children:e.jsxs("div",{className:"roadmaps-view__error-state",children:[e.jsx("p",{children:"Failed to load roadmaps"}),e.jsx("p",{className:"roadmaps-view__error-msg",children:C.message})]})}):e.jsxs("div",{className:"roadmaps-view",children:[f&&!Se&&e.jsx(Zt,{roadmaps:_,selectedRoadmapId:Se,onSelect:t=>A(t),onCreate:()=>Ge(!0),onEdit:w,onDelete:ae,onExport:t=>Ve(t.id,t.title),showCreateForm:Ye,onCancelCreate:()=>Ge(!1),onSaveCreate:async t=>{await We(t),Ge(!1)}}),!f&&e.jsxs("aside",{className:"roadmaps-view__sidebar","aria-label":"Roadmaps",children:[e.jsxs("div",{className:"roadmaps-view__sidebar-header",children:[e.jsx("h2",{className:"roadmaps-view__sidebar-title",children:"Roadmaps"}),e.jsx("button",{className:"roadmaps-view__add-btn",onClick:()=>U({type:"roadmap",title:"",description:""}),title:"Create roadmap","aria-label":"Create roadmap","data-testid":"create-roadmap-btn",children:e.jsx(Ae,{size:16})})]}),me.type==="roadmap"&&e.jsx(mt,{onSave:We,onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})}),e.jsx("div",{className:"roadmaps-view__sidebar-list",children:_.length===0?e.jsx("p",{className:"roadmaps-view__empty-sidebar",children:"No roadmaps yet. Click + to create one."}):_.map(t=>e.jsx(Qt,{roadmap:t,isSelected:t.id===Se,onSelect:()=>A(t.id),onEdit:()=>w(t),onDelete:()=>ae(t.id),onExport:()=>Ve(t.id,t.title)},t.id))})]}),e.jsxs("main",{className:"roadmaps-view__main","aria-label":"Roadmap content",children:[f&&Se&&e.jsx(ea,{roadmapTitle:S?.title||"Untitled Roadmap",onBack:()=>A(null),onEdit:()=>{S&&w(S)},onDelete:()=>ae(Se),onCreate:()=>Ge(!0)}),Se?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"roadmaps-view__roadmap-header",children:O.roadmapId===Se?e.jsx("div",{className:"roadmaps-view__inline-edit",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input roadmaps-view__inline-input--large",value:O.value,onChange:t=>ee(u=>({...u,value:t.target.value})),onKeyDown:t=>{t.key==="Enter"?Ne({title:O.value}):t.key==="Escape"&&G()},placeholder:"Roadmap title",autoFocus:!0,"data-testid":"roadmap-title-input"}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>Ne({title:O.value}),"aria-label":"Save",title:"Save",children:e.jsx(he,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:G,"aria-label":"Cancel",title:"Cancel",children:e.jsx(re,{size:16})})]})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__roadmap-title-row",children:[e.jsx("h1",{className:"roadmaps-view__roadmap-title",children:S?.title||"Untitled Roadmap"}),e.jsxs("div",{className:"roadmaps-view__roadmap-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>{S&&w(S)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"edit-roadmap-btn",children:e.jsx(Fe,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>ae(Se),title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"delete-roadmap-btn",children:e.jsx(Pe,{size:16})})]})]}),S?.description&&e.jsx("p",{className:"roadmaps-view__roadmap-desc",children:S.description})]})}),f?Le?e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"}),e.jsx("button",{className:"roadmap-suggestion-collapse-btn",onClick:()=>M(!1),"aria-label":"Collapse suggestion panel","data-testid":"collapse-suggestion-panel-btn",children:e.jsx(Ut,{size:16})})]}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:q,onChange:t=>_e(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:P||!j,"data-testid":"goal-prompt-input",autoFocus:!0}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:it,disabled:!q.trim()||P||!j,"data-testid":"generate-suggestions-btn",children:P?"Generating...":"Generate Milestones"}),B.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:lt,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",B.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:ct,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(re,{size:14})})]})]})]}),B.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:B.map(t=>e.jsx(ut,{suggestion:t,onUpdateDraft:u=>H(t.id,u),onAccept:()=>ot(t.id),testIdPrefix:"suggestion"},t.id))})]}):e.jsx("div",{className:"roadmap-suggestion-section",children:e.jsxs("button",{className:"roadmap-suggestion-expand-btn",onClick:()=>M(!0),disabled:!j,"data-testid":"expand-suggestion-panel-btn",children:[e.jsx(pt,{size:16}),"Generate Milestone Ideas"]})}):e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsx("div",{className:"roadmap-suggestion-header",children:e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"})}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:q,onChange:t=>_e(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:P||!j,"data-testid":"goal-prompt-input"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:it,disabled:!q.trim()||P||!j,"data-testid":"generate-suggestions-btn",children:P?"Generating...":"Generate Milestones"}),B.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:lt,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",B.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:ct,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(re,{size:14})})]})]})]}),B.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:B.map(t=>e.jsx(ut,{suggestion:t,onUpdateDraft:u=>H(t.id,u),onAccept:()=>ot(t.id),testIdPrefix:"suggestion"},t.id))})]}),e.jsxs("div",{className:"roadmaps-view__milestone-lanes",children:[me.type==="milestone"&&e.jsx(ra,{onSave:ft,onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})}),m.length===0&&me.type!=="milestone"?e.jsxs("div",{className:"roadmaps-view__empty-milestones",children:[e.jsx("p",{children:"This roadmap has no milestones."}),e.jsxs("button",{className:"roadmaps-view__add-milestone-btn",onClick:()=>U({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn-empty",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]})]}):e.jsxs(e.Fragment,{children:[me.type!=="milestone"&&e.jsxs("button",{className:"roadmaps-view__add-milestone-fab",onClick:()=>U({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]}),m.map(t=>e.jsx(ta,{milestone:t,features:F[t.id]||[],onEditMilestone:()=>st(t),onDeleteMilestone:()=>ht(t.id),onAddFeature:()=>U({type:"feature",parentId:t.id,title:"",description:""}),onEditFeature:u=>{const b=F[t.id]?.find(z=>z.id===u);b&&nt(u,b.title,b.description)},onDeleteFeature:vt,milestoneEdit:te,onStartMilestoneEdit:()=>st(t),onCancelMilestoneEdit:Ze,onSaveMilestoneEdit:gt,featureEdit:pe,onStartFeatureEdit:nt,onCancelFeatureEdit:et,onSaveFeatureEdit:bt,projectId:l,addToast:n,isMilestoneDragging:Ce.draggingId===t.id,isMilestoneDropTarget:Ce.dropTargetId===t.id,milestoneDropPosition:Ce.dropTargetId===t.id?Ce.dropPosition:null,onMilestoneDragStart:qe,onMilestoneDragEnd:ye,onMilestoneDragOver:Xe,onMilestoneDrop:g,onMilestoneDragLeave:p,isFeatureDragging:o,isFeatureDropTarget:ge.dropTargetMilestoneId===t.id,featureDropIndex:ge.dropTargetMilestoneId===t.id?ge.dropTargetIndex:null,onFeatureDragStart:Qe,onFeatureDragEnd:r,onFeatureDragOver:c,onFeatureDrop:s,onFeatureDragLeave:d,onFeatureDropOnMilestone:i,featureSuggestions:ce[t.id],isGeneratingFeatureSuggestions:Q(t.id),onGenerateFeatureSuggestions:()=>xt(t.id),onAcceptFeatureSuggestion:u=>wt(t.id,u),onAcceptAllFeatureSuggestions:()=>_t(t.id),onUpdateFeatureSuggestionDraft:(u,b,z)=>jt(u,b,z),onClearFeatureSuggestions:()=>Ct(t.id)},t.id))]})]})]}):e.jsx("div",{className:"roadmaps-view__empty-main",children:e.jsx("p",{children:"Select a roadmap from the sidebar to view its milestones."})})]}),me.type==="feature"&&me.parentId&&e.jsx("div",{className:"roadmaps-view__feature-create-overlay",children:e.jsx(sa,{onSave:t=>yt(me.parentId,t),onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})})}),e.jsx(Xt,{isOpen:N,onClose:k,roadmapId:we||"",roadmapTitle:I,handoffPayload:de,isLoading:ve,error:R,onFetchHandoff:K,onCopyToClipboard:Ke})]})}export{ca as RoadmapsView};
|