@burdenoff/microfe-planmagnet 2026.1001.5 → 2026.1001.6

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 (59) hide show
  1. package/dist/planmagnet/controls/CompetitorControls.d.ts +71 -0
  2. package/dist/planmagnet/controls/CompetitorControls.d.ts.map +1 -1
  3. package/dist/planmagnet/controls/CompetitorControls.js +346 -12
  4. package/dist/planmagnet/controls/CompetitorControls.js.map +1 -1
  5. package/dist/planmagnet/controls/FeatureControls.d.ts +5 -0
  6. package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
  7. package/dist/planmagnet/controls/FeatureControls.js +363 -218
  8. package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
  9. package/dist/planmagnet/controls/Pickers.d.ts +15 -0
  10. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
  11. package/dist/planmagnet/controls/Pickers.js +61 -1
  12. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  13. package/dist/planmagnet/controls/PrioritizationControls.d.ts +36 -0
  14. package/dist/planmagnet/controls/PrioritizationControls.d.ts.map +1 -1
  15. package/dist/planmagnet/controls/PrioritizationControls.js +118 -1
  16. package/dist/planmagnet/controls/PrioritizationControls.js.map +1 -1
  17. package/dist/planmagnet/dashboards/DashboardUI.js +1 -1
  18. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
  19. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +67 -59
  20. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
  21. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
  22. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +289 -282
  23. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  24. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.d.ts.map +1 -1
  25. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js +126 -63
  26. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js.map +1 -1
  27. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts.map +1 -1
  28. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js +14 -0
  29. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js.map +1 -1
  30. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts.map +1 -1
  31. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js +93 -57
  32. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js.map +1 -1
  33. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts.map +1 -1
  34. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js +125 -83
  35. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js.map +1 -1
  36. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts.map +1 -1
  37. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js +226 -126
  38. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js.map +1 -1
  39. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  40. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +162 -122
  41. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  42. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
  43. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +135 -109
  44. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
  45. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  46. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +15 -3
  47. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  48. package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
  49. package/dist/planmagnet/pages/TeamTeamPagePage.js +59 -53
  50. package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
  51. package/dist/planmagnet/pages/analytics/MetricsCard.d.ts +8 -0
  52. package/dist/planmagnet/pages/analytics/MetricsCard.d.ts.map +1 -0
  53. package/dist/planmagnet/pages/analytics/MetricsCard.js +164 -0
  54. package/dist/planmagnet/pages/analytics/MetricsCard.js.map +1 -0
  55. package/dist/planmagnet/team/UnmatchedCrewIdentities.d.ts +2 -0
  56. package/dist/planmagnet/team/UnmatchedCrewIdentities.d.ts.map +1 -0
  57. package/dist/planmagnet/team/UnmatchedCrewIdentities.js +155 -0
  58. package/dist/planmagnet/team/UnmatchedCrewIdentities.js.map +1 -0
  59. package/package.json +1 -1
@@ -6,15 +6,15 @@ import { enumLabel as o } from "./WorkItemControls.js";
6
6
  import { detailPath as s } from "../utils/rowNavigation.js";
7
7
  import { ProjectSelect as c, WorkItemSearchSelect as l } from "./Pickers.js";
8
8
  import { parseIntField as u } from "../utils/formValidation.js";
9
- import { PrioritizationScoreFields as d, QuadrantBadge as f, kanoLabel as p, moscowLabel as m, prioritizationScoresValid as h } from "./PrioritizationControls.js";
10
- import { useState as g } from "react";
11
- import { BarChart3 as _, Pencil as v, ThumbsUp as y, Trash2 as b } from "lucide-react";
12
- import { gql as x } from "@apollo/client";
13
- import { useMutation as S } from "@apollo/client/react";
14
- import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
15
- import { Button as E, Card as D, CardContent as O, CardHeader as k, CardTitle as A, Input as j, ResponsiveDialog as M, ResponsiveDialogContent as N, ResponsiveDialogDescription as P, ResponsiveDialogFooter as F, ResponsiveDialogHeader as I, ResponsiveDialogTitle as L, ResponsiveDialogTrigger as R } from "@burdenoff/fe-libs/ui";
9
+ import { PrioritizationScoreFields as d, QuadrantBadge as f, RiceScoreFields as p, kanoLabel as m, moscowLabel as h, prioritizationScoresValid as g, riceInputsValid as _, riceScoreMissingHint as v } from "./PrioritizationControls.js";
10
+ import { useState as y } from "react";
11
+ import { BarChart3 as b, Pencil as x, ThumbsUp as S, Trash2 as C } from "lucide-react";
12
+ import { gql as w } from "@apollo/client";
13
+ import { useMutation as T } from "@apollo/client/react";
14
+ import { Fragment as E, jsx as D, jsxs as O } from "react/jsx-runtime";
15
+ import { Button as k, Card as A, CardContent as j, CardHeader as M, CardTitle as N, Input as P, ResponsiveDialog as F, ResponsiveDialogContent as I, ResponsiveDialogDescription as L, ResponsiveDialogFooter as R, ResponsiveDialogHeader as z, ResponsiveDialogTitle as B, ResponsiveDialogTrigger as V } from "@burdenoff/fe-libs/ui";
16
16
  //#region src/planmagnet/controls/FeatureControls.tsx
17
- var z = [
17
+ var H = [
18
18
  "SUBMITTED",
19
19
  "UNDER_REVIEW",
20
20
  "PLANNED",
@@ -22,7 +22,7 @@ var z = [
22
22
  "COMPLETED",
23
23
  "DECLINED",
24
24
  "DUPLICATE"
25
- ], B = [
25
+ ], U = [
26
26
  "GetFeatureRequest",
27
27
  "ListFeatureRequests",
28
28
  "ListFeatureRequestsForProduct",
@@ -30,17 +30,17 @@ var z = [
30
30
  "ListAllFeaturesAnalytics",
31
31
  "GetFeatureRequestAnalytics",
32
32
  "ReleaseCustomerRequests"
33
- ], V = x`
33
+ ], W = w`
34
34
  mutation FeatureControlsVote($id: ID!) {
35
35
  planmagnetVoteOnFeature(featureRequestId: $id) {
36
36
  id
37
37
  }
38
38
  }
39
- `, H = x`
39
+ `, G = w`
40
40
  mutation FeatureControlsUnvote($id: ID!) {
41
41
  planmagnetRemoveFeatureVote(featureRequestId: $id)
42
42
  }
43
- `, U = x`
43
+ `, K = w`
44
44
  mutation FeatureControlsUpdate($id: ID!, $input: PlanmagnetUpdateFeatureRequestInput!) {
45
45
  planmagnetUpdateFeatureRequest(id: $id, input: $input) {
46
46
  id
@@ -56,18 +56,22 @@ var z = [
56
56
  valueScore
57
57
  effortScore
58
58
  valueEffortQuadrant
59
+ reach
60
+ impact
61
+ confidence
62
+ riceScore
59
63
  }
60
64
  }
61
- `, W = x`
65
+ `, q = w`
62
66
  mutation FeatureControlsDelete($id: ID!) {
63
67
  planmagnetDeleteFeatureRequest(id: $id)
64
68
  }
65
- `, G = {
66
- refetchQueries: B,
69
+ `, J = {
70
+ refetchQueries: U,
67
71
  awaitRefetchQueries: !0
68
72
  };
69
- function K({ featureId: e, voted: t }) {
70
- let [n, i] = S(V, G), [o, s] = S(H, G), [c, l] = g(null), u = i.loading || s.loading, d = async () => {
73
+ function Y({ featureId: e, voted: t }) {
74
+ let [n, i] = T(W, J), [o, s] = T(G, J), [c, l] = y(null), u = i.loading || s.loading, d = async () => {
71
75
  l(null);
72
76
  try {
73
77
  await r((t ? o : n)({ variables: { id: e } }));
@@ -75,24 +79,24 @@ function K({ featureId: e, voted: t }) {
75
79
  l(e instanceof Error ? e.message : "Your vote could not be saved.");
76
80
  }
77
81
  };
78
- return /* @__PURE__ */ T("div", {
82
+ return /* @__PURE__ */ O("div", {
79
83
  className: "flex flex-col items-end gap-1",
80
- children: [/* @__PURE__ */ T(E, {
84
+ children: [/* @__PURE__ */ O(k, {
81
85
  size: "sm",
82
86
  variant: t ? "default" : "outline",
83
87
  "data-testid": "feature-vote",
84
88
  "aria-pressed": t,
85
89
  disabled: u,
86
90
  onClick: () => void d(),
87
- children: [/* @__PURE__ */ w(y, { className: "mr-1 h-4 w-4" }), t ? "Voted" : "Vote"]
88
- }), c && /* @__PURE__ */ w(a, { message: c })]
91
+ children: [/* @__PURE__ */ D(S, { className: "mr-1 h-4 w-4" }), t ? "Voted" : "Vote"]
92
+ }), c && /* @__PURE__ */ D(a, { message: c })]
89
93
  });
90
94
  }
91
- function q({ feature: t }) {
92
- let c = e(), [l, u] = S(U, G), [d, f] = S(W, {
93
- refetchQueries: B.filter((e) => e !== "GetFeatureRequest"),
95
+ function X({ feature: t }) {
96
+ let c = e(), [l, u] = T(K, J), [d, f] = T(q, {
97
+ refetchQueries: U.filter((e) => e !== "GetFeatureRequest"),
94
98
  context: n
95
- }), [p, m] = g(null), h = u.loading || f.loading, v = z.includes(t.status) ? z : [t.status, ...z], y = async (e) => {
99
+ }), [p, m] = y(null), h = u.loading || f.loading, g = H.includes(t.status) ? H : [t.status, ...H], _ = async (e) => {
96
100
  m(null);
97
101
  try {
98
102
  await r(l({ variables: {
@@ -102,7 +106,7 @@ function q({ feature: t }) {
102
106
  } catch (e) {
103
107
  m(e instanceof Error ? e.message : "The status could not be changed.");
104
108
  }
105
- }, x = async () => {
109
+ }, v = async () => {
106
110
  m(null);
107
111
  try {
108
112
  await r(d({ variables: { id: t.id } })), c("/products/features-page");
@@ -110,49 +114,49 @@ function q({ feature: t }) {
110
114
  m(e instanceof Error ? e.message : "The request could not be deleted.");
111
115
  }
112
116
  };
113
- return /* @__PURE__ */ T("div", {
117
+ return /* @__PURE__ */ O("div", {
114
118
  className: "flex flex-col items-end gap-2",
115
- children: [/* @__PURE__ */ T("div", {
119
+ children: [/* @__PURE__ */ O("div", {
116
120
  className: "flex flex-wrap items-center justify-end gap-2",
117
121
  children: [
118
- /* @__PURE__ */ w("select", {
122
+ /* @__PURE__ */ D("select", {
119
123
  "aria-label": "Status",
120
124
  "data-testid": "feature-status",
121
125
  className: "rounded-md border border-input bg-background px-2 py-1 text-sm disabled:opacity-60",
122
126
  value: t.status,
123
127
  disabled: h,
124
128
  onChange: (e) => {
125
- e.target.value !== t.status && y(e.target.value);
129
+ e.target.value !== t.status && _(e.target.value);
126
130
  },
127
- children: v.map((e) => /* @__PURE__ */ w("option", {
131
+ children: g.map((e) => /* @__PURE__ */ D("option", {
128
132
  value: e,
129
133
  children: o(e)
130
134
  }, e))
131
135
  }),
132
- /* @__PURE__ */ w(J, { feature: t }),
133
- /* @__PURE__ */ T(E, {
136
+ /* @__PURE__ */ D(Z, { feature: t }),
137
+ /* @__PURE__ */ O(k, {
134
138
  size: "sm",
135
139
  variant: "outline",
136
140
  "data-testid": "feature-analytics",
137
141
  onClick: () => c(s("/products/feature-analytics-page", t.id)),
138
- children: [/* @__PURE__ */ w(_, { className: "mr-1 h-4 w-4" }), "Analytics"]
142
+ children: [/* @__PURE__ */ D(b, { className: "mr-1 h-4 w-4" }), "Analytics"]
139
143
  }),
140
- /* @__PURE__ */ w(i, {
144
+ /* @__PURE__ */ D(i, {
141
145
  label: "Delete",
142
146
  variant: "outline",
143
- icon: /* @__PURE__ */ w(b, { className: "mr-1 h-4 w-4" }),
147
+ icon: /* @__PURE__ */ D(C, { className: "mr-1 h-4 w-4" }),
144
148
  title: `Delete "${t.title}"?`,
145
149
  description: "The request and its votes are deleted. This cannot be undone here.",
146
150
  confirmLabel: "Delete request",
147
151
  destructive: !0,
148
152
  disabled: h,
149
- onConfirm: () => void x()
153
+ onConfirm: () => void v()
150
154
  })
151
155
  ]
152
- }), p && /* @__PURE__ */ w(a, { message: p })]
156
+ }), p && /* @__PURE__ */ D(a, { message: p })]
153
157
  });
154
158
  }
155
- function J({ feature: e }) {
159
+ function Z({ feature: e }) {
156
160
  let n = {
157
161
  title: e.title,
158
162
  description: e.description ?? "",
@@ -165,29 +169,45 @@ function J({ feature: e }) {
165
169
  kano: e.kano ?? "",
166
170
  valueScore: e.valueScore == null ? "" : String(e.valueScore),
167
171
  effortScore: e.effortScore == null ? "" : String(e.effortScore)
168
- }, [o, s] = g(!1), [p, m] = g(n), [_, y] = g(i), [b, x] = g(null), [C, D] = S(U, G), O = u(p.businessValue, {
172
+ }, o = {
173
+ reach: e.reach == null ? "" : String(e.reach),
174
+ impact: e.impact == null ? "" : String(e.impact),
175
+ confidence: e.confidence == null ? "" : String(e.confidence)
176
+ }, [s, m] = y(!1), [h, v] = y(n), [b, S] = y(i), [C, w] = y(o), [E, A] = y(null), [j, M] = T(K, J), N = u(h.businessValue, {
169
177
  min: 0,
170
178
  max: 100
171
- }), k = p.title.trim() !== "" && !O.invalid && h(_) && !D.loading, A = async () => {
172
- x(null);
173
- let a = (e) => e.trim() ? e.trim() : null, o = u(_.valueScore, {
179
+ }), H = h.title.trim() !== "" && !N.invalid && g(b) && _(C) && !M.loading, U = async () => {
180
+ A(null);
181
+ let a = (e) => e.trim() ? e.trim() : null, s = u(b.valueScore, {
174
182
  min: 1,
175
183
  max: 10
176
- }), c = u(_.effortScore, {
184
+ }), c = u(b.effortScore, {
177
185
  min: 1,
178
186
  max: 10
179
- }), l = {
180
- title: p.title.trim(),
181
- description: a(p.description),
182
- businessValue: O.value ?? null,
183
- effortEstimate: a(p.effortEstimate),
184
- projectId: p.projectId || null,
185
- workItemId: p.workItemId || null,
186
- moscow: _.moscow || null,
187
- kano: _.kano || null,
188
- valueScore: o.value ?? null,
189
- effortScore: c.value ?? null
190
- }, d = {
187
+ }), l = u(C.reach, {
188
+ min: 1,
189
+ max: 10
190
+ }), d = u(C.impact, {
191
+ min: 1,
192
+ max: 10
193
+ }), f = u(C.confidence, {
194
+ min: 1,
195
+ max: 10
196
+ }), p = {
197
+ title: h.title.trim(),
198
+ description: a(h.description),
199
+ businessValue: N.value ?? null,
200
+ effortEstimate: a(h.effortEstimate),
201
+ projectId: h.projectId || null,
202
+ workItemId: h.workItemId || null,
203
+ moscow: b.moscow || null,
204
+ kano: b.kano || null,
205
+ valueScore: s.value ?? null,
206
+ effortScore: c.value ?? null,
207
+ reach: l.value ?? null,
208
+ impact: d.value ?? null,
209
+ confidence: f.value ?? null
210
+ }, g = {
191
211
  title: n.title,
192
212
  description: a(n.description),
193
213
  businessValue: n.businessValue === "" ? null : Number(n.businessValue),
@@ -197,295 +217,420 @@ function J({ feature: e }) {
197
217
  moscow: i.moscow || null,
198
218
  kano: i.kano || null,
199
219
  valueScore: i.valueScore === "" ? null : Number(i.valueScore),
200
- effortScore: i.effortScore === "" ? null : Number(i.effortScore)
201
- }, f = Object.fromEntries(Object.entries(l).filter(([e, t]) => t !== d[e]));
202
- if (Object.keys(f).length === 0) {
203
- s(!1);
220
+ effortScore: i.effortScore === "" ? null : Number(i.effortScore),
221
+ reach: o.reach === "" ? null : Number(o.reach),
222
+ impact: o.impact === "" ? null : Number(o.impact),
223
+ confidence: o.confidence === "" ? null : Number(o.confidence)
224
+ }, _ = Object.fromEntries(Object.entries(p).filter(([e, t]) => t !== g[e]));
225
+ if (Object.keys(_).length === 0) {
226
+ m(!1);
204
227
  return;
205
228
  }
206
229
  try {
207
- await r(C({ variables: {
230
+ await r(j({ variables: {
208
231
  id: e.id,
209
- input: f
210
- } })), s(!1);
232
+ input: _
233
+ } })), m(!1);
211
234
  } catch (e) {
212
- x(t(e, "The request could not be saved."));
235
+ A(t(e, "The request could not be saved."));
213
236
  }
214
- }, z = "text-sm font-medium";
215
- return /* @__PURE__ */ T(M, {
216
- open: o,
237
+ }, W = "text-sm font-medium";
238
+ return /* @__PURE__ */ O(F, {
239
+ open: s,
217
240
  onOpenChange: (e) => {
218
- s(e), e ? (m(n), y(i)) : x(null);
241
+ m(e), e ? (v(n), S(i), w(o)) : A(null);
219
242
  },
220
- children: [/* @__PURE__ */ w(R, {
243
+ children: [/* @__PURE__ */ D(V, {
221
244
  asChild: !0,
222
- children: /* @__PURE__ */ T(E, {
245
+ children: /* @__PURE__ */ O(k, {
223
246
  size: "sm",
224
247
  variant: "outline",
225
248
  "data-testid": "feature-edit",
226
- children: [/* @__PURE__ */ w(v, { className: "mr-1 h-4 w-4" }), "Edit"]
249
+ children: [/* @__PURE__ */ D(x, { className: "mr-1 h-4 w-4" }), "Edit"]
227
250
  })
228
- }), /* @__PURE__ */ T(N, {
251
+ }), /* @__PURE__ */ O(I, {
229
252
  className: "max-w-lg",
230
253
  children: [
231
- /* @__PURE__ */ T(I, { children: [/* @__PURE__ */ w(L, { children: "Edit feature request" }), /* @__PURE__ */ w(P, { children: "Link the request to the work item that delivers it so releases can show who is waiting on it." })] }),
232
- /* @__PURE__ */ T("div", {
254
+ /* @__PURE__ */ O(z, { children: [/* @__PURE__ */ D(B, { children: "Edit feature request" }), /* @__PURE__ */ D(L, { children: "Link the request to the work item that delivers it so releases can show who is waiting on it." })] }),
255
+ /* @__PURE__ */ O("div", {
233
256
  className: "space-y-3",
234
257
  children: [
235
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
258
+ /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("label", {
236
259
  htmlFor: "feature-edit-title",
237
- className: z,
260
+ className: W,
238
261
  children: "Title"
239
- }), /* @__PURE__ */ w(j, {
262
+ }), /* @__PURE__ */ D(P, {
240
263
  id: "feature-edit-title",
241
264
  className: "mt-1",
242
- value: p.title,
243
- onChange: (e) => m({
244
- ...p,
265
+ value: h.title,
266
+ onChange: (e) => v({
267
+ ...h,
245
268
  title: e.target.value
246
269
  })
247
270
  })] }),
248
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
271
+ /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("label", {
249
272
  htmlFor: "feature-edit-description",
250
- className: z,
273
+ className: W,
251
274
  children: "Description"
252
- }), /* @__PURE__ */ w("textarea", {
275
+ }), /* @__PURE__ */ D("textarea", {
253
276
  id: "feature-edit-description",
254
277
  className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[72px]",
255
- value: p.description,
256
- onChange: (e) => m({
257
- ...p,
278
+ value: h.description,
279
+ onChange: (e) => v({
280
+ ...h,
258
281
  description: e.target.value
259
282
  })
260
283
  })] }),
261
- /* @__PURE__ */ T("div", {
284
+ /* @__PURE__ */ O("div", {
262
285
  className: "grid grid-cols-2 gap-3",
263
- children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
286
+ children: [/* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("label", {
264
287
  htmlFor: "feature-edit-value",
265
- className: z,
288
+ className: W,
266
289
  children: "Business value (0–100)"
267
- }), /* @__PURE__ */ w(j, {
290
+ }), /* @__PURE__ */ D(P, {
268
291
  id: "feature-edit-value",
269
292
  type: "number",
270
293
  min: 0,
271
294
  max: 100,
272
295
  className: "mt-1",
273
- value: p.businessValue,
274
- "aria-invalid": O.invalid,
275
- onChange: (e) => m({
276
- ...p,
296
+ value: h.businessValue,
297
+ "aria-invalid": N.invalid,
298
+ onChange: (e) => v({
299
+ ...h,
277
300
  businessValue: e.target.value
278
301
  })
279
- })] }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
302
+ })] }), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("label", {
280
303
  htmlFor: "feature-edit-effort",
281
- className: z,
304
+ className: W,
282
305
  children: "Effort"
283
- }), /* @__PURE__ */ w(j, {
306
+ }), /* @__PURE__ */ D(P, {
284
307
  id: "feature-edit-effort",
285
308
  className: "mt-1",
286
309
  placeholder: "e.g. M",
287
- value: p.effortEstimate,
288
- onChange: (e) => m({
289
- ...p,
310
+ value: h.effortEstimate,
311
+ onChange: (e) => v({
312
+ ...h,
290
313
  effortEstimate: e.target.value
291
314
  })
292
315
  })] })]
293
316
  }),
294
- O.invalid && /* @__PURE__ */ w(a, { message: "Business value is a whole number from 0 to 100." }),
295
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
317
+ N.invalid && /* @__PURE__ */ D(a, { message: "Business value is a whole number from 0 to 100." }),
318
+ /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("label", {
296
319
  htmlFor: "feature-edit-project",
297
- className: z,
320
+ className: W,
298
321
  children: "Project"
299
- }), /* @__PURE__ */ w("div", {
322
+ }), /* @__PURE__ */ D("div", {
300
323
  className: "mt-1",
301
- children: /* @__PURE__ */ w(c, {
324
+ children: /* @__PURE__ */ D(c, {
302
325
  id: "feature-edit-project",
303
- value: p.projectId,
326
+ value: h.projectId,
304
327
  noneLabel: "No project",
305
- onChange: (e) => m({
306
- ...p,
328
+ onChange: (e) => v({
329
+ ...h,
307
330
  projectId: e,
308
331
  workItemId: ""
309
332
  })
310
333
  })
311
334
  })] }),
312
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
335
+ /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("label", {
313
336
  htmlFor: "feature-edit-workitem",
314
- className: z,
337
+ className: W,
315
338
  children: "Delivered by work item"
316
- }), /* @__PURE__ */ w("div", {
339
+ }), /* @__PURE__ */ D("div", {
317
340
  className: "mt-1",
318
- children: /* @__PURE__ */ w(l, {
341
+ children: /* @__PURE__ */ D(l, {
319
342
  id: "feature-edit-workitem",
320
- projectId: p.projectId || void 0,
321
- value: p.workItemId,
322
- onChange: (e) => m({
323
- ...p,
343
+ projectId: h.projectId || void 0,
344
+ value: h.workItemId,
345
+ onChange: (e) => v({
346
+ ...h,
324
347
  workItemId: e
325
348
  })
326
349
  })
327
350
  })] }),
328
- /* @__PURE__ */ T("div", {
351
+ /* @__PURE__ */ O("div", {
329
352
  className: "border-t pt-3",
330
353
  children: [
331
- /* @__PURE__ */ w("p", {
332
- className: z,
354
+ /* @__PURE__ */ D("p", {
355
+ className: W,
333
356
  children: "Prioritization"
334
357
  }),
335
- /* @__PURE__ */ T("div", {
358
+ /* @__PURE__ */ O("div", {
336
359
  className: "mt-1 flex items-center gap-2",
337
- children: [/* @__PURE__ */ w("span", {
360
+ children: [/* @__PURE__ */ D("span", {
338
361
  className: "text-xs text-muted-foreground",
339
362
  children: "Current quadrant:"
340
- }), /* @__PURE__ */ w(f, { quadrant: e.valueEffortQuadrant ?? null })]
363
+ }), /* @__PURE__ */ D(f, { quadrant: e.valueEffortQuadrant ?? null })]
341
364
  }),
342
- /* @__PURE__ */ w("div", {
365
+ /* @__PURE__ */ D("div", {
343
366
  className: "mt-2",
344
- children: /* @__PURE__ */ w(d, {
367
+ children: /* @__PURE__ */ D(d, {
345
368
  idPrefix: "feature-edit",
346
- values: _,
347
- onChange: y
369
+ values: b,
370
+ onChange: S
348
371
  })
372
+ }),
373
+ /* @__PURE__ */ O("div", {
374
+ className: "mt-3 border-t pt-3",
375
+ children: [
376
+ /* @__PURE__ */ D("p", {
377
+ className: W,
378
+ children: "RICE"
379
+ }),
380
+ /* @__PURE__ */ O("div", {
381
+ className: "mt-1 flex items-center gap-2",
382
+ children: [/* @__PURE__ */ D("span", {
383
+ className: "text-xs text-muted-foreground",
384
+ children: "Current RICE score:"
385
+ }), /* @__PURE__ */ D("span", {
386
+ className: "text-sm font-medium",
387
+ "data-testid": "feature-edit-rice-score",
388
+ children: e.riceScore == null ? "—" : e.riceScore.toFixed(1)
389
+ })]
390
+ }),
391
+ /* @__PURE__ */ D("div", {
392
+ className: "mt-2",
393
+ children: /* @__PURE__ */ D(p, {
394
+ idPrefix: "feature-edit",
395
+ values: C,
396
+ onChange: w,
397
+ effortScoreMissing: u(b.effortScore, {
398
+ min: 1,
399
+ max: 10
400
+ }).value == null
401
+ })
402
+ })
403
+ ]
349
404
  })
350
405
  ]
351
406
  }),
352
- b && /* @__PURE__ */ w(a, { message: b })
407
+ E && /* @__PURE__ */ D(a, { message: E })
353
408
  ]
354
409
  }),
355
- /* @__PURE__ */ T(F, { children: [/* @__PURE__ */ w(E, {
410
+ /* @__PURE__ */ O(R, { children: [/* @__PURE__ */ D(k, {
356
411
  variant: "outline",
357
- onClick: () => s(!1),
412
+ onClick: () => m(!1),
358
413
  children: "Cancel"
359
- }), /* @__PURE__ */ w(E, {
360
- onClick: () => void A(),
361
- disabled: !k,
362
- children: D.loading ? "Saving…" : "Save"
414
+ }), /* @__PURE__ */ D(k, {
415
+ onClick: () => void U(),
416
+ disabled: !H,
417
+ children: M.loading ? "Saving…" : "Save"
363
418
  })] })
364
419
  ]
365
420
  })]
366
421
  });
367
422
  }
368
- function Y({ feature: e }) {
423
+ function Q({ feature: e }) {
369
424
  let n = {
370
425
  moscow: e.moscow ?? "",
371
426
  kano: e.kano ?? "",
372
427
  valueScore: e.valueScore == null ? "" : String(e.valueScore),
373
428
  effortScore: e.effortScore == null ? "" : String(e.effortScore)
374
- }, [i, o] = g(!1), [s, c] = g(n), [l, _] = g(null), [y, b] = S(U, G), x = () => {
375
- c(n), _(null), o(!0);
376
- }, j = async () => {
377
- _(null);
378
- let n = u(s.valueScore, {
429
+ }, i = {
430
+ reach: e.reach == null ? "" : String(e.reach),
431
+ impact: e.impact == null ? "" : String(e.impact),
432
+ confidence: e.confidence == null ? "" : String(e.confidence)
433
+ }, [o, s] = y(!1), [c, l] = y(n), [b, S] = y(i), [C, w] = y(null), [P, F] = T(K, J), I = () => {
434
+ l(n), S(i), w(null), s(!0);
435
+ }, L = async () => {
436
+ w(null);
437
+ let n = u(c.valueScore, {
379
438
  min: 1,
380
439
  max: 10
381
- }), i = u(s.effortScore, {
440
+ }), i = u(c.effortScore, {
382
441
  min: 1,
383
442
  max: 10
384
- }), a = {
385
- moscow: s.moscow || null,
386
- kano: s.kano || null,
443
+ }), a = u(b.reach, {
444
+ min: 1,
445
+ max: 10
446
+ }), o = u(b.impact, {
447
+ min: 1,
448
+ max: 10
449
+ }), l = u(b.confidence, {
450
+ min: 1,
451
+ max: 10
452
+ }), d = {
453
+ moscow: c.moscow || null,
454
+ kano: c.kano || null,
387
455
  valueScore: n.value ?? null,
388
- effortScore: i.value ?? null
456
+ effortScore: i.value ?? null,
457
+ reach: a.value ?? null,
458
+ impact: o.value ?? null,
459
+ confidence: l.value ?? null
389
460
  };
390
461
  try {
391
- await r(y({ variables: {
462
+ await r(P({ variables: {
392
463
  id: e.id,
393
- input: a
394
- } })), o(!1);
464
+ input: d
465
+ } })), s(!1);
395
466
  } catch (e) {
396
- _(t(e, "The prioritization could not be saved."));
467
+ w(t(e, "The prioritization could not be saved."));
397
468
  }
398
469
  };
399
- return /* @__PURE__ */ T(D, {
470
+ return /* @__PURE__ */ O(A, {
400
471
  "data-testid": "feature-prioritization-card",
401
- children: [/* @__PURE__ */ T(k, {
472
+ children: [/* @__PURE__ */ O(M, {
402
473
  className: "flex flex-row items-center justify-between gap-2",
403
- children: [/* @__PURE__ */ w(A, { children: "Prioritization" }), !i && /* @__PURE__ */ T(E, {
474
+ children: [/* @__PURE__ */ D(N, { children: "Prioritization" }), !o && /* @__PURE__ */ O(k, {
404
475
  size: "sm",
405
476
  variant: "outline",
406
477
  "data-testid": "feature-prioritization-edit",
407
- onClick: x,
408
- children: [/* @__PURE__ */ w(v, { className: "mr-1 h-4 w-4" }), "Edit"]
478
+ onClick: I,
479
+ children: [/* @__PURE__ */ D(x, { className: "mr-1 h-4 w-4" }), "Edit"]
409
480
  })]
410
- }), /* @__PURE__ */ w(O, {
481
+ }), /* @__PURE__ */ D(j, {
411
482
  className: "space-y-3",
412
- children: i ? /* @__PURE__ */ T(C, { children: [
413
- /* @__PURE__ */ w(d, {
483
+ children: o ? /* @__PURE__ */ O(E, { children: [
484
+ /* @__PURE__ */ D(d, {
414
485
  idPrefix: "feature-prio",
415
- values: s,
416
- onChange: c
486
+ values: c,
487
+ onChange: l
488
+ }),
489
+ /* @__PURE__ */ O("div", {
490
+ className: "border-t pt-3",
491
+ children: [/* @__PURE__ */ D("p", {
492
+ className: "text-sm font-medium mb-1",
493
+ children: "RICE"
494
+ }), /* @__PURE__ */ D(p, {
495
+ idPrefix: "feature-prio",
496
+ values: b,
497
+ onChange: S,
498
+ effortScoreMissing: u(c.effortScore, {
499
+ min: 1,
500
+ max: 10
501
+ }).value == null
502
+ })]
417
503
  }),
418
- l && /* @__PURE__ */ w(a, { message: l }),
419
- /* @__PURE__ */ T("div", {
504
+ C && /* @__PURE__ */ D(a, { message: C }),
505
+ /* @__PURE__ */ O("div", {
420
506
  className: "flex justify-end gap-2",
421
- children: [/* @__PURE__ */ w(E, {
507
+ children: [/* @__PURE__ */ D(k, {
422
508
  size: "sm",
423
509
  variant: "outline",
424
- onClick: () => o(!1),
510
+ onClick: () => s(!1),
425
511
  children: "Cancel"
426
- }), /* @__PURE__ */ w(E, {
512
+ }), /* @__PURE__ */ D(k, {
427
513
  size: "sm",
428
514
  "data-testid": "feature-prioritization-save",
429
- disabled: b.loading || !h(s),
430
- onClick: () => void j(),
431
- children: b.loading ? "Saving…" : "Save"
515
+ disabled: F.loading || !g(c) || !_(b),
516
+ onClick: () => void L(),
517
+ children: F.loading ? "Saving…" : "Save"
432
518
  })]
433
519
  })
434
- ] }) : /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ T("div", {
435
- className: "flex items-center gap-2",
436
- children: [/* @__PURE__ */ w("span", {
437
- className: "text-xs text-muted-foreground",
438
- children: "Quadrant:"
439
- }), /* @__PURE__ */ w(f, { quadrant: e.valueEffortQuadrant ?? null })]
440
- }), /* @__PURE__ */ T("div", {
441
- className: "grid grid-cols-2 gap-2 text-sm",
442
- children: [
443
- /* @__PURE__ */ T("div", {
444
- className: "flex justify-between",
445
- children: [/* @__PURE__ */ w("span", {
446
- className: "text-muted-foreground",
447
- children: "MoSCoW"
448
- }), /* @__PURE__ */ w("span", {
449
- className: "font-medium",
450
- children: m(e.moscow)
451
- })]
452
- }),
453
- /* @__PURE__ */ T("div", {
454
- className: "flex justify-between",
455
- children: [/* @__PURE__ */ w("span", {
456
- className: "text-muted-foreground",
457
- children: "Kano"
458
- }), /* @__PURE__ */ w("span", {
459
- className: "font-medium",
460
- children: p(e.kano)
461
- })]
462
- }),
463
- /* @__PURE__ */ T("div", {
464
- className: "flex justify-between",
465
- children: [/* @__PURE__ */ w("span", {
466
- className: "text-muted-foreground",
467
- children: "Value score"
468
- }), /* @__PURE__ */ w("span", {
469
- className: "font-medium",
470
- children: e.valueScore ?? "Not set"
471
- })]
472
- }),
473
- /* @__PURE__ */ T("div", {
474
- className: "flex justify-between",
475
- children: [/* @__PURE__ */ w("span", {
476
- className: "text-muted-foreground",
477
- children: "Effort score"
478
- }), /* @__PURE__ */ w("span", {
479
- className: "font-medium",
480
- children: e.effortScore ?? "Not set"
481
- })]
482
- })
483
- ]
484
- })] })
520
+ ] }) : /* @__PURE__ */ O(E, { children: [
521
+ /* @__PURE__ */ O("div", {
522
+ className: "flex items-center gap-2",
523
+ children: [/* @__PURE__ */ D("span", {
524
+ className: "text-xs text-muted-foreground",
525
+ children: "Quadrant:"
526
+ }), /* @__PURE__ */ D(f, { quadrant: e.valueEffortQuadrant ?? null })]
527
+ }),
528
+ /* @__PURE__ */ O("div", {
529
+ className: "grid grid-cols-2 gap-2 text-sm",
530
+ children: [
531
+ /* @__PURE__ */ O("div", {
532
+ className: "flex justify-between",
533
+ children: [/* @__PURE__ */ D("span", {
534
+ className: "text-muted-foreground",
535
+ children: "MoSCoW"
536
+ }), /* @__PURE__ */ D("span", {
537
+ className: "font-medium",
538
+ children: h(e.moscow)
539
+ })]
540
+ }),
541
+ /* @__PURE__ */ O("div", {
542
+ className: "flex justify-between",
543
+ children: [/* @__PURE__ */ D("span", {
544
+ className: "text-muted-foreground",
545
+ children: "Kano"
546
+ }), /* @__PURE__ */ D("span", {
547
+ className: "font-medium",
548
+ children: m(e.kano)
549
+ })]
550
+ }),
551
+ /* @__PURE__ */ O("div", {
552
+ className: "flex justify-between",
553
+ children: [/* @__PURE__ */ D("span", {
554
+ className: "text-muted-foreground",
555
+ children: "Value score"
556
+ }), /* @__PURE__ */ D("span", {
557
+ className: "font-medium",
558
+ children: e.valueScore ?? "Not set"
559
+ })]
560
+ }),
561
+ /* @__PURE__ */ O("div", {
562
+ className: "flex justify-between",
563
+ children: [/* @__PURE__ */ D("span", {
564
+ className: "text-muted-foreground",
565
+ children: "Effort score"
566
+ }), /* @__PURE__ */ D("span", {
567
+ className: "font-medium",
568
+ children: e.effortScore ?? "Not set"
569
+ })]
570
+ })
571
+ ]
572
+ }),
573
+ /* @__PURE__ */ O("div", {
574
+ className: "border-t pt-3",
575
+ children: [
576
+ /* @__PURE__ */ O("div", {
577
+ className: "flex items-center justify-between",
578
+ children: [/* @__PURE__ */ D("span", {
579
+ className: "text-xs text-muted-foreground",
580
+ children: "RICE score"
581
+ }), /* @__PURE__ */ D("span", {
582
+ className: "font-medium",
583
+ "data-testid": "feature-rice-score",
584
+ children: e.riceScore == null ? "—" : e.riceScore.toFixed(1)
585
+ })]
586
+ }),
587
+ e.riceScore == null && /* @__PURE__ */ D("p", {
588
+ className: "text-xs text-muted-foreground mt-0.5",
589
+ "data-testid": "feature-rice-missing-hint",
590
+ children: v(e)
591
+ }),
592
+ /* @__PURE__ */ O("div", {
593
+ className: "grid grid-cols-3 gap-2 text-sm mt-2",
594
+ children: [
595
+ /* @__PURE__ */ O("div", {
596
+ className: "flex justify-between",
597
+ children: [/* @__PURE__ */ D("span", {
598
+ className: "text-muted-foreground",
599
+ children: "Reach"
600
+ }), /* @__PURE__ */ D("span", {
601
+ className: "font-medium",
602
+ children: e.reach ?? "Not set"
603
+ })]
604
+ }),
605
+ /* @__PURE__ */ O("div", {
606
+ className: "flex justify-between",
607
+ children: [/* @__PURE__ */ D("span", {
608
+ className: "text-muted-foreground",
609
+ children: "Impact"
610
+ }), /* @__PURE__ */ D("span", {
611
+ className: "font-medium",
612
+ children: e.impact ?? "Not set"
613
+ })]
614
+ }),
615
+ /* @__PURE__ */ O("div", {
616
+ className: "flex justify-between",
617
+ children: [/* @__PURE__ */ D("span", {
618
+ className: "text-muted-foreground",
619
+ children: "Confidence"
620
+ }), /* @__PURE__ */ D("span", {
621
+ className: "font-medium",
622
+ children: e.confidence ?? "Not set"
623
+ })]
624
+ })
625
+ ]
626
+ })
627
+ ]
628
+ })
629
+ ] })
485
630
  })]
486
631
  });
487
632
  }
488
633
  //#endregion
489
- export { q as FeatureHeaderActions, Y as FeaturePrioritizationCard, K as FeatureVoteButton };
634
+ export { X as FeatureHeaderActions, Q as FeaturePrioritizationCard, Y as FeatureVoteButton };
490
635
 
491
636
  //# sourceMappingURL=FeatureControls.js.map