@burdenoff/microfe-planmagnet 2026.930.23 → 2026.930.25

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 (111) hide show
  1. package/dist/index.js +6 -5
  2. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  3. package/dist/planmagnet/PlanMagnetRoot.js +154 -147
  4. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  5. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  6. package/dist/planmagnet/PlanMagnetRoutes.js +66 -62
  7. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  8. package/dist/planmagnet/comments/CommentThread.d.ts +8 -1
  9. package/dist/planmagnet/comments/CommentThread.d.ts.map +1 -1
  10. package/dist/planmagnet/comments/CommentThread.js +188 -181
  11. package/dist/planmagnet/comments/CommentThread.js.map +1 -1
  12. package/dist/planmagnet/comments/TargetComments.d.ts +10 -2
  13. package/dist/planmagnet/comments/TargetComments.d.ts.map +1 -1
  14. package/dist/planmagnet/comments/TargetComments.js +10 -8
  15. package/dist/planmagnet/comments/TargetComments.js.map +1 -1
  16. package/dist/planmagnet/comments/WorkItemComments.d.ts +7 -1
  17. package/dist/planmagnet/comments/WorkItemComments.d.ts.map +1 -1
  18. package/dist/planmagnet/comments/WorkItemComments.js +5 -4
  19. package/dist/planmagnet/comments/WorkItemComments.js.map +1 -1
  20. package/dist/planmagnet/controls/FeatureControls.d.ts +11 -0
  21. package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
  22. package/dist/planmagnet/controls/FeatureControls.js +305 -135
  23. package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
  24. package/dist/planmagnet/controls/Pickers.d.ts +18 -0
  25. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
  26. package/dist/planmagnet/controls/Pickers.js +78 -1
  27. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  28. package/dist/planmagnet/controls/PrioritizationControls.d.ts +72 -0
  29. package/dist/planmagnet/controls/PrioritizationControls.d.ts.map +1 -0
  30. package/dist/planmagnet/controls/PrioritizationControls.js +246 -0
  31. package/dist/planmagnet/controls/PrioritizationControls.js.map +1 -0
  32. package/dist/planmagnet/discussion/WorkItemDiscussionPanel.d.ts +8 -0
  33. package/dist/planmagnet/discussion/WorkItemDiscussionPanel.d.ts.map +1 -0
  34. package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js +217 -0
  35. package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js.map +1 -0
  36. package/dist/planmagnet/docs/DocDiffView.d.ts +26 -0
  37. package/dist/planmagnet/docs/DocDiffView.d.ts.map +1 -0
  38. package/dist/planmagnet/docs/DocDiffView.js +52 -0
  39. package/dist/planmagnet/docs/DocDiffView.js.map +1 -0
  40. package/dist/planmagnet/docs/DocSuggestionsPanel.d.ts +13 -0
  41. package/dist/planmagnet/docs/DocSuggestionsPanel.d.ts.map +1 -0
  42. package/dist/planmagnet/docs/DocSuggestionsPanel.js +308 -0
  43. package/dist/planmagnet/docs/DocSuggestionsPanel.js.map +1 -0
  44. package/dist/planmagnet/docs/DocVersionCompare.d.ts +7 -0
  45. package/dist/planmagnet/docs/DocVersionCompare.d.ts.map +1 -0
  46. package/dist/planmagnet/docs/DocVersionCompare.js +105 -0
  47. package/dist/planmagnet/docs/DocVersionCompare.js.map +1 -0
  48. package/dist/planmagnet/hooks/usePresence.d.ts +39 -0
  49. package/dist/planmagnet/hooks/usePresence.d.ts.map +1 -0
  50. package/dist/planmagnet/hooks/usePresence.js +146 -0
  51. package/dist/planmagnet/hooks/usePresence.js.map +1 -0
  52. package/dist/planmagnet/index.d.ts +1 -0
  53. package/dist/planmagnet/index.d.ts.map +1 -1
  54. package/dist/planmagnet/index.js +1 -0
  55. package/dist/planmagnet/links/CodeLinksPanel.d.ts +22 -0
  56. package/dist/planmagnet/links/CodeLinksPanel.d.ts.map +1 -0
  57. package/dist/planmagnet/links/CodeLinksPanel.js +94 -0
  58. package/dist/planmagnet/links/CodeLinksPanel.js.map +1 -0
  59. package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
  60. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +488 -217
  61. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  62. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  63. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +131 -125
  64. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  65. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  66. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +183 -99
  67. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  68. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
  69. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +113 -97
  70. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
  71. package/dist/planmagnet/pages/ProductsPrioritizationPagePage.d.ts +2 -0
  72. package/dist/planmagnet/pages/ProductsPrioritizationPagePage.d.ts.map +1 -0
  73. package/dist/planmagnet/pages/ProductsPrioritizationPagePage.js +363 -0
  74. package/dist/planmagnet/pages/ProductsPrioritizationPagePage.js.map +1 -0
  75. package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
  76. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +96 -79
  77. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
  78. package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -1
  79. package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js +144 -128
  80. package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -1
  81. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  82. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +205 -196
  83. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  84. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  85. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +194 -160
  86. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  87. package/dist/planmagnet/presence/PresenceAvatars.d.ts +16 -0
  88. package/dist/planmagnet/presence/PresenceAvatars.d.ts.map +1 -0
  89. package/dist/planmagnet/presence/PresenceAvatars.js +56 -0
  90. package/dist/planmagnet/presence/PresenceAvatars.js.map +1 -0
  91. package/dist/planmagnet/product/ProductControls.d.ts +33 -0
  92. package/dist/planmagnet/product/ProductControls.d.ts.map +1 -1
  93. package/dist/planmagnet/product/ProductControls.js +593 -268
  94. package/dist/planmagnet/product/ProductControls.js.map +1 -1
  95. package/dist/planmagnet/product/routes.d.ts +10 -0
  96. package/dist/planmagnet/product/routes.d.ts.map +1 -0
  97. package/dist/planmagnet/product/routes.js +6 -0
  98. package/dist/planmagnet/product/routes.js.map +1 -0
  99. package/dist/planmagnet/roadmaps/RoadmapControls.d.ts +10 -0
  100. package/dist/planmagnet/roadmaps/RoadmapControls.d.ts.map +1 -1
  101. package/dist/planmagnet/roadmaps/RoadmapControls.js +235 -184
  102. package/dist/planmagnet/roadmaps/RoadmapControls.js.map +1 -1
  103. package/dist/planmagnet/utils/graphqlErrors.d.ts +6 -0
  104. package/dist/planmagnet/utils/graphqlErrors.d.ts.map +1 -1
  105. package/dist/planmagnet/utils/graphqlErrors.js +5 -2
  106. package/dist/planmagnet/utils/graphqlErrors.js.map +1 -1
  107. package/dist/planmagnet/utils/lineDiff.d.ts +21 -0
  108. package/dist/planmagnet/utils/lineDiff.d.ts.map +1 -0
  109. package/dist/planmagnet/utils/lineDiff.js +36 -0
  110. package/dist/planmagnet/utils/lineDiff.js.map +1 -0
  111. package/package.json +1 -1
@@ -1,22 +1,25 @@
1
1
  import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
2
  import { PersonName as t } from "../people/People.js";
3
3
  import { readUrlParam as n, writeUrlParam as r } from "../utils/urlParam.js";
4
- import { PlanningFocusBadge as i, planningFocusLabel as a } from "../roadmaps/planningFocus.js";
5
- import { RemoveRoadmapItemButton as o, RoadmapHeaderActions as s, RoadmapItemDialog as c } from "../roadmaps/RoadmapControls.js";
6
- import { RoadmapDiscussionPanel as l, RoadmapItemCommentsButton as u } from "../comments/RoadmapComments.js";
7
- import { RoadmapNowNextLater as d } from "../roadmaps/RoadmapNowNextLater.js";
8
- import { RoadmapPresentation as f } from "../roadmaps/RoadmapPresentation.js";
9
- import { RoadmapReviewPanel as p } from "../roadmaps/RoadmapReviewPanel.js";
10
- import { RoadmapVersionsPanel as m } from "../roadmaps/RoadmapVersionsPanel.js";
11
- import { useState as h } from "react";
12
- import { Calendar as g, Loader2 as _, Map as v } from "lucide-react";
13
- import { useParams as y } from "react-router";
14
- import { gql as b } from "@apollo/client";
15
- import { useQuery as x } from "@apollo/client/react";
16
- import { jsx as S, jsxs as C } from "react/jsx-runtime";
17
- import { Badge as w, Card as T, CardContent as E, CardHeader as D, CardTitle as O } from "@burdenoff/fe-libs/ui";
4
+ import { PresenceAvatars as i } from "../presence/PresenceAvatars.js";
5
+ import { usePresence as a } from "../hooks/usePresence.js";
6
+ import { PlanningFocusBadge as o, planningFocusLabel as s } from "../roadmaps/planningFocus.js";
7
+ import { QuadrantBadge as c } from "../controls/PrioritizationControls.js";
8
+ import { RemoveRoadmapItemButton as l, RoadmapHeaderActions as u, RoadmapItemDialog as d } from "../roadmaps/RoadmapControls.js";
9
+ import { RoadmapDiscussionPanel as f, RoadmapItemCommentsButton as p } from "../comments/RoadmapComments.js";
10
+ import { RoadmapNowNextLater as m } from "../roadmaps/RoadmapNowNextLater.js";
11
+ import { RoadmapPresentation as h } from "../roadmaps/RoadmapPresentation.js";
12
+ import { RoadmapReviewPanel as g } from "../roadmaps/RoadmapReviewPanel.js";
13
+ import { RoadmapVersionsPanel as _ } from "../roadmaps/RoadmapVersionsPanel.js";
14
+ import { useState as v } from "react";
15
+ import { Calendar as y, Loader2 as b, Map as x } from "lucide-react";
16
+ import { useParams as S } from "react-router";
17
+ import { gql as C } from "@apollo/client";
18
+ import { useQuery as w } from "@apollo/client/react";
19
+ import { jsx as T, jsxs as E } from "react/jsx-runtime";
20
+ import { Badge as D, Card as O, CardContent as k, CardHeader as A, CardTitle as j } from "@burdenoff/fe-libs/ui";
18
21
  //#region src/planmagnet/pages/ProductsRoadmapDetailPagePage.tsx
19
- var k = b`
22
+ var M = C`
20
23
  query GetRoadmapDetailPage($id: ID!) {
21
24
  planmagnetRoadmap(id: $id) {
22
25
  id
@@ -45,6 +48,11 @@ var k = b`
45
48
  confidence
46
49
  riskLevel
47
50
  riskNote
51
+ moscow
52
+ kano
53
+ valueScore
54
+ effortScore
55
+ valueEffortQuadrant
48
56
  featureRequestDemand {
49
57
  requests
50
58
  votes
@@ -52,7 +60,7 @@ var k = b`
52
60
  }
53
61
  }
54
62
  }
55
- `, A = (e) => e === "timeline" || e === "nnl", j = {
63
+ `, N = (e) => e === "timeline" || e === "nnl", P = {
56
64
  TODO: "bg-gray-100 text-gray-800",
57
65
  IN_PROGRESS: "bg-blue-100 text-blue-800",
58
66
  DONE: "bg-green-100 text-green-800",
@@ -60,106 +68,110 @@ var k = b`
60
68
  BLOCKED: "bg-red-100 text-red-800",
61
69
  PLANNED: "bg-yellow-100 text-yellow-800"
62
70
  };
63
- function M() {
64
- let { workspaceId: b } = e(), M = y().id ?? "", [N, P] = h(() => {
71
+ function F() {
72
+ let { workspaceId: C } = e(), F = S().id ?? "", I = a("ROADMAP", F || null), [L, R] = v(() => {
65
73
  let e = n("view");
66
- return A(e) ? e : "timeline";
67
- }), F = (e) => {
68
- P(e), r("view", e === "timeline" ? null : e);
69
- }, { data: I, loading: L, error: R } = x(k, {
70
- variables: { id: M },
71
- skip: !M
74
+ return N(e) ? e : "timeline";
75
+ }), z = (e) => {
76
+ R(e), r("view", e === "timeline" ? null : e);
77
+ }, { data: B, loading: V, error: H } = w(M, {
78
+ variables: { id: F },
79
+ skip: !F
72
80
  });
73
- if (L && !I) return /* @__PURE__ */ S("div", {
81
+ if (V && !B) return /* @__PURE__ */ T("div", {
74
82
  className: "flex items-center justify-center p-12",
75
- children: /* @__PURE__ */ S(_, { className: "h-8 w-8 animate-spin text-muted-foreground" })
83
+ children: /* @__PURE__ */ T(b, { className: "h-8 w-8 animate-spin text-muted-foreground" })
76
84
  });
77
- if (R) return /* @__PURE__ */ C("div", {
85
+ if (H) return /* @__PURE__ */ E("div", {
78
86
  className: "p-6 text-destructive",
79
- children: ["Failed to load roadmap: ", R.message]
87
+ children: ["Failed to load roadmap: ", H.message]
80
88
  });
81
- let z = I?.planmagnetRoadmap;
82
- if (!z) return /* @__PURE__ */ S("div", {
89
+ let U = B?.planmagnetRoadmap;
90
+ if (!U) return /* @__PURE__ */ T("div", {
83
91
  className: "p-6 text-muted-foreground",
84
92
  children: "Roadmap not found."
85
93
  });
86
- let B = (z.items ?? []).slice().sort((e, t) => e.sortOrder - t.sortOrder), V = B.filter((e) => e.status === "COMPLETED" || e.status === "DONE"), H = B.length > 0 ? Math.round(V.length / B.length * 100) : 0, U = [...new Set(B.map((e) => e.swimlane).filter(Boolean))], W = {};
87
- for (let e of B) {
94
+ let W = (U.items ?? []).slice().sort((e, t) => e.sortOrder - t.sortOrder), G = W.filter((e) => e.status === "COMPLETED" || e.status === "DONE"), K = W.length > 0 ? Math.round(G.length / W.length * 100) : 0, q = [...new Set(W.map((e) => e.swimlane).filter(Boolean))], J = {};
95
+ for (let e of W) {
88
96
  let t = e.swimlane ?? "Uncategorized";
89
- W[t] || (W[t] = []), W[t].push(e);
97
+ J[t] || (J[t] = []), J[t].push(e);
90
98
  }
91
- return /* @__PURE__ */ C("div", {
99
+ return /* @__PURE__ */ E("div", {
92
100
  className: "space-y-6 p-6",
93
101
  children: [
94
- /* @__PURE__ */ C("div", {
102
+ /* @__PURE__ */ E("div", {
95
103
  className: "flex items-center justify-between",
96
- children: [/* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("div", {
97
- className: "flex items-center gap-2",
98
- children: [/* @__PURE__ */ S(v, { className: "h-5 w-5 text-primary" }), /* @__PURE__ */ S("h1", {
99
- className: "text-2xl font-semibold",
100
- children: z.name
101
- })]
102
- }), /* @__PURE__ */ S("p", {
103
- className: "text-sm text-muted-foreground mt-1",
104
- children: z.description ?? "No description"
105
- })] }), /* @__PURE__ */ C("div", {
104
+ children: [/* @__PURE__ */ E("div", { children: [
105
+ /* @__PURE__ */ E("div", {
106
+ className: "flex items-center gap-2",
107
+ children: [/* @__PURE__ */ T(x, { className: "h-5 w-5 text-primary" }), /* @__PURE__ */ T("h1", {
108
+ className: "text-2xl font-semibold",
109
+ children: U.name
110
+ })]
111
+ }),
112
+ /* @__PURE__ */ T("p", {
113
+ className: "text-sm text-muted-foreground mt-1",
114
+ children: U.description ?? "No description"
115
+ }),
116
+ /* @__PURE__ */ T(i, { others: I.others })
117
+ ] }), /* @__PURE__ */ E("div", {
106
118
  className: "flex flex-col items-end gap-2",
107
- children: [/* @__PURE__ */ C("div", {
119
+ children: [/* @__PURE__ */ E("div", {
108
120
  className: "flex items-center gap-2",
109
- children: [/* @__PURE__ */ S(f, {
110
- roadmapName: z.name,
111
- roadmapDescription: z.description,
112
- view: N,
113
- items: B
114
- }), /* @__PURE__ */ S(s, {
115
- roadmapId: z.id,
116
- name: z.name
121
+ children: [/* @__PURE__ */ T(h, {
122
+ roadmapName: U.name,
123
+ roadmapDescription: U.description,
124
+ view: L,
125
+ items: W
126
+ }), /* @__PURE__ */ T(u, {
127
+ roadmapId: U.id,
128
+ name: U.name
117
129
  })]
118
- }), /* @__PURE__ */ C("div", {
130
+ }), /* @__PURE__ */ E("div", {
119
131
  className: "flex gap-2",
120
- children: [/* @__PURE__ */ S(w, {
121
- variant: z.isPublic ? "default" : "secondary",
132
+ children: [/* @__PURE__ */ T(D, {
133
+ variant: U.isPublic ? "default" : "secondary",
122
134
  className: "capitalize",
123
- children: z.isPublic ? "public" : "private"
124
- }), /* @__PURE__ */ S(i, { focus: z.planningFocus })]
135
+ children: U.isPublic ? "public" : "private"
136
+ }), /* @__PURE__ */ T(o, { focus: U.planningFocus })]
125
137
  })]
126
138
  })]
127
139
  }),
128
- /* @__PURE__ */ S("div", {
140
+ /* @__PURE__ */ T("div", {
129
141
  className: "grid grid-cols-2 md:grid-cols-5 gap-4",
130
142
  children: [
131
143
  {
132
144
  label: "Progress",
133
- value: `${H}%`
145
+ value: `${K}%`
134
146
  },
135
147
  {
136
148
  label: "Total Items",
137
- value: B.length
149
+ value: W.length
138
150
  },
139
151
  {
140
152
  label: "Completed",
141
- value: V.length
153
+ value: G.length
142
154
  },
143
155
  {
144
156
  label: "Planning focus",
145
- value: a(z.planningFocus)
157
+ value: s(U.planningFocus)
146
158
  },
147
159
  {
148
160
  label: "Visibility",
149
- value: z.isPublic ? "Public" : "Private"
161
+ value: U.isPublic ? "Public" : "Private"
150
162
  }
151
- ].map((e) => /* @__PURE__ */ S(T, { children: /* @__PURE__ */ C(E, {
163
+ ].map((e) => /* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(k, {
152
164
  className: "pt-4 text-center",
153
- children: [/* @__PURE__ */ S("p", {
165
+ children: [/* @__PURE__ */ T("p", {
154
166
  className: "text-xs text-muted-foreground",
155
167
  children: e.label
156
- }), /* @__PURE__ */ S("p", {
168
+ }), /* @__PURE__ */ T("p", {
157
169
  className: "text-lg font-semibold capitalize",
158
170
  children: e.value
159
171
  })]
160
172
  }) }, e.label))
161
173
  }),
162
- /* @__PURE__ */ S("div", {
174
+ /* @__PURE__ */ T("div", {
163
175
  className: "flex items-center gap-2",
164
176
  role: "group",
165
177
  "aria-label": "Roadmap view",
@@ -170,68 +182,68 @@ function M() {
170
182
  }, {
171
183
  key: "nnl",
172
184
  label: "Now / Next / Later"
173
- }].map((e) => /* @__PURE__ */ S("button", {
185
+ }].map((e) => /* @__PURE__ */ T("button", {
174
186
  type: "button",
175
- "aria-pressed": N === e.key,
176
- onClick: () => F(e.key),
177
- className: `px-2 py-1 text-xs rounded-md ${N === e.key ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
187
+ "aria-pressed": L === e.key,
188
+ onClick: () => z(e.key),
189
+ className: `px-2 py-1 text-xs rounded-md ${L === e.key ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
178
190
  children: e.label
179
191
  }, e.key))
180
192
  }),
181
- N === "nnl" && /* @__PURE__ */ S(d, { roadmapId: z.id }),
182
- N === "timeline" && /* @__PURE__ */ C("div", {
193
+ L === "nnl" && /* @__PURE__ */ T(m, { roadmapId: U.id }),
194
+ L === "timeline" && /* @__PURE__ */ E("div", {
183
195
  className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
184
- children: [/* @__PURE__ */ C("div", {
196
+ children: [/* @__PURE__ */ E("div", {
185
197
  className: "lg:col-span-2 space-y-6",
186
198
  children: [
187
- /* @__PURE__ */ C(T, { children: [/* @__PURE__ */ C(D, {
199
+ /* @__PURE__ */ E(O, { children: [/* @__PURE__ */ E(A, {
188
200
  className: "flex flex-row items-center justify-between gap-2",
189
- children: [/* @__PURE__ */ S(O, { children: "Progress Overview" }), /* @__PURE__ */ S(c, {
190
- roadmapId: z.id,
191
- lanes: U
201
+ children: [/* @__PURE__ */ T(j, { children: "Progress Overview" }), /* @__PURE__ */ T(d, {
202
+ roadmapId: U.id,
203
+ lanes: q
192
204
  })]
193
- }), /* @__PURE__ */ C(E, { children: [/* @__PURE__ */ C("div", {
205
+ }), /* @__PURE__ */ E(k, { children: [/* @__PURE__ */ E("div", {
194
206
  className: "flex justify-between text-sm mb-2",
195
- children: [/* @__PURE__ */ S("span", {
207
+ children: [/* @__PURE__ */ T("span", {
196
208
  className: "text-muted-foreground",
197
209
  children: "Overall Completion"
198
- }), /* @__PURE__ */ C("span", {
210
+ }), /* @__PURE__ */ E("span", {
199
211
  className: "font-medium",
200
- children: [H, "%"]
212
+ children: [K, "%"]
201
213
  })]
202
- }), /* @__PURE__ */ S("div", {
214
+ }), /* @__PURE__ */ T("div", {
203
215
  className: "w-full h-4 rounded-full bg-muted overflow-hidden",
204
- children: /* @__PURE__ */ S("div", {
216
+ children: /* @__PURE__ */ T("div", {
205
217
  className: "h-full bg-primary rounded-full transition-all",
206
- style: { width: `${H}%` }
218
+ style: { width: `${K}%` }
207
219
  })
208
220
  })] })] }),
209
- B.length === 0 && /* @__PURE__ */ C("p", {
221
+ W.length === 0 && /* @__PURE__ */ E("p", {
210
222
  className: "rounded-md border border-dashed p-6 text-center text-sm text-muted-foreground",
211
223
  children: [
212
224
  "This roadmap has no items yet. Use ",
213
- /* @__PURE__ */ S("span", {
225
+ /* @__PURE__ */ T("span", {
214
226
  className: "font-medium",
215
227
  children: "Add item"
216
228
  }),
217
229
  " to plan the first one."
218
230
  ]
219
231
  }),
220
- Object.entries(W).map(([e, t]) => /* @__PURE__ */ C(T, { children: [/* @__PURE__ */ S(D, { children: /* @__PURE__ */ C(O, { children: [
232
+ Object.entries(J).map(([e, t]) => /* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ E(j, { children: [
221
233
  e,
222
234
  " (",
223
235
  t.length,
224
236
  ")"
225
- ] }) }), /* @__PURE__ */ S(E, {
237
+ ] }) }), /* @__PURE__ */ T(k, {
226
238
  className: "space-y-3",
227
- children: t.map((e) => /* @__PURE__ */ C("div", {
239
+ children: t.map((e) => /* @__PURE__ */ E("div", {
228
240
  className: "flex items-center justify-between border rounded-md p-3",
229
- children: [/* @__PURE__ */ C("div", { children: [
230
- /* @__PURE__ */ S("p", {
241
+ children: [/* @__PURE__ */ E("div", { children: [
242
+ /* @__PURE__ */ T("p", {
231
243
  className: "text-sm font-medium",
232
244
  children: e.title
233
245
  }),
234
- e.featureRequestDemand && e.featureRequestDemand.requests > 0 && /* @__PURE__ */ C("p", {
246
+ e.featureRequestDemand && e.featureRequestDemand.requests > 0 && /* @__PURE__ */ E("p", {
235
247
  className: "text-xs text-muted-foreground",
236
248
  "data-testid": "roadmap-item-demand",
237
249
  children: [
@@ -245,41 +257,45 @@ function M() {
245
257
  e.featureRequestDemand.votes === 1 ? "" : "s"
246
258
  ]
247
259
  }),
248
- e.description && /* @__PURE__ */ S("p", {
260
+ e.description && /* @__PURE__ */ T("p", {
249
261
  className: "text-xs text-muted-foreground",
250
262
  children: e.description.length > 60 ? `${e.description.slice(0, 60)}…` : e.description
251
263
  }),
252
- (e.startDate || e.endDate) && /* @__PURE__ */ C("div", {
264
+ (e.startDate || e.endDate) && /* @__PURE__ */ E("div", {
253
265
  className: "flex items-center gap-1 mt-1 text-xs text-muted-foreground",
254
266
  children: [
255
- /* @__PURE__ */ S(g, { className: "h-3 w-3" }),
267
+ /* @__PURE__ */ T(y, { className: "h-3 w-3" }),
256
268
  e.startDate ? new Date(e.startDate).toLocaleDateString() : "?",
257
269
  " - ",
258
270
  e.endDate ? new Date(e.endDate).toLocaleDateString() : "?"
259
271
  ]
260
272
  })
261
- ] }), /* @__PURE__ */ C("div", {
273
+ ] }), /* @__PURE__ */ E("div", {
262
274
  className: "flex items-center gap-2",
263
275
  children: [
264
- e.color && /* @__PURE__ */ S("div", {
276
+ e.color && /* @__PURE__ */ T("div", {
265
277
  className: "h-3 w-3 rounded-full",
266
278
  style: { backgroundColor: e.color }
267
279
  }),
268
- /* @__PURE__ */ S("span", {
269
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${j[e.status] ?? "bg-gray-100"}`,
280
+ /* @__PURE__ */ T("span", {
281
+ className: `text-xs px-2 py-0.5 rounded-full capitalize ${P[e.status] ?? "bg-gray-100"}`,
270
282
  children: e.status.toLowerCase().replace("_", " ")
271
283
  }),
272
- /* @__PURE__ */ S(u, {
273
- roadmapId: z.id,
284
+ /* @__PURE__ */ T(c, {
285
+ quadrant: e.valueEffortQuadrant,
286
+ hideWhenUnscored: !0
287
+ }),
288
+ /* @__PURE__ */ T(p, {
289
+ roadmapId: U.id,
274
290
  itemId: e.id,
275
291
  itemTitle: e.title
276
292
  }),
277
- /* @__PURE__ */ S(c, {
278
- roadmapId: z.id,
293
+ /* @__PURE__ */ T(d, {
294
+ roadmapId: U.id,
279
295
  item: e,
280
- lanes: U
296
+ lanes: q
281
297
  }),
282
- /* @__PURE__ */ S(o, {
298
+ /* @__PURE__ */ T(l, {
283
299
  id: e.id,
284
300
  title: e.title
285
301
  })
@@ -288,57 +304,57 @@ function M() {
288
304
  }, e.id))
289
305
  })] }, e))
290
306
  ]
291
- }), /* @__PURE__ */ S("div", {
307
+ }), /* @__PURE__ */ T("div", {
292
308
  className: "space-y-6",
293
- children: /* @__PURE__ */ C(T, { children: [/* @__PURE__ */ S(D, { children: /* @__PURE__ */ S(O, { children: "Details" }) }), /* @__PURE__ */ C(E, {
309
+ children: /* @__PURE__ */ E(O, { children: [/* @__PURE__ */ T(A, { children: /* @__PURE__ */ T(j, { children: "Details" }) }), /* @__PURE__ */ E(k, {
294
310
  className: "space-y-2 text-sm",
295
311
  children: [
296
- /* @__PURE__ */ C("div", {
312
+ /* @__PURE__ */ E("div", {
297
313
  className: "flex justify-between",
298
- children: [/* @__PURE__ */ S("span", {
314
+ children: [/* @__PURE__ */ T("span", {
299
315
  className: "text-muted-foreground",
300
316
  children: "Planning focus"
301
- }), /* @__PURE__ */ S(i, { focus: z.planningFocus })]
317
+ }), /* @__PURE__ */ T(o, { focus: U.planningFocus })]
302
318
  }),
303
- /* @__PURE__ */ C("div", {
319
+ /* @__PURE__ */ E("div", {
304
320
  className: "flex justify-between",
305
- children: [/* @__PURE__ */ S("span", {
321
+ children: [/* @__PURE__ */ T("span", {
306
322
  className: "text-muted-foreground",
307
323
  children: "Owner"
308
- }), /* @__PURE__ */ S("span", { children: /* @__PURE__ */ S(t, { id: z.ownerId }) })]
324
+ }), /* @__PURE__ */ T("span", { children: /* @__PURE__ */ T(t, { id: U.ownerId }) })]
309
325
  }),
310
- /* @__PURE__ */ C("div", {
326
+ /* @__PURE__ */ E("div", {
311
327
  className: "flex justify-between",
312
- children: [/* @__PURE__ */ S("span", {
328
+ children: [/* @__PURE__ */ T("span", {
313
329
  className: "text-muted-foreground",
314
330
  children: "Created"
315
- }), /* @__PURE__ */ S("span", { children: new Date(z.createdAt).toLocaleDateString() })]
331
+ }), /* @__PURE__ */ T("span", { children: new Date(U.createdAt).toLocaleDateString() })]
316
332
  }),
317
- /* @__PURE__ */ C("div", {
333
+ /* @__PURE__ */ E("div", {
318
334
  className: "flex justify-between",
319
- children: [/* @__PURE__ */ S("span", {
335
+ children: [/* @__PURE__ */ T("span", {
320
336
  className: "text-muted-foreground",
321
337
  children: "Updated"
322
- }), /* @__PURE__ */ S("span", { children: new Date(z.updatedAt).toLocaleDateString() })]
338
+ }), /* @__PURE__ */ T("span", { children: new Date(U.updatedAt).toLocaleDateString() })]
323
339
  })
324
340
  ]
325
341
  })] })
326
342
  })]
327
343
  }),
328
- /* @__PURE__ */ C("div", {
344
+ /* @__PURE__ */ E("div", {
329
345
  className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
330
- children: [/* @__PURE__ */ S("div", {
346
+ children: [/* @__PURE__ */ T("div", {
331
347
  className: "lg:col-span-2",
332
- children: /* @__PURE__ */ S(l, { roadmapId: z.id })
333
- }), /* @__PURE__ */ C("div", {
348
+ children: /* @__PURE__ */ T(f, { roadmapId: U.id })
349
+ }), /* @__PURE__ */ E("div", {
334
350
  className: "space-y-6",
335
- children: [/* @__PURE__ */ S(p, { roadmapId: z.id }), /* @__PURE__ */ S(m, { roadmapId: z.id })]
351
+ children: [/* @__PURE__ */ T(g, { roadmapId: U.id }), /* @__PURE__ */ T(_, { roadmapId: U.id })]
336
352
  })]
337
353
  })
338
354
  ]
339
355
  });
340
356
  }
341
357
  //#endregion
342
- export { M as ProductsRoadmapDetailPagePage };
358
+ export { F as ProductsRoadmapDetailPagePage };
343
359
 
344
360
  //# sourceMappingURL=ProductsRoadmapDetailPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsRoadmapDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsRoadmapDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Map, Calendar, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { PlanningFocusBadge, planningFocusLabel } from '../roadmaps/planningFocus';\nimport {\n RemoveRoadmapItemButton,\n RoadmapHeaderActions,\n RoadmapItemDialog,\n} from '../roadmaps/RoadmapControls';\nimport { RoadmapNowNextLater } from '../roadmaps/RoadmapNowNextLater';\nimport { RoadmapPresentation } from '../roadmaps/RoadmapPresentation';\nimport { RoadmapReviewPanel } from '../roadmaps/RoadmapReviewPanel';\nimport { RoadmapVersionsPanel } from '../roadmaps/RoadmapVersionsPanel';\nimport { RoadmapDiscussionPanel, RoadmapItemCommentsButton } from '../comments/RoadmapComments';\nimport { readUrlParam, writeUrlParam } from '../utils/urlParam';\n\nconst GET_ROADMAP = gql`\n query GetRoadmapDetailPage($id: ID!) {\n planmagnetRoadmap(id: $id) {\n id\n workspaceId\n name\n description\n type\n planningFocus\n isPublic\n ownerId\n createdAt\n updatedAt\n items {\n id\n title\n description\n status\n startDate\n endDate\n color\n swimlane\n sortOrder\n projectId\n milestoneId\n horizon\n confidence\n riskLevel\n riskNote\n featureRequestDemand {\n requests\n votes\n }\n }\n }\n }\n`;\n\ninterface RoadmapItemNode {\n id: string;\n title: string;\n description: string | null;\n status: string;\n startDate: string | null;\n endDate: string | null;\n color: string | null;\n swimlane: string | null;\n sortOrder: number;\n projectId: string | null;\n milestoneId: string | null;\n /** Now/Next/Later placement (PRM-06) — read here only to hand off to `RoadmapItemDialog`'s edit form; the\n * Now/Next/Later view itself reads and writes these through its own query/mutation, not this one. */\n horizon: string | null;\n confidence: number | null;\n riskLevel: string | null;\n riskNote: string | null;\n featureRequestDemand: { requests: number; votes: number } | null;\n}\n\ntype RoadmapView = 'timeline' | 'nnl';\nconst isRoadmapView = (v: string | null): v is RoadmapView => v === 'timeline' || v === 'nnl';\n\nconst statusColor: Record<string, string> = {\n TODO: 'bg-gray-100 text-gray-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n DONE: 'bg-green-100 text-green-800',\n COMPLETED: 'bg-green-100 text-green-800',\n BLOCKED: 'bg-red-100 text-red-800',\n PLANNED: 'bg-yellow-100 text-yellow-800',\n};\n\nexport function ProductsRoadmapDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const roadmapId = params.id ?? '';\n // Timeline | Now-Next-Later (PRM-06): persisted in the URL (`?view=nnl`) so the applied view is linkable and\n // survives a reload, without touching the host shell's own router — same technique as\n // `board/boardViewConfig.ts`'s `?view=` for saved board views (see `utils/urlParam.ts`).\n const [view, setViewState] = useState<RoadmapView>(() => {\n const fromUrl = readUrlParam('view');\n return isRoadmapView(fromUrl) ? fromUrl : 'timeline';\n });\n const setView = (next: RoadmapView) => {\n setViewState(next);\n writeUrlParam('view', next === 'timeline' ? null : next);\n };\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_ROADMAP, {\n variables: { id: roadmapId },\n skip: !roadmapId,\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 roadmap: {error.message}</div>;\n }\n\n const roadmap = data?.planmagnetRoadmap;\n if (!roadmap) return <div className=\"p-6 text-muted-foreground\">Roadmap not found.</div>;\n\n const items: RoadmapItemNode[] = (roadmap.items ?? [])\n .slice()\n .sort((a: RoadmapItemNode, b: RoadmapItemNode) => a.sortOrder - b.sortOrder);\n const completedItems = items.filter((i) => i.status === 'COMPLETED' || i.status === 'DONE');\n const progress = items.length > 0 ? Math.round((completedItems.length / items.length) * 100) : 0;\n\n const lanes = [...new Set(items.map((i) => i.swimlane).filter(Boolean))] as string[];\n\n // Group items by swimlane\n const swimlaneGroups: Record<string, RoadmapItemNode[]> = {};\n for (const item of items) {\n const lane = item.swimlane ?? 'Uncategorized';\n if (!swimlaneGroups[lane]) swimlaneGroups[lane] = [];\n swimlaneGroups[lane].push(item);\n }\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 <Map className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{roadmap.name}</h1>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {roadmap.description ?? 'No description'}\n </p>\n </div>\n <div className=\"flex flex-col items-end gap-2\">\n <div className=\"flex items-center gap-2\">\n {/* PRM-11: reuses this same `items` list (already carries horizon/confidence/risk/dates) rather\n than firing a query of its own. */}\n <RoadmapPresentation\n roadmapName={roadmap.name}\n roadmapDescription={roadmap.description}\n view={view}\n items={items}\n />\n <RoadmapHeaderActions roadmapId={roadmap.id} name={roadmap.name} />\n </div>\n <div className=\"flex gap-2\">\n <Badge variant={roadmap.isPublic ? 'default' : 'secondary'} className=\"capitalize\">\n {roadmap.isPublic ? 'public' : 'private'}\n </Badge>\n <PlanningFocusBadge focus={roadmap.planningFocus} />\n </div>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-4\">\n {[\n { label: 'Progress', value: `${progress}%` },\n { label: 'Total Items', value: items.length },\n { label: 'Completed', value: completedItems.length },\n { label: 'Planning focus', value: planningFocusLabel(roadmap.planningFocus) },\n { label: 'Visibility', value: roadmap.isPublic ? 'Public' : 'Private' },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-xs text-muted-foreground\">{s.label}</p>\n <p className=\"text-lg font-semibold capitalize\">{s.value}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div\n className=\"flex items-center gap-2\"\n role=\"group\"\n aria-label=\"Roadmap view\"\n data-testid=\"roadmap-view-toggle\"\n >\n {(\n [\n { key: 'timeline', label: 'Timeline' },\n { key: 'nnl', label: 'Now / Next / Later' },\n ] as const\n ).map((v) => (\n <button\n key={v.key}\n type=\"button\"\n aria-pressed={view === v.key}\n onClick={() => setView(v.key)}\n className={`px-2 py-1 text-xs rounded-md ${view === v.key ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {v.label}\n </button>\n ))}\n </div>\n\n {view === 'nnl' && <RoadmapNowNextLater roadmapId={roadmap.id} />}\n\n {view === 'timeline' && (\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between gap-2\">\n <CardTitle>Progress Overview</CardTitle>\n <RoadmapItemDialog roadmapId={roadmap.id} lanes={lanes} />\n </CardHeader>\n <CardContent>\n <div className=\"flex justify-between text-sm mb-2\">\n <span className=\"text-muted-foreground\">Overall Completion</span>\n <span className=\"font-medium\">{progress}%</span>\n </div>\n <div className=\"w-full h-4 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full transition-all\"\n style={{ width: `${progress}%` }}\n />\n </div>\n </CardContent>\n </Card>\n\n {items.length === 0 && (\n <p className=\"rounded-md border border-dashed p-6 text-center text-sm text-muted-foreground\">\n This roadmap has no items yet. Use <span className=\"font-medium\">Add item</span> to\n plan the first one.\n </p>\n )}\n {Object.entries(swimlaneGroups).map(([lane, laneItems]) => (\n <Card key={lane}>\n <CardHeader>\n <CardTitle>\n {lane} ({laneItems.length})\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {laneItems.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{item.title}</p>\n {/* PRM-24: demand behind the initiative, counted by the server. */}\n {item.featureRequestDemand && item.featureRequestDemand.requests > 0 && (\n <p\n className=\"text-xs text-muted-foreground\"\n data-testid=\"roadmap-item-demand\"\n >\n {item.featureRequestDemand.requests} feature request\n {item.featureRequestDemand.requests === 1 ? '' : 's'} ·{' '}\n {item.featureRequestDemand.votes} vote\n {item.featureRequestDemand.votes === 1 ? '' : 's'}\n </p>\n )}\n {item.description && (\n <p className=\"text-xs text-muted-foreground\">\n {item.description.length > 60\n ? `${item.description.slice(0, 60)}…`\n : item.description}\n </p>\n )}\n {(item.startDate || item.endDate) && (\n <div className=\"flex items-center gap-1 mt-1 text-xs text-muted-foreground\">\n <Calendar className=\"h-3 w-3\" />\n {item.startDate ? new Date(item.startDate).toLocaleDateString() : '?'}\n {' - '}\n {item.endDate ? new Date(item.endDate).toLocaleDateString() : '?'}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {item.color && (\n <div\n className=\"h-3 w-3 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[item.status] ?? 'bg-gray-100'}`}\n >\n {item.status.toLowerCase().replace('_', ' ')}\n </span>\n <RoadmapItemCommentsButton\n roadmapId={roadmap.id}\n itemId={item.id}\n itemTitle={item.title}\n />\n <RoadmapItemDialog roadmapId={roadmap.id} item={item} lanes={lanes} />\n <RemoveRoadmapItemButton id={item.id} title={item.title} />\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"space-y-6\">\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\">Planning focus</span>\n <PlanningFocusBadge focus={roadmap.planningFocus} />\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={roadmap.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(roadmap.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(roadmap.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n </div>\n </div>\n )}\n\n {/* PRM-11: collaboration (discussion, review, versions) is roadmap-level state, not tied to either view\n above — shown regardless of the Timeline/Now-Next-Later toggle. */}\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2\">\n <RoadmapDiscussionPanel roadmapId={roadmap.id} />\n </div>\n <div className=\"space-y-6\">\n <RoadmapReviewPanel roadmapId={roadmap.id} />\n <RoadmapVersionsPanel roadmapId={roadmap.id} />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAuBA,IAAM,IAAc,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DjB,KAAiB,MAAuC,MAAM,cAAc,MAAM,OAElF,IAAsC;CAC1C,MAAM;CACN,aAAa;CACb,MAAM;CACN,WAAW;CACX,SAAS;CACT,SAAS;CACV;AAED,SAAgB,IAAgC;CAC9C,IAAM,EAAE,mBAAgB,GAAe,EAEjC,IADS,GAA2B,CACjB,MAAM,IAIzB,CAAC,GAAM,KAAgB,QAA4B;EACvD,IAAM,IAAU,EAAa,OAAO;AACpC,SAAO,EAAc,EAAQ,GAAG,IAAU;GAC1C,EACI,KAAW,MAAsB;AAErC,EADA,EAAa,EAAK,EAClB,EAAc,QAAQ,MAAS,aAAa,OAAO,EAAK;IAGpD,EACJ,SACA,YACA,aAGA,EAA8B,GAAa;EACzC,WAAW,EAAE,IAAI,GAAW;EAC5B,MAAM,CAAC;EACR,CAAC;AAMJ,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAS,WAAU,8CAA+C,CAAA;EAC9D,CAAA;AAIV,KAAI,EACF,QAAO,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAsC,4BAAyB,EAAM,QAAc;;CAG5F,IAAM,IAAU,GAAM;AACtB,KAAI,CAAC,EAAS,QAAO,kBAAC,OAAD;EAAK,WAAU;YAA4B;EAAwB,CAAA;CAExF,IAAM,KAA4B,EAAQ,SAAS,EAAE,EAClD,OAAO,CACP,MAAM,GAAoB,MAAuB,EAAE,YAAY,EAAE,UAAU,EACxE,IAAiB,EAAM,QAAQ,MAAM,EAAE,WAAW,eAAe,EAAE,WAAW,OAAO,EACrF,IAAW,EAAM,SAAS,IAAI,KAAK,MAAO,EAAe,SAAS,EAAM,SAAU,IAAI,GAAG,GAEzF,IAAQ,CAAC,GAAG,IAAI,IAAI,EAAM,KAAK,MAAM,EAAE,SAAS,CAAC,OAAO,QAAQ,CAAC,CAAC,EAGlE,IAAoD,EAAE;AAC5D,MAAK,IAAM,KAAQ,GAAO;EACxB,IAAM,IAAO,EAAK,YAAY;AAE9B,EADK,EAAe,OAAO,EAAe,KAAQ,EAAE,GACpD,EAAe,GAAM,KAAK,EAAK;;AAGjC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAK,WAAU,wBAAyB,CAAA,EACxC,kBAAC,MAAD;MAAI,WAAU;gBAA0B,EAAQ;MAAU,CAAA,CACtD;QACN,kBAAC,KAAD;KAAG,WAAU;eACV,EAAQ,eAAe;KACtB,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CAGE,kBAAC,GAAD;OACE,aAAa,EAAQ;OACrB,oBAAoB,EAAQ;OACtB;OACC;OACP,CAAA,EACF,kBAAC,GAAD;OAAsB,WAAW,EAAQ;OAAI,MAAM,EAAQ;OAAQ,CAAA,CAC/D;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAO,SAAS,EAAQ,WAAW,YAAY;OAAa,WAAU;iBACnE,EAAQ,WAAW,WAAW;OACzB,CAAA,EACR,kBAAC,GAAD,EAAoB,OAAO,EAAQ,eAAiB,CAAA,CAChD;QACF;OACF;;GAEN,kBAAC,OAAD;IAAK,WAAU;cACZ;KACC;MAAE,OAAO;MAAY,OAAO,GAAG,EAAS;MAAI;KAC5C;MAAE,OAAO;MAAe,OAAO,EAAM;MAAQ;KAC7C;MAAE,OAAO;MAAa,OAAO,EAAe;MAAQ;KACpD;MAAE,OAAO;MAAkB,OAAO,EAAmB,EAAQ,cAAc;MAAE;KAC7E;MAAE,OAAO;MAAc,OAAO,EAAQ,WAAW,WAAW;MAAW;KACxE,CAAC,KAAK,MACL,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;KAAa,WAAU;eAAvB,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAiC,EAAE;MAAU,CAAA,EAC1D,kBAAC,KAAD;MAAG,WAAU;gBAAoC,EAAE;MAAU,CAAA,CACjD;QACT,EALI,EAAE,MAKN,CACP;IACE,CAAA;GAEN,kBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,cAAW;IACX,eAAY;cAGV,CACE;KAAE,KAAK;KAAY,OAAO;KAAY,EACtC;KAAE,KAAK;KAAO,OAAO;KAAsB,CAC5C,CACD,KAAK,MACL,kBAAC,UAAD;KAEE,MAAK;KACL,gBAAc,MAAS,EAAE;KACzB,eAAe,EAAQ,EAAE,IAAI;KAC7B,WAAW,gCAAgC,MAAS,EAAE,MAAM,uCAAuC;eAElG,EAAE;KACI,EAPF,EAAE,IAOA,CACT;IACE,CAAA;GAEL,MAAS,SAAS,kBAAC,GAAD,EAAqB,WAAW,EAAQ,IAAM,CAAA;GAEhE,MAAS,cACR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD,EAAA,UAAW,qBAA6B,CAAA,EACxC,kBAAC,GAAD;QAAmB,WAAW,EAAQ;QAAW;QAAS,CAAA,CAC/C;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAwB;QAAyB,CAAA,EACjE,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CAA+B,GAAS,IAAQ;UAC5C;UACN,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,OAAD;QACE,WAAU;QACV,OAAO,EAAE,OAAO,GAAG,EAAS,IAAI;QAChC,CAAA;OACE,CAAA,CACM,EAAA,CAAA,CACT,EAAA,CAAA;MAEN,EAAM,WAAW,KAChB,kBAAC,KAAD;OAAG,WAAU;iBAAb;QAA6F;QACxD,kBAAC,QAAD;SAAM,WAAU;mBAAc;SAAe,CAAA;;QAE9E;;MAEL,OAAO,QAAQ,EAAe,CAAC,KAAK,CAAC,GAAM,OAC1C,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACG;OAAK;OAAG,EAAU;OAAO;OAChB,EAAA,CAAA,EACD,CAAA,EACb,kBAAC,GAAD;OAAa,WAAU;iBACpB,EAAU,KAAK,MACd,kBAAC,OAAD;QAEE,WAAU;kBAFZ,CAIE,kBAAC,OAAD,EAAA,UAAA;SACE,kBAAC,KAAD;UAAG,WAAU;oBAAuB,EAAK;UAAU,CAAA;SAElD,EAAK,wBAAwB,EAAK,qBAAqB,WAAW,KACjE,kBAAC,KAAD;UACE,WAAU;UACV,eAAY;oBAFd;WAIG,EAAK,qBAAqB;WAAS;WACnC,EAAK,qBAAqB,aAAa,IAAI,KAAK;WAAI;WAAG;WACvD,EAAK,qBAAqB;WAAM;WAChC,EAAK,qBAAqB,UAAU,IAAI,KAAK;WAC5C;;SAEL,EAAK,eACJ,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAK,YAAY,SAAS,KACvB,GAAG,EAAK,YAAY,MAAM,GAAG,GAAG,CAAC,KACjC,EAAK;UACP,CAAA;UAEJ,EAAK,aAAa,EAAK,YACvB,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;WAC/B,EAAK,YAAY,IAAI,KAAK,EAAK,UAAU,CAAC,oBAAoB,GAAG;WACjE;WACA,EAAK,UAAU,IAAI,KAAK,EAAK,QAAQ,CAAC,oBAAoB,GAAG;WAC1D;;SAEJ,EAAA,CAAA,EACN,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACG,EAAK,SACJ,kBAAC,OAAD;WACE,WAAU;WACV,OAAO,EAAE,iBAAiB,EAAK,OAAO;WACtC,CAAA;UAEJ,kBAAC,QAAD;WACE,WAAW,+CAA+C,EAAY,EAAK,WAAW;qBAErF,EAAK,OAAO,aAAa,CAAC,QAAQ,KAAK,IAAI;WACvC,CAAA;UACP,kBAAC,GAAD;WACE,WAAW,EAAQ;WACnB,QAAQ,EAAK;WACb,WAAW,EAAK;WAChB,CAAA;UACF,kBAAC,GAAD;WAAmB,WAAW,EAAQ;WAAU;WAAa;WAAS,CAAA;UACtE,kBAAC,GAAD;WAAyB,IAAI,EAAK;WAAI,OAAO,EAAK;WAAS,CAAA;UACvD;WACF;UArDC,EAAK,GAqDN,CACN;OACU,CAAA,CACT,EAAA,EAjEI,EAiEJ,CACP;MACE;QAEN,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,WAAmB,CAAA,EACnB,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAqB,CAAA,EAC7D,kBAAC,GAAD,EAAoB,OAAO,EAAQ,eAAiB,CAAA,CAChD;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAY,CAAA,EACpD,kBAAC,QAAD,EAAA,UACE,kBAAC,GAAD,EAAY,IAAI,EAAQ,SAAW,CAAA,EAC9B,CAAA,CACH;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAc,CAAA,EACtD,kBAAC,QAAD,EAAA,UAAO,IAAI,KAAK,EAAQ,UAAU,CAAC,oBAAoB,EAAQ,CAAA,CAC3D;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAwB;SAAc,CAAA,EACtD,kBAAC,QAAD,EAAA,UAAO,IAAI,KAAK,EAAQ,UAAU,CAAC,oBAAoB,EAAQ,CAAA,CAC3D;;OACM;QACT,EAAA,CAAA;KACH,CAAA,CACF;;GAKR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAwB,WAAW,EAAQ,IAAM,CAAA;KAC7C,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAoB,WAAW,EAAQ,IAAM,CAAA,EAC7C,kBAAC,GAAD,EAAsB,WAAW,EAAQ,IAAM,CAAA,CAC3C;OACF;;GACF"}
1
+ {"version":3,"file":"ProductsRoadmapDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsRoadmapDetailPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Map, Calendar, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router';\nimport { PersonName } from '../people/People';\nimport { PlanningFocusBadge, planningFocusLabel } from '../roadmaps/planningFocus';\nimport {\n RemoveRoadmapItemButton,\n RoadmapHeaderActions,\n RoadmapItemDialog,\n} from '../roadmaps/RoadmapControls';\nimport { RoadmapNowNextLater } from '../roadmaps/RoadmapNowNextLater';\nimport { RoadmapPresentation } from '../roadmaps/RoadmapPresentation';\nimport { RoadmapReviewPanel } from '../roadmaps/RoadmapReviewPanel';\nimport { RoadmapVersionsPanel } from '../roadmaps/RoadmapVersionsPanel';\nimport { RoadmapDiscussionPanel, RoadmapItemCommentsButton } from '../comments/RoadmapComments';\nimport { readUrlParam, writeUrlParam } from '../utils/urlParam';\nimport { QuadrantBadge } from '../controls/PrioritizationControls';\nimport { usePresence } from '../hooks/usePresence';\nimport { PresenceAvatars } from '../presence/PresenceAvatars';\n\nconst GET_ROADMAP = gql`\n query GetRoadmapDetailPage($id: ID!) {\n planmagnetRoadmap(id: $id) {\n id\n workspaceId\n name\n description\n type\n planningFocus\n isPublic\n ownerId\n createdAt\n updatedAt\n items {\n id\n title\n description\n status\n startDate\n endDate\n color\n swimlane\n sortOrder\n projectId\n milestoneId\n horizon\n confidence\n riskLevel\n riskNote\n moscow\n kano\n valueScore\n effortScore\n valueEffortQuadrant\n featureRequestDemand {\n requests\n votes\n }\n }\n }\n }\n`;\n\ninterface RoadmapItemNode {\n id: string;\n title: string;\n description: string | null;\n status: string;\n startDate: string | null;\n endDate: string | null;\n color: string | null;\n swimlane: string | null;\n sortOrder: number;\n projectId: string | null;\n milestoneId: string | null;\n /** Now/Next/Later placement (PRM-06) — read here only to hand off to `RoadmapItemDialog`'s edit form; the\n * Now/Next/Later view itself reads and writes these through its own query/mutation, not this one. */\n horizon: string | null;\n confidence: number | null;\n riskLevel: string | null;\n riskNote: string | null;\n /** PRM-27 — read here only to show on the row and hand off to RoadmapItemDialog's edit form. */\n moscow: string | null;\n kano: string | null;\n valueScore: number | null;\n effortScore: number | null;\n valueEffortQuadrant: string | null;\n featureRequestDemand: { requests: number; votes: number } | null;\n}\n\ntype RoadmapView = 'timeline' | 'nnl';\nconst isRoadmapView = (v: string | null): v is RoadmapView => v === 'timeline' || v === 'nnl';\n\nconst statusColor: Record<string, string> = {\n TODO: 'bg-gray-100 text-gray-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n DONE: 'bg-green-100 text-green-800',\n COMPLETED: 'bg-green-100 text-green-800',\n BLOCKED: 'bg-red-100 text-red-800',\n PLANNED: 'bg-yellow-100 text-yellow-800',\n};\n\nexport function ProductsRoadmapDetailPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const roadmapId = params.id ?? '';\n // CWF-24: who else is looking at this roadmap right now.\n const presence = usePresence('ROADMAP', roadmapId || null);\n // Timeline | Now-Next-Later (PRM-06): persisted in the URL (`?view=nnl`) so the applied view is linkable and\n // survives a reload, without touching the host shell's own router — same technique as\n // `board/boardViewConfig.ts`'s `?view=` for saved board views (see `utils/urlParam.ts`).\n const [view, setViewState] = useState<RoadmapView>(() => {\n const fromUrl = readUrlParam('view');\n return isRoadmapView(fromUrl) ? fromUrl : 'timeline';\n });\n const setView = (next: RoadmapView) => {\n setViewState(next);\n writeUrlParam('view', next === 'timeline' ? null : next);\n };\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_ROADMAP, {\n variables: { id: roadmapId },\n skip: !roadmapId,\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 roadmap: {error.message}</div>;\n }\n\n const roadmap = data?.planmagnetRoadmap;\n if (!roadmap) return <div className=\"p-6 text-muted-foreground\">Roadmap not found.</div>;\n\n const items: RoadmapItemNode[] = (roadmap.items ?? [])\n .slice()\n .sort((a: RoadmapItemNode, b: RoadmapItemNode) => a.sortOrder - b.sortOrder);\n const completedItems = items.filter((i) => i.status === 'COMPLETED' || i.status === 'DONE');\n const progress = items.length > 0 ? Math.round((completedItems.length / items.length) * 100) : 0;\n\n const lanes = [...new Set(items.map((i) => i.swimlane).filter(Boolean))] as string[];\n\n // Group items by swimlane\n const swimlaneGroups: Record<string, RoadmapItemNode[]> = {};\n for (const item of items) {\n const lane = item.swimlane ?? 'Uncategorized';\n if (!swimlaneGroups[lane]) swimlaneGroups[lane] = [];\n swimlaneGroups[lane].push(item);\n }\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 <Map className=\"h-5 w-5 text-primary\" />\n <h1 className=\"text-2xl font-semibold\">{roadmap.name}</h1>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {roadmap.description ?? 'No description'}\n </p>\n <PresenceAvatars others={presence.others} />\n </div>\n <div className=\"flex flex-col items-end gap-2\">\n <div className=\"flex items-center gap-2\">\n {/* PRM-11: reuses this same `items` list (already carries horizon/confidence/risk/dates) rather\n than firing a query of its own. */}\n <RoadmapPresentation\n roadmapName={roadmap.name}\n roadmapDescription={roadmap.description}\n view={view}\n items={items}\n />\n <RoadmapHeaderActions roadmapId={roadmap.id} name={roadmap.name} />\n </div>\n <div className=\"flex gap-2\">\n <Badge variant={roadmap.isPublic ? 'default' : 'secondary'} className=\"capitalize\">\n {roadmap.isPublic ? 'public' : 'private'}\n </Badge>\n <PlanningFocusBadge focus={roadmap.planningFocus} />\n </div>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-4\">\n {[\n { label: 'Progress', value: `${progress}%` },\n { label: 'Total Items', value: items.length },\n { label: 'Completed', value: completedItems.length },\n { label: 'Planning focus', value: planningFocusLabel(roadmap.planningFocus) },\n { label: 'Visibility', value: roadmap.isPublic ? 'Public' : 'Private' },\n ].map((s) => (\n <Card key={s.label}>\n <CardContent className=\"pt-4 text-center\">\n <p className=\"text-xs text-muted-foreground\">{s.label}</p>\n <p className=\"text-lg font-semibold capitalize\">{s.value}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div\n className=\"flex items-center gap-2\"\n role=\"group\"\n aria-label=\"Roadmap view\"\n data-testid=\"roadmap-view-toggle\"\n >\n {(\n [\n { key: 'timeline', label: 'Timeline' },\n { key: 'nnl', label: 'Now / Next / Later' },\n ] as const\n ).map((v) => (\n <button\n key={v.key}\n type=\"button\"\n aria-pressed={view === v.key}\n onClick={() => setView(v.key)}\n className={`px-2 py-1 text-xs rounded-md ${view === v.key ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {v.label}\n </button>\n ))}\n </div>\n\n {view === 'nnl' && <RoadmapNowNextLater roadmapId={roadmap.id} />}\n\n {view === 'timeline' && (\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between gap-2\">\n <CardTitle>Progress Overview</CardTitle>\n <RoadmapItemDialog roadmapId={roadmap.id} lanes={lanes} />\n </CardHeader>\n <CardContent>\n <div className=\"flex justify-between text-sm mb-2\">\n <span className=\"text-muted-foreground\">Overall Completion</span>\n <span className=\"font-medium\">{progress}%</span>\n </div>\n <div className=\"w-full h-4 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full transition-all\"\n style={{ width: `${progress}%` }}\n />\n </div>\n </CardContent>\n </Card>\n\n {items.length === 0 && (\n <p className=\"rounded-md border border-dashed p-6 text-center text-sm text-muted-foreground\">\n This roadmap has no items yet. Use <span className=\"font-medium\">Add item</span> to\n plan the first one.\n </p>\n )}\n {Object.entries(swimlaneGroups).map(([lane, laneItems]) => (\n <Card key={lane}>\n <CardHeader>\n <CardTitle>\n {lane} ({laneItems.length})\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {laneItems.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{item.title}</p>\n {/* PRM-24: demand behind the initiative, counted by the server. */}\n {item.featureRequestDemand && item.featureRequestDemand.requests > 0 && (\n <p\n className=\"text-xs text-muted-foreground\"\n data-testid=\"roadmap-item-demand\"\n >\n {item.featureRequestDemand.requests} feature request\n {item.featureRequestDemand.requests === 1 ? '' : 's'} ·{' '}\n {item.featureRequestDemand.votes} vote\n {item.featureRequestDemand.votes === 1 ? '' : 's'}\n </p>\n )}\n {item.description && (\n <p className=\"text-xs text-muted-foreground\">\n {item.description.length > 60\n ? `${item.description.slice(0, 60)}…`\n : item.description}\n </p>\n )}\n {(item.startDate || item.endDate) && (\n <div className=\"flex items-center gap-1 mt-1 text-xs text-muted-foreground\">\n <Calendar className=\"h-3 w-3\" />\n {item.startDate ? new Date(item.startDate).toLocaleDateString() : '?'}\n {' - '}\n {item.endDate ? new Date(item.endDate).toLocaleDateString() : '?'}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {item.color && (\n <div\n className=\"h-3 w-3 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[item.status] ?? 'bg-gray-100'}`}\n >\n {item.status.toLowerCase().replace('_', ' ')}\n </span>\n {/* PRM-27 — read back from the server; hidden for the common case of an unscored item. */}\n <QuadrantBadge quadrant={item.valueEffortQuadrant} hideWhenUnscored />\n <RoadmapItemCommentsButton\n roadmapId={roadmap.id}\n itemId={item.id}\n itemTitle={item.title}\n />\n <RoadmapItemDialog roadmapId={roadmap.id} item={item} lanes={lanes} />\n <RemoveRoadmapItemButton id={item.id} title={item.title} />\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"space-y-6\">\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\">Planning focus</span>\n <PlanningFocusBadge focus={roadmap.planningFocus} />\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Owner</span>\n <span>\n <PersonName id={roadmap.ownerId} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Created</span>\n <span>{new Date(roadmap.createdAt).toLocaleDateString()}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-muted-foreground\">Updated</span>\n <span>{new Date(roadmap.updatedAt).toLocaleDateString()}</span>\n </div>\n </CardContent>\n </Card>\n </div>\n </div>\n )}\n\n {/* PRM-11: collaboration (discussion, review, versions) is roadmap-level state, not tied to either view\n above — shown regardless of the Timeline/Now-Next-Later toggle. */}\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2\">\n <RoadmapDiscussionPanel roadmapId={roadmap.id} />\n </div>\n <div className=\"space-y-6\">\n <RoadmapReviewPanel roadmapId={roadmap.id} />\n <RoadmapVersionsPanel roadmapId={roadmap.id} />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsProjectDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsProjectDetailPagePage.tsx"],"names":[],"mappings":"AAiIA,wBAAgB,6BAA6B,4CAmkB5C"}
1
+ {"version":3,"file":"ProjectsProjectDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsProjectDetailPagePage.tsx"],"names":[],"mappings":"AAmIA,wBAAgB,6BAA6B,4CAskB5C"}