1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4145],{54145:function(e,t,s){s.r(t),s.d(t,{default:function(){return g}});var a=s(57437),l=s(2265),r=s(95728),n=s(87321),i=s(63094),o=s(95046),d=s(11933);let c="Interactive Project Management Chart",m="project-management",x="portal_gantt_tasks";function p(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;let[t,s,a]=e.split("-").map(e=>Number(e));if(!t||!s||!a)return null;let l=new Date(Date.UTC(t,s-1,a,0,0,0,0));return Number.isNaN(l.getTime())?null:l}function h(e,t,s){return Math.min(s,Math.max(t,e))}function u(e,t){return Math.round((t.getTime()-e.getTime())/864e5)}function b(e){return"".concat(e.start," â ").concat(e.end)}function g(){let{toolKey:e="workshop_project_gantt_v1",vaultToolId:t="project-management",enterpriseMode:s=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},g=(0,o.k)(),{data:f,setData:j,clearDraft:v,hydrated:N}=(0,n.S)(e,{tasks:[],lastSavedAt:null},{debounceMs:400}),w=f.tasks,y=f.lastSavedAt,k=(0,l.useCallback)(e=>{j(t=>({tasks:"function"==typeof e?e(t.tasks):e,lastSavedAt:new Date().toISOString()}))},[j]),[T,C]=(0,l.useState)(0),[S,M]=(0,l.useState)(!1),[D,I]=(0,l.useState)(null),_=(0,l.useRef)(!1);(0,l.useEffect)(()=>{if(!N||_.current||(_.current=!0,w.length>0))return;let e=window.localStorage.getItem(x);if(e)try{let t=JSON.parse(e);Array.isArray(t)&&t.length>0&&j({tasks:t,lastSavedAt:new Date().toISOString()})}catch(e){}},[N,w.length,j]),(0,l.useEffect)(()=>{if(0===w.length){C(0);return}C(Math.round(w.reduce((e,t)=>e+t.progress,0)/w.length))},[w]);let A=(0,l.useMemo)(()=>{let e=[...w];return e.sort((e,t)=>{var s,a,l,r,n,i,o,d;let c=null!==(n=null===(s=p(e.start))||void 0===s?void 0:s.getTime())&&void 0!==n?n:Number.POSITIVE_INFINITY,m=null!==(i=null===(a=p(t.start))||void 0===a?void 0:a.getTime())&&void 0!==i?i:Number.POSITIVE_INFINITY;return c!==m?c-m:(null!==(o=null===(l=p(e.end))||void 0===l?void 0:l.getTime())&&void 0!==o?o:c)-(null!==(d=null===(r=p(t.end))||void 0===r?void 0:r.getTime())&&void 0!==d?d:m)}),e},[w]),E=(0,l.useMemo)(()=>{let e=A.flatMap(e=>[p(e.start),p(e.end)]).filter(Boolean),t=e.length?new Date(Math.min(...e.map(e=>e.getTime()))):null,s=e.length?new Date(Math.max(...e.map(e=>e.getTime()))):null;if(!t||!s)return null;let a=Math.max(1,u(t,s)),l=a<=14?a+1:Math.min(10,Math.ceil(a/7)+1),r=Array.from({length:l},(e,a)=>{let r=a/(l-1||1),n=new Date(t.getTime()+r*(s.getTime()-t.getTime())).toLocaleDateString(void 0,{month:"short",day:"2-digit"});return{t:r,label:n}});return{start:t,end:s,spanDays:a,ticks:r}},[A]),O=e=>{let t=!w.find(t=>t.id===e.id);if(k(t=>t.find(t=>t.id===e.id)?t.map(t=>t.id===e.id?e:t):[...t,e]),t&&s&&g){let t=p(e.start),s=p(e.end),a=t&&s?Math.max(1,u(t,s)):void 0;g.syncWork({workDescription:"Project task: ".concat(e.name),sourceTool:"project-management",sourceRef:String(e.id),expectedDurationDays:a,priority:e.isMilestone?"high":"medium",additionalComments:e.description||void 0})}M(!1),I(null)},P=e=>{k(t=>t.filter(t=>t.id!==e))},L=e=>{let t=new Date().toISOString().slice(0,10);I({id:Date.now(),name:e?"New Milestone":"New Task",start:t,end:t,progress:e?100:0,color:e?"#f97316":"#4b6cb7",description:"",isMilestone:e}),M(!0)};return(0,a.jsxs)("div",{className:"project-gantt-wrapper text-black bg-white rounded-lg shadow-md overflow-hidden",children:[(0,a.jsxs)("div",{className:"header px-6 py-4 bg-gradient-to-r from-[#4b6cb7] to-[#182848] text-white",children:[(0,a.jsx)("h2",{className:"text-lg font-semibold",children:"Interactive Project Management Chart"}),(0,a.jsx)("p",{className:"text-xs mt-1",children:"Plan and track projects with tasks and milestones. All data stays in your browser and is never sent to the server."})]}),(0,a.jsxs)("div",{className:"px-6 py-4 bg-slate-100 border-b border-slate-200",children:[(0,a.jsx)("p",{className:"text-xs font-semibold text-slate-800",children:"How-to tutorial"}),(0,a.jsx)("p",{className:"text-[11px] text-slate-600 mt-1 italic",children:"Example how-to create your chart video here."}),(0,a.jsx)("a",{href:"https://share.descript.com/view/13Z1J6VQCJg",target:"_blank",rel:"noopener noreferrer",className:"mt-2 inline-flex items-center gap-2 rounded-md border border-slate-300 bg-white px-3 py-2 text-[12px] font-semibold text-[#4b6cb7] hover:bg-slate-50",children:"Open the Descript tutorial in a
1new tab"})]}),(0,a.jsx)("div",{className:"px-6 py-3",children:(0,a.jsx)(i.Z,{toolId:t,titlePrefix:"Project management chart",getDraft:()=>f,applyDraft:j,pickerHint:"These are stored in your browser's local Vault (IndexedDB). Click one to load it back into this tool."})}),(0,a.jsxs)("div",{className:"px-6 py-3 flex flex-wrap items-center gap-3 bg-slate-50 border-b border-slate-200",children:[(0,a.jsx)("button",{type:"button",onClick:()=>L(!1),className:"px-3 py-1.5 rounded-md text-sm font-semibold bg-[#4b6cb7] text-white hover:bg-[#3a56a4]",children:"Add Task"}),(0,a.jsx)("button",{type:"button",onClick:()=>L(!0),className:"px-3 py-1.5 rounded-md text-sm font-semibold bg-emerald-600 text-white hover:bg-emerald-700",children:"Add Milestone"}),(0,a.jsx)("button",{type:"button",onClick:()=>{if(0===w.length)return;let e=["Task Name,Type,Start Date,End Date,Progress (%),Status,Description",...w.map(e=>[e.name,e.isMilestone?"Milestone":"Task",e.start,e.end,String(e.progress),100===e.progress?"Completed":"In Progress",e.description||""]).map(e=>e.map(e=>{let t=String(null!=e?e:"").replace(/"/g,'""');return'"'.concat(t,'"')}).join(","))];(0,r.m)({action:"export_csv",calculatorName:c,surface:"workshop",metadata:{toolId:m,rowCount:w.length}});let t=new Blob([(0,d.rs)(e.join("\n"))],{type:"text/csv;charset=utf-8;"}),s=URL.createObjectURL(t),a=document.createElement("a");a.href=s,a.download="portal-project-chart-".concat(Date.now(),".csv"),document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(s)},className:"px-3 py-1.5 rounded-md text-sm font-semibold bg-slate-800 text-white hover:bg-slate-900",children:"Export CSV"}),(0,a.jsx)("button",{type:"button",onClick:()=>{(0,r.m)({action:"print_results",calculatorName:c,surface:"workshop",metadata:{toolId:m,taskCount:w.length}}),window.print()},className:"px-3 py-1.5 rounded-md text-sm font-semibold bg-slate-200 text-slate-900 hover:bg-slate-300",children:"Print View"}),(0,a.jsx)("button",{type:"button",onClick:()=>{if(confirm("Clear all tasks and milestones from this tool? This only affects your browser.")){v(),j({tasks:[],lastSavedAt:new Date().toISOString()});try{window.localStorage.removeItem(x)}catch(e){}(0,r.m)({action:"save_calculation",calculatorName:c,surface:"workshop",metadata:{toolId:m,action:"clear_project"}})}},className:"px-3 py-1.5 rounded-md text-sm font-semibold bg-white border border-red-300 text-red-700 hover:bg-red-50",title:"Clear local project",children:"Clear"}),(0,a.jsxs)("div",{className:"ml-auto flex items-center gap-2",children:[(0,a.jsx)("div",{className:"hidden lg:flex flex-col items-end mr-2 max-w-[220px]",children:(0,a.jsx)("span",{className:"text-[11px] text-slate-500 text-right",children:y?"Local vault (IndexedDB): ".concat(new Date(y).toLocaleString()):"Local vault (IndexedDB): savingâ¦"})}),(0,a.jsx)("span",{className:"text-xs text-slate-600",children:"Overall progress"}),(0,a.jsx)("div",{className:"w-32 h-2 rounded-full bg-slate-200 overflow-hidden",children:(0,a.jsx)("div",{className:"h-full rounded-full bg-gradient-to-r from-[#4b6cb7] to-emerald-500 transition-all",style:{width:"".concat(T,"%")}})}),(0,a.jsxs)("span",{className:"text-xs text-slate-700 font-semibold",children:[T,"%"]})]})]}),(0,a.jsxs)("div",{className:"flex flex-col md:flex-row",children:[(0,a.jsxs)("aside",{className:"w-full md:w-72 border-r border-slate-200 bg-slate-50 p-4 max-h-[400px] md:max-h-none overflow-y-auto",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,a.jsx)("h3",{className:"text-sm font-semibold text-slate-800",children:"Tasks"}),(0,a.jsx)("span",{className:"text-xs text-slate-500",children:A.length})]}),0===A.length?(0,a.jsx)("div",{className:"text-center text-xs text-slate-500 py-8",children:"No tasks yet. Use âAdd Taskâ or âAdd Milestoneâ to get started."}):(0,a.jsx)("ul",{className:"space-y-2",children:A.map(e=>(0,a.jsxs)("li",{className:"bg-white rounded-md border border-slate-200 px-3 py-2 flex flex-col gap-1",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsxs)("span",{className:"text-sm font-medium text-slate-800",children:[e.name,e.isMilestone&&(0,a.jsx)("span",{className:"ml-2 inline-block rounded-full bg-emerald-100 text-emerald-700 text-[10px] px-2 py-0.5",children:"Milestone"})]}),(0,a.jsxs)("span",{className:"text-xs text-slate-500",children:[e.progress,"%"]})]}),(0,a.jsx)("div",{className:"text-xs text-slate-600",children:b(e)}),e.description&&(0,a.jsx)("div",{className:"text-[11px] text-slate-500 line-clamp-2",children:e.description}),(0,a.jsxs)("div",{className:"flex items-center gap-2 mt-1",children:[(0,a.jsx)("button",{type:"button",onClick:()=>{I(e),M(!0)},className:"text-xs text-blue-600 hover:underline",children:"Edit"}),(0,a.jsx)("button",{type:"button",onClick:()=>P(e.id),className:"text-xs text-red-600 hover:underline",children:"Delete"})]})]},e.id))})]}),(0,a.jsx)("section",{className:"flex-1 p-4 overflow-auto min-h-[280px]",children:0===A.length?(0,a.jsx)("div",{className:"text-center text-sm text-slate-500 py-12",children:"Once you add tasks, they will appear here in a timeline-friendly list you can print or export."}):(0,a.jsxs)("div",{className:"text-sm text-slate-700",children:[(0,a.jsxs)("div",{className:"flex flex-col gap-1 sm:flex-row sm:items-end sm:justify-between",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("p",{className:"font-semibold",children:"Timeline (Gantt view)"}),(0,a.jsx)("p",{className:"text-xs text-slate-500 mt-1",children:"Tasks are ordered by start date (nearest first). Milestones appear as diamonds. Bars scale to your date range."})]}),(0,a.jsxs)("div",{className:"flex items-center gap-2 text-xs text-slate-600 mt-2 sm:mt-0",children:[(0,a.jsxs)("span",{className:"inline-flex items-center gap-1",children:[(0,a.jsx)("span",{className:"inline-block w-3 h-3 rounded-sm bg-[#4b6cb7]"})," Task"]}),(0,a.jsxs)("span",{className:"inline-flex items-center gap-1",children:[(0,a.jsx)("span",{className:"inline-block w-3 h-3 rotate-45 bg-[#f97316]"})," Milestone"]})]})]}),E?(0,a.jsxs)("div",{className:"mt-4 rounded-lg border border-slate-200 overflow-hidden",children:[(0,a.jsxs)("div",{className:"bg-slate-50 border-b border-slate-200 px-4 py-2",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsxs)("p",{className:"text-xs font-semibold text-slate-700",children:[E.start.toLocaleDateString()," â ",E.end.toLocaleDateString()," (",E.spanDays," ","days)"]}),(0,a.jsx)("p",{className:"text-[11px] text-slate-500",children:"Tip: use âSave to deviceâ for backups"})]}),(0,a.jsx)("div",{className:"relative mt-2 h-6",children:E.ticks.map((e,t)=>(0,a.jsxs)("div",{className:"absolute top-0 h-6",style:{left:"".concat(100*e.t,"%")},children:[(0,a.jsx)("div",{className:"h-6 border-l border-slate-300/70"}),(0,a.jsx)("div",{className:"-translate-x-1/2 text-[10px] text-slate-500
1whitespace-nowrap",children:e.label})]},t))})]}),(0,a.jsx)("div",{className:"divide-y divide-slate-100",children:A.map(e=>{var t;let s=p(e.start),l=null!==(t=p(e.end))&&void 0!==t?t:s;if(!s||!l)return null;let r=E.end.getTime()-E.start.getTime(),n=0===r?0:(s.getTime()-E.start.getTime())/r*100,i=0===r?0:(l.getTime()-E.start.getTime())/r*100,o=h(n,0,100),d=h(i,0,100),c=h(d-o,e.isMilestone?1:2,100);return(0,a.jsxs)("div",{className:"px-4 py-3",children:[(0,a.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,a.jsxs)("div",{className:"min-w-0",children:[(0,a.jsx)("p",{className:"text-sm font-semibold text-slate-900 truncate",children:e.name}),(0,a.jsx)("p",{className:"text-[11px] text-slate-500 mt-0.5",children:b(e)})]}),(0,a.jsxs)("div",{className:"text-[11px] text-slate-600 flex items-center gap-2 shrink-0",children:[(0,a.jsxs)("span",{className:"font-semibold",children:[e.progress,"%"]}),(0,a.jsx)("span",{className:"text-slate-400",children:"â¢"}),(0,a.jsx)("span",{className:"uppercase tracking-wide",children:e.isMilestone?"Milestone":"Task"})]})]}),(0,a.jsxs)("div",{className:"mt-2 relative h-8 rounded-md bg-slate-100 overflow-hidden",children:[(0,a.jsx)("div",{className:"absolute inset-0 bg-[linear-gradient(to_right,rgba(0,0,0,0)_0%,rgba(0,0,0,0)_9.5%,rgba(15,23,42,0.06)_10%,rgba(0,0,0,0)_10.5%)] bg-[length:10%_100%]"}),e.isMilestone?(0,a.jsx)("div",{className:"absolute top-1/2 -translate-y-1/2 w-3.5 h-3.5 rotate-45 shadow-sm",style:{left:"calc(".concat(o,"% - 7px)"),backgroundColor:e.color||"#f97316"},title:"".concat(e.name," (").concat(e.start,")")}):(0,a.jsx)("div",{className:"absolute top-1/2 -translate-y-1/2 h-4 rounded-md shadow-sm",style:{left:"".concat(o,"%"),width:"".concat(c,"%"),backgroundColor:e.color||"#4b6cb7"},title:"".concat(e.name," (").concat(e.start," â ").concat(e.end,")"),children:(0,a.jsx)("div",{className:"h-full rounded-md bg-white/25",style:{width:"".concat(h(e.progress,0,100),"%")}})})]})]},e.id)})})]}):(0,a.jsx)("div",{className:"mt-4 rounded-lg border border-slate-200 bg-slate-50 p-4 text-sm text-slate-700",children:"Add valid start/end dates to render a timeline."})]})})]}),S&&D&&(0,a.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:(0,a.jsxs)("div",{className:"bg-white rounded-lg shadow-lg p-4 w-full max-w-md",children:[(0,a.jsx)("h3",{className:"text-sm font-semibold mb-3",children:D.isMilestone?"Edit milestone":"Edit task"}),(0,a.jsxs)("div",{className:"space-y-3 text-xs text-slate-700",children:[(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{children:"Title"}),(0,a.jsx)("input",{type:"text",className:"mt-1 w-full border border-slate-300 rounded px-2 py-1 text-sm",value:D.name,onChange:e=>I(t=>t?{...t,name:e.target.value}:t)})]}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsxs)("label",{className:"block flex-1",children:[(0,a.jsx)("span",{children:"Start date"}),(0,a.jsx)("input",{type:"date",className:"mt-1 w-full border border-slate-300 rounded px-2 py-1 text-sm",value:D.start,onChange:e=>I(t=>t?{...t,start:e.target.value}:t)})]}),(0,a.jsxs)("label",{className:"block flex-1",children:[(0,a.jsx)("span",{children:"End date"}),(0,a.jsx)("input",{type:"date",className:"mt-1 w-full border border-slate-300 rounded px-2 py-1 text-sm",value:D.end,onChange:e=>I(t=>t?{...t,end:e.target.value}:t)})]})]}),!D.isMilestone&&(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{children:"Bar colour"}),(0,a.jsx)("input",{type:"color",className:"mt-1 h-9 w-16 border border-slate-300 rounded",value:D.color||"#4b6cb7",onChange:e=>I(t=>t?{...t,color:e.target.value}:t),"aria-label":"Choose task colour"})]}),!D.isMilestone&&(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{children:"Progress (%)"}),(0,a.jsx)("input",{type:"number",min:0,max:100,className:"mt-1 w-full border border-slate-300 rounded px-2 py-1 text-sm",value:D.progress,onChange:e=>I(t=>t?{...t,progress:Number(e.target.value)||0}:t)})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{children:"Description (optional)"}),(0,a.jsx)("textarea",{className:"mt-1 w-full border border-slate-300 rounded px-2 py-1 text-sm min-h-[60
1px]",value:D.description,onChange:e=>I(t=>t?{...t,description:e.target.value}:t)})]})]}),(0,a.jsxs)("div",{className:"flex justify-end gap-2 mt-4",children:[(0,a.jsx)("button",{type:"button",onClick:()=>{M(!1),I(null)},className:"px-3 py-1.5 text-xs rounded border border-slate-300 text-slate-700",children:"Cancel"}),(0,a.jsx)("button",{type:"button",onClick:()=>{D&&O(D)},className:"px-3 py-1.5 text-xs rounded bg-[#4b6cb7] text-white",children:"Save"})]})]})})]})}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.