@burdenoff/microfe-planmagnet 2026.924.5 → 2026.925.1
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.
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +191 -172
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.js +59 -51
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.js.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +115 -105
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.d.ts +39 -0
- package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -0
- package/dist/planmagnet/sprints/SprintControls.js +522 -0
- package/dist/planmagnet/sprints/SprintControls.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AA+DA,wBAAgB,8BAA8B,4CAgQ7C"}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { PersonName as e } from "../people/People.js";
|
|
2
2
|
import { useEntityId as t } from "../hooks/useEntityId.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { SprintLifecycleActions as n, SprintWorkItemsPanel as r } from "../sprints/SprintControls.js";
|
|
4
|
+
import { BarChart3 as i, CalendarClock as a, FolderKanban as o, Users 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";
|
|
8
9
|
//#region src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx
|
|
9
|
-
var
|
|
10
|
+
var _ = c`
|
|
10
11
|
query GetSprintDetail($id: ID!) {
|
|
11
12
|
planmagnetSprint(id: $id) {
|
|
12
13
|
id
|
|
13
14
|
name
|
|
14
15
|
projectId
|
|
16
|
+
project {
|
|
17
|
+
id
|
|
18
|
+
name
|
|
19
|
+
}
|
|
15
20
|
status
|
|
16
21
|
startDate
|
|
17
22
|
endDate
|
|
@@ -21,6 +26,7 @@ var h = o`
|
|
|
21
26
|
workItems {
|
|
22
27
|
id
|
|
23
28
|
key
|
|
29
|
+
title
|
|
24
30
|
status
|
|
25
31
|
storyPoints
|
|
26
32
|
assigneeId
|
|
@@ -28,7 +34,7 @@ var h = o`
|
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
|
-
`,
|
|
37
|
+
`, v = c`
|
|
32
38
|
query GetSprintCapacity($sprintId: ID!) {
|
|
33
39
|
planmagnetSprintCapacity(sprintId: $sprintId) {
|
|
34
40
|
sprintId
|
|
@@ -48,262 +54,275 @@ var h = o`
|
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
`;
|
|
51
|
-
function
|
|
52
|
-
let
|
|
53
|
-
variables: { id:
|
|
54
|
-
skip: !
|
|
55
|
-
}), { data:
|
|
56
|
-
variables: { sprintId:
|
|
57
|
-
skip: !
|
|
57
|
+
function y() {
|
|
58
|
+
let c = t("sprintId"), { data: y, loading: b, error: x } = l(_, {
|
|
59
|
+
variables: { id: c },
|
|
60
|
+
skip: !c
|
|
61
|
+
}), { data: S } = l(v, {
|
|
62
|
+
variables: { sprintId: c },
|
|
63
|
+
skip: !c
|
|
58
64
|
});
|
|
59
|
-
if (!
|
|
65
|
+
if (!c) return /* @__PURE__ */ u("div", {
|
|
60
66
|
className: "p-6 text-muted-foreground",
|
|
61
67
|
children: "No planning session selected. Open one from the list."
|
|
62
68
|
});
|
|
63
|
-
if (
|
|
69
|
+
if (b) return /* @__PURE__ */ u("div", {
|
|
64
70
|
className: "flex items-center justify-center p-12",
|
|
65
|
-
children: /* @__PURE__ */
|
|
71
|
+
children: /* @__PURE__ */ u("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
|
|
66
72
|
});
|
|
67
|
-
if (
|
|
73
|
+
if (x) return /* @__PURE__ */ d("div", {
|
|
68
74
|
className: "p-6 text-red-500",
|
|
69
|
-
children: ["Error loading planning session: ",
|
|
75
|
+
children: ["Error loading planning session: ", x.message]
|
|
70
76
|
});
|
|
71
|
-
let
|
|
72
|
-
if (!
|
|
77
|
+
let C = y?.planmagnetSprint;
|
|
78
|
+
if (!C) return /* @__PURE__ */ u("div", {
|
|
73
79
|
className: "p-6 text-muted-foreground",
|
|
74
80
|
children: "Planning session not found."
|
|
75
81
|
});
|
|
76
|
-
let
|
|
77
|
-
for (let e of
|
|
82
|
+
let w = S?.planmagnetSprintCapacity, T = {};
|
|
83
|
+
for (let e of w?.members ?? []) T[e.actorId] = {
|
|
78
84
|
employeeName: e.employeeName,
|
|
79
85
|
allocatedHours: e.allocatedHours,
|
|
80
86
|
billableHours: e.billableHours,
|
|
81
87
|
utilizationPercent: e.utilizationPercent
|
|
82
88
|
};
|
|
83
|
-
let
|
|
84
|
-
|
|
85
|
-
let
|
|
86
|
-
return /* @__PURE__ */
|
|
89
|
+
let E = C.workItems ?? [], D = E.reduce((e, t) => e + (t.storyPoints ?? 0), 0);
|
|
90
|
+
E.filter((e) => e.status === "DONE").reduce((e, t) => e + (t.storyPoints ?? 0), 0);
|
|
91
|
+
let O = C.capacity ?? D, k = O > 0 ? Math.round(D / O * 100) : 0, A = O - D, j = [...new Set(E.map((e) => e.assigneeId).filter(Boolean))];
|
|
92
|
+
return /* @__PURE__ */ d("div", {
|
|
87
93
|
className: "space-y-6 p-6",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
94
|
+
children: [/* @__PURE__ */ d("div", {
|
|
89
95
|
className: "flex items-center justify-between",
|
|
90
|
-
children: [/* @__PURE__ */
|
|
96
|
+
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h1", {
|
|
91
97
|
className: "text-2xl font-semibold",
|
|
92
|
-
children:
|
|
93
|
-
}), /* @__PURE__ */
|
|
98
|
+
children: C.name
|
|
99
|
+
}), /* @__PURE__ */ d("p", {
|
|
94
100
|
className: "text-sm text-muted-foreground",
|
|
95
101
|
children: [
|
|
96
|
-
|
|
102
|
+
C.project?.name ?? "Unknown project",
|
|
97
103
|
" ·",
|
|
98
104
|
" ",
|
|
99
|
-
|
|
105
|
+
C.startDate ? new Date(C.startDate).toLocaleDateString() : "—",
|
|
100
106
|
" -",
|
|
101
107
|
" ",
|
|
102
|
-
|
|
108
|
+
C.endDate ? new Date(C.endDate).toLocaleDateString() : "—"
|
|
103
109
|
]
|
|
104
|
-
})] }), /* @__PURE__ */
|
|
105
|
-
className: "flex gap-
|
|
106
|
-
children: /* @__PURE__ */
|
|
110
|
+
})] }), /* @__PURE__ */ d("div", {
|
|
111
|
+
className: "flex items-start gap-3",
|
|
112
|
+
children: [/* @__PURE__ */ u(f, {
|
|
107
113
|
className: "capitalize",
|
|
108
|
-
children:
|
|
109
|
-
})
|
|
114
|
+
children: C.status.toLowerCase().replace("_", " ")
|
|
115
|
+
}), /* @__PURE__ */ u(n, {
|
|
116
|
+
sprintId: C.id,
|
|
117
|
+
sprintName: C.name,
|
|
118
|
+
status: C.status
|
|
119
|
+
})]
|
|
110
120
|
})]
|
|
111
|
-
}), /* @__PURE__ */
|
|
121
|
+
}), /* @__PURE__ */ d("div", {
|
|
112
122
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
113
|
-
children: [/* @__PURE__ */
|
|
123
|
+
children: [/* @__PURE__ */ d("div", {
|
|
114
124
|
className: "lg:col-span-2 space-y-6",
|
|
115
|
-
children: [
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
children: "Capacity"
|
|
128
|
-
})]
|
|
129
|
-
}),
|
|
130
|
-
/* @__PURE__ */ l("div", {
|
|
131
|
-
className: "p-4 bg-primary/10 rounded-md",
|
|
132
|
-
children: [/* @__PURE__ */ c("p", {
|
|
133
|
-
className: "text-2xl font-bold text-primary",
|
|
134
|
-
children: T
|
|
135
|
-
}), /* @__PURE__ */ c("p", {
|
|
136
|
-
className: "text-xs text-muted-foreground",
|
|
137
|
-
children: "Allocated"
|
|
138
|
-
})]
|
|
139
|
-
}),
|
|
140
|
-
/* @__PURE__ */ l("div", {
|
|
141
|
-
className: "p-4 bg-muted rounded-md",
|
|
142
|
-
children: [/* @__PURE__ */ c("p", {
|
|
143
|
-
className: "text-2xl font-bold",
|
|
144
|
-
children: O > 0 ? O : 0
|
|
145
|
-
}), /* @__PURE__ */ c("p", {
|
|
146
|
-
className: "text-xs text-muted-foreground",
|
|
147
|
-
children: "Remaining"
|
|
148
|
-
})]
|
|
149
|
-
})
|
|
150
|
-
]
|
|
151
|
-
}), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ l("div", {
|
|
152
|
-
className: "flex justify-between text-sm mb-2",
|
|
153
|
-
children: [/* @__PURE__ */ c("span", {
|
|
154
|
-
className: "text-muted-foreground",
|
|
155
|
-
children: "Utilization"
|
|
156
|
-
}), /* @__PURE__ */ l("span", {
|
|
157
|
-
className: "font-medium",
|
|
158
|
-
children: [D, "%"]
|
|
159
|
-
})]
|
|
160
|
-
}), /* @__PURE__ */ c("div", {
|
|
161
|
-
className: "w-full h-4 rounded-full bg-muted overflow-hidden",
|
|
162
|
-
children: /* @__PURE__ */ c("div", {
|
|
163
|
-
className: `h-full rounded-full ${D > 90 ? "bg-red-400" : "bg-green-400"}`,
|
|
164
|
-
style: { width: `${Math.min(D, 100)}%` }
|
|
165
|
-
})
|
|
166
|
-
})] })]
|
|
167
|
-
})] }), /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ c(p, { children: /* @__PURE__ */ l(m, { children: [
|
|
168
|
-
"Team Members (",
|
|
169
|
-
k.length,
|
|
170
|
-
")"
|
|
171
|
-
] }) }), /* @__PURE__ */ l(f, { children: [
|
|
172
|
-
/* @__PURE__ */ l("div", {
|
|
173
|
-
className: "grid grid-cols-2 gap-3",
|
|
174
|
-
children: [k.map((t) => {
|
|
175
|
-
let n = C[t];
|
|
176
|
-
return /* @__PURE__ */ l("div", {
|
|
177
|
-
className: "flex items-center gap-2 border rounded-md p-2.5",
|
|
178
|
-
children: [/* @__PURE__ */ c("div", {
|
|
179
|
-
className: "h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-medium text-primary",
|
|
180
|
-
children: t.slice(0, 2).toUpperCase()
|
|
181
|
-
}), /* @__PURE__ */ l("div", {
|
|
182
|
-
className: "min-w-0",
|
|
183
|
-
children: [/* @__PURE__ */ c("span", {
|
|
184
|
-
className: "text-sm truncate block",
|
|
185
|
-
children: n?.employeeName ?? /* @__PURE__ */ c(e, { id: t })
|
|
186
|
-
}), n && /* @__PURE__ */ l("span", {
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Capacity Allocation" }) }), /* @__PURE__ */ d(m, {
|
|
127
|
+
className: "space-y-4",
|
|
128
|
+
children: [/* @__PURE__ */ d("div", {
|
|
129
|
+
className: "grid grid-cols-3 gap-4 text-center",
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ d("div", {
|
|
132
|
+
className: "p-4 bg-muted rounded-md",
|
|
133
|
+
children: [/* @__PURE__ */ u("p", {
|
|
134
|
+
className: "text-2xl font-bold",
|
|
135
|
+
children: O
|
|
136
|
+
}), /* @__PURE__ */ u("p", {
|
|
187
137
|
className: "text-xs text-muted-foreground",
|
|
188
|
-
children:
|
|
189
|
-
n.allocatedHours,
|
|
190
|
-
"h allocated (",
|
|
191
|
-
n.billableHours,
|
|
192
|
-
"h billable)",
|
|
193
|
-
n.utilizationPercent != null && ` · ${n.utilizationPercent}% util`
|
|
194
|
-
]
|
|
138
|
+
children: "Capacity"
|
|
195
139
|
})]
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
140
|
+
}),
|
|
141
|
+
/* @__PURE__ */ d("div", {
|
|
142
|
+
className: "p-4 bg-primary/10 rounded-md",
|
|
143
|
+
children: [/* @__PURE__ */ u("p", {
|
|
144
|
+
className: "text-2xl font-bold text-primary",
|
|
145
|
+
children: D
|
|
146
|
+
}), /* @__PURE__ */ u("p", {
|
|
147
|
+
className: "text-xs text-muted-foreground",
|
|
148
|
+
children: "Allocated"
|
|
149
|
+
})]
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ d("div", {
|
|
152
|
+
className: "p-4 bg-muted rounded-md",
|
|
153
|
+
children: [/* @__PURE__ */ u("p", {
|
|
154
|
+
className: "text-2xl font-bold",
|
|
155
|
+
children: A > 0 ? A : 0
|
|
156
|
+
}), /* @__PURE__ */ u("p", {
|
|
157
|
+
className: "text-xs text-muted-foreground",
|
|
158
|
+
children: "Remaining"
|
|
159
|
+
})]
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
}), /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ d("div", {
|
|
163
|
+
className: "flex justify-between text-sm mb-2",
|
|
164
|
+
children: [/* @__PURE__ */ u("span", {
|
|
165
|
+
className: "text-muted-foreground",
|
|
166
|
+
children: "Utilization"
|
|
167
|
+
}), /* @__PURE__ */ d("span", {
|
|
168
|
+
className: "font-medium",
|
|
169
|
+
children: [k, "%"]
|
|
170
|
+
})]
|
|
171
|
+
}), /* @__PURE__ */ u("div", {
|
|
172
|
+
className: "w-full h-4 rounded-full bg-muted overflow-hidden",
|
|
173
|
+
children: /* @__PURE__ */ u("div", {
|
|
174
|
+
className: `h-full rounded-full ${k > 90 ? "bg-red-400" : "bg-green-400"}`,
|
|
175
|
+
style: { width: `${Math.min(k, 100)}%` }
|
|
176
|
+
})
|
|
177
|
+
})] })]
|
|
178
|
+
})] }),
|
|
179
|
+
/* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Work Items" }) }), /* @__PURE__ */ u(m, { children: /* @__PURE__ */ u(r, {
|
|
180
|
+
sprintId: C.id,
|
|
181
|
+
projectId: C.projectId,
|
|
182
|
+
status: C.status,
|
|
183
|
+
items: E
|
|
184
|
+
}) })] }),
|
|
185
|
+
/* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ d(g, { children: [
|
|
186
|
+
"Team Members (",
|
|
187
|
+
j.length,
|
|
188
|
+
")"
|
|
189
|
+
] }) }), /* @__PURE__ */ d(m, { children: [
|
|
190
|
+
/* @__PURE__ */ d("div", {
|
|
191
|
+
className: "grid grid-cols-2 gap-3",
|
|
192
|
+
children: [j.map((t) => {
|
|
193
|
+
let n = T[t];
|
|
194
|
+
return /* @__PURE__ */ d("div", {
|
|
195
|
+
className: "flex items-center gap-2 border rounded-md p-2.5",
|
|
196
|
+
children: [/* @__PURE__ */ u("div", {
|
|
197
|
+
className: "h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-medium text-primary",
|
|
198
|
+
children: t.slice(0, 2).toUpperCase()
|
|
199
|
+
}), /* @__PURE__ */ d("div", {
|
|
200
|
+
className: "min-w-0",
|
|
201
|
+
children: [/* @__PURE__ */ u("span", {
|
|
202
|
+
className: "text-sm truncate block",
|
|
203
|
+
children: n?.employeeName ?? /* @__PURE__ */ u(e, { id: t })
|
|
204
|
+
}), n && /* @__PURE__ */ d("span", {
|
|
205
|
+
className: "text-xs text-muted-foreground",
|
|
206
|
+
children: [
|
|
207
|
+
n.allocatedHours,
|
|
208
|
+
"h allocated (",
|
|
209
|
+
n.billableHours,
|
|
210
|
+
"h billable)",
|
|
211
|
+
n.utilizationPercent != null && ` · ${n.utilizationPercent}% util`
|
|
212
|
+
]
|
|
213
|
+
})]
|
|
214
|
+
})]
|
|
215
|
+
}, t);
|
|
216
|
+
}), j.length === 0 && /* @__PURE__ */ u("p", {
|
|
217
|
+
className: "text-sm text-muted-foreground col-span-2 text-center py-4",
|
|
218
|
+
children: "No team members assigned."
|
|
219
|
+
})]
|
|
220
|
+
}),
|
|
221
|
+
w?.crewfoundryUnavailable && j.length > 0 && /* @__PURE__ */ u("p", {
|
|
222
|
+
className: "text-xs text-muted-foreground mt-3 border-t pt-3",
|
|
223
|
+
children: "Workforce allocation from CrewFoundry is unavailable for this workspace — no CrewFoundry module provisioned yet."
|
|
224
|
+
}),
|
|
225
|
+
!w?.crewfoundryUnavailable && (w?.unmatchedAssigneeIds?.length ?? 0) > 0 && /* @__PURE__ */ d("p", {
|
|
226
|
+
className: "text-xs text-muted-foreground mt-3 border-t pt-3",
|
|
227
|
+
children: [w.unmatchedAssigneeIds.length, " assignee(s) have no matching CrewFoundry employee record — allocation hours shown only for matched employees."]
|
|
228
|
+
})
|
|
229
|
+
] })] })
|
|
230
|
+
]
|
|
231
|
+
}), /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Session Info" }) }), /* @__PURE__ */ d(m, {
|
|
213
232
|
className: "space-y-3 text-sm",
|
|
214
233
|
children: [
|
|
215
|
-
/* @__PURE__ */
|
|
234
|
+
/* @__PURE__ */ d("div", {
|
|
216
235
|
className: "flex items-center gap-2",
|
|
217
236
|
children: [
|
|
218
|
-
/* @__PURE__ */
|
|
219
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ u(o, { className: "h-4 w-4 text-muted-foreground" }),
|
|
238
|
+
/* @__PURE__ */ u("span", {
|
|
220
239
|
className: "text-muted-foreground",
|
|
221
240
|
children: "Project:"
|
|
222
241
|
}),
|
|
223
|
-
/* @__PURE__ */
|
|
242
|
+
/* @__PURE__ */ u("span", {
|
|
224
243
|
className: "font-medium",
|
|
225
|
-
children:
|
|
244
|
+
children: C.project?.name ?? "Unknown project"
|
|
226
245
|
})
|
|
227
246
|
]
|
|
228
247
|
}),
|
|
229
|
-
/* @__PURE__ */
|
|
248
|
+
/* @__PURE__ */ d("div", {
|
|
230
249
|
className: "flex items-center gap-2",
|
|
231
250
|
children: [
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ u(a, { className: "h-4 w-4 text-muted-foreground" }),
|
|
252
|
+
/* @__PURE__ */ u("span", {
|
|
234
253
|
className: "text-muted-foreground",
|
|
235
254
|
children: "Start:"
|
|
236
255
|
}),
|
|
237
|
-
/* @__PURE__ */
|
|
256
|
+
/* @__PURE__ */ u("span", {
|
|
238
257
|
className: "font-medium",
|
|
239
|
-
children:
|
|
258
|
+
children: C.startDate ? new Date(C.startDate).toLocaleDateString() : "Not set"
|
|
240
259
|
})
|
|
241
260
|
]
|
|
242
261
|
}),
|
|
243
|
-
/* @__PURE__ */
|
|
262
|
+
/* @__PURE__ */ d("div", {
|
|
244
263
|
className: "flex items-center gap-2",
|
|
245
264
|
children: [
|
|
246
|
-
/* @__PURE__ */
|
|
247
|
-
/* @__PURE__ */
|
|
265
|
+
/* @__PURE__ */ u(a, { className: "h-4 w-4 text-muted-foreground" }),
|
|
266
|
+
/* @__PURE__ */ u("span", {
|
|
248
267
|
className: "text-muted-foreground",
|
|
249
268
|
children: "End:"
|
|
250
269
|
}),
|
|
251
|
-
/* @__PURE__ */
|
|
270
|
+
/* @__PURE__ */ u("span", {
|
|
252
271
|
className: "font-medium",
|
|
253
|
-
children:
|
|
272
|
+
children: C.endDate ? new Date(C.endDate).toLocaleDateString() : "Not set"
|
|
254
273
|
})
|
|
255
274
|
]
|
|
256
275
|
}),
|
|
257
|
-
/* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ d("div", {
|
|
258
277
|
className: "flex items-center gap-2",
|
|
259
278
|
children: [
|
|
260
|
-
/* @__PURE__ */
|
|
261
|
-
/* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ u(s, { className: "h-4 w-4 text-muted-foreground" }),
|
|
280
|
+
/* @__PURE__ */ u("span", {
|
|
262
281
|
className: "text-muted-foreground",
|
|
263
282
|
children: "Assignees:"
|
|
264
283
|
}),
|
|
265
|
-
/* @__PURE__ */
|
|
284
|
+
/* @__PURE__ */ u("span", {
|
|
266
285
|
className: "font-medium",
|
|
267
|
-
children:
|
|
286
|
+
children: j.length
|
|
268
287
|
})
|
|
269
288
|
]
|
|
270
289
|
}),
|
|
271
|
-
/* @__PURE__ */
|
|
290
|
+
/* @__PURE__ */ d("div", {
|
|
272
291
|
className: "flex items-center gap-2",
|
|
273
292
|
children: [
|
|
274
|
-
/* @__PURE__ */
|
|
275
|
-
/* @__PURE__ */
|
|
293
|
+
/* @__PURE__ */ u(i, { className: "h-4 w-4 text-muted-foreground" }),
|
|
294
|
+
/* @__PURE__ */ u("span", {
|
|
276
295
|
className: "text-muted-foreground",
|
|
277
296
|
children: "Capacity:"
|
|
278
297
|
}),
|
|
279
|
-
/* @__PURE__ */
|
|
298
|
+
/* @__PURE__ */ d("span", {
|
|
280
299
|
className: "font-medium",
|
|
281
|
-
children: [
|
|
300
|
+
children: [O, " pts"]
|
|
282
301
|
})
|
|
283
302
|
]
|
|
284
303
|
}),
|
|
285
|
-
|
|
304
|
+
C.velocity != null && /* @__PURE__ */ d("div", {
|
|
286
305
|
className: "flex items-center gap-2",
|
|
287
306
|
children: [
|
|
288
|
-
/* @__PURE__ */
|
|
289
|
-
/* @__PURE__ */
|
|
307
|
+
/* @__PURE__ */ u(i, { className: "h-4 w-4 text-muted-foreground" }),
|
|
308
|
+
/* @__PURE__ */ u("span", {
|
|
290
309
|
className: "text-muted-foreground",
|
|
291
310
|
children: "Velocity:"
|
|
292
311
|
}),
|
|
293
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ d("span", {
|
|
294
313
|
className: "font-medium",
|
|
295
|
-
children: [
|
|
314
|
+
children: [C.velocity, " pts"]
|
|
296
315
|
})
|
|
297
316
|
]
|
|
298
317
|
}),
|
|
299
|
-
|
|
318
|
+
C.goal && /* @__PURE__ */ d("div", {
|
|
300
319
|
className: "border-t pt-3 mt-3",
|
|
301
|
-
children: [/* @__PURE__ */
|
|
320
|
+
children: [/* @__PURE__ */ u("p", {
|
|
302
321
|
className: "text-muted-foreground text-xs mb-1",
|
|
303
322
|
children: "Goal"
|
|
304
|
-
}), /* @__PURE__ */
|
|
323
|
+
}), /* @__PURE__ */ u("p", {
|
|
305
324
|
className: "text-sm",
|
|
306
|
-
children:
|
|
325
|
+
children: C.goal
|
|
307
326
|
})]
|
|
308
327
|
})
|
|
309
328
|
]
|
|
@@ -312,6 +331,6 @@ function _() {
|
|
|
312
331
|
});
|
|
313
332
|
}
|
|
314
333
|
//#endregion
|
|
315
|
-
export {
|
|
334
|
+
export { y as ProjectsPlanningDetailPagePage };
|
|
316
335
|
|
|
317
336
|
//# sourceMappingURL=ProjectsPlanningDetailPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsPlanningDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.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 { CalendarClock, Users, BarChart3, FolderKanban } from 'lucide-react';\nimport { useEntityId } from '../hooks/useEntityId';\nimport { PersonName } from '../people/People';\n\nconst GET_SPRINT_DETAIL = gql`\n query GetSprintDetail($id: ID!) {\n planmagnetSprint(id: $id) {\n id\n name\n projectId\n status\n startDate\n endDate\n goal\n capacity\n velocity\n workItems {\n id\n key\n status\n storyPoints\n assigneeId\n priority\n }\n }\n }\n`;\n\n// Real cross-layer CrewFoundry workforce capacity (BOFF-4444). Fails open on\n// the backend — an unreachable/unprovisioned CrewFoundry never blocks this\n// page, it just yields crewfoundryUnavailable: true, handled below.\nconst GET_SPRINT_CAPACITY = gql`\n query GetSprintCapacity($sprintId: ID!) {\n planmagnetSprintCapacity(sprintId: $sprintId) {\n sprintId\n crewfoundryUnavailable\n unmatchedAssigneeIds\n members {\n actorId\n employeeName\n department\n position\n allocatedHours\n billableHours\n utilizationPercent\n assignedStoryPoints\n assignedWorkItemCount\n }\n }\n }\n`;\n\nexport function ProjectsPlanningDetailPagePage() {\n const sprintId = useEntityId('sprintId');\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_SPRINT_DETAIL, {\n variables: { id: sprintId },\n skip: !sprintId,\n });\n\n // Real cross-layer CrewFoundry capacity (BOFF-4444) — called unconditionally\n // (with `skip`) to keep hook order stable across the loading/error/loaded\n // renders above.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const { data: capacityData } = useQuery<Record<string, any>>(GET_SPRINT_CAPACITY, {\n variables: { sprintId },\n skip: !sprintId,\n });\n\n if (!sprintId)\n return (\n <div className=\"p-6 text-muted-foreground\">\n No planning session selected. Open one from the list.\n </div>\n );\n if (loading)\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 if (error)\n return <div className=\"p-6 text-red-500\">Error loading planning session: {error.message}</div>;\n\n const sprint = data?.planmagnetSprint;\n if (!sprint) return <div className=\"p-6 text-muted-foreground\">Planning session not found.</div>;\n\n const capacity = capacityData?.planmagnetSprintCapacity;\n const allocationByAssignee: Record<\n string,\n {\n employeeName: string;\n allocatedHours: number;\n billableHours: number;\n utilizationPercent: number | null;\n }\n > = {};\n for (const member of capacity?.members ?? []) {\n allocationByAssignee[member.actorId] = {\n employeeName: member.employeeName,\n allocatedHours: member.allocatedHours,\n billableHours: member.billableHours,\n utilizationPercent: member.utilizationPercent,\n };\n }\n\n const workItems = sprint.workItems ?? [];\n const totalPoints = workItems.reduce(\n (sum: number, wi: { storyPoints: number | null }) => sum + (wi.storyPoints ?? 0),\n 0\n );\n const completedPoints = workItems\n .filter((wi: { status: string }) => wi.status === 'DONE')\n .reduce((sum: number, wi: { storyPoints: number | null }) => sum + (wi.storyPoints ?? 0), 0);\n const allocatedCapacity = sprint.capacity ?? totalPoints;\n const capPct = allocatedCapacity > 0 ? Math.round((totalPoints / allocatedCapacity) * 100) : 0;\n const remaining = allocatedCapacity - totalPoints;\n\n // Derive unique assignees from work items\n const uniqueAssignees = [\n ...new Set(\n workItems\n .map((wi: { assigneeId: string | null }) => wi.assigneeId)\n .filter(Boolean) as string[]\n ),\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.name}</h1>\n <p className=\"text-sm text-muted-foreground\">\n {sprint.projectId} ·{' '}\n {sprint.startDate ? new Date(sprint.startDate).toLocaleDateString() : '—'} -{' '}\n {sprint.endDate ? new Date(sprint.endDate).toLocaleDateString() : '—'}\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Badge className=\"capitalize\">{sprint.status.toLowerCase().replace('_', ' ')}</Badge>\n </div>\n </div>\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Capacity Allocation</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-3 gap-4 text-center\">\n <div className=\"p-4 bg-muted rounded-md\">\n <p className=\"text-2xl font-bold\">{allocatedCapacity}</p>\n <p className=\"text-xs text-muted-foreground\">Capacity</p>\n </div>\n <div className=\"p-4 bg-primary/10 rounded-md\">\n <p className=\"text-2xl font-bold text-primary\">{totalPoints}</p>\n <p className=\"text-xs text-muted-foreground\">Allocated</p>\n </div>\n <div className=\"p-4 bg-muted rounded-md\">\n <p className=\"text-2xl font-bold\">{remaining > 0 ? remaining : 0}</p>\n <p className=\"text-xs text-muted-foreground\">Remaining</p>\n </div>\n </div>\n <div>\n <div className=\"flex justify-between text-sm mb-2\">\n <span className=\"text-muted-foreground\">Utilization</span>\n <span className=\"font-medium\">{capPct}%</span>\n </div>\n <div className=\"w-full h-4 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${capPct > 90 ? 'bg-red-400' : 'bg-green-400'}`}\n style={{ width: `${Math.min(capPct, 100)}%` }}\n />\n </div>\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>Team Members ({uniqueAssignees.length})</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 gap-3\">\n {uniqueAssignees.map((assigneeId: string) => {\n const workforce = allocationByAssignee[assigneeId];\n return (\n <div\n key={assigneeId}\n className=\"flex items-center gap-2 border rounded-md p-2.5\"\n >\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-medium text-primary\">\n {assigneeId.slice(0, 2).toUpperCase()}\n </div>\n <div className=\"min-w-0\">\n <span className=\"text-sm truncate block\">\n {workforce?.employeeName ?? <PersonName id={assigneeId} />}\n </span>\n {workforce && (\n <span className=\"text-xs text-muted-foreground\">\n {workforce.allocatedHours}h allocated ({workforce.billableHours}h\n billable)\n {workforce.utilizationPercent != null &&\n ` · ${workforce.utilizationPercent}% util`}\n </span>\n )}\n </div>\n </div>\n );\n })}\n {uniqueAssignees.length === 0 && (\n <p className=\"text-sm text-muted-foreground col-span-2 text-center py-4\">\n No team members assigned.\n </p>\n )}\n </div>\n {/* Real cross-layer CrewFoundry workforce allocation (BOFF-4444). */}\n {capacity?.crewfoundryUnavailable && uniqueAssignees.length > 0 && (\n <p className=\"text-xs text-muted-foreground mt-3 border-t pt-3\">\n Workforce allocation from CrewFoundry is unavailable for this workspace — no\n CrewFoundry module provisioned yet.\n </p>\n )}\n {!capacity?.crewfoundryUnavailable &&\n (capacity?.unmatchedAssigneeIds?.length ?? 0) > 0 && (\n <p className=\"text-xs text-muted-foreground mt-3 border-t pt-3\">\n {capacity.unmatchedAssigneeIds.length} assignee(s) have no matching CrewFoundry\n employee record — allocation hours shown only for matched employees.\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n <Card>\n <CardHeader>\n <CardTitle>Session Info</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <FolderKanban className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Project:</span>\n <span className=\"font-medium\">{sprint.projectId}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <CalendarClock className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Start:</span>\n <span className=\"font-medium\">\n {sprint.startDate ? new Date(sprint.startDate).toLocaleDateString() : 'Not set'}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <CalendarClock className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">End:</span>\n <span className=\"font-medium\">\n {sprint.endDate ? new Date(sprint.endDate).toLocaleDateString() : 'Not set'}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Assignees:</span>\n <span className=\"font-medium\">{uniqueAssignees.length}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Capacity:</span>\n <span className=\"font-medium\">{allocatedCapacity} pts</span>\n </div>\n {sprint.velocity != null && (\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Velocity:</span>\n <span className=\"font-medium\">{sprint.velocity} pts</span>\n </div>\n )}\n {sprint.goal && (\n <div className=\"border-t pt-3 mt-3\">\n <p className=\"text-muted-foreground text-xs mb-1\">Goal</p>\n <p className=\"text-sm\">{sprint.goal}</p>\n </div>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningDetailPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.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 { CalendarClock, Users, BarChart3, FolderKanban } from 'lucide-react';\nimport { useEntityId } from '../hooks/useEntityId';\nimport { PersonName } from '../people/People';\nimport { SprintLifecycleActions, SprintWorkItemsPanel } from '../sprints/SprintControls';\n\nconst GET_SPRINT_DETAIL = gql`\n query GetSprintDetail($id: ID!) {\n planmagnetSprint(id: $id) {\n id\n name\n projectId\n project {\n id\n name\n }\n status\n startDate\n endDate\n goal\n capacity\n velocity\n workItems {\n id\n key\n title\n status\n storyPoints\n assigneeId\n priority\n }\n }\n }\n`;\n\n// Real cross-layer CrewFoundry workforce capacity (BOFF-4444). Fails open on\n// the backend — an unreachable/unprovisioned CrewFoundry never blocks this\n// page, it just yields crewfoundryUnavailable: true, handled below.\nconst GET_SPRINT_CAPACITY = gql`\n query GetSprintCapacity($sprintId: ID!) {\n planmagnetSprintCapacity(sprintId: $sprintId) {\n sprintId\n crewfoundryUnavailable\n unmatchedAssigneeIds\n members {\n actorId\n employeeName\n department\n position\n allocatedHours\n billableHours\n utilizationPercent\n assignedStoryPoints\n assignedWorkItemCount\n }\n }\n }\n`;\n\nexport function ProjectsPlanningDetailPagePage() {\n const sprintId = useEntityId('sprintId');\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_SPRINT_DETAIL, {\n variables: { id: sprintId },\n skip: !sprintId,\n });\n\n // Real cross-layer CrewFoundry capacity (BOFF-4444) — called unconditionally\n // (with `skip`) to keep hook order stable across the loading/error/loaded\n // renders above.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const { data: capacityData } = useQuery<Record<string, any>>(GET_SPRINT_CAPACITY, {\n variables: { sprintId },\n skip: !sprintId,\n });\n\n if (!sprintId)\n return (\n <div className=\"p-6 text-muted-foreground\">\n No planning session selected. Open one from the list.\n </div>\n );\n if (loading)\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 if (error)\n return <div className=\"p-6 text-red-500\">Error loading planning session: {error.message}</div>;\n\n const sprint = data?.planmagnetSprint;\n if (!sprint) return <div className=\"p-6 text-muted-foreground\">Planning session not found.</div>;\n\n const capacity = capacityData?.planmagnetSprintCapacity;\n const allocationByAssignee: Record<\n string,\n {\n employeeName: string;\n allocatedHours: number;\n billableHours: number;\n utilizationPercent: number | null;\n }\n > = {};\n for (const member of capacity?.members ?? []) {\n allocationByAssignee[member.actorId] = {\n employeeName: member.employeeName,\n allocatedHours: member.allocatedHours,\n billableHours: member.billableHours,\n utilizationPercent: member.utilizationPercent,\n };\n }\n\n const workItems = sprint.workItems ?? [];\n const totalPoints = workItems.reduce(\n (sum: number, wi: { storyPoints: number | null }) => sum + (wi.storyPoints ?? 0),\n 0\n );\n const completedPoints = workItems\n .filter((wi: { status: string }) => wi.status === 'DONE')\n .reduce((sum: number, wi: { storyPoints: number | null }) => sum + (wi.storyPoints ?? 0), 0);\n const allocatedCapacity = sprint.capacity ?? totalPoints;\n const capPct = allocatedCapacity > 0 ? Math.round((totalPoints / allocatedCapacity) * 100) : 0;\n const remaining = allocatedCapacity - totalPoints;\n\n // Derive unique assignees from work items\n const uniqueAssignees = [\n ...new Set(\n workItems\n .map((wi: { assigneeId: string | null }) => wi.assigneeId)\n .filter(Boolean) as string[]\n ),\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.name}</h1>\n <p className=\"text-sm text-muted-foreground\">\n {sprint.project?.name ?? 'Unknown project'} ·{' '}\n {sprint.startDate ? new Date(sprint.startDate).toLocaleDateString() : '—'} -{' '}\n {sprint.endDate ? new Date(sprint.endDate).toLocaleDateString() : '—'}\n </p>\n </div>\n <div className=\"flex items-start gap-3\">\n <Badge className=\"capitalize\">{sprint.status.toLowerCase().replace('_', ' ')}</Badge>\n <SprintLifecycleActions\n sprintId={sprint.id}\n sprintName={sprint.name}\n status={sprint.status}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle>Capacity Allocation</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-3 gap-4 text-center\">\n <div className=\"p-4 bg-muted rounded-md\">\n <p className=\"text-2xl font-bold\">{allocatedCapacity}</p>\n <p className=\"text-xs text-muted-foreground\">Capacity</p>\n </div>\n <div className=\"p-4 bg-primary/10 rounded-md\">\n <p className=\"text-2xl font-bold text-primary\">{totalPoints}</p>\n <p className=\"text-xs text-muted-foreground\">Allocated</p>\n </div>\n <div className=\"p-4 bg-muted rounded-md\">\n <p className=\"text-2xl font-bold\">{remaining > 0 ? remaining : 0}</p>\n <p className=\"text-xs text-muted-foreground\">Remaining</p>\n </div>\n </div>\n <div>\n <div className=\"flex justify-between text-sm mb-2\">\n <span className=\"text-muted-foreground\">Utilization</span>\n <span className=\"font-medium\">{capPct}%</span>\n </div>\n <div className=\"w-full h-4 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${capPct > 90 ? 'bg-red-400' : 'bg-green-400'}`}\n style={{ width: `${Math.min(capPct, 100)}%` }}\n />\n </div>\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>Work Items</CardTitle>\n </CardHeader>\n <CardContent>\n <SprintWorkItemsPanel\n sprintId={sprint.id}\n projectId={sprint.projectId}\n status={sprint.status}\n items={workItems}\n />\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>Team Members ({uniqueAssignees.length})</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 gap-3\">\n {uniqueAssignees.map((assigneeId: string) => {\n const workforce = allocationByAssignee[assigneeId];\n return (\n <div\n key={assigneeId}\n className=\"flex items-center gap-2 border rounded-md p-2.5\"\n >\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-medium text-primary\">\n {assigneeId.slice(0, 2).toUpperCase()}\n </div>\n <div className=\"min-w-0\">\n <span className=\"text-sm truncate block\">\n {workforce?.employeeName ?? <PersonName id={assigneeId} />}\n </span>\n {workforce && (\n <span className=\"text-xs text-muted-foreground\">\n {workforce.allocatedHours}h allocated ({workforce.billableHours}h\n billable)\n {workforce.utilizationPercent != null &&\n ` · ${workforce.utilizationPercent}% util`}\n </span>\n )}\n </div>\n </div>\n );\n })}\n {uniqueAssignees.length === 0 && (\n <p className=\"text-sm text-muted-foreground col-span-2 text-center py-4\">\n No team members assigned.\n </p>\n )}\n </div>\n {/* Real cross-layer CrewFoundry workforce allocation (BOFF-4444). */}\n {capacity?.crewfoundryUnavailable && uniqueAssignees.length > 0 && (\n <p className=\"text-xs text-muted-foreground mt-3 border-t pt-3\">\n Workforce allocation from CrewFoundry is unavailable for this workspace — no\n CrewFoundry module provisioned yet.\n </p>\n )}\n {!capacity?.crewfoundryUnavailable &&\n (capacity?.unmatchedAssigneeIds?.length ?? 0) > 0 && (\n <p className=\"text-xs text-muted-foreground mt-3 border-t pt-3\">\n {capacity.unmatchedAssigneeIds.length} assignee(s) have no matching CrewFoundry\n employee record — allocation hours shown only for matched employees.\n </p>\n )}\n </CardContent>\n </Card>\n </div>\n <Card>\n <CardHeader>\n <CardTitle>Session Info</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <FolderKanban className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Project:</span>\n <span className=\"font-medium\">{sprint.project?.name ?? 'Unknown project'}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <CalendarClock className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Start:</span>\n <span className=\"font-medium\">\n {sprint.startDate ? new Date(sprint.startDate).toLocaleDateString() : 'Not set'}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <CalendarClock className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">End:</span>\n <span className=\"font-medium\">\n {sprint.endDate ? new Date(sprint.endDate).toLocaleDateString() : 'Not set'}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Assignees:</span>\n <span className=\"font-medium\">{uniqueAssignees.length}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Capacity:</span>\n <span className=\"font-medium\">{allocatedCapacity} pts</span>\n </div>\n {sprint.velocity != null && (\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-muted-foreground\">Velocity:</span>\n <span className=\"font-medium\">{sprint.velocity} pts</span>\n </div>\n )}\n {sprint.goal && (\n <div className=\"border-t pt-3 mt-3\">\n <p className=\"text-muted-foreground text-xs mb-1\">Goal</p>\n <p className=\"text-sm\">{sprint.goal}</p>\n </div>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsPlanningPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningPagePage.tsx"],"names":[],"mappings":"AA8CA,wBAAgB,wBAAwB,4CAoIvC"}
|