@burdenoff/microfe-planmagnet 2026.925.7 → 2026.925.9
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/generated/wspace-types.d.ts +49 -0
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/planmagnet/board/ProjectBoard.d.ts.map +1 -1
- package/dist/planmagnet/board/ProjectBoard.js +159 -158
- package/dist/planmagnet/board/ProjectBoard.js.map +1 -1
- package/dist/planmagnet/comments/WorkItemComments.d.ts +4 -0
- package/dist/planmagnet/comments/WorkItemComments.d.ts.map +1 -0
- package/dist/planmagnet/comments/WorkItemComments.js +260 -0
- package/dist/planmagnet/comments/WorkItemComments.js.map +1 -0
- package/dist/planmagnet/create/CreateDialogs.d.ts.map +1 -1
- package/dist/planmagnet/create/CreateDialogs.js +118 -117
- package/dist/planmagnet/create/CreateDialogs.js.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsCreateObjectivePagePage.js.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js +322 -280
- package/dist/planmagnet/pages/GoalsObjectiveDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +166 -143
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.d.ts.map +1 -1
- package/dist/planmagnet/sprints/SprintControls.js +202 -201
- package/dist/planmagnet/sprints/SprintControls.js.map +1 -1
- package/dist/planmagnet/utils/mutationResult.d.ts +16 -0
- package/dist/planmagnet/utils/mutationResult.d.ts.map +1 -0
- package/dist/planmagnet/utils/mutationResult.js +10 -0
- package/dist/planmagnet/utils/mutationResult.js.map +1 -0
- package/package.json +3 -2
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { throwOnError as t } from "../utils/mutationResult.js";
|
|
3
|
+
import { useState as n } from "react";
|
|
4
|
+
import { Plus as r } from "lucide-react";
|
|
5
|
+
import { gql as i } from "@apollo/client";
|
|
6
|
+
import { useMutation as a, useQuery as o } from "@apollo/client/react";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import { Button as l, Input as u, ResponsiveDialog as d, ResponsiveDialogContent as f, ResponsiveDialogDescription as p, ResponsiveDialogFooter as m, ResponsiveDialogHeader as h, ResponsiveDialogTitle as g, ResponsiveDialogTrigger as _ } from "@burdenoff/fe-libs/ui";
|
|
8
9
|
//#region src/planmagnet/create/CreateDialogs.tsx
|
|
9
|
-
var
|
|
10
|
+
var v = i`
|
|
10
11
|
query CreateDialogProjects($workspaceId: ID!) {
|
|
11
12
|
planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {
|
|
12
13
|
items {
|
|
@@ -15,16 +16,16 @@ var _ = r`
|
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
|
-
`,
|
|
19
|
-
function
|
|
20
|
-
return /* @__PURE__ */
|
|
19
|
+
`, y = "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm";
|
|
20
|
+
function b({ message: e }) {
|
|
21
|
+
return /* @__PURE__ */ s("p", {
|
|
21
22
|
role: "alert",
|
|
22
23
|
className: "text-sm text-destructive",
|
|
23
24
|
children: e
|
|
24
25
|
});
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
-
let { workspaceId: n } = e(), { data: r, loading: i } =
|
|
27
|
+
function x(t) {
|
|
28
|
+
let { workspaceId: n } = e(), { data: r, loading: i } = o(v, {
|
|
28
29
|
variables: { workspaceId: n ?? "" },
|
|
29
30
|
skip: !t || !n
|
|
30
31
|
});
|
|
@@ -33,31 +34,31 @@ function b(t) {
|
|
|
33
34
|
loading: i
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
|
-
function
|
|
37
|
-
return /* @__PURE__ */
|
|
37
|
+
function S({ id: e, value: t, onChange: n, projects: r, loading: i }) {
|
|
38
|
+
return /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
|
|
38
39
|
htmlFor: e,
|
|
39
40
|
className: "text-sm font-medium",
|
|
40
41
|
children: "Project"
|
|
41
|
-
}), /* @__PURE__ */
|
|
42
|
+
}), /* @__PURE__ */ c("select", {
|
|
42
43
|
id: e,
|
|
43
|
-
className:
|
|
44
|
+
className: y,
|
|
44
45
|
value: t,
|
|
45
46
|
onChange: (e) => n(e.target.value),
|
|
46
|
-
children: [r.length === 0 && /* @__PURE__ */
|
|
47
|
+
children: [r.length === 0 && /* @__PURE__ */ s("option", {
|
|
47
48
|
value: "",
|
|
48
49
|
children: i ? "Loading…" : "No projects"
|
|
49
|
-
}), r.map((e) => /* @__PURE__ */
|
|
50
|
+
}), r.map((e) => /* @__PURE__ */ s("option", {
|
|
50
51
|
value: e.id,
|
|
51
52
|
children: e.name
|
|
52
53
|
}, e.id))]
|
|
53
54
|
})] });
|
|
54
55
|
}
|
|
55
|
-
function
|
|
56
|
-
return /* @__PURE__ */
|
|
56
|
+
function C({ id: e, label: t, value: n, onChange: r, type: i = "text", placeholder: a }) {
|
|
57
|
+
return /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("label", {
|
|
57
58
|
htmlFor: e,
|
|
58
59
|
className: "text-sm font-medium",
|
|
59
60
|
children: t
|
|
60
|
-
}), /* @__PURE__ */
|
|
61
|
+
}), /* @__PURE__ */ s(u, {
|
|
61
62
|
id: e,
|
|
62
63
|
type: i,
|
|
63
64
|
className: "mt-1",
|
|
@@ -66,217 +67,217 @@ function S({ id: e, label: t, value: n, onChange: r, type: i = "text", placehold
|
|
|
66
67
|
onChange: (e) => r(e.target.value)
|
|
67
68
|
})] });
|
|
68
69
|
}
|
|
69
|
-
var
|
|
70
|
+
var w = (e, t) => e instanceof Error ? e.message : t, T = i`
|
|
70
71
|
mutation CreateDialogRelease($input: PlanmagnetCreateReleaseInput!) {
|
|
71
72
|
planmagnetCreateRelease(input: $input) {
|
|
72
73
|
id
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
`,
|
|
76
|
+
`, E = {
|
|
76
77
|
name: "",
|
|
77
78
|
version: "",
|
|
78
79
|
projectId: "",
|
|
79
80
|
plannedDate: "",
|
|
80
81
|
description: ""
|
|
81
82
|
};
|
|
82
|
-
function
|
|
83
|
-
let [
|
|
83
|
+
function D({ onCreated: e }) {
|
|
84
|
+
let [i, o] = n(!1), [u, v] = n(E), [y, D] = n(null), { projects: O, loading: k } = x(i), A = u.projectId || O[0]?.id || "", [j, { loading: M }] = a(T, {
|
|
84
85
|
refetchQueries: ["ListReleases"],
|
|
85
86
|
awaitRefetchQueries: !0
|
|
86
|
-
}),
|
|
87
|
-
return /* @__PURE__ */
|
|
88
|
-
open:
|
|
87
|
+
}), N = u.name.trim() !== "" && u.version.trim() !== "" && A !== "" && !M;
|
|
88
|
+
return /* @__PURE__ */ c(d, {
|
|
89
|
+
open: i,
|
|
89
90
|
onOpenChange: (e) => {
|
|
90
|
-
|
|
91
|
+
o(e), e || D(null);
|
|
91
92
|
},
|
|
92
|
-
children: [/* @__PURE__ */
|
|
93
|
+
children: [/* @__PURE__ */ s(_, {
|
|
93
94
|
asChild: !0,
|
|
94
|
-
children: /* @__PURE__ */
|
|
95
|
+
children: /* @__PURE__ */ c(l, {
|
|
95
96
|
size: "sm",
|
|
96
|
-
children: [/* @__PURE__ */
|
|
97
|
+
children: [/* @__PURE__ */ s(r, { className: "mr-1 h-4 w-4" }), "New Release"]
|
|
97
98
|
})
|
|
98
|
-
}), /* @__PURE__ */
|
|
99
|
+
}), /* @__PURE__ */ c(f, {
|
|
99
100
|
className: "max-w-lg",
|
|
100
101
|
children: [
|
|
101
|
-
/* @__PURE__ */
|
|
102
|
-
/* @__PURE__ */
|
|
102
|
+
/* @__PURE__ */ c(h, { children: [/* @__PURE__ */ s(g, { children: "New release" }), /* @__PURE__ */ s(p, { children: "The release starts in Planning." })] }),
|
|
103
|
+
/* @__PURE__ */ c("div", {
|
|
103
104
|
className: "space-y-3",
|
|
104
105
|
children: [
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ s(C, {
|
|
106
107
|
id: "new-release-name",
|
|
107
108
|
label: "Name",
|
|
108
|
-
value:
|
|
109
|
-
onChange: (e) =>
|
|
110
|
-
...
|
|
109
|
+
value: u.name,
|
|
110
|
+
onChange: (e) => v({
|
|
111
|
+
...u,
|
|
111
112
|
name: e
|
|
112
113
|
})
|
|
113
114
|
}),
|
|
114
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ s(C, {
|
|
115
116
|
id: "new-release-version",
|
|
116
117
|
label: "Version",
|
|
117
118
|
placeholder: "e.g. 1.4.0",
|
|
118
|
-
value:
|
|
119
|
-
onChange: (e) =>
|
|
120
|
-
...
|
|
119
|
+
value: u.version,
|
|
120
|
+
onChange: (e) => v({
|
|
121
|
+
...u,
|
|
121
122
|
version: e
|
|
122
123
|
})
|
|
123
124
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ s(S, {
|
|
125
126
|
id: "new-release-project",
|
|
126
|
-
value:
|
|
127
|
-
onChange: (e) =>
|
|
128
|
-
...
|
|
127
|
+
value: A,
|
|
128
|
+
onChange: (e) => v({
|
|
129
|
+
...u,
|
|
129
130
|
projectId: e
|
|
130
131
|
}),
|
|
131
|
-
projects:
|
|
132
|
-
loading:
|
|
132
|
+
projects: O,
|
|
133
|
+
loading: k
|
|
133
134
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ s(C, {
|
|
135
136
|
id: "new-release-date",
|
|
136
137
|
label: "Planned date",
|
|
137
138
|
type: "date",
|
|
138
|
-
value:
|
|
139
|
-
onChange: (e) =>
|
|
140
|
-
...
|
|
139
|
+
value: u.plannedDate,
|
|
140
|
+
onChange: (e) => v({
|
|
141
|
+
...u,
|
|
141
142
|
plannedDate: e
|
|
142
143
|
})
|
|
143
144
|
}),
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ s(C, {
|
|
145
146
|
id: "new-release-description",
|
|
146
147
|
label: "Description",
|
|
147
|
-
value:
|
|
148
|
-
onChange: (e) =>
|
|
149
|
-
...
|
|
148
|
+
value: u.description,
|
|
149
|
+
onChange: (e) => v({
|
|
150
|
+
...u,
|
|
150
151
|
description: e
|
|
151
152
|
})
|
|
152
153
|
})
|
|
153
154
|
]
|
|
154
155
|
}),
|
|
155
|
-
|
|
156
|
-
/* @__PURE__ */
|
|
156
|
+
y && /* @__PURE__ */ s(b, { message: y }),
|
|
157
|
+
/* @__PURE__ */ s(m, { children: /* @__PURE__ */ s(l, {
|
|
157
158
|
onClick: async () => {
|
|
158
|
-
|
|
159
|
+
D(null);
|
|
159
160
|
try {
|
|
160
|
-
let
|
|
161
|
-
name:
|
|
162
|
-
version:
|
|
163
|
-
projectId:
|
|
164
|
-
plannedDate:
|
|
165
|
-
description:
|
|
166
|
-
} } })).data?.planmagnetCreateRelease.id;
|
|
167
|
-
|
|
161
|
+
let n = (await t(j({ variables: { input: {
|
|
162
|
+
name: u.name.trim(),
|
|
163
|
+
version: u.version.trim(),
|
|
164
|
+
projectId: A,
|
|
165
|
+
plannedDate: u.plannedDate || void 0,
|
|
166
|
+
description: u.description.trim() || void 0
|
|
167
|
+
} } }))).data?.planmagnetCreateRelease.id;
|
|
168
|
+
v(E), o(!1), n && e(n);
|
|
168
169
|
} catch (e) {
|
|
169
|
-
|
|
170
|
+
D(w(e, "The release could not be created."));
|
|
170
171
|
}
|
|
171
172
|
},
|
|
172
|
-
disabled: !
|
|
173
|
+
disabled: !N,
|
|
173
174
|
"data-testid": "new-release-submit",
|
|
174
|
-
children:
|
|
175
|
+
children: M ? "Creating…" : "Create release"
|
|
175
176
|
}) })
|
|
176
177
|
]
|
|
177
178
|
})]
|
|
178
179
|
});
|
|
179
180
|
}
|
|
180
|
-
var
|
|
181
|
+
var O = i`
|
|
181
182
|
mutation CreateDialogMilestone($input: PlanmagnetCreateMilestoneInput!) {
|
|
182
183
|
planmagnetCreateMilestone(input: $input) {
|
|
183
184
|
id
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
|
-
`,
|
|
187
|
+
`, k = {
|
|
187
188
|
name: "",
|
|
188
189
|
projectId: "",
|
|
189
190
|
dueDate: "",
|
|
190
191
|
description: ""
|
|
191
192
|
};
|
|
192
|
-
function
|
|
193
|
-
let [
|
|
193
|
+
function A({ onCreated: e }) {
|
|
194
|
+
let [i, o] = n(!1), [u, v] = n(k), [y, T] = n(null), { projects: E, loading: D } = x(i), A = u.projectId || E[0]?.id || "", [j, { loading: M }] = a(O, {
|
|
194
195
|
refetchQueries: ["GetMilestones"],
|
|
195
196
|
awaitRefetchQueries: !0
|
|
196
|
-
}),
|
|
197
|
-
return /* @__PURE__ */
|
|
198
|
-
open:
|
|
197
|
+
}), N = u.name.trim() !== "" && A !== "" && !M;
|
|
198
|
+
return /* @__PURE__ */ c(d, {
|
|
199
|
+
open: i,
|
|
199
200
|
onOpenChange: (e) => {
|
|
200
|
-
|
|
201
|
+
o(e), e || T(null);
|
|
201
202
|
},
|
|
202
|
-
children: [/* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ s(_, {
|
|
203
204
|
asChild: !0,
|
|
204
|
-
children: /* @__PURE__ */
|
|
205
|
+
children: /* @__PURE__ */ c(l, {
|
|
205
206
|
size: "sm",
|
|
206
|
-
children: [/* @__PURE__ */
|
|
207
|
+
children: [/* @__PURE__ */ s(r, { className: "mr-1 h-4 w-4" }), "New Milestone"]
|
|
207
208
|
})
|
|
208
|
-
}), /* @__PURE__ */
|
|
209
|
+
}), /* @__PURE__ */ c(f, {
|
|
209
210
|
className: "max-w-lg",
|
|
210
211
|
children: [
|
|
211
|
-
/* @__PURE__ */
|
|
212
|
-
/* @__PURE__ */
|
|
212
|
+
/* @__PURE__ */ c(h, { children: [/* @__PURE__ */ s(g, { children: "New milestone" }), /* @__PURE__ */ s(p, { children: "The milestone starts as Pending." })] }),
|
|
213
|
+
/* @__PURE__ */ c("div", {
|
|
213
214
|
className: "space-y-3",
|
|
214
215
|
children: [
|
|
215
|
-
/* @__PURE__ */
|
|
216
|
+
/* @__PURE__ */ s(C, {
|
|
216
217
|
id: "new-milestone-name",
|
|
217
218
|
label: "Name",
|
|
218
|
-
value:
|
|
219
|
-
onChange: (e) =>
|
|
220
|
-
...
|
|
219
|
+
value: u.name,
|
|
220
|
+
onChange: (e) => v({
|
|
221
|
+
...u,
|
|
221
222
|
name: e
|
|
222
223
|
})
|
|
223
224
|
}),
|
|
224
|
-
/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ s(S, {
|
|
225
226
|
id: "new-milestone-project",
|
|
226
|
-
value:
|
|
227
|
-
onChange: (e) =>
|
|
228
|
-
...
|
|
227
|
+
value: A,
|
|
228
|
+
onChange: (e) => v({
|
|
229
|
+
...u,
|
|
229
230
|
projectId: e
|
|
230
231
|
}),
|
|
231
|
-
projects:
|
|
232
|
-
loading:
|
|
232
|
+
projects: E,
|
|
233
|
+
loading: D
|
|
233
234
|
}),
|
|
234
|
-
/* @__PURE__ */
|
|
235
|
+
/* @__PURE__ */ s(C, {
|
|
235
236
|
id: "new-milestone-due",
|
|
236
237
|
label: "Due date",
|
|
237
238
|
type: "date",
|
|
238
|
-
value:
|
|
239
|
-
onChange: (e) =>
|
|
240
|
-
...
|
|
239
|
+
value: u.dueDate,
|
|
240
|
+
onChange: (e) => v({
|
|
241
|
+
...u,
|
|
241
242
|
dueDate: e
|
|
242
243
|
})
|
|
243
244
|
}),
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ s(C, {
|
|
245
246
|
id: "new-milestone-description",
|
|
246
247
|
label: "Description",
|
|
247
|
-
value:
|
|
248
|
-
onChange: (e) =>
|
|
249
|
-
...
|
|
248
|
+
value: u.description,
|
|
249
|
+
onChange: (e) => v({
|
|
250
|
+
...u,
|
|
250
251
|
description: e
|
|
251
252
|
})
|
|
252
253
|
})
|
|
253
254
|
]
|
|
254
255
|
}),
|
|
255
|
-
|
|
256
|
-
/* @__PURE__ */
|
|
256
|
+
y && /* @__PURE__ */ s(b, { message: y }),
|
|
257
|
+
/* @__PURE__ */ s(m, { children: /* @__PURE__ */ s(l, {
|
|
257
258
|
onClick: async () => {
|
|
258
|
-
|
|
259
|
+
T(null);
|
|
259
260
|
try {
|
|
260
|
-
let
|
|
261
|
-
name:
|
|
262
|
-
projectId:
|
|
263
|
-
dueDate:
|
|
264
|
-
description:
|
|
265
|
-
} } })).data?.planmagnetCreateMilestone.id;
|
|
266
|
-
|
|
261
|
+
let n = (await t(j({ variables: { input: {
|
|
262
|
+
name: u.name.trim(),
|
|
263
|
+
projectId: A,
|
|
264
|
+
dueDate: u.dueDate || void 0,
|
|
265
|
+
description: u.description.trim() || void 0
|
|
266
|
+
} } }))).data?.planmagnetCreateMilestone.id;
|
|
267
|
+
v(k), o(!1), n && e(n);
|
|
267
268
|
} catch (e) {
|
|
268
|
-
w(
|
|
269
|
+
T(w(e, "The milestone could not be created."));
|
|
269
270
|
}
|
|
270
271
|
},
|
|
271
|
-
disabled: !
|
|
272
|
+
disabled: !N,
|
|
272
273
|
"data-testid": "new-milestone-submit",
|
|
273
|
-
children:
|
|
274
|
+
children: M ? "Creating…" : "Create milestone"
|
|
274
275
|
}) })
|
|
275
276
|
]
|
|
276
277
|
})]
|
|
277
278
|
});
|
|
278
279
|
}
|
|
279
280
|
//#endregion
|
|
280
|
-
export {
|
|
281
|
+
export { A as NewMilestoneDialog, D as NewReleaseDialog };
|
|
281
282
|
|
|
282
283
|
//# sourceMappingURL=CreateDialogs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateDialogs.js","names":[],"sources":["../../../src/planmagnet/create/CreateDialogs.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Button,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { Plus } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\n/**\n * Create dialogs for records whose list pages had a dead \"New …\" button, or\n * none at all (QA report 2026-09-23: C4 New Release had no onClick; H7 there\n * was no way to create a milestone). Both mutations were already served and\n * verified in prod; only the UI trigger was missing.\n */\n\nconst DIALOG_PROJECTS = gql`\n query CreateDialogProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n }\n }\n`;\n\nconst FIELD = 'mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm';\n\nfunction ErrorLine({ message }: { message: string }) {\n return (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n );\n}\n\nfunction useDialogProjects(open: boolean) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading } = useQuery<{\n planmagnetProjects: { items: Array<{ id: string; name: string }> };\n }>(DIALOG_PROJECTS, {\n variables: { workspaceId: workspaceId ?? '' },\n skip: !open || !workspaceId,\n });\n return { projects: data?.planmagnetProjects.items ?? [], loading };\n}\n\nfunction ProjectField({\n id,\n value,\n onChange,\n projects,\n loading,\n}: {\n id: string;\n value: string;\n onChange: (id: string) => void;\n projects: Array<{ id: string; name: string }>;\n loading: boolean;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n Project\n </label>\n <select id={id} className={FIELD} value={value} onChange={(e) => onChange(e.target.value)}>\n {projects.length === 0 && <option value=\"\">{loading ? 'Loading…' : 'No projects'}</option>}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\nfunction TextField({\n id,\n label,\n value,\n onChange,\n type = 'text',\n placeholder,\n}: {\n id: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n type?: string;\n placeholder?: string;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n {label}\n </label>\n <Input\n id={id}\n type={type}\n className=\"mt-1\"\n value={value}\n placeholder={placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n );\n}\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback);\n\n// ─── New release (C4) ────────────────────────────────────────────────────────\n\nconst CREATE_RELEASE = gql`\n mutation CreateDialogRelease($input: PlanmagnetCreateReleaseInput!) {\n planmagnetCreateRelease(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_RELEASE = { name: '', version: '', projectId: '', plannedDate: '', description: '' };\n\nexport function NewReleaseDialog({ onCreated }: { onCreated: (releaseId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_RELEASE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateRelease: { id: string } }>(\n CREATE_RELEASE,\n { refetchQueries: ['ListReleases'], awaitRefetchQueries: true }\n );\n\n const canSubmit =\n form.name.trim() !== '' && form.version.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await create({\n variables: {\n input: {\n name: form.name.trim(),\n version: form.version.trim(),\n projectId,\n plannedDate: form.plannedDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n });\n const id = result.data?.planmagnetCreateRelease.id;\n setForm(EMPTY_RELEASE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The release could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Release\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New release</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>The release starts in Planning.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-release-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <TextField\n id=\"new-release-version\"\n label=\"Version\"\n placeholder=\"e.g. 1.4.0\"\n value={form.version}\n onChange={(version) => setForm({ ...form, version })}\n />\n <ProjectField\n id=\"new-release-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-release-date\"\n label=\"Planned date\"\n type=\"date\"\n value={form.plannedDate}\n onChange={(plannedDate) => setForm({ ...form, plannedDate })}\n />\n <TextField\n id=\"new-release-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-release-submit\">\n {loading ? 'Creating…' : 'Create release'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New milestone (H7) ──────────────────────────────────────────────────────\n\nconst CREATE_MILESTONE = gql`\n mutation CreateDialogMilestone($input: PlanmagnetCreateMilestoneInput!) {\n planmagnetCreateMilestone(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_MILESTONE = { name: '', projectId: '', dueDate: '', description: '' };\n\nexport function NewMilestoneDialog({ onCreated }: { onCreated: (milestoneId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_MILESTONE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateMilestone: { id: string } }>(\n CREATE_MILESTONE,\n { refetchQueries: ['GetMilestones'], awaitRefetchQueries: true }\n );\n\n const canSubmit = form.name.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await create({\n variables: {\n input: {\n name: form.name.trim(),\n projectId,\n dueDate: form.dueDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n });\n const id = result.data?.planmagnetCreateMilestone.id;\n setForm(EMPTY_MILESTONE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The milestone could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Milestone\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New milestone</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n The milestone starts as Pending.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-milestone-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <ProjectField\n id=\"new-milestone-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-milestone-due\"\n label=\"Due date\"\n type=\"date\"\n value={form.dueDate}\n onChange={(dueDate) => setForm({ ...form, dueDate })}\n />\n <TextField\n id=\"new-milestone-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-milestone-submit\">\n {loading ? 'Creating…' : 'Create milestone'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateDialogs.js","names":[],"sources":["../../../src/planmagnet/create/CreateDialogs.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Button,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { Plus } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { throwOnError } from '../utils/mutationResult';\n\n/**\n * Create dialogs for records whose list pages had a dead \"New …\" button, or\n * none at all (QA report 2026-09-23: C4 New Release had no onClick; H7 there\n * was no way to create a milestone). Both mutations were already served and\n * verified in prod; only the UI trigger was missing.\n */\n\nconst DIALOG_PROJECTS = gql`\n query CreateDialogProjects($workspaceId: ID!) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: { first: 100 }) {\n items {\n id\n name\n }\n }\n }\n`;\n\nconst FIELD = 'mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm';\n\nfunction ErrorLine({ message }: { message: string }) {\n return (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {message}\n </p>\n );\n}\n\nfunction useDialogProjects(open: boolean) {\n const { workspaceId } = usePlanMagnet();\n const { data, loading } = useQuery<{\n planmagnetProjects: { items: Array<{ id: string; name: string }> };\n }>(DIALOG_PROJECTS, {\n variables: { workspaceId: workspaceId ?? '' },\n skip: !open || !workspaceId,\n });\n return { projects: data?.planmagnetProjects.items ?? [], loading };\n}\n\nfunction ProjectField({\n id,\n value,\n onChange,\n projects,\n loading,\n}: {\n id: string;\n value: string;\n onChange: (id: string) => void;\n projects: Array<{ id: string; name: string }>;\n loading: boolean;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n Project\n </label>\n <select id={id} className={FIELD} value={value} onChange={(e) => onChange(e.target.value)}>\n {projects.length === 0 && <option value=\"\">{loading ? 'Loading…' : 'No projects'}</option>}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\nfunction TextField({\n id,\n label,\n value,\n onChange,\n type = 'text',\n placeholder,\n}: {\n id: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n type?: string;\n placeholder?: string;\n}) {\n return (\n <div>\n <label htmlFor={id} className=\"text-sm font-medium\">\n {label}\n </label>\n <Input\n id={id}\n type={type}\n className=\"mt-1\"\n value={value}\n placeholder={placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n );\n}\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback);\n\n// ─── New release (C4) ────────────────────────────────────────────────────────\n\nconst CREATE_RELEASE = gql`\n mutation CreateDialogRelease($input: PlanmagnetCreateReleaseInput!) {\n planmagnetCreateRelease(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_RELEASE = { name: '', version: '', projectId: '', plannedDate: '', description: '' };\n\nexport function NewReleaseDialog({ onCreated }: { onCreated: (releaseId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_RELEASE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateRelease: { id: string } }>(\n CREATE_RELEASE,\n { refetchQueries: ['ListReleases'], awaitRefetchQueries: true }\n );\n\n const canSubmit =\n form.name.trim() !== '' && form.version.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await throwOnError(\n create({\n variables: {\n input: {\n name: form.name.trim(),\n version: form.version.trim(),\n projectId,\n plannedDate: form.plannedDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n })\n );\n const id = result.data?.planmagnetCreateRelease.id;\n setForm(EMPTY_RELEASE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The release could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Release\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New release</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>The release starts in Planning.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-release-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <TextField\n id=\"new-release-version\"\n label=\"Version\"\n placeholder=\"e.g. 1.4.0\"\n value={form.version}\n onChange={(version) => setForm({ ...form, version })}\n />\n <ProjectField\n id=\"new-release-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-release-date\"\n label=\"Planned date\"\n type=\"date\"\n value={form.plannedDate}\n onChange={(plannedDate) => setForm({ ...form, plannedDate })}\n />\n <TextField\n id=\"new-release-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-release-submit\">\n {loading ? 'Creating…' : 'Create release'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New milestone (H7) ──────────────────────────────────────────────────────\n\nconst CREATE_MILESTONE = gql`\n mutation CreateDialogMilestone($input: PlanmagnetCreateMilestoneInput!) {\n planmagnetCreateMilestone(input: $input) {\n id\n }\n }\n`;\n\nconst EMPTY_MILESTONE = { name: '', projectId: '', dueDate: '', description: '' };\n\nexport function NewMilestoneDialog({ onCreated }: { onCreated: (milestoneId: string) => void }) {\n const [open, setOpen] = useState(false);\n const [form, setForm] = useState(EMPTY_MILESTONE);\n const [error, setError] = useState<string | null>(null);\n const { projects, loading: projectsLoading } = useDialogProjects(open);\n const projectId = form.projectId || projects[0]?.id || '';\n const [create, { loading }] = useMutation<{ planmagnetCreateMilestone: { id: string } }>(\n CREATE_MILESTONE,\n { refetchQueries: ['GetMilestones'], awaitRefetchQueries: true }\n );\n\n const canSubmit = form.name.trim() !== '' && projectId !== '' && !loading;\n\n const handleCreate = async () => {\n setError(null);\n try {\n const result = await throwOnError(\n create({\n variables: {\n input: {\n name: form.name.trim(),\n projectId,\n dueDate: form.dueDate || undefined,\n description: form.description.trim() || undefined,\n },\n },\n })\n );\n const id = result.data?.planmagnetCreateMilestone.id;\n setForm(EMPTY_MILESTONE);\n setOpen(false);\n if (id) onCreated(id);\n } catch (e) {\n setError(messageOf(e, 'The milestone could not be created.'));\n }\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setError(null);\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n New Milestone\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New milestone</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n The milestone starts as Pending.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3\">\n <TextField\n id=\"new-milestone-name\"\n label=\"Name\"\n value={form.name}\n onChange={(name) => setForm({ ...form, name })}\n />\n <ProjectField\n id=\"new-milestone-project\"\n value={projectId}\n onChange={(id) => setForm({ ...form, projectId: id })}\n projects={projects}\n loading={projectsLoading}\n />\n <TextField\n id=\"new-milestone-due\"\n label=\"Due date\"\n type=\"date\"\n value={form.dueDate}\n onChange={(dueDate) => setForm({ ...form, dueDate })}\n />\n <TextField\n id=\"new-milestone-description\"\n label=\"Description\"\n value={form.description}\n onChange={(description) => setForm({ ...form, description })}\n />\n </div>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button onClick={handleCreate} disabled={!canSubmit} data-testid=\"new-milestone-submit\">\n {loading ? 'Creating…' : 'Create milestone'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoalsCreateObjectivePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,4BAA4B,
|
|
1
|
+
{"version":3,"file":"GoalsCreateObjectivePagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,4BAA4B,4CA4G3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoalsCreateObjectivePagePage.js","names":[],"sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, Flag } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst CREATE_OBJECTIVE = gql`\n mutation CreateObjective($input: PlanmagnetCreateObjectiveInput!) {\n planmagnetCreateObjective(input: $input) {\n id\n }\n }\n`;\n\nexport function GoalsCreateObjectivePagePage() {\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState({\n title: '',\n description: '',\n periodLabel: '',\n endDate: '',\n });\n\n const [createObjective, { loading: saving, error }] = useMutation(CREATE_OBJECTIVE);\n\n const handleCreate = async () => {\n if (!form.title.trim() || !form.periodLabel.trim()) return;\n const result = await createObjective({\n variables: {\n input: {\n title: form.title.trim(),\n description: form.description.trim() || undefined,\n periodLabel: form.periodLabel.trim(),\n endDate: form.endDate || undefined,\n },\n },\n });\n const newId = result.data?.planmagnetCreateObjective?.id;\n if (newId) {\n navigate(`/goals/objective-detail-page?objectiveId=${newId}`);\n } else {\n navigate('/goals/goals-page');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Objective</h1>\n <p className=\"text-sm text-muted-foreground\">\n Define a workspace goal for a time period, then add key results to make progress\n measurable.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/goals/goals-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={handleCreate}\n disabled={saving || !form.title.trim() || !form.periodLabel.trim()}\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Creating...' : 'Create Objective'}\n </Button>\n </div>\n </div>\n {error && <div className=\"p-6 text-red-500\">Error: {error.message}</div>}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Flag className=\"h-4 w-4\" />\n Objective Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Grow enterprise revenue\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Why this objective matters this period...\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Time Period</label>\n <Input\n value={form.periodLabel}\n onChange={(e) => setForm({ ...form, periodLabel: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Q3 2026\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Target End Date</label>\n <Input\n type=\"date\"\n value={form.endDate}\n onChange={(e) => setForm({ ...form, endDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAAmB,CAAG;;;;;;;AAQ5B,SAAgB,IAA+B;CAC7C,IAAM,IAAW,GAAuB,EAClC,CAAC,GAAM,KAAW,EAAS;EAC/B,OAAO;EACP,aAAa;EACb,aAAa;EACb,SAAS;EACV,CAAC,EAEI,CAAC,GAAiB,EAAE,SAAS,GAAQ,cAAW,EAAY,EAAiB;
|
|
1
|
+
{"version":3,"file":"GoalsCreateObjectivePagePage.js","names":[],"sources":["../../../src/planmagnet/pages/GoalsCreateObjectivePagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, Flag } from 'lucide-react';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst CREATE_OBJECTIVE = gql`\n mutation CreateObjective($input: PlanmagnetCreateObjectiveInput!) {\n planmagnetCreateObjective(input: $input) {\n id\n }\n }\n`;\n\nexport function GoalsCreateObjectivePagePage() {\n const navigate = usePlanMagnetNavigate();\n const [form, setForm] = useState({\n title: '',\n description: '',\n periodLabel: '',\n endDate: '',\n });\n\n const [createObjective, { loading: saving, error }] = useMutation(CREATE_OBJECTIVE);\n\n const handleCreate = async () => {\n if (!form.title.trim() || !form.periodLabel.trim()) return;\n // mutation-error: shown from the hook's `error`; it only navigates when an id came back.\n const result = await createObjective({\n variables: {\n input: {\n title: form.title.trim(),\n description: form.description.trim() || undefined,\n periodLabel: form.periodLabel.trim(),\n endDate: form.endDate || undefined,\n },\n },\n });\n const newId = result.data?.planmagnetCreateObjective?.id;\n if (newId) {\n navigate(`/goals/objective-detail-page?objectiveId=${newId}`);\n } else {\n navigate('/goals/goals-page');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Objective</h1>\n <p className=\"text-sm text-muted-foreground\">\n Define a workspace goal for a time period, then add key results to make progress\n measurable.\n </p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/goals/goals-page')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button\n size=\"sm\"\n onClick={handleCreate}\n disabled={saving || !form.title.trim() || !form.periodLabel.trim()}\n >\n <Save className=\"mr-1 h-4 w-4\" />\n {saving ? 'Creating...' : 'Create Objective'}\n </Button>\n </div>\n </div>\n {error && <div className=\"p-6 text-red-500\">Error: {error.message}</div>}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Flag className=\"h-4 w-4\" />\n Objective Details\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Title</label>\n <Input\n value={form.title}\n onChange={(e) => setForm({ ...form, title: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Grow enterprise revenue\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[100px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n placeholder=\"Why this objective matters this period...\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Time Period</label>\n <Input\n value={form.periodLabel}\n onChange={(e) => setForm({ ...form, periodLabel: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Q3 2026\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Target End Date</label>\n <Input\n type=\"date\"\n value={form.endDate}\n onChange={(e) => setForm({ ...form, endDate: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoalsObjectiveDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsObjectiveDetailPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GoalsObjectiveDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/GoalsObjectiveDetailPagePage.tsx"],"names":[],"mappings":"AAqPA,wBAAgB,4BAA4B,4CAqQ3C"}
|