@burdenoff/microfe-planmagnet 2026.924.5 → 2026.925.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"SprintsStartSprintPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"names":[],"mappings":"AAyFA,wBAAgB,0BAA0B,4CAsMzC"}
1
+ {"version":3,"file":"SprintsStartSprintPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"names":[],"mappings":"AAiFA,wBAAgB,0BAA0B,4CAsNzC"}
@@ -1,11 +1,13 @@
1
- import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
- import { Calendar as t, Play as n, Users as r, Zap as i } from "lucide-react";
3
- import { gql as a } from "@apollo/client";
4
- import { useMutation as o, useQuery as s } from "@apollo/client/react";
5
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
- import { Badge as u, Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h } from "@burdenoff/fe-libs/ui";
1
+ import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
2
+ import { detailPath as n } from "../utils/rowNavigation.js";
3
+ import { NewSprintDialog as r, SprintLifecycleActions as i } from "../sprints/SprintControls.js";
4
+ import { Calendar as a, Users as o, Zap as s } from "lucide-react";
5
+ import { gql as c } from "@apollo/client";
6
+ import { useQuery as l } from "@apollo/client/react";
7
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
8
+ import { Badge as f, Card as p, CardContent as m, CardHeader as h, CardTitle as g } from "@burdenoff/fe-libs/ui";
7
9
  //#region src/planmagnet/pages/SprintsStartSprintPagePage.tsx
8
- var g = a`
10
+ var _ = c`
9
11
  query GetSprints(
10
12
  $workspaceId: ID!
11
13
  $filter: PlanmagnetSprintFilter
@@ -31,14 +33,6 @@ var g = a`
31
33
  totalCount
32
34
  }
33
35
  }
34
- `, _ = a`
35
- mutation StartSprint($sprintId: ID!) {
36
- planmagnetStartSprint(id: $sprintId) {
37
- id
38
- status
39
- startDate
40
- }
41
- }
42
36
  `;
43
37
  function v(e) {
44
38
  let t = e.workItems ?? [], n = t.reduce((e, t) => e + (t.storyPoints ?? 0), 0), r = t.filter((e) => e.status === "DONE").reduce((e, t) => e + (t.storyPoints ?? 0), 0);
@@ -52,163 +46,176 @@ function v(e) {
52
46
  };
53
47
  }
54
48
  function y() {
55
- let { workspaceId: a } = e(), { data: y, loading: b, error: x } = s(g, {
49
+ let { workspaceId: c } = e(), { data: y, loading: b, error: x } = l(_, {
56
50
  variables: {
57
- workspaceId: a,
51
+ workspaceId: c,
58
52
  pagination: { first: 50 }
59
53
  },
60
- skip: !a
61
- }), S = y?.planmagnetSprints?.items ?? [], C = S.filter((e) => e.status === "ACTIVE"), w = S.filter((e) => e.status === "PLANNING"), [T, { loading: E }] = o(_, { refetchQueries: ["GetSprints"] }), D = async (e) => {
62
- a && await T({ variables: { sprintId: e } });
63
- };
64
- return b ? /* @__PURE__ */ c("div", {
54
+ skip: !c
55
+ }), S = y?.planmagnetSprints?.items ?? [], C = S.filter((e) => e.status === "ACTIVE" || e.status === "REVIEW"), w = S.filter((e) => e.status === "PLANNING"), T = t(), E = (e) => T(n("/projects/planning-detail-page", e));
56
+ return b ? /* @__PURE__ */ u("div", {
65
57
  className: "flex items-center justify-center p-12",
66
- children: /* @__PURE__ */ c("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
67
- }) : x ? /* @__PURE__ */ l("div", {
58
+ children: /* @__PURE__ */ u("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
59
+ }) : x ? /* @__PURE__ */ d("div", {
68
60
  className: "p-6 text-red-500",
69
61
  children: ["Error: ", x.message]
70
- }) : /* @__PURE__ */ l("div", {
62
+ }) : /* @__PURE__ */ d("div", {
71
63
  className: "space-y-6 p-6",
72
64
  children: [
73
- /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h1", {
74
- className: "text-2xl font-semibold",
75
- children: "Sprint Management"
76
- }), /* @__PURE__ */ l("p", {
77
- className: "text-sm text-muted-foreground",
78
- children: [
79
- S.length,
80
- " sprints total · ",
81
- C.length,
82
- " active"
83
- ]
84
- })] }),
85
- C.length > 0 && /* @__PURE__ */ l("div", {
65
+ /* @__PURE__ */ d("div", {
66
+ className: "flex items-center justify-between",
67
+ children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h1", {
68
+ className: "text-2xl font-semibold",
69
+ children: "Sprint Management"
70
+ }), /* @__PURE__ */ d("p", {
71
+ className: "text-sm text-muted-foreground",
72
+ children: [
73
+ S.length,
74
+ " sprints total · ",
75
+ C.length,
76
+ " active"
77
+ ]
78
+ })] }), /* @__PURE__ */ u(r, { onCreated: E })]
79
+ }),
80
+ C.length > 0 && /* @__PURE__ */ d("div", {
86
81
  className: "space-y-4",
87
- children: [/* @__PURE__ */ c("h2", {
82
+ children: [/* @__PURE__ */ u("h2", {
88
83
  className: "text-lg font-medium",
89
84
  children: "Active Sprints"
90
85
  }), C.map((e) => {
91
- let n = v(e), a = e.workItems ?? [], o = n.totalPoints > 0 ? Math.round(n.completedPoints / n.totalPoints * 100) : 0;
92
- return /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c(m, {
86
+ let t = v(e), n = e.workItems ?? [], r = t.totalPoints > 0 ? Math.round(t.completedPoints / t.totalPoints * 100) : 0;
87
+ return /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, {
93
88
  className: "pb-2",
94
- children: /* @__PURE__ */ l("div", {
89
+ children: /* @__PURE__ */ d("div", {
95
90
  className: "flex items-center justify-between",
96
- children: [/* @__PURE__ */ l(h, {
91
+ children: [/* @__PURE__ */ d(g, {
97
92
  className: "text-base flex items-center gap-2",
98
- children: [/* @__PURE__ */ c(i, { className: "h-4 w-4 text-primary" }), e.name]
99
- }), /* @__PURE__ */ c(u, { children: "Active" })]
93
+ children: [/* @__PURE__ */ u(s, { className: "h-4 w-4 text-primary" }), /* @__PURE__ */ u("button", {
94
+ type: "button",
95
+ className: "hover:underline text-left",
96
+ onClick: () => E(e.id),
97
+ children: e.name
98
+ })]
99
+ }), /* @__PURE__ */ d("div", {
100
+ className: "flex items-start gap-2",
101
+ children: [/* @__PURE__ */ u(f, { children: e.status === "REVIEW" ? "Review" : "Active" }), /* @__PURE__ */ u(i, {
102
+ sprintId: e.id,
103
+ sprintName: e.name,
104
+ status: e.status
105
+ })]
106
+ })]
100
107
  })
101
- }), /* @__PURE__ */ l(p, {
108
+ }), /* @__PURE__ */ d(m, {
102
109
  className: "space-y-4",
103
110
  children: [
104
- /* @__PURE__ */ c("p", {
111
+ /* @__PURE__ */ u("p", {
105
112
  className: "text-sm text-muted-foreground",
106
113
  children: e.goal ?? ""
107
114
  }),
108
- /* @__PURE__ */ l("div", {
115
+ /* @__PURE__ */ d("div", {
109
116
  className: "flex gap-4 text-xs text-muted-foreground",
110
- children: [/* @__PURE__ */ l("span", {
117
+ children: [/* @__PURE__ */ d("span", {
111
118
  className: "flex items-center gap-1",
112
119
  children: [
113
- /* @__PURE__ */ c(t, { className: "h-3 w-3" }),
120
+ /* @__PURE__ */ u(a, { className: "h-3 w-3" }),
114
121
  e.startDate ?? "?",
115
122
  " - ",
116
123
  e.endDate ?? "?"
117
124
  ]
118
- }), /* @__PURE__ */ l("span", {
125
+ }), /* @__PURE__ */ d("span", {
119
126
  className: "flex items-center gap-1",
120
127
  children: [
121
- /* @__PURE__ */ c(r, { className: "h-3 w-3" }),
122
- n.teamMemberIds.length,
128
+ /* @__PURE__ */ u(o, { className: "h-3 w-3" }),
129
+ t.teamMemberIds.length,
123
130
  " members"
124
131
  ]
125
132
  })]
126
133
  }),
127
- /* @__PURE__ */ l("div", {
134
+ /* @__PURE__ */ d("div", {
128
135
  className: "grid grid-cols-3 gap-4 text-center",
129
136
  children: [
130
- /* @__PURE__ */ l("div", {
137
+ /* @__PURE__ */ d("div", {
131
138
  className: "p-3 bg-muted rounded-md",
132
- children: [/* @__PURE__ */ l("p", {
139
+ children: [/* @__PURE__ */ d("p", {
133
140
  className: "text-lg font-bold",
134
141
  children: [
135
- n.completedPoints,
142
+ t.completedPoints,
136
143
  "/",
137
- n.totalPoints
144
+ t.totalPoints
138
145
  ]
139
- }), /* @__PURE__ */ c("p", {
146
+ }), /* @__PURE__ */ u("p", {
140
147
  className: "text-xs text-muted-foreground",
141
148
  children: "Points"
142
149
  })]
143
150
  }),
144
- /* @__PURE__ */ l("div", {
151
+ /* @__PURE__ */ d("div", {
145
152
  className: "p-3 bg-muted rounded-md",
146
- children: [/* @__PURE__ */ l("p", {
153
+ children: [/* @__PURE__ */ d("p", {
147
154
  className: "text-lg font-bold",
148
155
  children: [
149
- n.tasksCompleted,
156
+ t.tasksCompleted,
150
157
  "/",
151
- n.tasksTotal
158
+ t.tasksTotal
152
159
  ]
153
- }), /* @__PURE__ */ c("p", {
160
+ }), /* @__PURE__ */ u("p", {
154
161
  className: "text-xs text-muted-foreground",
155
162
  children: "Tasks"
156
163
  })]
157
164
  }),
158
- /* @__PURE__ */ l("div", {
165
+ /* @__PURE__ */ d("div", {
159
166
  className: "p-3 bg-muted rounded-md",
160
- children: [/* @__PURE__ */ c("p", {
167
+ children: [/* @__PURE__ */ u("p", {
161
168
  className: "text-lg font-bold",
162
- children: n.velocity
163
- }), /* @__PURE__ */ c("p", {
169
+ children: t.velocity
170
+ }), /* @__PURE__ */ u("p", {
164
171
  className: "text-xs text-muted-foreground",
165
172
  children: "Velocity"
166
173
  })]
167
174
  })
168
175
  ]
169
176
  }),
170
- /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ l("div", {
177
+ /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d("div", {
171
178
  className: "flex justify-between text-xs mb-1",
172
- children: [/* @__PURE__ */ c("span", {
179
+ children: [/* @__PURE__ */ u("span", {
173
180
  className: "text-muted-foreground",
174
181
  children: "Sprint Progress"
175
- }), /* @__PURE__ */ l("span", {
182
+ }), /* @__PURE__ */ d("span", {
176
183
  className: "font-medium",
177
- children: [o, "%"]
184
+ children: [r, "%"]
178
185
  })]
179
- }), /* @__PURE__ */ c("div", {
186
+ }), /* @__PURE__ */ u("div", {
180
187
  className: "w-full h-2 rounded-full bg-muted overflow-hidden",
181
- children: /* @__PURE__ */ c("div", {
188
+ children: /* @__PURE__ */ u("div", {
182
189
  className: "h-full bg-primary rounded-full",
183
- style: { width: `${o}%` }
190
+ style: { width: `${r}%` }
184
191
  })
185
192
  })] }),
186
- a.length > 0 && /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("p", {
193
+ n.length > 0 && /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
187
194
  className: "text-xs font-medium text-muted-foreground mb-2",
188
195
  children: "Sprint Backlog"
189
- }), /* @__PURE__ */ c("div", {
196
+ }), /* @__PURE__ */ u("div", {
190
197
  className: "space-y-1",
191
- children: a.map((e) => /* @__PURE__ */ l("div", {
198
+ children: n.map((e) => /* @__PURE__ */ d("div", {
192
199
  className: "flex items-center justify-between border rounded p-2 text-sm",
193
- children: [/* @__PURE__ */ c("span", { children: e.title }), /* @__PURE__ */ l("div", {
200
+ children: [/* @__PURE__ */ u("span", { children: e.title }), /* @__PURE__ */ d("div", {
194
201
  className: "flex gap-1",
195
- children: [/* @__PURE__ */ c(u, {
202
+ children: [/* @__PURE__ */ u(f, {
196
203
  variant: "secondary",
197
204
  className: "text-xs capitalize",
198
205
  children: e.status.toLowerCase().replace("_", " ")
199
- }), /* @__PURE__ */ l("span", {
206
+ }), /* @__PURE__ */ d("span", {
200
207
  className: "text-xs text-muted-foreground",
201
208
  children: [e.storyPoints ?? 0, "pts"]
202
209
  })]
203
210
  })]
204
211
  }, e.id))
205
212
  })] }),
206
- /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("p", {
213
+ /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
207
214
  className: "text-xs font-medium text-muted-foreground mb-1",
208
215
  children: "Team"
209
- }), /* @__PURE__ */ c("div", {
216
+ }), /* @__PURE__ */ u("div", {
210
217
  className: "flex gap-2",
211
- children: n.teamMemberIds.map((e) => /* @__PURE__ */ c("div", {
218
+ children: t.teamMemberIds.map((e) => /* @__PURE__ */ u("div", {
212
219
  className: "h-7 w-7 rounded-full bg-primary/10 flex items-center justify-center text-[10px] font-medium text-primary",
213
220
  title: e,
214
221
  children: e.slice(0, 2).toUpperCase()
@@ -218,49 +225,52 @@ function y() {
218
225
  })] }, e.id);
219
226
  })]
220
227
  }),
221
- w.length > 0 && /* @__PURE__ */ l("div", {
228
+ w.length > 0 && /* @__PURE__ */ d("div", {
222
229
  className: "space-y-4",
223
- children: [/* @__PURE__ */ c("h2", {
230
+ children: [/* @__PURE__ */ u("h2", {
224
231
  className: "text-lg font-medium",
225
232
  children: "Planning"
226
233
  }), w.map((e) => {
227
234
  let t = v(e);
228
- return /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c(m, {
235
+ return /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, {
229
236
  className: "pb-2",
230
- children: /* @__PURE__ */ l("div", {
237
+ children: /* @__PURE__ */ d("div", {
231
238
  className: "flex items-center justify-between",
232
- children: [/* @__PURE__ */ c(h, {
239
+ children: [/* @__PURE__ */ u(g, {
233
240
  className: "text-base",
234
- children: e.name
235
- }), /* @__PURE__ */ l("div", {
236
- className: "flex items-center gap-2",
237
- children: [/* @__PURE__ */ c(u, {
241
+ children: /* @__PURE__ */ u("button", {
242
+ type: "button",
243
+ className: "hover:underline text-left",
244
+ onClick: () => E(e.id),
245
+ children: e.name
246
+ })
247
+ }), /* @__PURE__ */ d("div", {
248
+ className: "flex items-start gap-2",
249
+ children: [/* @__PURE__ */ u(f, {
238
250
  variant: "secondary",
239
251
  children: "Planning"
240
- }), /* @__PURE__ */ l(d, {
241
- size: "sm",
242
- variant: "outline",
243
- onClick: () => D(e.id),
244
- disabled: E,
245
- children: [/* @__PURE__ */ c(n, { className: "mr-1 h-3 w-3" }), "Start Sprint"]
252
+ }), /* @__PURE__ */ u(i, {
253
+ sprintId: e.id,
254
+ sprintName: e.name,
255
+ status: e.status
246
256
  })]
247
257
  })]
248
258
  })
249
- }), /* @__PURE__ */ l(p, {
259
+ }), /* @__PURE__ */ d(m, {
250
260
  className: "space-y-2",
251
- children: [/* @__PURE__ */ c("p", {
261
+ children: [/* @__PURE__ */ u("p", {
252
262
  className: "text-sm text-muted-foreground",
253
263
  children: e.goal ?? ""
254
- }), /* @__PURE__ */ l("div", {
264
+ }), /* @__PURE__ */ d("div", {
255
265
  className: "flex gap-4 text-xs text-muted-foreground",
256
266
  children: [
257
- /* @__PURE__ */ l("span", { children: [
267
+ /* @__PURE__ */ d("span", { children: [
258
268
  e.startDate ?? "?",
259
269
  " - ",
260
270
  e.endDate ?? "?"
261
271
  ] }),
262
- /* @__PURE__ */ l("span", { children: [t.totalPoints, " points planned"] }),
263
- /* @__PURE__ */ l("span", { children: [t.teamMemberIds.length, " members"] })
272
+ /* @__PURE__ */ d("span", { children: [t.totalPoints, " points planned"] }),
273
+ /* @__PURE__ */ d("span", { children: [t.teamMemberIds.length, " members"] })
264
274
  ]
265
275
  })]
266
276
  })] }, e.id);
@@ -1 +1 @@
1
- {"version":3,"file":"SprintsStartSprintPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { Zap, Calendar, Users, Play } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\nconst GET_SPRINTS = gql`\n query GetSprints(\n $workspaceId: ID!\n $filter: PlanmagnetSprintFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetSprints(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n goal\n status\n startDate\n endDate\n velocity\n workItems {\n id\n title\n status\n storyPoints\n assigneeId\n }\n }\n totalCount\n }\n }\n`;\n\nconst START_SPRINT = gql`\n mutation StartSprint($sprintId: ID!) {\n planmagnetStartSprint(id: $sprintId) {\n id\n status\n startDate\n }\n }\n`;\n\ninterface SprintWorkItem {\n id: string;\n title: string;\n status: string;\n storyPoints: number | null;\n assigneeId: string | null;\n}\n\ninterface SprintNode {\n id: string;\n name: string;\n goal: string | null;\n status: string;\n startDate: string | null;\n endDate: string | null;\n velocity: number | null;\n workItems: SprintWorkItem[];\n}\n\ninterface SprintMetrics {\n totalPoints: number;\n completedPoints: number;\n tasksTotal: number;\n tasksCompleted: number;\n teamMemberIds: string[];\n velocity: number;\n}\n\nfunction deriveSprintMetrics(sprint: SprintNode): SprintMetrics {\n const items = sprint.workItems ?? [];\n const totalPoints = items.reduce((sum, w) => sum + (w.storyPoints ?? 0), 0);\n const completedPoints = items\n .filter((w) => w.status === 'DONE')\n .reduce((sum, w) => sum + (w.storyPoints ?? 0), 0);\n const tasksTotal = items.length;\n const tasksCompleted = items.filter((w) => w.status === 'DONE').length;\n const teamMemberIds = Array.from(\n new Set(items.map((w) => w.assigneeId).filter((id): id is string => Boolean(id)))\n );\n const velocity = sprint.velocity ?? completedPoints;\n return { totalPoints, completedPoints, tasksTotal, tasksCompleted, teamMemberIds, velocity };\n}\n\nexport function SprintsStartSprintPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n const {\n data: sprintData,\n loading: sprintsLoading,\n error: sprintsError,\n } = useQuery<{\n planmagnetSprints: { items: SprintNode[]; totalCount: number };\n }>(GET_SPRINTS, {\n variables: { workspaceId, pagination: { first: 50 } },\n skip: !workspaceId,\n });\n\n const sprints = sprintData?.planmagnetSprints?.items ?? [];\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE');\n const planningSprints = sprints.filter((s) => s.status === 'PLANNING');\n\n const [startSprint, { loading: startingSprintLoading }] = useMutation(START_SPRINT, {\n refetchQueries: ['GetSprints'],\n });\n\n const handleStartSprint = async (sprintId: string) => {\n if (!workspaceId) return;\n await startSprint({ variables: { sprintId } });\n };\n\n if (sprintsLoading) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n }\n\n if (sprintsError) {\n return <div className=\"p-6 text-red-500\">Error: {sprintsError.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Sprint Management</h1>\n <p className=\"text-sm text-muted-foreground\">\n {sprints.length} sprints total &middot; {activeSprints.length} active\n </p>\n </div>\n\n {activeSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Active Sprints</h2>\n {activeSprints.map((sprint) => {\n const metrics = deriveSprintMetrics(sprint);\n const tasksForSprint = sprint.workItems ?? [];\n const pctDone =\n metrics.totalPoints > 0\n ? Math.round((metrics.completedPoints / metrics.totalPoints) * 100)\n : 0;\n return (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Zap className=\"h-4 w-4 text-primary\" />\n {sprint.name}\n </CardTitle>\n <Badge>Active</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {metrics.teamMemberIds.length} members\n </span>\n </div>\n <div className=\"grid grid-cols-3 gap-4 text-center\">\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {metrics.completedPoints}/{metrics.totalPoints}\n </p>\n <p className=\"text-xs text-muted-foreground\">Points</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {metrics.tasksCompleted}/{metrics.tasksTotal}\n </p>\n <p className=\"text-xs text-muted-foreground\">Tasks</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">{metrics.velocity}</p>\n <p className=\"text-xs text-muted-foreground\">Velocity</p>\n </div>\n </div>\n <div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-muted-foreground\">Sprint Progress</span>\n <span className=\"font-medium\">{pctDone}%</span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full\"\n style={{ width: `${pctDone}%` }}\n />\n </div>\n </div>\n {tasksForSprint.length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Sprint Backlog\n </p>\n <div className=\"space-y-1\">\n {tasksForSprint.map((t) => (\n <div\n key={t.id}\n className=\"flex items-center justify-between border rounded p-2 text-sm\"\n >\n <span>{t.title}</span>\n <div className=\"flex gap-1\">\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {t.status.toLowerCase().replace('_', ' ')}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">\n {t.storyPoints ?? 0}pts\n </span>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Team</p>\n <div className=\"flex gap-2\">\n {metrics.teamMemberIds.map((memberId) => (\n <div\n key={memberId}\n className=\"h-7 w-7 rounded-full bg-primary/10 flex items-center justify-center text-[10px] font-medium text-primary\"\n title={memberId}\n >\n {memberId.slice(0, 2).toUpperCase()}\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n\n {planningSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Planning</h2>\n {planningSprints.map((sprint) => {\n const metrics = deriveSprintMetrics(sprint);\n return (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{sprint.name}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\">Planning</Badge>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartSprint(sprint.id)}\n disabled={startingSprintLoading}\n >\n <Play className=\"mr-1 h-3 w-3\" />\n Start Sprint\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span>\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span>{metrics.totalPoints} points planned</span>\n <span>{metrics.teamMemberIds.length} members</span>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SprintsStartSprintPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Zap, Calendar, Users } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { detailPath } from '../utils/rowNavigation';\nimport { NewSprintDialog, SprintLifecycleActions } from '../sprints/SprintControls';\n\nconst GET_SPRINTS = gql`\n query GetSprints(\n $workspaceId: ID!\n $filter: PlanmagnetSprintFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetSprints(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n goal\n status\n startDate\n endDate\n velocity\n workItems {\n id\n title\n status\n storyPoints\n assigneeId\n }\n }\n totalCount\n }\n }\n`;\n\ninterface SprintWorkItem {\n id: string;\n title: string;\n status: string;\n storyPoints: number | null;\n assigneeId: string | null;\n}\n\ninterface SprintNode {\n id: string;\n name: string;\n goal: string | null;\n status: string;\n startDate: string | null;\n endDate: string | null;\n velocity: number | null;\n workItems: SprintWorkItem[];\n}\n\ninterface SprintMetrics {\n totalPoints: number;\n completedPoints: number;\n tasksTotal: number;\n tasksCompleted: number;\n teamMemberIds: string[];\n velocity: number;\n}\n\nfunction deriveSprintMetrics(sprint: SprintNode): SprintMetrics {\n const items = sprint.workItems ?? [];\n const totalPoints = items.reduce((sum, w) => sum + (w.storyPoints ?? 0), 0);\n const completedPoints = items\n .filter((w) => w.status === 'DONE')\n .reduce((sum, w) => sum + (w.storyPoints ?? 0), 0);\n const tasksTotal = items.length;\n const tasksCompleted = items.filter((w) => w.status === 'DONE').length;\n const teamMemberIds = Array.from(\n new Set(items.map((w) => w.assigneeId).filter((id): id is string => Boolean(id)))\n );\n const velocity = sprint.velocity ?? completedPoints;\n return { totalPoints, completedPoints, tasksTotal, tasksCompleted, teamMemberIds, velocity };\n}\n\nexport function SprintsStartSprintPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n const {\n data: sprintData,\n loading: sprintsLoading,\n error: sprintsError,\n } = useQuery<{\n planmagnetSprints: { items: SprintNode[]; totalCount: number };\n }>(GET_SPRINTS, {\n variables: { workspaceId, pagination: { first: 50 } },\n skip: !workspaceId,\n });\n\n const sprints = sprintData?.planmagnetSprints?.items ?? [];\n // REVIEW is still in flight (it can be completed or cancelled), so it\n // belongs with the active sprints rather than vanishing from this page.\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE' || s.status === 'REVIEW');\n const planningSprints = sprints.filter((s) => s.status === 'PLANNING');\n\n const navigate = usePlanMagnetNavigate();\n const openSprint = (id: string) => navigate(detailPath('/projects/planning-detail-page', id));\n\n if (sprintsLoading) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n }\n\n if (sprintsError) {\n return <div className=\"p-6 text-red-500\">Error: {sprintsError.message}</div>;\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\">Sprint Management</h1>\n <p className=\"text-sm text-muted-foreground\">\n {sprints.length} sprints total &middot; {activeSprints.length} active\n </p>\n </div>\n <NewSprintDialog onCreated={openSprint} />\n </div>\n\n {activeSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Active Sprints</h2>\n {activeSprints.map((sprint) => {\n const metrics = deriveSprintMetrics(sprint);\n const tasksForSprint = sprint.workItems ?? [];\n const pctDone =\n metrics.totalPoints > 0\n ? Math.round((metrics.completedPoints / metrics.totalPoints) * 100)\n : 0;\n return (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Zap className=\"h-4 w-4 text-primary\" />\n <button\n type=\"button\"\n className=\"hover:underline text-left\"\n onClick={() => openSprint(sprint.id)}\n >\n {sprint.name}\n </button>\n </CardTitle>\n <div className=\"flex items-start gap-2\">\n <Badge>{sprint.status === 'REVIEW' ? 'Review' : 'Active'}</Badge>\n <SprintLifecycleActions\n sprintId={sprint.id}\n sprintName={sprint.name}\n status={sprint.status}\n />\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {metrics.teamMemberIds.length} members\n </span>\n </div>\n <div className=\"grid grid-cols-3 gap-4 text-center\">\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {metrics.completedPoints}/{metrics.totalPoints}\n </p>\n <p className=\"text-xs text-muted-foreground\">Points</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {metrics.tasksCompleted}/{metrics.tasksTotal}\n </p>\n <p className=\"text-xs text-muted-foreground\">Tasks</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">{metrics.velocity}</p>\n <p className=\"text-xs text-muted-foreground\">Velocity</p>\n </div>\n </div>\n <div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-muted-foreground\">Sprint Progress</span>\n <span className=\"font-medium\">{pctDone}%</span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full\"\n style={{ width: `${pctDone}%` }}\n />\n </div>\n </div>\n {tasksForSprint.length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Sprint Backlog\n </p>\n <div className=\"space-y-1\">\n {tasksForSprint.map((t) => (\n <div\n key={t.id}\n className=\"flex items-center justify-between border rounded p-2 text-sm\"\n >\n <span>{t.title}</span>\n <div className=\"flex gap-1\">\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {t.status.toLowerCase().replace('_', ' ')}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">\n {t.storyPoints ?? 0}pts\n </span>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Team</p>\n <div className=\"flex gap-2\">\n {metrics.teamMemberIds.map((memberId) => (\n <div\n key={memberId}\n className=\"h-7 w-7 rounded-full bg-primary/10 flex items-center justify-center text-[10px] font-medium text-primary\"\n title={memberId}\n >\n {memberId.slice(0, 2).toUpperCase()}\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n\n {planningSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Planning</h2>\n {planningSprints.map((sprint) => {\n const metrics = deriveSprintMetrics(sprint);\n return (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">\n <button\n type=\"button\"\n className=\"hover:underline text-left\"\n onClick={() => openSprint(sprint.id)}\n >\n {sprint.name}\n </button>\n </CardTitle>\n <div className=\"flex items-start gap-2\">\n <Badge variant=\"secondary\">Planning</Badge>\n <SprintLifecycleActions\n sprintId={sprint.id}\n sprintName={sprint.name}\n status={sprint.status}\n />\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span>\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span>{metrics.totalPoints} points planned</span>\n <span>{metrics.teamMemberIds.length} members</span>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Sprint lifecycle + membership controls.
3
+ *
4
+ * The buttons mirror the service's transition table exactly
5
+ * (wspace-planmagnet-svc sprint.service.ts `TRANSITIONS`):
6
+ * start PLANNING -> ACTIVE
7
+ * complete ACTIVE | REVIEW -> COMPLETED
8
+ * cancel PLANNING|ACTIVE|REVIEW -> CANCELLED
9
+ * A COMPLETED or CANCELLED sprint is finished: no transitions, and its work
10
+ * items can no longer be added or removed. The server enforces all of this;
11
+ * the UI only hides what would be refused, and still surfaces a refusal (a
12
+ * concurrent change can make a shown button stale).
13
+ */
14
+ export type SprintStatus = 'PLANNING' | 'ACTIVE' | 'REVIEW' | 'COMPLETED' | 'CANCELLED';
15
+ export type SprintAction = 'start' | 'complete' | 'cancel';
16
+ export declare function sprintActionsFor(status: string): SprintAction[];
17
+ export declare function isSprintFinished(status: string): boolean;
18
+ export declare function SprintLifecycleActions({ sprintId, sprintName, status, }: {
19
+ sprintId: string;
20
+ sprintName: string;
21
+ status: string;
22
+ }): import("react/jsx-runtime").JSX.Element | null;
23
+ export interface SprintWorkItem {
24
+ id: string;
25
+ key: string;
26
+ title?: string | null;
27
+ status: string;
28
+ storyPoints: number | null;
29
+ }
30
+ export declare function SprintWorkItemsPanel({ sprintId, projectId, status, items, }: {
31
+ sprintId: string;
32
+ projectId: string;
33
+ status: string;
34
+ items: SprintWorkItem[];
35
+ }): import("react/jsx-runtime").JSX.Element;
36
+ export declare function NewSprintDialog({ onCreated }: {
37
+ onCreated: (sprintId: string) => void;
38
+ }): import("react/jsx-runtime").JSX.Element;
39
+ //# sourceMappingURL=SprintControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SprintControls.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/sprints/SprintControls.tsx"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AACxF,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAQ3D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAI/D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAsCD,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,kDAyDA;AAsFD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAQD,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,2CAyEA;AAmKD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,2CAqKvF"}