@burdenoff/microfe-planmagnet 2026.1002.1 → 2026.1002.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/dist/generated/wspace-operations.d.ts +2533 -546
  2. package/dist/generated/wspace-operations.d.ts.map +1 -1
  3. package/dist/generated/wspace-types.d.ts +5654 -71
  4. package/dist/generated/wspace-types.d.ts.map +1 -1
  5. package/dist/index.js +8 -8
  6. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  7. package/dist/planmagnet/PlanMagnetRoot.js +180 -162
  8. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  9. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  10. package/dist/planmagnet/PlanMagnetRoutes.js +100 -84
  11. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  12. package/dist/planmagnet/board/BulkActions.d.ts.map +1 -1
  13. package/dist/planmagnet/board/BulkActions.js +106 -55
  14. package/dist/planmagnet/board/BulkActions.js.map +1 -1
  15. package/dist/planmagnet/controls/Pickers.d.ts +10 -5
  16. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
  17. package/dist/planmagnet/controls/Pickers.js +10 -9
  18. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  19. package/dist/planmagnet/dashboards/DashboardUI.d.ts +0 -4
  20. package/dist/planmagnet/dashboards/DashboardUI.d.ts.map +1 -1
  21. package/dist/planmagnet/dashboards/DashboardUI.js +6 -13
  22. package/dist/planmagnet/dashboards/DashboardUI.js.map +1 -1
  23. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
  24. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +70 -59
  25. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
  26. package/dist/planmagnet/forecast/ResourceForecastCard.js +1 -1
  27. package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -1
  28. package/dist/planmagnet/index.d.ts +1 -1
  29. package/dist/planmagnet/index.d.ts.map +1 -1
  30. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts +3 -3
  31. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts.map +1 -1
  32. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js +26 -19
  33. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js.map +1 -1
  34. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts +2 -2
  35. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts.map +1 -1
  36. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js +18 -12
  37. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js.map +1 -1
  38. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts +2 -0
  39. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts.map +1 -0
  40. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js +251 -0
  41. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js.map +1 -0
  42. package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js +4 -4
  43. package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js.map +1 -1
  44. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  45. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +133 -131
  46. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  47. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  48. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +5 -5
  49. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  50. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +6 -6
  51. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
  52. package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
  53. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +107 -82
  54. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
  55. package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.d.ts +2 -0
  56. package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.d.ts.map +1 -0
  57. package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.js +174 -0
  58. package/dist/planmagnet/pages/ProductsProductFeatureDetailPagePage.js.map +1 -0
  59. package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.d.ts +2 -0
  60. package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.d.ts.map +1 -0
  61. package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.js +350 -0
  62. package/dist/planmagnet/pages/ProductsProductHierarchyPagePage.js.map +1 -0
  63. package/dist/planmagnet/pages/ProductsProductLinesPagePage.d.ts +2 -0
  64. package/dist/planmagnet/pages/ProductsProductLinesPagePage.d.ts.map +1 -0
  65. package/dist/planmagnet/pages/ProductsProductLinesPagePage.js +168 -0
  66. package/dist/planmagnet/pages/ProductsProductLinesPagePage.js.map +1 -0
  67. package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -1
  68. package/dist/planmagnet/pages/ProductsProductsPagePage.js +1 -1
  69. package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -1
  70. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
  71. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +116 -114
  72. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
  73. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  74. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +174 -159
  75. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  76. package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
  77. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +159 -145
  78. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
  79. package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
  80. package/dist/planmagnet/pages/TasksEditTaskPagePage.js +161 -143
  81. package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
  82. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  83. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +160 -156
  84. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  85. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.d.ts.map +1 -1
  86. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +97 -99
  87. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js.map +1 -1
  88. package/dist/planmagnet/product/FeatureLinkPanels.d.ts +29 -0
  89. package/dist/planmagnet/product/FeatureLinkPanels.d.ts.map +1 -0
  90. package/dist/planmagnet/product/FeatureLinkPanels.js +373 -0
  91. package/dist/planmagnet/product/FeatureLinkPanels.js.map +1 -0
  92. package/dist/planmagnet/product/ProductControls.js +1 -1
  93. package/dist/planmagnet/product/ProductControls.js.map +1 -1
  94. package/dist/planmagnet/product/ProductFeatureControls.d.ts +39 -0
  95. package/dist/planmagnet/product/ProductFeatureControls.d.ts.map +1 -0
  96. package/dist/planmagnet/product/ProductFeatureControls.js +315 -0
  97. package/dist/planmagnet/product/ProductFeatureControls.js.map +1 -0
  98. package/dist/planmagnet/product/ProductFeatureLinkCard.d.ts +4 -0
  99. package/dist/planmagnet/product/ProductFeatureLinkCard.d.ts.map +1 -0
  100. package/dist/planmagnet/product/ProductFeatureLinkCard.js +192 -0
  101. package/dist/planmagnet/product/ProductFeatureLinkCard.js.map +1 -0
  102. package/dist/planmagnet/product/ProductLineControls.d.ts +52 -0
  103. package/dist/planmagnet/product/ProductLineControls.d.ts.map +1 -0
  104. package/dist/planmagnet/product/ProductLineControls.js +417 -0
  105. package/dist/planmagnet/product/ProductLineControls.js.map +1 -0
  106. package/dist/planmagnet/product/ProductTeamsPanel.d.ts +4 -0
  107. package/dist/planmagnet/product/ProductTeamsPanel.d.ts.map +1 -0
  108. package/dist/planmagnet/product/ProductTeamsPanel.js +129 -0
  109. package/dist/planmagnet/product/ProductTeamsPanel.js.map +1 -0
  110. package/dist/planmagnet/product/WorkItemProductFeatureChip.d.ts +4 -0
  111. package/dist/planmagnet/product/WorkItemProductFeatureChip.d.ts.map +1 -0
  112. package/dist/planmagnet/product/WorkItemProductFeatureChip.js +41 -0
  113. package/dist/planmagnet/product/WorkItemProductFeatureChip.js.map +1 -0
  114. package/dist/planmagnet/product/hierarchy.d.ts +127 -0
  115. package/dist/planmagnet/product/hierarchy.d.ts.map +1 -0
  116. package/dist/planmagnet/product/hierarchy.js +173 -0
  117. package/dist/planmagnet/product/hierarchy.js.map +1 -0
  118. package/dist/planmagnet/product/hierarchyOperations.d.ts +35 -0
  119. package/dist/planmagnet/product/hierarchyOperations.d.ts.map +1 -0
  120. package/dist/planmagnet/product/hierarchyOperations.js +440 -0
  121. package/dist/planmagnet/product/hierarchyOperations.js.map +1 -0
  122. package/dist/planmagnet/product/refusal.d.ts +14 -0
  123. package/dist/planmagnet/product/refusal.d.ts.map +1 -0
  124. package/dist/planmagnet/product/refusal.js +10 -0
  125. package/dist/planmagnet/product/refusal.js.map +1 -0
  126. package/dist/planmagnet/product/routes.d.ts +10 -0
  127. package/dist/planmagnet/product/routes.d.ts.map +1 -1
  128. package/dist/planmagnet/product/routes.js +2 -2
  129. package/dist/planmagnet/product/routes.js.map +1 -1
  130. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts +20 -0
  131. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts.map +1 -0
  132. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js +55 -0
  133. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js.map +1 -0
  134. package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts +30 -0
  135. package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts.map +1 -0
  136. package/dist/planmagnet/satisfaction/SatisfactionFigures.js +282 -0
  137. package/dist/planmagnet/satisfaction/SatisfactionFigures.js.map +1 -0
  138. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts +9 -0
  139. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts.map +1 -0
  140. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js +390 -0
  141. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js.map +1 -0
  142. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts +17 -0
  143. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts.map +1 -0
  144. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js +77 -0
  145. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js.map +1 -0
  146. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts +18 -0
  147. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts.map +1 -0
  148. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js +87 -0
  149. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js.map +1 -0
  150. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts +13 -0
  151. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts.map +1 -0
  152. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js +326 -0
  153. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js.map +1 -0
  154. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts +23 -0
  155. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts.map +1 -0
  156. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js +258 -0
  157. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js.map +1 -0
  158. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts +6 -0
  159. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts.map +1 -0
  160. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js +56 -0
  161. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js.map +1 -0
  162. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts +16 -0
  163. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts.map +1 -0
  164. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js +102 -0
  165. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js.map +1 -0
  166. package/dist/planmagnet/satisfaction/satisfaction.d.ts +154 -0
  167. package/dist/planmagnet/satisfaction/satisfaction.d.ts.map +1 -0
  168. package/dist/planmagnet/satisfaction/satisfaction.js +210 -0
  169. package/dist/planmagnet/satisfaction/satisfaction.js.map +1 -0
  170. package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts +108 -0
  171. package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts.map +1 -0
  172. package/dist/planmagnet/satisfaction/satisfactionCsv.js +211 -0
  173. package/dist/planmagnet/satisfaction/satisfactionCsv.js.map +1 -0
  174. package/dist/planmagnet/satisfaction/satisfactionForm.d.ts +90 -0
  175. package/dist/planmagnet/satisfaction/satisfactionForm.d.ts.map +1 -0
  176. package/dist/planmagnet/satisfaction/satisfactionForm.js +90 -0
  177. package/dist/planmagnet/satisfaction/satisfactionForm.js.map +1 -0
  178. package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts +116 -0
  179. package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts.map +1 -0
  180. package/dist/planmagnet/satisfaction/satisfactionOperations.js +86 -0
  181. package/dist/planmagnet/satisfaction/satisfactionOperations.js.map +1 -0
  182. package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts +20 -0
  183. package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts.map +1 -0
  184. package/dist/planmagnet/satisfaction/useSatisfactionAccess.js +31 -0
  185. package/dist/planmagnet/satisfaction/useSatisfactionAccess.js.map +1 -0
  186. package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts +35 -0
  187. package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts.map +1 -0
  188. package/dist/planmagnet/skills/RequiredSkillsEditor.js +124 -0
  189. package/dist/planmagnet/skills/RequiredSkillsEditor.js.map +1 -0
  190. package/dist/planmagnet/skills/SkillChips.d.ts +30 -0
  191. package/dist/planmagnet/skills/SkillChips.d.ts.map +1 -0
  192. package/dist/planmagnet/skills/SkillChips.js +57 -0
  193. package/dist/planmagnet/skills/SkillChips.js.map +1 -0
  194. package/dist/planmagnet/skills/SkillCoverageCard.d.ts +24 -0
  195. package/dist/planmagnet/skills/SkillCoverageCard.d.ts.map +1 -0
  196. package/dist/planmagnet/skills/SkillCoverageCard.js +256 -0
  197. package/dist/planmagnet/skills/SkillCoverageCard.js.map +1 -0
  198. package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts +10 -0
  199. package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts.map +1 -0
  200. package/dist/planmagnet/skills/WorkItemRequiredSkills.js +65 -0
  201. package/dist/planmagnet/skills/WorkItemRequiredSkills.js.map +1 -0
  202. package/dist/planmagnet/skills/skillOperations.d.ts +52 -0
  203. package/dist/planmagnet/skills/skillOperations.d.ts.map +1 -0
  204. package/dist/planmagnet/skills/skillOperations.js +44 -0
  205. package/dist/planmagnet/skills/skillOperations.js.map +1 -0
  206. package/dist/planmagnet/skills/skillTags.d.ts +103 -0
  207. package/dist/planmagnet/skills/skillTags.d.ts.map +1 -0
  208. package/dist/planmagnet/skills/skillTags.js +115 -0
  209. package/dist/planmagnet/skills/skillTags.js.map +1 -0
  210. package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts +28 -0
  211. package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts.map +1 -0
  212. package/dist/planmagnet/skills/useRequiredSkillsDraft.js +30 -0
  213. package/dist/planmagnet/skills/useRequiredSkillsDraft.js.map +1 -0
  214. package/dist/shared/utils/i18n.d.ts +3 -0
  215. package/dist/shared/utils/i18n.d.ts.map +1 -1
  216. package/dist/shared/utils/i18n.js +1 -1
  217. package/dist/shared/utils/i18n.js.map +1 -1
  218. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"TasksCreateTaskPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TasksCreateTaskPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, CheckSquare } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { MilestoneSelect } from '../milestones/MilestoneControls';\nimport { throwOnError } from '../utils/mutationResult';\nimport { parseEstimateHours, parseIntField } from '../utils/formValidation';\nimport { AssigneeSelect, WORK_ITEM_PRIORITIES } from '../controls/WorkItemControls';\n\ninterface PlanmagnetProjectOption {\n id: string;\n name: string;\n key: string;\n}\n\nconst CREATE_WORK_ITEM = gql`\n mutation CreateWorkItem($input: PlanmagnetCreateWorkItemInput!) {\n planmagnetCreateWorkItem(input: $input) {\n id\n title\n type\n status\n priority\n key\n storyPoints\n dueDate\n labels\n sprintId\n createdAt\n }\n }\n`;\n\n// BOFF-4442/4443 live-verify fix: a WorkItem must belong to a real project\n// (PlanmagnetCreateWorkItemInput.projectId is non-null); the form needs the\n// caller's actual projects to choose from rather than a free-text name.\nconst GET_PROJECTS = gql`\n query GetProjectsForTaskCreate($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n key\n }\n }\n }\n`;\n\n// Sprints of the chosen project that can still take work (BOFF-7962: this was a free-text \"Sprint ID\" box — the id\n// was only discoverable from a sprint URL, and a name or another project's id was refused).\nconst GET_SPRINTS = gql`\n query GetSprintsForTaskCreate($workspaceId: ID!, $projectId: String) {\n planmagnetSprints(\n workspaceId: $workspaceId\n filter: { projectId: $projectId }\n pagination: { first: 100 }\n ) {\n items {\n id\n name\n status\n }\n }\n }\n`;\nconst OPEN_SPRINT_STATUSES = new Set(['PLANNING', 'ACTIVE', 'REVIEW']);\n\nexport function TasksCreateTaskPagePage() {\n const { workspaceId } = usePlanMagnet();\n const [form, setForm] = useState({\n title: '',\n description: '',\n projectId: '',\n priority: 'MEDIUM',\n type: 'STORY',\n storyPoints: '5',\n labels: '',\n sprintId: '',\n milestoneId: '',\n assigneeId: '',\n dueDate: '',\n estimateHours: '',\n });\n\n const {\n data: projectsData,\n loading: projectsLoading,\n error: projectsError,\n refetch: refetchProjects,\n } = useQuery<{ planmagnetProjects?: { items: PlanmagnetProjectOption[] } }>(GET_PROJECTS, {\n variables: { workspaceId: workspaceId ?? 'default' },\n skip: !workspaceId,\n });\n const projects: PlanmagnetProjectOption[] = projectsData?.planmagnetProjects?.items ?? [];\n // Fall back to the first loaded project when the user hasn't picked one\n // yet, without stashing derived state in an effect (avoids the extra\n // render cycle and keeps a single source of truth: `projects`).\n const selectedProjectId = form.projectId || projects[0]?.id || '';\n const { data: sprintsData, loading: sprintsLoading } = useQuery<{\n planmagnetSprints?: { items: { id: string; name: string; status: string }[] };\n }>(GET_SPRINTS, {\n variables: { workspaceId: workspaceId ?? 'default', projectId: selectedProjectId },\n skip: !workspaceId || !selectedProjectId,\n });\n const openSprints = (sprintsData?.planmagnetSprints?.items ?? []).filter((s) =>\n OPEN_SPRINT_STATUSES.has(s.status)\n );\n\n const navigate = usePlanMagnetNavigate();\n const [createWorkItem, { loading: saving }] = useMutation(CREATE_WORK_ITEM, {\n refetchQueries: ['GetWorkItems'],\n });\n const [saveError, setSaveError] = useState<string | null>(null);\n // Story points are a whole number, 0 or more (BOFF-7833: prod accepted -3).\n const storyPoints = parseIntField(form.storyPoints, { min: 0 });\n const estimate = parseEstimateHours(form.estimateHours);\n\n const handleCreate = async () => {\n if (\n !form.title.trim() ||\n !selectedProjectId ||\n !workspaceId ||\n storyPoints.invalid ||\n estimate.invalid\n )\n return;\n setSaveError(null);\n // Success opens the new task; a refusal shows the service's reason (errorPolicy 'all' resolves refused\n // mutations, so the old code showed nothing either way).\n try {\n const result = await throwOnError(\n createWorkItem({\n variables: {\n input: {\n projectId: selectedProjectId,\n title: form.title,\n description: form.description || undefined,\n type: form.type,\n priority: form.priority,\n storyPoints: storyPoints.value,\n labels: form.labels\n ? form.labels\n .split(',')\n .map((l) => l.trim())\n .filter(Boolean)\n : undefined,\n sprintId: form.sprintId || undefined,\n milestoneId: form.milestoneId || undefined,\n assigneeId: form.assigneeId || undefined,\n dueDate: form.dueDate || undefined,\n estimateMinutes: estimate.minutes,\n },\n },\n })\n );\n const id = (result.data as { planmagnetCreateWorkItem?: { id: string } } | undefined)\n ?.planmagnetCreateWorkItem?.id;\n navigate(\n id ? `/tasks/task-detail-page?taskId=${encodeURIComponent(id)}` : '/tasks/tasks-page'\n );\n } catch (e) {\n setSaveError(e instanceof Error ? e.message : 'The task could not be created.');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Task</h1>\n <p className=\"text-sm text-muted-foreground\">Add a new task to the project backlog.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/tasks/tasks-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={handleCreate}\n disabled={\n saving ||\n !form.title.trim() ||\n !selectedProjectId ||\n storyPoints.invalid ||\n estimate.invalid\n }\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Creating...' : 'Create Task'}\n </Button>\n </div>\n </div>\n {saveError && (\n <div role=\"alert\" className=\"p-3 bg-destructive/10 text-destructive rounded-md text-sm\">\n {saveError}\n </div>\n )}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <CheckSquare className=\"h-4 w-4\" />\n Task Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Implement search query parser\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Describe the task requirements...\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Project</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedProjectId}\n // A sprint belongs to one project: changing the project clears the chosen sprint.\n onChange={(e) =>\n setForm({ ...form, projectId: e.target.value, sprintId: '', milestoneId: '' })\n }\n >\n {projects.length === 0 && (\n <option value=\"\" disabled>\n {projectsLoading && !projectsData\n ? 'Loading projects…'\n : projectsError\n ? 'Projects could not be loaded'\n : 'No projects yet'}\n </option>\n )}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.key} — {p.name}\n </option>\n ))}\n </select>\n {/* C2 (BOFF-7833): loading, failure and \"no projects\" are told apart. */}\n {projectsError && (\n <p role=\"alert\" className=\"mt-1 flex items-center gap-2 text-xs text-destructive\">\n {projectsError.message}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-6 px-2 text-xs\"\n onClick={() => void refetchProjects()}\n >\n Retry\n </Button>\n </p>\n )}\n {!projectsLoading && !projectsError && projectsData && projects.length === 0 && (\n <button\n type=\"button\"\n className=\"mt-1 text-xs text-muted-foreground underline\"\n onClick={() => navigate('/projects/create-project-page')}\n >\n Create a project first\n </button>\n )}\n </div>\n <div>\n <label className=\"text-sm font-medium\">Priority</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.priority}\n onChange={(e) => setForm({ ...form, priority: e.target.value })}\n >\n {WORK_ITEM_PRIORITIES.map((p) => (\n <option key={p} value={p}>\n {p.toLowerCase()}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Type</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.type}\n onChange={(e) => setForm({ ...form, type: e.target.value })}\n >\n {['STORY', 'BUG', 'TASK', 'EPIC', 'SUB_TASK'].map((t) => (\n <option key={t} value={t}>\n {t.toLowerCase().replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label htmlFor=\"task-story-points\" className=\"text-sm font-medium\">\n Story Points\n </label>\n <Input\n id=\"task-story-points\"\n type=\"number\"\n min={0}\n step={1}\n value={form.storyPoints}\n onChange={(e) => setForm({ ...form, storyPoints: e.target.value })}\n aria-invalid={storyPoints.invalid}\n className=\"mt-1\"\n />\n {storyPoints.invalid && (\n <p role=\"alert\" className=\"mt-1 text-xs text-destructive\">\n Story points must be a whole number, 0 or more.\n </p>\n )}\n </div>\n <div>\n <label htmlFor=\"task-milestone\" className=\"text-sm font-medium\">\n Milestone\n </label>\n <MilestoneSelect\n id=\"task-milestone\"\n projectId={selectedProjectId}\n value={form.milestoneId}\n onChange={(milestoneId) => setForm({ ...form, milestoneId })}\n />\n </div>\n <div>\n <label htmlFor=\"task-sprint\" className=\"text-sm font-medium\">\n Sprint\n </label>\n <select\n id=\"task-sprint\"\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.sprintId}\n onChange={(e) => setForm({ ...form, sprintId: e.target.value })}\n >\n <option value=\"\">\n {sprintsLoading && !sprintsData ? 'Loading sprints…' : 'No sprint'}\n </option>\n {openSprints.map((s) => (\n <option key={s.id} value={s.id}>\n {s.name} ({s.status.toLowerCase()})\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Due Date</label>\n <Input\n type=\"date\"\n value={form.dueDate}\n onChange={(e) => setForm({ ...form, dueDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label htmlFor=\"task-estimate-hours\" className=\"text-sm font-medium\">\n Estimate (hours)\n </label>\n <Input\n id=\"task-estimate-hours\"\n type=\"number\"\n min={0}\n step={0.25}\n value={form.estimateHours}\n onChange={(e) => setForm({ ...form, estimateHours: e.target.value })}\n aria-invalid={estimate.invalid}\n aria-describedby=\"task-estimate-hint\"\n className=\"mt-1\"\n />\n {estimate.invalid ? (\n <p role=\"alert\" className=\"mt-1 text-xs text-destructive\">\n The estimate must be a number of hours, 0 or more.\n </p>\n ) : (\n <p id=\"task-estimate-hint\" className=\"mt-1 text-xs text-muted-foreground\">\n Used as the task&apos;s duration on the critical path.\n </p>\n )}\n </div>\n </div>\n <div>\n <label htmlFor=\"task-assignee\" className=\"text-sm font-medium\">\n Assignee\n </label>\n <div className=\"mt-1\">\n <AssigneeSelect\n id=\"task-assignee\"\n value={form.assigneeId}\n onChange={(assigneeId) => setForm({ ...form, assigneeId })}\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Labels (comma-separated)</label>\n <Input\n value={form.labels}\n onChange={(e) => setForm({ ...form, labels: e.target.value })}\n className=\"mt-1\"\n placeholder=\"backend, search, performance\"\n />\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TasksCreateTaskPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TasksCreateTaskPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, CheckSquare } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { MilestoneSelect } from '../milestones/MilestoneControls';\nimport { throwOnError } from '../utils/mutationResult';\nimport { parseEstimateHours, parseIntField } from '../utils/formValidation';\nimport { AssigneeSelect, WORK_ITEM_PRIORITIES } from '../controls/WorkItemControls';\nimport { RequiredSkillsField } from '../skills/RequiredSkillsEditor';\nimport { requiredSkillsRefusal } from '../skills/skillTags';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface PlanmagnetProjectOption {\n id: string;\n name: string;\n key: string;\n}\n\nconst CREATE_WORK_ITEM = gql`\n mutation CreateWorkItem($input: PlanmagnetCreateWorkItemInput!) {\n planmagnetCreateWorkItem(input: $input) {\n id\n title\n type\n status\n priority\n key\n storyPoints\n dueDate\n labels\n sprintId\n createdAt\n }\n }\n`;\n\n// BOFF-4442/4443 live-verify fix: a WorkItem must belong to a real project\n// (PlanmagnetCreateWorkItemInput.projectId is non-null); the form needs the\n// caller's actual projects to choose from rather than a free-text name.\nconst GET_PROJECTS = gql`\n query GetProjectsForTaskCreate($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n key\n }\n }\n }\n`;\n\n// Sprints of the chosen project that can still take work (BOFF-7962: this was a free-text \"Sprint ID\" box — the id\n// was only discoverable from a sprint URL, and a name or another project's id was refused).\nconst GET_SPRINTS = gql`\n query GetSprintsForTaskCreate($workspaceId: ID!, $projectId: String) {\n planmagnetSprints(\n workspaceId: $workspaceId\n filter: { projectId: $projectId }\n pagination: { first: 100 }\n ) {\n items {\n id\n name\n status\n }\n }\n }\n`;\nconst OPEN_SPRINT_STATUSES = new Set(['PLANNING', 'ACTIVE', 'REVIEW']);\n\nexport function TasksCreateTaskPagePage() {\n const { workspaceId } = usePlanMagnet();\n const tr = useTr();\n const [form, setForm] = useState({\n title: '',\n description: '',\n projectId: '',\n priority: 'MEDIUM',\n type: 'STORY',\n storyPoints: '5',\n labels: '',\n sprintId: '',\n milestoneId: '',\n assigneeId: '',\n dueDate: '',\n estimateHours: '',\n });\n\n const {\n data: projectsData,\n loading: projectsLoading,\n error: projectsError,\n refetch: refetchProjects,\n } = useQuery<{ planmagnetProjects?: { items: PlanmagnetProjectOption[] } }>(GET_PROJECTS, {\n variables: { workspaceId: workspaceId ?? 'default' },\n skip: !workspaceId,\n });\n const projects: PlanmagnetProjectOption[] = projectsData?.planmagnetProjects?.items ?? [];\n // Fall back to the first loaded project when the user hasn't picked one\n // yet, without stashing derived state in an effect (avoids the extra\n // render cycle and keeps a single source of truth: `projects`).\n const selectedProjectId = form.projectId || projects[0]?.id || '';\n const { data: sprintsData, loading: sprintsLoading } = useQuery<{\n planmagnetSprints?: { items: { id: string; name: string; status: string }[] };\n }>(GET_SPRINTS, {\n variables: { workspaceId: workspaceId ?? 'default', projectId: selectedProjectId },\n skip: !workspaceId || !selectedProjectId,\n });\n const openSprints = (sprintsData?.planmagnetSprints?.items ?? []).filter((s) =>\n OPEN_SPRINT_STATUSES.has(s.status)\n );\n\n const navigate = usePlanMagnetNavigate();\n const [createWorkItem, { loading: saving }] = useMutation(CREATE_WORK_ITEM, {\n refetchQueries: ['GetWorkItems'],\n });\n const [saveError, setSaveError] = useState<string | null>(null);\n // ANR-07/ANR-28: the skills this task needs, sent only when there are some; a refusal of them shows on the field.\n const [requiredSkills, setRequiredSkills] = useState<string[]>([]);\n const [skillsError, setSkillsError] = useState<string | null>(null);\n // Story points are a whole number, 0 or more (BOFF-7833: prod accepted -3).\n const storyPoints = parseIntField(form.storyPoints, { min: 0 });\n const estimate = parseEstimateHours(form.estimateHours);\n\n const handleCreate = async () => {\n if (\n !form.title.trim() ||\n !selectedProjectId ||\n !workspaceId ||\n storyPoints.invalid ||\n estimate.invalid\n )\n return;\n setSaveError(null);\n setSkillsError(null);\n // Success opens the new task; a refusal shows the service's reason (errorPolicy 'all' resolves refused\n // mutations, so the old code showed nothing either way).\n try {\n const result = await throwOnError(\n createWorkItem({\n variables: {\n input: {\n projectId: selectedProjectId,\n title: form.title,\n description: form.description || undefined,\n type: form.type,\n priority: form.priority,\n storyPoints: storyPoints.value,\n labels: form.labels\n ? form.labels\n .split(',')\n .map((l) => l.trim())\n .filter(Boolean)\n : undefined,\n sprintId: form.sprintId || undefined,\n milestoneId: form.milestoneId || undefined,\n assigneeId: form.assigneeId || undefined,\n dueDate: form.dueDate || undefined,\n estimateMinutes: estimate.minutes,\n requiredSkills: requiredSkills.length > 0 ? requiredSkills : undefined,\n },\n },\n })\n );\n const id = (result.data as { planmagnetCreateWorkItem?: { id: string } } | undefined)\n ?.planmagnetCreateWorkItem?.id;\n navigate(\n id ? `/tasks/task-detail-page?taskId=${encodeURIComponent(id)}` : '/tasks/tasks-page'\n );\n } catch (e) {\n const skillsRefusal = requiredSkillsRefusal(e);\n if (skillsRefusal) {\n setSkillsError(skillsRefusal);\n setSaveError(\n tr(\n 'planmagnet.skills.editor.createRefused',\n 'The task was not created: see Required skills below.'\n )\n );\n } else {\n setSaveError(e instanceof Error ? e.message : 'The task could not be created.');\n }\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Task</h1>\n <p className=\"text-sm text-muted-foreground\">Add a new task to the project backlog.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/tasks/tasks-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={handleCreate}\n disabled={\n saving ||\n !form.title.trim() ||\n !selectedProjectId ||\n storyPoints.invalid ||\n estimate.invalid\n }\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Creating...' : 'Create Task'}\n </Button>\n </div>\n </div>\n {saveError && (\n <div role=\"alert\" className=\"p-3 bg-destructive/10 text-destructive rounded-md text-sm\">\n {saveError}\n </div>\n )}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <CheckSquare className=\"h-4 w-4\" />\n Task Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Implement search query parser\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Describe the task requirements...\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Project</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedProjectId}\n // A sprint belongs to one project: changing the project clears the chosen sprint.\n onChange={(e) =>\n setForm({ ...form, projectId: e.target.value, sprintId: '', milestoneId: '' })\n }\n >\n {projects.length === 0 && (\n <option value=\"\" disabled>\n {projectsLoading && !projectsData\n ? 'Loading projects…'\n : projectsError\n ? 'Projects could not be loaded'\n : 'No projects yet'}\n </option>\n )}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.key} — {p.name}\n </option>\n ))}\n </select>\n {/* C2 (BOFF-7833): loading, failure and \"no projects\" are told apart. */}\n {projectsError && (\n <p role=\"alert\" className=\"mt-1 flex items-center gap-2 text-xs text-destructive\">\n {projectsError.message}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-6 px-2 text-xs\"\n onClick={() => void refetchProjects()}\n >\n Retry\n </Button>\n </p>\n )}\n {!projectsLoading && !projectsError && projectsData && projects.length === 0 && (\n <button\n type=\"button\"\n className=\"mt-1 text-xs text-muted-foreground underline\"\n onClick={() => navigate('/projects/create-project-page')}\n >\n Create a project first\n </button>\n )}\n </div>\n <div>\n <label className=\"text-sm font-medium\">Priority</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.priority}\n onChange={(e) => setForm({ ...form, priority: e.target.value })}\n >\n {WORK_ITEM_PRIORITIES.map((p) => (\n <option key={p} value={p}>\n {p.toLowerCase()}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Type</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.type}\n onChange={(e) => setForm({ ...form, type: e.target.value })}\n >\n {['STORY', 'BUG', 'TASK', 'EPIC', 'SUB_TASK'].map((t) => (\n <option key={t} value={t}>\n {t.toLowerCase().replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label htmlFor=\"task-story-points\" className=\"text-sm font-medium\">\n Story Points\n </label>\n <Input\n id=\"task-story-points\"\n type=\"number\"\n min={0}\n step={1}\n value={form.storyPoints}\n onChange={(e) => setForm({ ...form, storyPoints: e.target.value })}\n aria-invalid={storyPoints.invalid}\n className=\"mt-1\"\n />\n {storyPoints.invalid && (\n <p role=\"alert\" className=\"mt-1 text-xs text-destructive\">\n Story points must be a whole number, 0 or more.\n </p>\n )}\n </div>\n <div>\n <label htmlFor=\"task-milestone\" className=\"text-sm font-medium\">\n Milestone\n </label>\n <MilestoneSelect\n id=\"task-milestone\"\n projectId={selectedProjectId}\n value={form.milestoneId}\n onChange={(milestoneId) => setForm({ ...form, milestoneId })}\n />\n </div>\n <div>\n <label htmlFor=\"task-sprint\" className=\"text-sm font-medium\">\n Sprint\n </label>\n <select\n id=\"task-sprint\"\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.sprintId}\n onChange={(e) => setForm({ ...form, sprintId: e.target.value })}\n >\n <option value=\"\">\n {sprintsLoading && !sprintsData ? 'Loading sprints…' : 'No sprint'}\n </option>\n {openSprints.map((s) => (\n <option key={s.id} value={s.id}>\n {s.name} ({s.status.toLowerCase()})\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Due Date</label>\n <Input\n type=\"date\"\n value={form.dueDate}\n onChange={(e) => setForm({ ...form, dueDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label htmlFor=\"task-estimate-hours\" className=\"text-sm font-medium\">\n Estimate (hours)\n </label>\n <Input\n id=\"task-estimate-hours\"\n type=\"number\"\n min={0}\n step={0.25}\n value={form.estimateHours}\n onChange={(e) => setForm({ ...form, estimateHours: e.target.value })}\n aria-invalid={estimate.invalid}\n aria-describedby=\"task-estimate-hint\"\n className=\"mt-1\"\n />\n {estimate.invalid ? (\n <p role=\"alert\" className=\"mt-1 text-xs text-destructive\">\n The estimate must be a number of hours, 0 or more.\n </p>\n ) : (\n <p id=\"task-estimate-hint\" className=\"mt-1 text-xs text-muted-foreground\">\n Used as the task&apos;s duration on the critical path.\n </p>\n )}\n </div>\n </div>\n <div>\n <label htmlFor=\"task-assignee\" className=\"text-sm font-medium\">\n Assignee\n </label>\n <div className=\"mt-1\">\n <AssigneeSelect\n id=\"task-assignee\"\n value={form.assigneeId}\n onChange={(assigneeId) => setForm({ ...form, assigneeId })}\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Labels (comma-separated)</label>\n <Input\n value={form.labels}\n onChange={(e) => setForm({ ...form, labels: e.target.value })}\n className=\"mt-1\"\n placeholder=\"backend, search, performance\"\n />\n </div>\n <RequiredSkillsField\n id=\"task-required-skills\"\n value={requiredSkills}\n onChange={(next) => {\n setRequiredSkills(next);\n setSkillsError(null);\n }}\n disabled={saving}\n serverError={skillsError}\n />\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TasksEditTaskPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksEditTaskPagePage.tsx"],"names":[],"mappings":"AA0EA,wBAAgB,qBAAqB,4CAsSpC"}
1
+ {"version":3,"file":"TasksEditTaskPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksEditTaskPagePage.tsx"],"names":[],"mappings":"AA8EA,wBAAgB,qBAAqB,4CAsUpC"}
@@ -1,16 +1,20 @@
1
1
  import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
2
- import { throwOnError as n } from "../utils/mutationResult.js";
3
- import { WORK_ITEM_PRIORITIES as r } from "../controls/WorkItemControls.js";
4
- import { estimateHoursText as i, parseEstimateHours as a, parseIntField as o } from "../utils/formValidation.js";
5
- import { MilestoneSelect as s } from "../milestones/MilestoneControls.js";
6
- import { useMemo as c, useState as l } from "react";
7
- import { ArrowLeft as u, Save as d } from "lucide-react";
8
- import { gql as f } from "@apollo/client";
9
- import { useMutation as p, useQuery as m } from "@apollo/client/react";
10
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
11
- import { Button as _, Card as v, CardContent as y, CardHeader as b, CardTitle as x, Input as S } from "@burdenoff/fe-libs/ui";
2
+ import { useTr as n } from "../../shared/hooks/useTr.js";
3
+ import { throwOnError as r } from "../utils/mutationResult.js";
4
+ import { WORK_ITEM_PRIORITIES as i } from "../controls/WorkItemControls.js";
5
+ import { estimateHoursText as a, parseEstimateHours as o, parseIntField as s } from "../utils/formValidation.js";
6
+ import { requiredSkillsRefusal as c } from "../skills/skillTags.js";
7
+ import { MilestoneSelect as l } from "../milestones/MilestoneControls.js";
8
+ import { RequiredSkillsField as u } from "../skills/RequiredSkillsEditor.js";
9
+ import { useRequiredSkillsDraft as d } from "../skills/useRequiredSkillsDraft.js";
10
+ import { useMemo as f, useState as p } from "react";
11
+ import { ArrowLeft as m, Save as h } from "lucide-react";
12
+ import { gql as g } from "@apollo/client";
13
+ import { useMutation as _, useQuery as v } from "@apollo/client/react";
14
+ import { jsx as y, jsxs as b } from "react/jsx-runtime";
15
+ import { Button as x, Card as S, CardContent as C, CardHeader as w, CardTitle as T, Input as E } from "@burdenoff/fe-libs/ui";
12
16
  //#region src/planmagnet/pages/TasksEditTaskPagePage.tsx
13
- var C = f`
17
+ var D = g`
14
18
  query GetWorkItem($workItemId: ID!) {
15
19
  planmagnetWorkItem(id: $workItemId) {
16
20
  id
@@ -31,7 +35,7 @@ var C = f`
31
35
  updatedAt
32
36
  }
33
37
  }
34
- `, w = f`
38
+ `, O = g`
35
39
  mutation UpdateWorkItem($workItemId: ID!, $input: PlanmagnetUpdateWorkItemInput!) {
36
40
  planmagnetUpdateWorkItem(id: $workItemId, input: $input) {
37
41
  id
@@ -49,172 +53,177 @@ var C = f`
49
53
  }
50
54
  }
51
55
  `;
52
- function T() {
53
- let { workspaceId: f } = e(), T = new URLSearchParams(window.location.search).get("taskId") ?? "", E = t(), { data: D, loading: O, error: k } = m(C, {
54
- variables: { workItemId: T },
55
- skip: !f || !T
56
- }), [A, { loading: j }] = p(w, {
56
+ function k() {
57
+ let { workspaceId: g } = e(), k = new URLSearchParams(window.location.search).get("taskId") ?? "", A = t(), j = n(), { data: M, loading: N, error: P } = v(D, {
58
+ variables: { workItemId: k },
59
+ skip: !g || !k
60
+ }), F = d(k, !g), [I, { loading: L }] = _(O, {
57
61
  refetchQueries: [
58
62
  "GetWorkItems",
59
63
  "GetWorkItemDetail",
60
64
  "GetWorkItemCounts",
61
- "ProjectBoard"
65
+ "ProjectBoard",
66
+ "WorkItemRequiredSkills"
62
67
  ],
63
68
  awaitRefetchQueries: !0
64
- }), [M, N] = l(null), [P, F] = l(!1), I = D?.planmagnetWorkItem, L = c(() => ({
65
- title: I?.title ?? "",
66
- description: I?.description ?? "",
67
- priority: I?.priority ?? "MEDIUM",
68
- type: I?.type ?? "STORY",
69
- storyPoints: I?.storyPoints?.toString() ?? "",
70
- labels: (I?.labels ?? []).join(", "),
71
- dueDate: I?.dueDate ? String(I.dueDate).slice(0, 10) : "",
72
- estimateHours: i(I?.estimateMinutes),
73
- milestoneId: I?.milestoneId ?? ""
74
- }), [I]), [R, z] = l({}), B = {
75
- ...L,
76
- ...R
77
- }, V = (e) => z(e), H = o(B.storyPoints, { min: 0 }), U = a(B.estimateHours), W = async () => {
78
- if (!f || !T || H.invalid || U.invalid) return;
79
- if (!B.title.trim()) {
80
- N("A task needs a title.");
69
+ }), [R, z] = p(null), [B, V] = p(!1), H = M?.planmagnetWorkItem, U = f(() => ({
70
+ title: H?.title ?? "",
71
+ description: H?.description ?? "",
72
+ priority: H?.priority ?? "MEDIUM",
73
+ type: H?.type ?? "STORY",
74
+ storyPoints: H?.storyPoints?.toString() ?? "",
75
+ labels: (H?.labels ?? []).join(", "),
76
+ dueDate: H?.dueDate ? String(H.dueDate).slice(0, 10) : "",
77
+ estimateHours: a(H?.estimateMinutes),
78
+ milestoneId: H?.milestoneId ?? ""
79
+ }), [H]), [W, G] = p({}), K = {
80
+ ...U,
81
+ ...W
82
+ }, q = (e) => G(e), J = s(K.storyPoints, { min: 0 }), Y = o(K.estimateHours), X = async () => {
83
+ if (!g || !k || J.invalid || Y.invalid) return;
84
+ if (!K.title.trim()) {
85
+ z("A task needs a title.");
81
86
  return;
82
87
  }
83
88
  let e = (e) => e.split(",").map((e) => e.trim()).filter(Boolean), t = {
84
- title: B.title.trim(),
85
- description: B.description.trim() || null,
86
- priority: B.priority,
87
- type: B.type,
88
- storyPoints: H.value ?? null,
89
- labels: e(B.labels),
90
- dueDate: B.dueDate || null,
91
- estimateMinutes: U.minutes ?? null,
92
- milestoneId: B.milestoneId || null
93
- }, r = {
94
- title: L.title,
95
- description: L.description.trim() || null,
96
- priority: L.priority,
97
- type: L.type,
98
- storyPoints: L.storyPoints === "" ? null : Number(L.storyPoints),
99
- labels: e(L.labels),
100
- dueDate: L.dueDate || null,
101
- estimateMinutes: a(L.estimateHours).minutes ?? null,
102
- milestoneId: L.milestoneId || null
103
- }, i = Object.fromEntries(Object.entries(t).filter(([e, t]) => JSON.stringify(t) !== JSON.stringify(r[e])));
104
- if (N(null), F(!1), Object.keys(i).length === 0) {
105
- F(!0);
89
+ title: K.title.trim(),
90
+ description: K.description.trim() || null,
91
+ priority: K.priority,
92
+ type: K.type,
93
+ storyPoints: J.value ?? null,
94
+ labels: e(K.labels),
95
+ dueDate: K.dueDate || null,
96
+ estimateMinutes: Y.minutes ?? null,
97
+ milestoneId: K.milestoneId || null
98
+ }, n = {
99
+ title: U.title,
100
+ description: U.description.trim() || null,
101
+ priority: U.priority,
102
+ type: U.type,
103
+ storyPoints: U.storyPoints === "" ? null : Number(U.storyPoints),
104
+ labels: e(U.labels),
105
+ dueDate: U.dueDate || null,
106
+ estimateMinutes: o(U.estimateHours).minutes ?? null,
107
+ milestoneId: U.milestoneId || null
108
+ }, i = {
109
+ ...Object.fromEntries(Object.entries(t).filter(([e, t]) => JSON.stringify(t) !== JSON.stringify(n[e]))),
110
+ ...F.changedValue ? { requiredSkills: F.changedValue } : {}
111
+ };
112
+ if (z(null), V(!1), F.setServerError(null), Object.keys(i).length === 0) {
113
+ V(!0);
106
114
  return;
107
115
  }
108
116
  try {
109
- await n(A({ variables: {
110
- workItemId: T,
117
+ await r(I({ variables: {
118
+ workItemId: k,
111
119
  input: i
112
- } })), F(!0);
120
+ } })), F.reset(), V(!0);
113
121
  } catch (e) {
114
- N(e instanceof Error ? e.message : "The task could not be saved.");
122
+ let t = c(e);
123
+ t ? (F.setServerError(t), z(j("planmagnet.skills.editor.saveRefused", "Not saved: see Required skills below."))) : z(e instanceof Error ? e.message : "The task could not be saved.");
115
124
  }
116
125
  };
117
- if (O && !D) return /* @__PURE__ */ h("div", {
126
+ if (N && !M) return /* @__PURE__ */ y("div", {
118
127
  className: "flex items-center justify-center p-12",
119
- children: /* @__PURE__ */ h("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
128
+ children: /* @__PURE__ */ y("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
120
129
  });
121
- if (k) return /* @__PURE__ */ g("div", {
130
+ if (P) return /* @__PURE__ */ b("div", {
122
131
  className: "p-6 text-destructive",
123
- children: ["Error: ", k.message]
132
+ children: ["Error: ", P.message]
124
133
  });
125
- if (!D?.planmagnetWorkItem) return /* @__PURE__ */ h("div", {
134
+ if (!M?.planmagnetWorkItem) return /* @__PURE__ */ y("div", {
126
135
  className: "p-6 text-muted-foreground",
127
136
  children: "Task not found."
128
137
  });
129
- let G = D.planmagnetWorkItem;
130
- return /* @__PURE__ */ g("div", {
138
+ let Z = M.planmagnetWorkItem;
139
+ return /* @__PURE__ */ b("div", {
131
140
  className: "space-y-6 p-6 max-w-4xl",
132
141
  children: [
133
- /* @__PURE__ */ g("div", {
142
+ /* @__PURE__ */ b("div", {
134
143
  className: "flex items-center justify-between",
135
- children: [/* @__PURE__ */ g("div", {
144
+ children: [/* @__PURE__ */ b("div", {
136
145
  className: "flex items-center gap-3",
137
- children: [/* @__PURE__ */ h(_, {
146
+ children: [/* @__PURE__ */ y(x, {
138
147
  variant: "ghost",
139
148
  size: "sm",
140
149
  "aria-label": "Back to the task",
141
- onClick: () => E(`/tasks/task-detail-page?taskId=${encodeURIComponent(T)}`),
142
- children: /* @__PURE__ */ h(u, { className: "h-4 w-4" })
143
- }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
150
+ onClick: () => A(`/tasks/task-detail-page?taskId=${encodeURIComponent(k)}`),
151
+ children: /* @__PURE__ */ y(m, { className: "h-4 w-4" })
152
+ }), /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h1", {
144
153
  className: "text-2xl font-semibold",
145
154
  children: "Edit Task"
146
- }), /* @__PURE__ */ h("p", {
155
+ }), /* @__PURE__ */ y("p", {
147
156
  className: "text-sm text-muted-foreground",
148
- children: G.title
157
+ children: Z.title
149
158
  })] })]
150
- }), /* @__PURE__ */ g(_, {
159
+ }), /* @__PURE__ */ b(x, {
151
160
  size: "sm",
152
- onClick: W,
153
- disabled: j || H.invalid || U.invalid,
154
- children: [/* @__PURE__ */ h(d, { className: "mr-1 h-4 w-4" }), j ? "Saving..." : "Save Changes"]
161
+ onClick: X,
162
+ disabled: L || J.invalid || Y.invalid,
163
+ children: [/* @__PURE__ */ y(h, { className: "mr-1 h-4 w-4" }), L ? "Saving..." : "Save Changes"]
155
164
  })]
156
165
  }),
157
- P && /* @__PURE__ */ h("div", {
166
+ B && /* @__PURE__ */ y("div", {
158
167
  role: "status",
159
168
  className: "p-3 bg-muted text-status-success-text rounded-md text-sm",
160
169
  children: "Changes saved."
161
170
  }),
162
- M && /* @__PURE__ */ h("div", {
171
+ R && /* @__PURE__ */ y("div", {
163
172
  role: "alert",
164
173
  className: "p-3 bg-destructive/10 text-destructive rounded-md text-sm",
165
- children: M
174
+ children: R
166
175
  }),
167
- /* @__PURE__ */ g(v, { children: [/* @__PURE__ */ h(b, { children: /* @__PURE__ */ h(x, { children: "Task Details" }) }), /* @__PURE__ */ g(y, {
176
+ /* @__PURE__ */ b(S, { children: [/* @__PURE__ */ y(w, { children: /* @__PURE__ */ y(T, { children: "Task Details" }) }), /* @__PURE__ */ b(C, {
168
177
  className: "space-y-4",
169
178
  children: [
170
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
179
+ /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
171
180
  className: "text-sm font-medium",
172
181
  children: "Title"
173
- }), /* @__PURE__ */ h(S, {
174
- value: B.title,
175
- onChange: (e) => V({
176
- ...B,
182
+ }), /* @__PURE__ */ y(E, {
183
+ value: K.title,
184
+ onChange: (e) => q({
185
+ ...K,
177
186
  title: e.target.value
178
187
  }),
179
188
  className: "mt-1"
180
189
  })] }),
181
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
190
+ /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
182
191
  className: "text-sm font-medium",
183
192
  children: "Description"
184
- }), /* @__PURE__ */ h("textarea", {
193
+ }), /* @__PURE__ */ y("textarea", {
185
194
  className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]",
186
- value: B.description,
187
- onChange: (e) => V({
188
- ...B,
195
+ value: K.description,
196
+ onChange: (e) => q({
197
+ ...K,
189
198
  description: e.target.value
190
199
  })
191
200
  })] }),
192
- /* @__PURE__ */ g("div", {
201
+ /* @__PURE__ */ b("div", {
193
202
  className: "grid grid-cols-3 gap-4",
194
203
  children: [
195
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
204
+ /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
196
205
  className: "text-sm font-medium",
197
206
  children: "Priority"
198
- }), /* @__PURE__ */ h("select", {
207
+ }), /* @__PURE__ */ y("select", {
199
208
  className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
200
- value: B.priority,
201
- onChange: (e) => V({
202
- ...B,
209
+ value: K.priority,
210
+ onChange: (e) => q({
211
+ ...K,
203
212
  priority: e.target.value
204
213
  }),
205
- children: r.map((e) => /* @__PURE__ */ h("option", {
214
+ children: i.map((e) => /* @__PURE__ */ y("option", {
206
215
  value: e,
207
216
  children: e.toLowerCase()
208
217
  }, e))
209
218
  })] }),
210
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
219
+ /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
211
220
  className: "text-sm font-medium",
212
221
  children: "Type"
213
- }), /* @__PURE__ */ h("select", {
222
+ }), /* @__PURE__ */ y("select", {
214
223
  className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
215
- value: B.type,
216
- onChange: (e) => V({
217
- ...B,
224
+ value: K.type,
225
+ onChange: (e) => q({
226
+ ...K,
218
227
  type: e.target.value
219
228
  }),
220
229
  children: [
@@ -223,31 +232,31 @@ function T() {
223
232
  "TASK",
224
233
  "EPIC",
225
234
  "SUB_TASK"
226
- ].map((e) => /* @__PURE__ */ h("option", {
235
+ ].map((e) => /* @__PURE__ */ y("option", {
227
236
  value: e,
228
237
  children: e.toLowerCase().replace("_", " ")
229
238
  }, e))
230
239
  })] }),
231
- /* @__PURE__ */ g("div", { children: [
232
- /* @__PURE__ */ h("label", {
240
+ /* @__PURE__ */ b("div", { children: [
241
+ /* @__PURE__ */ y("label", {
233
242
  htmlFor: "task-story-points",
234
243
  className: "text-sm font-medium",
235
244
  children: "Story Points"
236
245
  }),
237
- /* @__PURE__ */ h(S, {
246
+ /* @__PURE__ */ y(E, {
238
247
  id: "task-story-points",
239
248
  type: "number",
240
249
  min: 0,
241
250
  step: 1,
242
- value: B.storyPoints,
243
- onChange: (e) => V({
244
- ...B,
251
+ value: K.storyPoints,
252
+ onChange: (e) => q({
253
+ ...K,
245
254
  storyPoints: e.target.value
246
255
  }),
247
- "aria-invalid": H.invalid,
256
+ "aria-invalid": J.invalid,
248
257
  className: "mt-1"
249
258
  }),
250
- H.invalid && /* @__PURE__ */ h("p", {
259
+ J.invalid && /* @__PURE__ */ y("p", {
251
260
  role: "alert",
252
261
  className: "mt-1 text-xs text-destructive",
253
262
  children: "Story points must be a whole number, 0 or more."
@@ -255,79 +264,88 @@ function T() {
255
264
  ] })
256
265
  ]
257
266
  }),
258
- /* @__PURE__ */ g("div", {
267
+ /* @__PURE__ */ b("div", {
259
268
  className: "grid grid-cols-3 gap-4",
260
269
  children: [
261
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
270
+ /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
262
271
  className: "text-sm font-medium",
263
272
  children: "Due Date"
264
- }), /* @__PURE__ */ h(S, {
273
+ }), /* @__PURE__ */ y(E, {
265
274
  type: "date",
266
- value: B.dueDate,
267
- onChange: (e) => V({
268
- ...B,
275
+ value: K.dueDate,
276
+ onChange: (e) => q({
277
+ ...K,
269
278
  dueDate: e.target.value
270
279
  }),
271
280
  className: "mt-1"
272
281
  })] }),
273
- /* @__PURE__ */ g("div", { children: [
274
- /* @__PURE__ */ h("label", {
282
+ /* @__PURE__ */ b("div", { children: [
283
+ /* @__PURE__ */ y("label", {
275
284
  htmlFor: "task-estimate-hours",
276
285
  className: "text-sm font-medium",
277
286
  children: "Estimate (hours)"
278
287
  }),
279
- /* @__PURE__ */ h(S, {
288
+ /* @__PURE__ */ y(E, {
280
289
  id: "task-estimate-hours",
281
290
  type: "number",
282
291
  min: 0,
283
292
  step: .25,
284
- value: B.estimateHours,
285
- onChange: (e) => V({
286
- ...B,
293
+ value: K.estimateHours,
294
+ onChange: (e) => q({
295
+ ...K,
287
296
  estimateHours: e.target.value
288
297
  }),
289
- "aria-invalid": U.invalid,
298
+ "aria-invalid": Y.invalid,
290
299
  "aria-describedby": "task-estimate-hint",
291
300
  className: "mt-1"
292
301
  }),
293
- U.invalid ? /* @__PURE__ */ h("p", {
302
+ Y.invalid ? /* @__PURE__ */ y("p", {
294
303
  role: "alert",
295
304
  className: "mt-1 text-xs text-destructive",
296
305
  children: "The estimate must be a number of hours, 0 or more."
297
- }) : /* @__PURE__ */ h("p", {
306
+ }) : /* @__PURE__ */ y("p", {
298
307
  id: "task-estimate-hint",
299
308
  className: "mt-1 text-xs text-muted-foreground",
300
309
  children: "Used as the task's duration on the critical path."
301
310
  })
302
311
  ] }),
303
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
312
+ /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
304
313
  className: "text-sm font-medium",
305
314
  children: "Labels"
306
- }), /* @__PURE__ */ h(S, {
307
- value: B.labels,
308
- onChange: (e) => V({
309
- ...B,
315
+ }), /* @__PURE__ */ y(E, {
316
+ value: K.labels,
317
+ onChange: (e) => q({
318
+ ...K,
310
319
  labels: e.target.value
311
320
  }),
312
321
  className: "mt-1"
313
322
  })] })
314
323
  ]
315
324
  }),
316
- /* @__PURE__ */ h("div", {
325
+ /* @__PURE__ */ y("div", {
317
326
  className: "grid grid-cols-3 gap-4",
318
- children: /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
327
+ children: /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("label", {
319
328
  htmlFor: "task-milestone",
320
329
  className: "text-sm font-medium",
321
330
  children: "Milestone"
322
- }), /* @__PURE__ */ h(s, {
331
+ }), /* @__PURE__ */ y(l, {
323
332
  id: "task-milestone",
324
- projectId: G.projectId,
325
- value: B.milestoneId,
326
- onChange: (e) => V({
327
- ...B,
333
+ projectId: Z.projectId,
334
+ value: K.milestoneId,
335
+ onChange: (e) => q({
336
+ ...K,
328
337
  milestoneId: e
329
338
  })
330
339
  })] })
340
+ }),
341
+ /* @__PURE__ */ y(u, {
342
+ id: "task-required-skills",
343
+ value: F.value,
344
+ onChange: F.setValue,
345
+ disabled: L,
346
+ serverError: F.serverError,
347
+ loading: F.loading,
348
+ loadError: F.loadError
331
349
  })
332
350
  ]
333
351
  })] })
@@ -335,6 +353,6 @@ function T() {
335
353
  });
336
354
  }
337
355
  //#endregion
338
- export { T as TasksEditTaskPagePage };
356
+ export { k as TasksEditTaskPagePage };
339
357
 
340
358
  //# sourceMappingURL=TasksEditTaskPagePage.js.map