@burdenoff/microfe-planmagnet 2026.927.1 → 2026.927.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/planmagnet/admin/PlanMagnetAdminRoot.d.ts.map +1 -1
  2. package/dist/planmagnet/admin/PlanMagnetAdminRoot.js +128 -124
  3. package/dist/planmagnet/admin/PlanMagnetAdminRoot.js.map +1 -1
  4. package/dist/planmagnet/controls/ConfirmButton.d.ts +25 -0
  5. package/dist/planmagnet/controls/ConfirmButton.d.ts.map +1 -0
  6. package/dist/planmagnet/controls/ConfirmButton.js +30 -0
  7. package/dist/planmagnet/controls/ConfirmButton.js.map +1 -0
  8. package/dist/planmagnet/controls/ProjectControls.d.ts +13 -0
  9. package/dist/planmagnet/controls/ProjectControls.d.ts.map +1 -0
  10. package/dist/planmagnet/controls/ProjectControls.js +104 -0
  11. package/dist/planmagnet/controls/ProjectControls.js.map +1 -0
  12. package/dist/planmagnet/controls/WorkItemControls.d.ts +52 -0
  13. package/dist/planmagnet/controls/WorkItemControls.d.ts.map +1 -0
  14. package/dist/planmagnet/controls/WorkItemControls.js +198 -0
  15. package/dist/planmagnet/controls/WorkItemControls.js.map +1 -0
  16. package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts.map +1 -1
  17. package/dist/planmagnet/pages/DashboardDashboardPagePage.js +14 -4
  18. package/dist/planmagnet/pages/DashboardDashboardPagePage.js.map +1 -1
  19. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +4 -4
  20. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  21. package/dist/planmagnet/pages/DocsDocsPagePage.js +4 -4
  22. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  23. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +102 -100
  24. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  25. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  26. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +95 -94
  27. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  28. package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
  29. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +97 -90
  30. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
  31. package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -1
  32. package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js +150 -111
  33. package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.js.map +1 -1
  34. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts.map +1 -1
  35. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js +121 -94
  36. package/dist/planmagnet/pages/ProjectsEditProjectPagePage.js.map +1 -1
  37. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts.map +1 -1
  38. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js +84 -73
  39. package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.js.map +1 -1
  40. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -1
  41. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +13 -8
  42. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -1
  43. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  44. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +129 -125
  45. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  46. package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts.map +1 -1
  47. package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js +112 -109
  48. package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.js.map +1 -1
  49. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  50. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +134 -132
  51. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  52. package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -1
  53. package/dist/planmagnet/pages/ReportsReportsPagePage.js +72 -83
  54. package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -1
  55. package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -1
  56. package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +109 -108
  57. package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
  58. package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
  59. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +167 -111
  60. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
  61. package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
  62. package/dist/planmagnet/pages/TasksEditTaskPagePage.js +101 -99
  63. package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
  64. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  65. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +149 -147
  66. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  67. package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -1
  68. package/dist/planmagnet/pages/TasksTasksPagePage.js +4 -8
  69. package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
  70. package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
  71. package/dist/planmagnet/pages/TeamTeamPagePage.js +68 -69
  72. package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
  73. package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.d.ts.map +1 -1
  74. package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.js +1 -5
  75. package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.js.map +1 -1
  76. package/dist/planmagnet/people/People.d.ts +18 -0
  77. package/dist/planmagnet/people/People.d.ts.map +1 -1
  78. package/dist/planmagnet/people/People.js +26 -12
  79. package/dist/planmagnet/people/People.js.map +1 -1
  80. package/dist/planmagnet/roadmaps/RoadmapControls.d.ts +34 -0
  81. package/dist/planmagnet/roadmaps/RoadmapControls.d.ts.map +1 -0
  82. package/dist/planmagnet/roadmaps/RoadmapControls.js +301 -0
  83. package/dist/planmagnet/roadmaps/RoadmapControls.js.map +1 -0
  84. package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
  85. package/dist/planmagnet/sprints/SprintControls.js +194 -215
  86. package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
  87. package/package.json +1 -1
@@ -1,13 +1,14 @@
1
1
  import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
2
- import { detailPath as n, rowLinkProps as r } from "../utils/rowNavigation.js";
3
- import { useState as i } from "react";
4
- import { ArrowUpDown as a, Filter as o, Loader2 as s, Plus as c, Star as l, Target as u, ThumbsUp as d } from "lucide-react";
5
- import { gql as f } from "@apollo/client";
6
- import { useQuery as p } from "@apollo/client/react";
7
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
8
- import { Badge as g, Button as _, Card as v, CardContent as y } from "@burdenoff/fe-libs/ui";
2
+ import { PersonName as n } from "../people/People.js";
3
+ import { detailPath as r, rowLinkProps as i } from "../utils/rowNavigation.js";
4
+ import { useState as a } from "react";
5
+ import { ArrowUpDown as o, Filter as s, Loader2 as c, Plus as l, Star as u, Target as d, ThumbsUp as f } from "lucide-react";
6
+ import { gql as p } from "@apollo/client";
7
+ import { useQuery as m } from "@apollo/client/react";
8
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
9
+ import { Badge as _, Button as v, Card as y, CardContent as b } from "@burdenoff/fe-libs/ui";
9
10
  //#region src/planmagnet/pages/ProductsFeaturesPagePage.tsx
10
- var b = f`
11
+ var x = p`
11
12
  query ListFeatureRequests(
12
13
  $workspaceId: ID!
13
14
  $filter: PlanmagnetFeatureRequestFilter
@@ -31,7 +32,7 @@ var b = f`
31
32
  totalCount
32
33
  }
33
34
  }
34
- `, x = {
35
+ `, S = {
35
36
  SUBMITTED: "bg-gray-100 text-gray-800",
36
37
  UNDER_REVIEW: "bg-yellow-100 text-yellow-800",
37
38
  PLANNED: "bg-blue-100 text-blue-800",
@@ -40,27 +41,27 @@ var b = f`
40
41
  DECLINED: "bg-red-100 text-red-800",
41
42
  DUPLICATE: "bg-orange-100 text-orange-800"
42
43
  };
43
- function S() {
44
- let f = t(), { workspaceId: S } = e(), [C, w] = i("all"), [T, E] = i("priorityScore"), { data: D, loading: O, error: k } = p(b, {
44
+ function C() {
45
+ let p = t(), { workspaceId: C } = e(), [w, T] = a("all"), [E, D] = a("priorityScore"), { data: O, loading: k, error: A } = m(x, {
45
46
  variables: {
46
- workspaceId: S,
47
- filter: C === "all" ? void 0 : { status: C },
47
+ workspaceId: C,
48
+ filter: w === "all" ? void 0 : { status: w },
48
49
  pagination: { first: 50 }
49
50
  },
50
- skip: !S
51
+ skip: !C
51
52
  });
52
- if (O && !D) return /* @__PURE__ */ m("div", {
53
+ if (k && !O) return /* @__PURE__ */ h("div", {
53
54
  className: "flex items-center justify-center p-12",
54
- children: /* @__PURE__ */ m(s, { className: "h-8 w-8 animate-spin text-muted-foreground" })
55
+ children: /* @__PURE__ */ h(c, { className: "h-8 w-8 animate-spin text-muted-foreground" })
55
56
  });
56
- if (k) return /* @__PURE__ */ h("div", {
57
+ if (A) return /* @__PURE__ */ g("div", {
57
58
  className: "p-6 text-destructive",
58
- children: ["Failed to load features: ", k.message]
59
+ children: ["Failed to load features: ", A.message]
59
60
  });
60
- let A = D?.planmagnetFeatureRequests?.items ?? [], j = D?.planmagnetFeatureRequests?.totalCount ?? 0, M = [...A].sort((e, t) => {
61
- let n = e[T] ?? 0;
62
- return (t[T] ?? 0) - n;
63
- }), N = [
61
+ let j = O?.planmagnetFeatureRequests?.items ?? [], M = O?.planmagnetFeatureRequests?.totalCount ?? 0, N = [...j].sort((e, t) => {
62
+ let n = e[E] ?? 0;
63
+ return (t[E] ?? 0) - n;
64
+ }), P = [
64
65
  "all",
65
66
  "SUBMITTED",
66
67
  "UNDER_REVIEW",
@@ -69,176 +70,176 @@ function S() {
69
70
  "COMPLETED",
70
71
  "DECLINED",
71
72
  "DUPLICATE"
72
- ], P = {
73
- total: j,
74
- inProgress: A.filter((e) => e.status === "IN_PROGRESS").length,
75
- completed: A.filter((e) => e.status === "COMPLETED").length,
76
- avgPriority: A.length > 0 ? Math.round(A.reduce((e, t) => e + (t.priorityScore ?? 0), 0) / A.length) : 0
73
+ ], F = {
74
+ total: M,
75
+ inProgress: j.filter((e) => e.status === "IN_PROGRESS").length,
76
+ completed: j.filter((e) => e.status === "COMPLETED").length,
77
+ avgPriority: j.length > 0 ? Math.round(j.reduce((e, t) => e + (t.priorityScore ?? 0), 0) / j.length) : 0
77
78
  };
78
- return /* @__PURE__ */ h("div", {
79
+ return /* @__PURE__ */ g("div", {
79
80
  className: "space-y-6 p-6",
80
81
  children: [
81
- /* @__PURE__ */ h("div", {
82
+ /* @__PURE__ */ g("div", {
82
83
  className: "flex items-center justify-between",
83
- children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
84
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
84
85
  className: "text-2xl font-semibold",
85
86
  children: "Features"
86
- }), /* @__PURE__ */ h("p", {
87
+ }), /* @__PURE__ */ g("p", {
87
88
  className: "text-sm text-muted-foreground",
88
- children: [j, " feature requests across all products"]
89
- })] }), /* @__PURE__ */ h(_, {
89
+ children: [M, " feature requests across all products"]
90
+ })] }), /* @__PURE__ */ g(v, {
90
91
  size: "sm",
91
- onClick: () => f("/products/new-feature-page"),
92
- children: [/* @__PURE__ */ m(c, { className: "mr-1 h-4 w-4" }), "New Feature"]
92
+ onClick: () => p("/products/new-feature-page"),
93
+ children: [/* @__PURE__ */ h(l, { className: "mr-1 h-4 w-4" }), "New Feature"]
93
94
  })]
94
95
  }),
95
- /* @__PURE__ */ h("div", {
96
+ /* @__PURE__ */ g("div", {
96
97
  className: "grid grid-cols-2 md:grid-cols-4 gap-4",
97
98
  children: [
98
- /* @__PURE__ */ m(v, { children: /* @__PURE__ */ h(y, {
99
+ /* @__PURE__ */ h(y, { children: /* @__PURE__ */ g(b, {
99
100
  className: "pt-4",
100
- children: [/* @__PURE__ */ m("p", {
101
+ children: [/* @__PURE__ */ h("p", {
101
102
  className: "text-xs text-muted-foreground",
102
103
  children: "Total Features"
103
- }), /* @__PURE__ */ m("p", {
104
+ }), /* @__PURE__ */ h("p", {
104
105
  className: "text-xl font-bold",
105
- children: P.total
106
+ children: F.total
106
107
  })]
107
108
  }) }),
108
- /* @__PURE__ */ m(v, { children: /* @__PURE__ */ h(y, {
109
+ /* @__PURE__ */ h(y, { children: /* @__PURE__ */ g(b, {
109
110
  className: "pt-4",
110
- children: [/* @__PURE__ */ m("p", {
111
+ children: [/* @__PURE__ */ h("p", {
111
112
  className: "text-xs text-muted-foreground",
112
113
  children: "In Progress"
113
- }), /* @__PURE__ */ m("p", {
114
+ }), /* @__PURE__ */ h("p", {
114
115
  className: "text-xl font-bold",
115
- children: P.inProgress
116
+ children: F.inProgress
116
117
  })]
117
118
  }) }),
118
- /* @__PURE__ */ m(v, { children: /* @__PURE__ */ h(y, {
119
+ /* @__PURE__ */ h(y, { children: /* @__PURE__ */ g(b, {
119
120
  className: "pt-4",
120
- children: [/* @__PURE__ */ m("p", {
121
+ children: [/* @__PURE__ */ h("p", {
121
122
  className: "text-xs text-muted-foreground",
122
123
  children: "Completed"
123
- }), /* @__PURE__ */ m("p", {
124
+ }), /* @__PURE__ */ h("p", {
124
125
  className: "text-xl font-bold",
125
- children: P.completed
126
+ children: F.completed
126
127
  })]
127
128
  }) }),
128
- /* @__PURE__ */ m(v, { children: /* @__PURE__ */ h(y, {
129
+ /* @__PURE__ */ h(y, { children: /* @__PURE__ */ g(b, {
129
130
  className: "pt-4",
130
- children: [/* @__PURE__ */ m("p", {
131
+ children: [/* @__PURE__ */ h("p", {
131
132
  className: "text-xs text-muted-foreground",
132
133
  children: "Avg Priority Score"
133
- }), /* @__PURE__ */ m("p", {
134
+ }), /* @__PURE__ */ h("p", {
134
135
  className: "text-xl font-bold",
135
- children: P.avgPriority
136
+ children: F.avgPriority
136
137
  })]
137
138
  }) })
138
139
  ]
139
140
  }),
140
- /* @__PURE__ */ h("div", {
141
+ /* @__PURE__ */ g("div", {
141
142
  className: "flex items-center justify-between flex-wrap gap-2",
142
- children: [/* @__PURE__ */ h("div", {
143
+ children: [/* @__PURE__ */ g("div", {
143
144
  className: "flex items-center gap-2",
144
- children: [/* @__PURE__ */ m(o, { className: "h-4 w-4 text-muted-foreground" }), N.map((e) => /* @__PURE__ */ m("button", {
145
- onClick: () => w(e),
146
- className: `px-2 py-1 text-xs rounded-md capitalize ${C === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
145
+ children: [/* @__PURE__ */ h(s, { className: "h-4 w-4 text-muted-foreground" }), P.map((e) => /* @__PURE__ */ h("button", {
146
+ onClick: () => T(e),
147
+ className: `px-2 py-1 text-xs rounded-md capitalize ${w === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
147
148
  children: e === "all" ? "All" : e.toLowerCase().replace("_", " ")
148
149
  }, e))]
149
- }), /* @__PURE__ */ h("div", {
150
+ }), /* @__PURE__ */ g("div", {
150
151
  className: "flex items-center gap-2",
151
- children: [/* @__PURE__ */ m(a, { className: "h-4 w-4 text-muted-foreground" }), [
152
+ children: [/* @__PURE__ */ h(o, { className: "h-4 w-4 text-muted-foreground" }), [
152
153
  "priorityScore",
153
154
  "voteCount",
154
155
  "businessValue"
155
- ].map((e) => /* @__PURE__ */ m("button", {
156
- onClick: () => E(e),
157
- className: `px-2 py-1 text-xs rounded-md capitalize ${T === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
156
+ ].map((e) => /* @__PURE__ */ h("button", {
157
+ onClick: () => D(e),
158
+ className: `px-2 py-1 text-xs rounded-md capitalize ${E === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
158
159
  children: e === "priorityScore" ? "Priority" : e === "voteCount" ? "Votes" : "Value"
159
160
  }, e))]
160
161
  })]
161
162
  }),
162
- /* @__PURE__ */ m("div", {
163
+ /* @__PURE__ */ h("div", {
163
164
  className: "space-y-3",
164
- children: M.map((e) => /* @__PURE__ */ m(v, {
165
- ...r(() => f(n("/products/feature-detail-page", e.id)), e.title),
166
- children: /* @__PURE__ */ m(y, {
165
+ children: N.map((e) => /* @__PURE__ */ h(y, {
166
+ ...i(() => p(r("/products/feature-detail-page", e.id)), e.title),
167
+ children: /* @__PURE__ */ h(b, {
167
168
  className: "py-4",
168
- children: /* @__PURE__ */ h("div", {
169
+ children: /* @__PURE__ */ g("div", {
169
170
  className: "flex items-start justify-between gap-4",
170
- children: [/* @__PURE__ */ h("div", {
171
+ children: [/* @__PURE__ */ g("div", {
171
172
  className: "flex-1 space-y-2",
172
173
  children: [
173
- /* @__PURE__ */ h("div", {
174
+ /* @__PURE__ */ g("div", {
174
175
  className: "flex items-center gap-2",
175
- children: [/* @__PURE__ */ m("span", {
176
+ children: [/* @__PURE__ */ h("span", {
176
177
  className: "text-sm font-medium",
177
178
  children: e.title
178
- }), /* @__PURE__ */ m("span", {
179
- className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${x[e.status] ?? "bg-gray-100"}`,
179
+ }), /* @__PURE__ */ h("span", {
180
+ className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${S[e.status] ?? "bg-gray-100"}`,
180
181
  children: e.status.toLowerCase().replace("_", " ")
181
182
  })]
182
183
  }),
183
- /* @__PURE__ */ m("p", {
184
+ /* @__PURE__ */ h("p", {
184
185
  className: "text-xs text-muted-foreground",
185
186
  children: e.description
186
187
  }),
187
- /* @__PURE__ */ h("div", {
188
+ /* @__PURE__ */ g("div", {
188
189
  className: "flex items-center gap-4 text-xs text-muted-foreground",
189
190
  children: [
190
- /* @__PURE__ */ h("span", { children: ["Effort: ", e.effortEstimate ?? "N/A"] }),
191
- /* @__PURE__ */ h("span", { children: ["Submitted by: ", e.submittedBy] }),
192
- /* @__PURE__ */ m("span", { children: new Date(e.updatedAt).toLocaleDateString() })
191
+ /* @__PURE__ */ g("span", { children: ["Effort: ", e.effortEstimate ?? "N/A"] }),
192
+ /* @__PURE__ */ g("span", { children: ["Submitted by: ", /* @__PURE__ */ h(n, { id: e.submittedBy })] }),
193
+ /* @__PURE__ */ h("span", { children: new Date(e.updatedAt).toLocaleDateString() })
193
194
  ]
194
195
  }),
195
- e.tags.length > 0 && /* @__PURE__ */ m("div", {
196
+ e.tags.length > 0 && /* @__PURE__ */ h("div", {
196
197
  className: "flex gap-1",
197
- children: e.tags.map((e) => /* @__PURE__ */ m(g, {
198
+ children: e.tags.map((e) => /* @__PURE__ */ h(_, {
198
199
  variant: "outline",
199
200
  className: "text-[10px]",
200
201
  children: e
201
202
  }, e))
202
203
  })
203
204
  ]
204
- }), /* @__PURE__ */ h("div", {
205
+ }), /* @__PURE__ */ g("div", {
205
206
  className: "flex items-center gap-4 shrink-0",
206
207
  children: [
207
- /* @__PURE__ */ h("div", {
208
+ /* @__PURE__ */ g("div", {
208
209
  className: "text-center",
209
- children: [/* @__PURE__ */ h("div", {
210
+ children: [/* @__PURE__ */ g("div", {
210
211
  className: "flex items-center gap-1",
211
- children: [/* @__PURE__ */ m(u, { className: "h-3 w-3 text-primary" }), /* @__PURE__ */ m("span", {
212
+ children: [/* @__PURE__ */ h(d, { className: "h-3 w-3 text-primary" }), /* @__PURE__ */ h("span", {
212
213
  className: "text-sm font-bold",
213
214
  children: e.priorityScore ?? 0
214
215
  })]
215
- }), /* @__PURE__ */ m("p", {
216
+ }), /* @__PURE__ */ h("p", {
216
217
  className: "text-[10px] text-muted-foreground",
217
218
  children: "Priority"
218
219
  })]
219
220
  }),
220
- /* @__PURE__ */ h("div", {
221
+ /* @__PURE__ */ g("div", {
221
222
  className: "text-center",
222
- children: [/* @__PURE__ */ h("div", {
223
+ children: [/* @__PURE__ */ g("div", {
223
224
  className: "flex items-center gap-1",
224
- children: [/* @__PURE__ */ m(d, { className: "h-3 w-3 text-green-500" }), /* @__PURE__ */ m("span", {
225
+ children: [/* @__PURE__ */ h(f, { className: "h-3 w-3 text-green-500" }), /* @__PURE__ */ h("span", {
225
226
  className: "text-sm font-bold",
226
227
  children: e.voteCount
227
228
  })]
228
- }), /* @__PURE__ */ m("p", {
229
+ }), /* @__PURE__ */ h("p", {
229
230
  className: "text-[10px] text-muted-foreground",
230
231
  children: "Votes"
231
232
  })]
232
233
  }),
233
- /* @__PURE__ */ h("div", {
234
+ /* @__PURE__ */ g("div", {
234
235
  className: "text-center",
235
- children: [/* @__PURE__ */ h("div", {
236
+ children: [/* @__PURE__ */ g("div", {
236
237
  className: "flex items-center gap-1",
237
- children: [/* @__PURE__ */ m(l, { className: "h-3 w-3 text-yellow-500" }), /* @__PURE__ */ m("span", {
238
+ children: [/* @__PURE__ */ h(u, { className: "h-3 w-3 text-yellow-500" }), /* @__PURE__ */ h("span", {
238
239
  className: "text-sm font-bold",
239
240
  children: e.businessValue ?? 0
240
241
  })]
241
- }), /* @__PURE__ */ m("p", {
242
+ }), /* @__PURE__ */ h("p", {
242
243
  className: "text-[10px] text-muted-foreground",
243
244
  children: "Value"
244
245
  })]
@@ -249,7 +250,7 @@ function S() {
249
250
  })
250
251
  }, e.id))
251
252
  }),
252
- M.length === 0 && /* @__PURE__ */ m("p", {
253
+ N.length === 0 && /* @__PURE__ */ h("p", {
253
254
  className: "text-center text-muted-foreground py-8",
254
255
  children: "No features match the selected filters."
255
256
  })
@@ -257,6 +258,6 @@ function S() {
257
258
  });
258
259
  }
259
260
  //#endregion
260
- export { S as ProductsFeaturesPagePage };
261
+ export { C as ProductsFeaturesPagePage };
261
262
 
262
263
  //# sourceMappingURL=ProductsFeaturesPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsFeaturesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeaturesPagePage.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, Button } from '@burdenoff/fe-libs/ui';\nimport {\n Star,\n Plus,\n ThumbsUp,\n MessageSquare,\n Target,\n Filter,\n ArrowUpDown,\n Loader2,\n} from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\n\nconst LIST_FEATURE_REQUESTS = gql`\n query ListFeatureRequests(\n $workspaceId: ID!\n $filter: PlanmagnetFeatureRequestFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetFeatureRequests(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n tags\n createdAt\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface FeatureRequestNode {\n id: string;\n title: string;\n description: string | null;\n status: string;\n businessValue: number | null;\n effortEstimate: string | null;\n priorityScore: number | null;\n voteCount: number;\n submittedBy: string;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nconst statusColor: Record<string, string> = {\n SUBMITTED: 'bg-gray-100 text-gray-800',\n UNDER_REVIEW: 'bg-yellow-100 text-yellow-800',\n PLANNED: 'bg-blue-100 text-blue-800',\n IN_PROGRESS: 'bg-purple-100 text-purple-800',\n COMPLETED: 'bg-green-100 text-green-800',\n DECLINED: 'bg-red-100 text-red-800',\n DUPLICATE: 'bg-orange-100 text-orange-800',\n};\n\nexport function ProductsFeaturesPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const [statusFilter, setStatusFilter] = useState<string>('all');\n const [sortBy, setSortBy] = useState<'priorityScore' | 'voteCount' | 'businessValue'>(\n 'priorityScore'\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>>(LIST_FEATURE_REQUESTS, {\n variables: {\n workspaceId,\n filter: statusFilter !== 'all' ? { status: statusFilter } : undefined,\n pagination: { first: 50 },\n },\n skip: !workspaceId,\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 features: {error.message}</div>;\n }\n\n const features: FeatureRequestNode[] = data?.planmagnetFeatureRequests?.items ?? [];\n const totalCount = data?.planmagnetFeatureRequests?.totalCount ?? 0;\n\n const sorted = [...features].sort((a, b) => {\n const aVal = a[sortBy] ?? 0;\n const bVal = b[sortBy] ?? 0;\n return (bVal as number) - (aVal as number);\n });\n\n const statuses = [\n 'all',\n 'SUBMITTED',\n 'UNDER_REVIEW',\n 'PLANNED',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'DECLINED',\n 'DUPLICATE',\n ];\n\n const stats = {\n total: totalCount,\n inProgress: features.filter((f) => f.status === 'IN_PROGRESS').length,\n completed: features.filter((f) => f.status === 'COMPLETED').length,\n avgPriority:\n features.length > 0\n ? Math.round(features.reduce((s, f) => s + (f.priorityScore ?? 0), 0) / features.length)\n : 0,\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Features</h1>\n <p className=\"text-sm text-muted-foreground\">\n {totalCount} feature requests across all products\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/products/new-feature-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Feature\n </Button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Features</p>\n <p className=\"text-xl font-bold\">{stats.total}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">In Progress</p>\n <p className=\"text-xl font-bold\">{stats.inProgress}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Completed</p>\n <p className=\"text-xl font-bold\">{stats.completed}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Avg Priority Score</p>\n <p className=\"text-xl font-bold\">{stats.avgPriority}</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n {statuses.map((s) => (\n <button\n key={s}\n onClick={() => setStatusFilter(s)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${statusFilter === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'all' ? 'All' : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <ArrowUpDown className=\"h-4 w-4 text-muted-foreground\" />\n {(['priorityScore', 'voteCount', 'businessValue'] as const).map((s) => (\n <button\n key={s}\n onClick={() => setSortBy(s)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${sortBy === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'priorityScore' ? 'Priority' : s === 'voteCount' ? 'Votes' : 'Value'}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-3\">\n {sorted.map((feature) => (\n <Card\n key={feature.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/feature-detail-page', feature.id)),\n feature.title\n )}\n >\n <CardContent className=\"py-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{feature.title}</span>\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${statusColor[feature.status] ?? 'bg-gray-100'}`}\n >\n {feature.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{feature.description}</p>\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\n <span>Effort: {feature.effortEstimate ?? 'N/A'}</span>\n <span>Submitted by: {feature.submittedBy}</span>\n <span>{new Date(feature.updatedAt).toLocaleDateString()}</span>\n </div>\n {feature.tags.length > 0 && (\n <div className=\"flex gap-1\">\n {feature.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-[10px]\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-4 shrink-0\">\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Target className=\"h-3 w-3 text-primary\" />\n <span className=\"text-sm font-bold\">{feature.priorityScore ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Priority</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <ThumbsUp className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-sm font-bold\">{feature.voteCount}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Votes</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-yellow-500\" />\n <span className=\"text-sm font-bold\">{feature.businessValue ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Value</p>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n {sorted.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n No features match the selected filters.\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProductsFeaturesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsFeaturesPagePage.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, Button } from '@burdenoff/fe-libs/ui';\nimport {\n Star,\n Plus,\n ThumbsUp,\n MessageSquare,\n Target,\n Filter,\n ArrowUpDown,\n Loader2,\n} from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\n\nconst LIST_FEATURE_REQUESTS = gql`\n query ListFeatureRequests(\n $workspaceId: ID!\n $filter: PlanmagnetFeatureRequestFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetFeatureRequests(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n description\n status\n businessValue\n effortEstimate\n priorityScore\n voteCount\n submittedBy\n tags\n createdAt\n updatedAt\n }\n totalCount\n }\n }\n`;\n\ninterface FeatureRequestNode {\n id: string;\n title: string;\n description: string | null;\n status: string;\n businessValue: number | null;\n effortEstimate: string | null;\n priorityScore: number | null;\n voteCount: number;\n submittedBy: string;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nconst statusColor: Record<string, string> = {\n SUBMITTED: 'bg-gray-100 text-gray-800',\n UNDER_REVIEW: 'bg-yellow-100 text-yellow-800',\n PLANNED: 'bg-blue-100 text-blue-800',\n IN_PROGRESS: 'bg-purple-100 text-purple-800',\n COMPLETED: 'bg-green-100 text-green-800',\n DECLINED: 'bg-red-100 text-red-800',\n DUPLICATE: 'bg-orange-100 text-orange-800',\n};\n\nexport function ProductsFeaturesPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const [statusFilter, setStatusFilter] = useState<string>('all');\n const [sortBy, setSortBy] = useState<'priorityScore' | 'voteCount' | 'businessValue'>(\n 'priorityScore'\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>>(LIST_FEATURE_REQUESTS, {\n variables: {\n workspaceId,\n filter: statusFilter !== 'all' ? { status: statusFilter } : undefined,\n pagination: { first: 50 },\n },\n skip: !workspaceId,\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 features: {error.message}</div>;\n }\n\n const features: FeatureRequestNode[] = data?.planmagnetFeatureRequests?.items ?? [];\n const totalCount = data?.planmagnetFeatureRequests?.totalCount ?? 0;\n\n const sorted = [...features].sort((a, b) => {\n const aVal = a[sortBy] ?? 0;\n const bVal = b[sortBy] ?? 0;\n return (bVal as number) - (aVal as number);\n });\n\n const statuses = [\n 'all',\n 'SUBMITTED',\n 'UNDER_REVIEW',\n 'PLANNED',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'DECLINED',\n 'DUPLICATE',\n ];\n\n const stats = {\n total: totalCount,\n inProgress: features.filter((f) => f.status === 'IN_PROGRESS').length,\n completed: features.filter((f) => f.status === 'COMPLETED').length,\n avgPriority:\n features.length > 0\n ? Math.round(features.reduce((s, f) => s + (f.priorityScore ?? 0), 0) / features.length)\n : 0,\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Features</h1>\n <p className=\"text-sm text-muted-foreground\">\n {totalCount} feature requests across all products\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/products/new-feature-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Feature\n </Button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Features</p>\n <p className=\"text-xl font-bold\">{stats.total}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">In Progress</p>\n <p className=\"text-xl font-bold\">{stats.inProgress}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Completed</p>\n <p className=\"text-xl font-bold\">{stats.completed}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Avg Priority Score</p>\n <p className=\"text-xl font-bold\">{stats.avgPriority}</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n {statuses.map((s) => (\n <button\n key={s}\n onClick={() => setStatusFilter(s)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${statusFilter === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'all' ? 'All' : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <ArrowUpDown className=\"h-4 w-4 text-muted-foreground\" />\n {(['priorityScore', 'voteCount', 'businessValue'] as const).map((s) => (\n <button\n key={s}\n onClick={() => setSortBy(s)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${sortBy === s ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {s === 'priorityScore' ? 'Priority' : s === 'voteCount' ? 'Votes' : 'Value'}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-3\">\n {sorted.map((feature) => (\n <Card\n key={feature.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/feature-detail-page', feature.id)),\n feature.title\n )}\n >\n <CardContent className=\"py-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{feature.title}</span>\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${statusColor[feature.status] ?? 'bg-gray-100'}`}\n >\n {feature.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{feature.description}</p>\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\n <span>Effort: {feature.effortEstimate ?? 'N/A'}</span>\n {/* By name, not user UUID (BOFF-7950). */}\n <span>\n Submitted by: <PersonName id={feature.submittedBy} />\n </span>\n <span>{new Date(feature.updatedAt).toLocaleDateString()}</span>\n </div>\n {feature.tags.length > 0 && (\n <div className=\"flex gap-1\">\n {feature.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-[10px]\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-4 shrink-0\">\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Target className=\"h-3 w-3 text-primary\" />\n <span className=\"text-sm font-bold\">{feature.priorityScore ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Priority</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <ThumbsUp className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-sm font-bold\">{feature.voteCount}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Votes</p>\n </div>\n <div className=\"text-center\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-yellow-500\" />\n <span className=\"text-sm font-bold\">{feature.businessValue ?? 0}</span>\n </div>\n <p className=\"text-[10px] text-muted-foreground\">Value</p>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n {sorted.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n No features match the selected filters.\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsProductDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsProductDetailPagePage.tsx"],"names":[],"mappings":"AAmGA,wBAAgB,6BAA6B,4CAyN5C"}
1
+ {"version":3,"file":"ProductsProductDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsProductDetailPagePage.tsx"],"names":[],"mappings":"AAoGA,wBAAgB,6BAA6B,4CA8N5C"}