@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":"ProductsProductsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsProductsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Package, Plus, Archive, Loader2, Map, GitBranch, Star } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { enumLabel } from '../controls/WorkItemControls';\n\n/**\n * The real \"Products\" list (BOFF-8045). Before this shipped, this page listed Roadmaps\n * relabelled as products (CAPABILITY_REGISTER: \"not-built\") — it now queries the Product\n * entity directly, which links roadmaps/releases/feature requests/OKR objectives rather\n * than being one.\n */\n\nconst LIST_PRODUCTS = gql`\n query GetProducts(\n $workspaceId: ID!\n $filter: PlanmagnetProductFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetProducts(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n description\n vision\n lifecycleStage\n ownerId\n archivedAt\n northStar {\n name\n unit\n target\n current\n progressRatio\n }\n roadmaps {\n id\n }\n releases {\n id\n }\n featureRequests {\n id\n }\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProductNorthStar {\n name: string;\n unit: string;\n target: number;\n current: number;\n progressRatio: number | null;\n}\n\ninterface ProductListNode {\n id: string;\n name: string;\n description: string | null;\n vision: string;\n lifecycleStage: string;\n ownerId: string;\n archivedAt: string | null;\n northStar: ProductNorthStar | null;\n roadmaps: { id: string }[];\n releases: { id: string }[];\n featureRequests: { id: string }[];\n updatedAt: string;\n}\n\nexport function ProductsProductsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const { t } = useI18n();\n const [showArchived, setShowArchived] = useState(false);\n\n const { data, loading, error } = useQuery<{\n planmagnetProducts: { items: ProductListNode[]; totalCount: number };\n }>(LIST_PRODUCTS, {\n variables: {\n workspaceId,\n filter: showArchived ? undefined : { isActive: true },\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch must not blank the page.\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-6 text-destructive\">\n {t('planmagnet.products.errorLoading', 'Failed to load products')}: {error.message}\n </div>\n );\n }\n\n const products = data?.planmagnetProducts?.items ?? [];\n const totalProducts = data?.planmagnetProducts?.totalCount ?? 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <Package className=\"h-6 w-6\" /> {t('planmagnet.products.title', 'Products')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t(\n 'planmagnet.products.subtitle',\n 'Strategy entities that link roadmaps, releases, feature requests and OKRs'\n )}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant={showArchived ? 'default' : 'outline'}\n onClick={() => setShowArchived((v) => !v)}\n data-testid=\"products-toggle-archived\"\n >\n <Archive className=\"h-4 w-4 mr-1\" />\n {showArchived\n ? t('planmagnet.products.actions.hideArchived', 'Hide archived')\n : t('planmagnet.products.actions.showArchived', 'Show archived')}\n </Button>\n <Button size=\"sm\" onClick={() => navigate('/products/create-product-page')}>\n <Plus className=\"h-4 w-4 mr-1\" />\n {t('planmagnet.products.actions.newProduct', 'New Product')}\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n {\n label: t('planmagnet.products.metrics.totalProducts', 'Total Products'),\n val: totalProducts,\n icon: Package,\n color: 'text-blue-500',\n },\n {\n label: t('planmagnet.products.metrics.roadmaps', 'Linked roadmaps'),\n val: products.reduce((sum, p) => sum + p.roadmaps.length, 0),\n icon: Map,\n color: 'text-green-500',\n },\n {\n label: t('planmagnet.products.metrics.releases', 'Linked releases'),\n val: products.reduce((sum, p) => sum + p.releases.length, 0),\n icon: GitBranch,\n color: 'text-purple-500',\n },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-muted-foreground\">{s.label}</p>\n <p className=\"text-2xl font-bold\">{s.val}</p>\n </div>\n <s.icon className={`h-8 w-8 ${s.color} opacity-60`} />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {products.length === 0 ? (\n <Card>\n <CardContent className=\"py-12 text-center text-sm text-muted-foreground\">\n {t('planmagnet.products.empty', 'No products yet. Create one to get started.')}\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-2\">\n {products.map((product) => (\n <Card\n key={product.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/product-detail-page', product.id)),\n product.name\n )}\n >\n <CardHeader>\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-base\">{product.name}</CardTitle>\n <div className=\"flex items-center gap-1 shrink-0\">\n {product.archivedAt && (\n <Badge variant=\"outline\" className=\"text-xs\">\n {t('planmagnet.products.shared.archived', 'Archived')}\n </Badge>\n )}\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {enumLabel(product.lifecycleStage)}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground line-clamp-2\">\n {product.vision || t('planmagnet.products.shared.noVision', 'No vision set')}\n </p>\n <div className=\"grid grid-cols-3 gap-2 text-center\">\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.roadmaps.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.roadmaps', 'Roadmaps')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.releases.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.releases', 'Releases')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.featureRequests.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n <Star className=\"inline h-3 w-3 mr-0.5\" />\n {t('planmagnet.products.shared.features', 'Features')}\n </p>\n </div>\n </div>\n {product.northStar && (\n <div className=\"rounded border p-2 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-muted-foreground\">{product.northStar.name}</span>\n <span className=\"font-medium\">\n {product.northStar.current} / {product.northStar.target}{' '}\n {product.northStar.unit}\n {product.northStar.progressRatio != null\n ? ` (${Math.round(product.northStar.progressRatio * 100)}%)`\n : ''}\n </span>\n </div>\n </div>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {t('planmagnet.products.shared.owner', 'Owner')}:{' '}\n <PersonName id={product.ownerId} />\n </span>\n <span>\n {t('planmagnet.products.shared.updated', 'Updated')}{' '}\n {new Date(product.updatedAt).toLocaleDateString()}\n </span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProductsProductsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsProductsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Package, Plus, Archive, Loader2, Map, GitBranch, Star } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { enumLabel } from '../controls/WorkItemControls';\n\n/**\n * The real \"Products\" list (BOFF-8045). Before this shipped, this page listed Roadmaps\n * relabelled as products (CAPABILITY_REGISTER: \"not-built\") — it now queries the Product\n * entity directly, which links roadmaps/releases/feature requests/OKR objectives rather\n * than being one.\n */\n\nconst LIST_PRODUCTS = gql`\n query GetProducts(\n $workspaceId: ID!\n $filter: PlanmagnetProductFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetProducts(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n description\n vision\n lifecycleStage\n ownerId\n archivedAt\n northStar {\n name\n unit\n target\n current\n progressRatio\n }\n roadmaps {\n id\n }\n releases {\n id\n }\n featureRequests {\n id\n }\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProductNorthStar {\n name: string;\n unit: string;\n target: number;\n current: number;\n progressRatio: number | null;\n}\n\ninterface ProductListNode {\n id: string;\n name: string;\n description: string | null;\n vision: string;\n lifecycleStage: string;\n ownerId: string;\n archivedAt: string | null;\n northStar: ProductNorthStar | null;\n roadmaps: { id: string }[];\n releases: { id: string }[];\n featureRequests: { id: string }[];\n updatedAt: string;\n}\n\nexport function ProductsProductsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const { t } = useI18n();\n const [showArchived, setShowArchived] = useState(false);\n\n const { data, loading, error } = useQuery<{\n planmagnetProducts: { items: ProductListNode[]; totalCount: number };\n }>(LIST_PRODUCTS, {\n variables: {\n workspaceId,\n filter: showArchived ? undefined : { isActive: true },\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n // Only before the first load: a refetch must not blank the page.\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-6 text-destructive\">\n {t('planmagnet.products.errorLoading', 'Failed to load products')}: {error.message}\n </div>\n );\n }\n\n const products = data?.planmagnetProducts?.items ?? [];\n const totalProducts = data?.planmagnetProducts?.totalCount ?? 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold flex items-center gap-2\">\n <Package className=\"h-6 w-6\" /> {t('planmagnet.products.title', 'Products')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t(\n 'planmagnet.products.subtitle',\n 'Strategy entities that link roadmaps, releases, feature requests and OKRs'\n )}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant={showArchived ? 'default' : 'outline'}\n onClick={() => setShowArchived((v) => !v)}\n data-testid=\"products-toggle-archived\"\n >\n <Archive className=\"h-4 w-4 mr-1\" />\n {showArchived\n ? t('planmagnet.products.actions.hideArchived', 'Hide archived')\n : t('planmagnet.products.actions.showArchived', 'Show archived')}\n </Button>\n <Button size=\"sm\" onClick={() => navigate('/products/create-product-page')}>\n <Plus className=\"h-4 w-4 mr-1\" />\n {t('planmagnet.products.actions.newProduct', 'New Product')}\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n {[\n {\n label: t('planmagnet.products.metrics.totalProducts', 'Total Products'),\n val: totalProducts,\n icon: Package,\n color: 'text-blue-500',\n },\n {\n label: t('planmagnet.products.metrics.roadmaps', 'Linked roadmaps'),\n val: products.reduce((sum, p) => sum + p.roadmaps.length, 0),\n icon: Map,\n color: 'text-green-500',\n },\n {\n label: t('planmagnet.products.metrics.releases', 'Linked releases'),\n val: products.reduce((sum, p) => sum + p.releases.length, 0),\n icon: GitBranch,\n color: 'text-purple-500',\n },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-muted-foreground\">{s.label}</p>\n <p className=\"text-2xl font-bold\">{s.val}</p>\n </div>\n <s.icon className={`h-8 w-8 ${s.color} opacity-60`} />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n {products.length === 0 ? (\n <Card>\n <CardContent className=\"py-12 text-center text-sm text-muted-foreground\">\n {t('planmagnet.products.empty', 'No products yet. Create one to get started.')}\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-2\">\n {products.map((product) => (\n <Card\n key={product.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/product-detail-page', product.id)),\n product.name\n )}\n >\n <CardHeader>\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-base\">{product.name}</CardTitle>\n <div className=\"flex items-center gap-1 shrink-0\">\n {product.archivedAt && (\n <Badge variant=\"outline\" className=\"text-xs\">\n {t('planmagnet.products.shared.archived', 'Archived')}\n </Badge>\n )}\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {enumLabel(product.lifecycleStage)}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground line-clamp-2\">\n {product.vision || t('planmagnet.products.shared.noVision', 'No vision set')}\n </p>\n <div className=\"grid grid-cols-3 gap-2 text-center\">\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.roadmaps.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.roadmaps', 'Roadmaps')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.releases.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('planmagnet.products.shared.releases', 'Releases')}\n </p>\n </div>\n <div className=\"rounded border p-2\">\n <p className=\"text-lg font-bold\">{product.featureRequests.length}</p>\n <p className=\"text-xs text-muted-foreground\">\n <Star className=\"inline h-3 w-3 mr-0.5\" />\n {/* PRM-01: these are feature REQUESTS (customer feedback), not product features.\n A new key, so a locale that translated the old one as \"Features\" cannot keep\n the old wording. */}\n {t('planmagnet.products.shared.featureRequests', 'Feature requests')}\n </p>\n </div>\n </div>\n {product.northStar && (\n <div className=\"rounded border p-2 text-xs\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-muted-foreground\">{product.northStar.name}</span>\n <span className=\"font-medium\">\n {product.northStar.current} / {product.northStar.target}{' '}\n {product.northStar.unit}\n {product.northStar.progressRatio != null\n ? ` (${Math.round(product.northStar.progressRatio * 100)}%)`\n : ''}\n </span>\n </div>\n </div>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {t('planmagnet.products.shared.owner', 'Owner')}:{' '}\n <PersonName id={product.ownerId} />\n </span>\n <span>\n {t('planmagnet.products.shared.updated', 'Updated')}{' '}\n {new Date(product.updatedAt).toLocaleDateString()}\n </span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsReleaseDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"names":[],"mappings":"AAgEA,wBAAgB,6BAA6B,4CAuM5C"}
1
+ {"version":3,"file":"ProductsReleaseDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"names":[],"mappings":"AAiEA,wBAAgB,6BAA6B,4CAyM5C"}
@@ -1,20 +1,21 @@
1
1
  import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
2
  import { PersonName as t } from "../people/People.js";
3
3
  import { ReleaseHeaderActions as n } from "../controls/ReleaseControls.js";
4
- import { ReleaseNotesCard as r } from "../releases/ReleaseNotesCard.js";
5
- import { ReleaseGatesCard as i } from "../releases/ReleaseGatesCard.js";
6
- import { ReleaseReadinessCard as a } from "../releases/ReleaseReadinessCard.js";
7
- import { ReleaseChecklistCard as o } from "../releases/ReleaseChecklistCard.js";
8
- import { ReleaseWorkItemsCard as s } from "../releases/ReleaseWorkItemsCard.js";
9
- import { Calendar as c, Clock as l, GitBranch as u, Loader2 as d } from "lucide-react";
10
- import { useParams as f } from "react-router";
11
- import { gql as p } from "@apollo/client";
12
- import { useQuery as m } from "@apollo/client/react";
13
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
14
- import { Badge as _, Card as v, CardContent as y, CardHeader as b, CardTitle as x } from "@burdenoff/fe-libs/ui";
15
- import { Markdown as S } from "@burdenoff/fe-libs/shared/components";
4
+ import { SatisfactionSummaryCard as r } from "../satisfaction/SatisfactionSummaryCard.js";
5
+ import { ReleaseNotesCard as i } from "../releases/ReleaseNotesCard.js";
6
+ import { ReleaseGatesCard as a } from "../releases/ReleaseGatesCard.js";
7
+ import { ReleaseReadinessCard as o } from "../releases/ReleaseReadinessCard.js";
8
+ import { ReleaseChecklistCard as s } from "../releases/ReleaseChecklistCard.js";
9
+ import { ReleaseWorkItemsCard as c } from "../releases/ReleaseWorkItemsCard.js";
10
+ import { Calendar as l, Clock as u, GitBranch as d, Loader2 as f } from "lucide-react";
11
+ import { useParams as p } from "react-router";
12
+ import { gql as m } from "@apollo/client";
13
+ import { useQuery as h } from "@apollo/client/react";
14
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
15
+ import { Badge as v, Card as y, CardContent as b, CardHeader as x, CardTitle as S } from "@burdenoff/fe-libs/ui";
16
+ import { Markdown as C } from "@burdenoff/fe-libs/shared/components";
16
17
  //#region src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx
17
- var C = p`
18
+ var w = m`
18
19
  query GetRelease($id: ID!) {
19
20
  planmagnetRelease(id: $id) {
20
21
  id
@@ -41,7 +42,7 @@ var C = p`
41
42
  }
42
43
  }
43
44
  }
44
- `, w = {
45
+ `, T = {
45
46
  DRAFT: "bg-gray-100 text-gray-800",
46
47
  PLANNING: "bg-yellow-100 text-yellow-800",
47
48
  IN_PROGRESS: "bg-blue-100 text-blue-800",
@@ -50,109 +51,109 @@ var C = p`
50
51
  CANCELLED: "bg-red-100 text-red-800",
51
52
  ROLLED_BACK: "bg-red-100 text-red-800"
52
53
  };
53
- function T() {
54
- let { workspaceId: p } = e(), T = f().id ?? "", { data: E, loading: D, error: O } = m(C, {
55
- variables: { id: T },
56
- skip: !T
54
+ function E() {
55
+ let { workspaceId: m } = e(), E = p().id ?? "", { data: D, loading: O, error: k } = h(w, {
56
+ variables: { id: E },
57
+ skip: !E
57
58
  });
58
- if (D && !E) return /* @__PURE__ */ h("div", {
59
+ if (O && !D) return /* @__PURE__ */ g("div", {
59
60
  className: "flex items-center justify-center p-12",
60
- children: /* @__PURE__ */ h(d, { className: "h-8 w-8 animate-spin text-muted-foreground" })
61
+ children: /* @__PURE__ */ g(f, { className: "h-8 w-8 animate-spin text-muted-foreground" })
61
62
  });
62
- if (O) return /* @__PURE__ */ g("div", {
63
+ if (k) return /* @__PURE__ */ _("div", {
63
64
  className: "p-6 text-destructive",
64
- children: ["Failed to load release: ", O.message]
65
+ children: ["Failed to load release: ", k.message]
65
66
  });
66
- let k = E?.planmagnetRelease;
67
- if (!k) return /* @__PURE__ */ h("div", {
67
+ let A = D?.planmagnetRelease;
68
+ if (!A) return /* @__PURE__ */ g("div", {
68
69
  className: "p-6 text-muted-foreground",
69
70
  children: "Release not found."
70
71
  });
71
- let A = k.workItems ?? [], j = A.filter((e) => e.type === "EPIC" || e.type === "STORY"), M = A.filter((e) => e.type === "BUG"), N = A.length - j.length - M.length;
72
- return /* @__PURE__ */ g("div", {
72
+ let j = A.workItems ?? [], M = j.filter((e) => e.type === "EPIC" || e.type === "STORY"), N = j.filter((e) => e.type === "BUG"), P = j.length - M.length - N.length;
73
+ return /* @__PURE__ */ _("div", {
73
74
  className: "space-y-6 p-6",
74
- children: [/* @__PURE__ */ g("div", {
75
+ children: [/* @__PURE__ */ _("div", {
75
76
  className: "flex items-center justify-between",
76
- children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ g("div", {
77
+ children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("div", {
77
78
  className: "flex items-center gap-2",
78
79
  children: [
79
- /* @__PURE__ */ h(u, { className: "h-5 w-5 text-primary" }),
80
- /* @__PURE__ */ h("h1", {
80
+ /* @__PURE__ */ g(d, { className: "h-5 w-5 text-primary" }),
81
+ /* @__PURE__ */ g("h1", {
81
82
  className: "text-2xl font-semibold",
82
- children: k.version
83
+ children: A.version
83
84
  }),
84
- /* @__PURE__ */ h("span", {
85
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${w[k.status] ?? "bg-gray-100"}`,
86
- children: k.status.toLowerCase().replace("_", " ")
85
+ /* @__PURE__ */ g("span", {
86
+ className: `text-xs px-2 py-0.5 rounded-full capitalize ${T[A.status] ?? "bg-gray-100"}`,
87
+ children: A.status.toLowerCase().replace("_", " ")
87
88
  })
88
89
  ]
89
- }), /* @__PURE__ */ h("p", {
90
+ }), /* @__PURE__ */ g("p", {
90
91
  className: "text-sm text-muted-foreground mt-1",
91
- children: k.name
92
- })] }), /* @__PURE__ */ h(n, {
93
- releaseId: k.id,
94
- version: k.version,
95
- status: k.status
92
+ children: A.name
93
+ })] }), /* @__PURE__ */ g(n, {
94
+ releaseId: A.id,
95
+ version: A.version,
96
+ status: A.status
96
97
  })]
97
- }), /* @__PURE__ */ g("div", {
98
+ }), /* @__PURE__ */ _("div", {
98
99
  className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
99
- children: [/* @__PURE__ */ g("div", {
100
+ children: [/* @__PURE__ */ _("div", {
100
101
  className: "lg:col-span-2 space-y-6",
101
102
  children: [
102
- /* @__PURE__ */ h(a, {
103
- releaseId: k.id,
104
- projectId: k.projectId || null,
105
- releaseStatus: k.status,
106
- plannedDate: k.plannedDate ?? null
103
+ /* @__PURE__ */ g(o, {
104
+ releaseId: A.id,
105
+ projectId: A.projectId || null,
106
+ releaseStatus: A.status,
107
+ plannedDate: A.plannedDate ?? null
107
108
  }),
108
- /* @__PURE__ */ h(o, {
109
- releaseId: k.id,
110
- projectId: k.projectId || null
109
+ /* @__PURE__ */ g(s, {
110
+ releaseId: A.id,
111
+ projectId: A.projectId || null
111
112
  }),
112
- /* @__PURE__ */ g(v, { children: [/* @__PURE__ */ h(b, { children: /* @__PURE__ */ h(x, { children: "Overview" }) }), /* @__PURE__ */ g(y, {
113
+ /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Overview" }) }), /* @__PURE__ */ _(b, {
113
114
  className: "space-y-4",
114
- children: [/* @__PURE__ */ h("div", {
115
+ children: [/* @__PURE__ */ g("div", {
115
116
  className: "text-sm prose prose-sm dark:prose-invert max-w-none",
116
- children: k.description ? /* @__PURE__ */ h(S, { children: k.description }) : /* @__PURE__ */ h("p", { children: "No description provided." })
117
- }), /* @__PURE__ */ g("div", {
117
+ children: A.description ? /* @__PURE__ */ g(C, { children: A.description }) : /* @__PURE__ */ g("p", { children: "No description provided." })
118
+ }), /* @__PURE__ */ _("div", {
118
119
  className: "grid grid-cols-4 gap-4",
119
120
  children: [
120
- /* @__PURE__ */ g("div", {
121
+ /* @__PURE__ */ _("div", {
121
122
  className: "text-center p-3 bg-muted rounded-md",
122
- children: [/* @__PURE__ */ h("p", {
123
+ children: [/* @__PURE__ */ g("p", {
123
124
  className: "text-lg font-semibold mt-1",
124
- children: j.length
125
- }), /* @__PURE__ */ h("p", {
125
+ children: M.length
126
+ }), /* @__PURE__ */ g("p", {
126
127
  className: "text-xs text-muted-foreground",
127
128
  children: "Features"
128
129
  })]
129
130
  }),
130
- /* @__PURE__ */ g("div", {
131
+ /* @__PURE__ */ _("div", {
131
132
  className: "text-center p-3 bg-muted rounded-md",
132
- children: [/* @__PURE__ */ h("p", {
133
+ children: [/* @__PURE__ */ g("p", {
133
134
  className: "text-lg font-semibold mt-1",
134
- children: M.length
135
- }), /* @__PURE__ */ h("p", {
135
+ children: N.length
136
+ }), /* @__PURE__ */ g("p", {
136
137
  className: "text-xs text-muted-foreground",
137
138
  children: "Bug Fixes"
138
139
  })]
139
140
  }),
140
- /* @__PURE__ */ g("div", {
141
+ /* @__PURE__ */ _("div", {
141
142
  className: "text-center p-3 bg-muted rounded-md",
142
- children: [/* @__PURE__ */ h("p", {
143
+ children: [/* @__PURE__ */ g("p", {
143
144
  className: "text-lg font-semibold mt-1",
144
- children: N
145
- }), /* @__PURE__ */ h("p", {
145
+ children: P
146
+ }), /* @__PURE__ */ g("p", {
146
147
  className: "text-xs text-muted-foreground",
147
148
  children: "Other"
148
149
  })]
149
150
  }),
150
- /* @__PURE__ */ g("div", {
151
+ /* @__PURE__ */ _("div", {
151
152
  className: "text-center p-3 bg-muted rounded-md",
152
- children: [/* @__PURE__ */ h("p", {
153
+ children: [/* @__PURE__ */ g("p", {
153
154
  className: "text-lg font-semibold mt-1",
154
- children: A.length
155
- }), /* @__PURE__ */ h("p", {
155
+ children: j.length
156
+ }), /* @__PURE__ */ g("p", {
156
157
  className: "text-xs text-muted-foreground",
157
158
  children: "Total Items"
158
159
  })]
@@ -160,104 +161,105 @@ function T() {
160
161
  ]
161
162
  })]
162
163
  })] }),
163
- /* @__PURE__ */ h(i, {
164
- releaseId: k.id,
165
- projectId: k.projectId ?? null,
166
- releaseStatus: k.status
164
+ /* @__PURE__ */ g(a, {
165
+ releaseId: A.id,
166
+ projectId: A.projectId ?? null,
167
+ releaseStatus: A.status
167
168
  }),
168
- /* @__PURE__ */ h(r, {
169
- releaseId: k.id,
170
- notes: k.releaseNotes ?? null
169
+ /* @__PURE__ */ g(i, {
170
+ releaseId: A.id,
171
+ notes: A.releaseNotes ?? null
171
172
  }),
172
- /* @__PURE__ */ h(s, {
173
- releaseId: k.id,
174
- projectId: k.projectId || null,
175
- items: A
173
+ /* @__PURE__ */ g(c, {
174
+ releaseId: A.id,
175
+ projectId: A.projectId || null,
176
+ items: j
176
177
  })
177
178
  ]
178
- }), /* @__PURE__ */ g("div", {
179
+ }), /* @__PURE__ */ _("div", {
179
180
  className: "space-y-6",
180
181
  children: [
181
- /* @__PURE__ */ g(v, { children: [/* @__PURE__ */ h(b, { children: /* @__PURE__ */ h(x, { children: "Timeline" }) }), /* @__PURE__ */ g(y, {
182
+ /* @__PURE__ */ g(r, { scope: { releaseId: A.id } }),
183
+ /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Timeline" }) }), /* @__PURE__ */ _(b, {
182
184
  className: "space-y-3 text-sm",
183
- children: [/* @__PURE__ */ g("div", {
185
+ children: [/* @__PURE__ */ _("div", {
184
186
  className: "flex items-center gap-2",
185
187
  children: [
186
- /* @__PURE__ */ h(c, { className: "h-4 w-4 text-muted-foreground" }),
187
- /* @__PURE__ */ h("span", {
188
+ /* @__PURE__ */ g(l, { className: "h-4 w-4 text-muted-foreground" }),
189
+ /* @__PURE__ */ g("span", {
188
190
  className: "text-muted-foreground",
189
191
  children: "Planned:"
190
192
  }),
191
- /* @__PURE__ */ h("span", {
193
+ /* @__PURE__ */ g("span", {
192
194
  className: "font-medium",
193
- children: k.plannedDate ? new Date(k.plannedDate).toLocaleDateString() : "Not set"
195
+ children: A.plannedDate ? new Date(A.plannedDate).toLocaleDateString() : "Not set"
194
196
  })
195
197
  ]
196
- }), k.releasedAt && /* @__PURE__ */ g("div", {
198
+ }), A.releasedAt && /* @__PURE__ */ _("div", {
197
199
  className: "flex items-center gap-2",
198
200
  children: [
199
- /* @__PURE__ */ h(l, { className: "h-4 w-4 text-green-500" }),
200
- /* @__PURE__ */ h("span", {
201
+ /* @__PURE__ */ g(u, { className: "h-4 w-4 text-green-500" }),
202
+ /* @__PURE__ */ g("span", {
201
203
  className: "text-muted-foreground",
202
204
  children: "Released:"
203
205
  }),
204
- /* @__PURE__ */ h("span", {
206
+ /* @__PURE__ */ g("span", {
205
207
  className: "font-medium",
206
- children: new Date(k.releasedAt).toLocaleDateString()
208
+ children: new Date(A.releasedAt).toLocaleDateString()
207
209
  })
208
210
  ]
209
211
  })]
210
212
  })] }),
211
- /* @__PURE__ */ g(v, { children: [/* @__PURE__ */ h(b, { children: /* @__PURE__ */ h(x, { children: "Details" }) }), /* @__PURE__ */ g(y, {
213
+ /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Details" }) }), /* @__PURE__ */ _(b, {
212
214
  className: "space-y-2 text-sm",
213
215
  children: [
214
- /* @__PURE__ */ g("div", {
216
+ /* @__PURE__ */ _("div", {
215
217
  className: "flex justify-between",
216
- children: [/* @__PURE__ */ h("span", {
218
+ children: [/* @__PURE__ */ g("span", {
217
219
  className: "text-muted-foreground",
218
220
  children: "Version"
219
- }), /* @__PURE__ */ h("span", {
221
+ }), /* @__PURE__ */ g("span", {
220
222
  className: "font-medium",
221
- children: k.version
223
+ children: A.version
222
224
  })]
223
225
  }),
224
- /* @__PURE__ */ g("div", {
226
+ /* @__PURE__ */ _("div", {
225
227
  className: "flex justify-between",
226
- children: [/* @__PURE__ */ h("span", {
228
+ children: [/* @__PURE__ */ g("span", {
227
229
  className: "text-muted-foreground",
228
230
  children: "Status"
229
- }), /* @__PURE__ */ h(_, {
231
+ }), /* @__PURE__ */ g(v, {
230
232
  variant: "outline",
231
233
  className: "text-xs capitalize",
232
- children: k.status.toLowerCase().replace("_", " ")
234
+ children: A.status.toLowerCase().replace("_", " ")
233
235
  })]
234
236
  }),
235
- /* @__PURE__ */ g("div", {
237
+ /* @__PURE__ */ _("div", {
236
238
  className: "flex justify-between",
237
- children: [/* @__PURE__ */ h("span", {
239
+ children: [/* @__PURE__ */ g("span", {
238
240
  className: "text-muted-foreground",
239
241
  children: "Owner"
240
- }), /* @__PURE__ */ h("span", { children: /* @__PURE__ */ h(t, { id: k.ownerId }) })]
242
+ }), /* @__PURE__ */ g("span", { children: /* @__PURE__ */ g(t, { id: A.ownerId }) })]
241
243
  }),
242
- /* @__PURE__ */ g("div", {
244
+ /* @__PURE__ */ _("div", {
243
245
  className: "flex justify-between",
244
- children: [/* @__PURE__ */ h("span", {
246
+ children: [/* @__PURE__ */ g("span", {
245
247
  className: "text-muted-foreground",
246
248
  children: "Created"
247
- }), /* @__PURE__ */ h("span", { children: new Date(k.createdAt).toLocaleDateString() })]
249
+ }), /* @__PURE__ */ g("span", { children: new Date(A.createdAt).toLocaleDateString() })]
248
250
  }),
249
- /* @__PURE__ */ g("div", {
251
+ /* @__PURE__ */ _("div", {
250
252
  className: "flex justify-between",
251
- children: [/* @__PURE__ */ h("span", {
253
+ children: [/* @__PURE__ */ g("span", {
252
254
  className: "text-muted-foreground",
253
255
  children: "Updated"
254
- }), /* @__PURE__ */ h("span", { children: new Date(k.updatedAt).toLocaleDateString() })]
256
+ }), /* @__PURE__ */ g("span", { children: new Date(A.updatedAt).toLocaleDateString() })]
255
257
  })
256
258
  ]
257
259
  })] }),
258
- k.tags?.length > 0 && /* @__PURE__ */ g(v, { children: [/* @__PURE__ */ h(b, { children: /* @__PURE__ */ h(x, { children: "Tags" }) }), /* @__PURE__ */ h(y, {
260
+ A.tags?.length > 0 && /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ g(x, { children: /* @__PURE__ */ g(S, { children: "Tags" }) }), /* @__PURE__ */ g(b, {
259
261
  className: "flex flex-wrap gap-1",
260
- children: k.tags.map((e) => /* @__PURE__ */ h(_, {
262
+ children: A.tags.map((e) => /* @__PURE__ */ g(v, {
261
263
  variant: "outline",
262
264
  className: "text-xs",
263
265
  children: e
@@ -269,6 +271,6 @@ function T() {
269
271
  });
270
272
  }
271
273
  //#endregion
272
- export { T as ProductsReleaseDetailPagePage };
274
+ export { E as ProductsReleaseDetailPagePage };
273
275
 
274
276
  //# sourceMappingURL=ProductsReleaseDetailPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsReleaseDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { GitBranch, Calendar, Clock, Server, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { ReleaseNotesCard } from '../releases/ReleaseNotesCard';\nimport { ReleaseHeaderActions } from '../controls/ReleaseControls';\nimport { ReleaseGatesCard } from '../releases/ReleaseGatesCard';\nimport { ReleaseReadinessCard } from '../releases/ReleaseReadinessCard';\nimport { ReleaseChecklistCard } from '../releases/ReleaseChecklistCard';\nimport { ReleaseWorkItemsCard } from '../releases/ReleaseWorkItemsCard';\n\nconst GET_RELEASE = gql`\n query GetRelease($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n metadata\n createdAt\n updatedAt\n workItems {\n id\n title\n status\n type\n priority\n }\n }\n }\n`;\n\ninterface WorkItemSummary {\n id: string;\n title: string;\n status: string;\n type: string;\n priority: string;\n}\n\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleaseDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const releaseId = params.id ?? '';\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_RELEASE, {\n variables: { id: releaseId },\n skip: !releaseId,\n });\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load release: {error.message}</div>;\n }\n\n const release = data?.planmagnetRelease;\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n const workItems: WorkItemSummary[] = release.workItems ?? [];\n // The release notes' classification (svc release-notes.ts): EPIC and STORY are features, BUG a fix, the rest other\n // — so these tiles agree with the notes on the same page and add up to the total (BOFF-7988).\n const featureItems = workItems.filter((w) => w.type === 'EPIC' || w.type === 'STORY');\n const bugItems = workItems.filter((w) => w.type === 'BUG');\n const otherItems = workItems.length - featureItems.length - bugItems.length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <GitBranch className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{release.version}</h1>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{release.name}</p>\n </div>\n {/* Status, Edit and Delete (BOFF-7952): nothing could release, edit or delete a release. */}\n <ReleaseHeaderActions\n releaseId={release.id}\n version={release.version}\n status={release.status}\n />\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <ReleaseReadinessCard\n releaseId={release.id}\n projectId={release.projectId || null}\n releaseStatus={release.status}\n plannedDate={release.plannedDate ?? null}\n />\n {/* PRM-19: the team's readiness criteria; a required one still open blocks releasing. */}\n <ReleaseChecklistCard releaseId={release.id} projectId={release.projectId || null} />\n <Card>\n <CardHeader>\n <CardTitle>Overview</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n {release.description ? (\n <Markdown>{release.description}</Markdown>\n ) : (\n <p>No description provided.</p>\n )}\n </div>\n <div className=\"grid grid-cols-4 gap-4\">\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{featureItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Features</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{bugItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Bug Fixes</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{otherItems}</p>\n <p className=\"text-xs text-muted-foreground\">Other</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{workItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Total Items</p>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ReleaseGatesCard\n releaseId={release.id}\n projectId={release.projectId ?? null}\n releaseStatus={release.status}\n />\n <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n <ReleaseWorkItemsCard\n releaseId={release.id}\n projectId={release.projectId || null}\n items={workItems}\n />\n </div>\n\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Timeline</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Planned:</span>\n <span className=\"font-medium\">\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'Not set'}\n </span>\n </div>\n {release.releasedAt && (\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-green-500\" />\n <span className=\"text-muted-foreground\">Released:</span>\n <span className=\"font-medium\">\n {new Date(release.releasedAt).toLocaleDateString()}\n </span>\n </div>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Version</span>\n <span className=\"font-medium\">{release.version}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={release.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(release.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(release.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {release.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {release.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProductsReleaseDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsReleaseDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { GitBranch, Calendar, Clock, Server, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { ReleaseNotesCard } from '../releases/ReleaseNotesCard';\nimport { ReleaseHeaderActions } from '../controls/ReleaseControls';\nimport { ReleaseGatesCard } from '../releases/ReleaseGatesCard';\nimport { ReleaseReadinessCard } from '../releases/ReleaseReadinessCard';\nimport { ReleaseChecklistCard } from '../releases/ReleaseChecklistCard';\nimport { ReleaseWorkItemsCard } from '../releases/ReleaseWorkItemsCard';\nimport { SatisfactionSummaryCard } from '../satisfaction/SatisfactionSummaryCard';\n\nconst GET_RELEASE = gql`\n query GetRelease($id: ID!) {\n planmagnetRelease(id: $id) {\n id\n workspaceId\n projectId\n name\n description\n version\n status\n plannedDate\n releasedAt\n releaseNotes\n ownerId\n tags\n metadata\n createdAt\n updatedAt\n workItems {\n id\n title\n status\n type\n priority\n }\n }\n }\n`;\n\ninterface WorkItemSummary {\n id: string;\n title: string;\n status: string;\n type: string;\n priority: string;\n}\n\nconst statusColor: Record<string, string> = {\n DRAFT: 'bg-gray-100 text-gray-800',\n PLANNING: 'bg-yellow-100 text-yellow-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n READY: 'bg-orange-100 text-orange-800',\n RELEASED: 'bg-green-100 text-green-800',\n CANCELLED: 'bg-red-100 text-red-800',\n ROLLED_BACK: 'bg-red-100 text-red-800',\n};\n\nexport function ProductsReleaseDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const releaseId = params.id ?? '';\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_RELEASE, {\n variables: { id: releaseId },\n skip: !releaseId,\n });\n\n // Only before the first load: a refetch must not blank the page (it\n\n // unmounts every component on it and loses their state).\n\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load release: {error.message}</div>;\n }\n\n const release = data?.planmagnetRelease;\n if (!release) return <div className=\"p-6 text-muted-foreground\">Release not found.</div>;\n\n const workItems: WorkItemSummary[] = release.workItems ?? [];\n // The release notes' classification (svc release-notes.ts): EPIC and STORY are features, BUG a fix, the rest other\n // — so these tiles agree with the notes on the same page and add up to the total (BOFF-7988).\n const featureItems = workItems.filter((w) => w.type === 'EPIC' || w.type === 'STORY');\n const bugItems = workItems.filter((w) => w.type === 'BUG');\n const otherItems = workItems.length - featureItems.length - bugItems.length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <GitBranch className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{release.version}</h1>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[release.status] ?? 'bg-gray-100'}`}\n >\n {release.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">{release.name}</p>\n </div>\n {/* Status, Edit and Delete (BOFF-7952): nothing could release, edit or delete a release. */}\n <ReleaseHeaderActions\n releaseId={release.id}\n version={release.version}\n status={release.status}\n />\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <ReleaseReadinessCard\n releaseId={release.id}\n projectId={release.projectId || null}\n releaseStatus={release.status}\n plannedDate={release.plannedDate ?? null}\n />\n {/* PRM-19: the team's readiness criteria; a required one still open blocks releasing. */}\n <ReleaseChecklistCard releaseId={release.id} projectId={release.projectId || null} />\n <Card>\n <CardHeader>\n <CardTitle>Overview</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm prose prose-sm dark:prose-invert max-w-none\">\n {release.description ? (\n <Markdown>{release.description}</Markdown>\n ) : (\n <p>No description provided.</p>\n )}\n </div>\n <div className=\"grid grid-cols-4 gap-4\">\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{featureItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Features</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{bugItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Bug Fixes</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{otherItems}</p>\n <p className=\"text-xs text-muted-foreground\">Other</p>\n </div>\n <div className=\"text-center p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-semibold mt-1\">{workItems.length}</p>\n <p className=\"text-xs text-muted-foreground\">Total Items</p>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ReleaseGatesCard\n releaseId={release.id}\n projectId={release.projectId ?? null}\n releaseStatus={release.status}\n />\n <ReleaseNotesCard releaseId={release.id} notes={release.releaseNotes ?? null} />\n\n <ReleaseWorkItemsCard\n releaseId={release.id}\n projectId={release.projectId || null}\n items={workItems}\n />\n </div>\n\n <div className=\"space-y-6\">\n {/* ANR-21: CSAT and NPS from responses about this release (its own query). */}\n <SatisfactionSummaryCard scope={{ releaseId: release.id }} />\n <Card>\n <CardHeader>\n <CardTitle>Timeline</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Planned:</span>\n <span className=\"font-medium\">\n {release.plannedDate\n ? new Date(release.plannedDate).toLocaleDateString()\n : 'Not set'}\n </span>\n </div>\n {release.releasedAt && (\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-green-500\" />\n <span className=\"text-muted-foreground\">Released:</span>\n <span className=\"font-medium\">\n {new Date(release.releasedAt).toLocaleDateString()}\n </span>\n </div>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Version</span>\n <span className=\"font-medium\">{release.version}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Status</span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {release.status.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={release.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(release.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(release.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n\n {release.tags?.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Tags</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1\">\n {release.tags.map((tag: string) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AA8FA,wBAAgB,8BAA8B,4CA0W7C"}
1
+ {"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AAuGA,wBAAgB,8BAA8B,4CA4X7C"}