@burdenoff/microfe-proserviceworld 2026.706.2 → 2026.706.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/proserviceworld/components/DiscussionThread.js +1 -1
- package/dist/proserviceworld/components/DiscussionThread.js.map +1 -1
- package/dist/proserviceworld/components/ui.js +18 -18
- package/dist/proserviceworld/components/ui.js.map +1 -1
- package/dist/proserviceworld/hooks/useEntityComments.js.map +1 -1
- package/dist/proserviceworld/pages/AnalyticsPage.js +277 -111
- package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
- package/dist/proserviceworld/pages/ClientDetailPage.js +219 -151
- package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -1
- package/dist/proserviceworld/pages/ClientsPage.js +148 -127
- package/dist/proserviceworld/pages/ClientsPage.js.map +1 -1
- package/dist/proserviceworld/pages/CompliancePage.js +140 -96
- package/dist/proserviceworld/pages/CompliancePage.js.map +1 -1
- package/dist/proserviceworld/pages/DashboardPage.js +221 -104
- package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
- package/dist/proserviceworld/pages/EngagementDetailPage.js +211 -181
- package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -1
- package/dist/proserviceworld/pages/EngagementsPage.js +144 -106
- package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -1
- package/dist/proserviceworld/pages/InvoicesPage.js +144 -129
- package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
- package/dist/proserviceworld/pages/MattersPage.js +163 -122
- package/dist/proserviceworld/pages/MattersPage.js.map +1 -1
- package/dist/proserviceworld/pages/TimePage.js +112 -92
- package/dist/proserviceworld/pages/TimePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,55 +1,90 @@
|
|
|
1
1
|
import { useClients as e, useComplianceChecks as t, useCreateComplianceCheck as n, useEngagements as r, useMatters as i, useResolveComplianceCheck as a } from "../hooks/useProServiceWorldApi.js";
|
|
2
|
-
import { Banner as o, Empty as s, ErrorState as c, Field as l, LoadingBlock as u,
|
|
3
|
-
import { useState as
|
|
4
|
-
import { Plus as
|
|
5
|
-
import { Fragment as
|
|
6
|
-
import { Button as
|
|
2
|
+
import { Banner as o, Empty as s, ErrorState as c, Field as l, LoadingBlock as u, MetricCard as d, Modal as f, NativeSelect as p, PageHeader as m, SectionCard as h, StatusPill as g, TableWrap as _, Td as v, TextArea as y, TextInput as b, Th as x, enumOptions as S, fmtDate as C, humanize as w } from "../components/ui.js";
|
|
3
|
+
import { useState as T } from "react";
|
|
4
|
+
import { BadgeCheck as E, CheckCircle2 as D, Clock as O, Database as k, FileCheck as A, GraduationCap as j, ListChecks as M, Lock as N, Plus as P, Scale as F, ShieldCheck as I } from "lucide-react";
|
|
5
|
+
import { Fragment as L, jsx as R, jsxs as z } from "react/jsx-runtime";
|
|
6
|
+
import { Button as B } from "@burdenoff/fe-libs/ui";
|
|
7
7
|
//#region src/proserviceworld/pages/CompliancePage.tsx
|
|
8
|
-
var
|
|
8
|
+
var V = [
|
|
9
9
|
"ENGAGEMENT_ACCEPTANCE",
|
|
10
10
|
"INDEPENDENCE",
|
|
11
11
|
"LICENSING",
|
|
12
12
|
"CONTINUING_EDUCATION",
|
|
13
13
|
"DATA_RETENTION",
|
|
14
14
|
"LEGAL_HOLD"
|
|
15
|
-
],
|
|
15
|
+
], H = [
|
|
16
16
|
"IN_REVIEW",
|
|
17
17
|
"PASSED",
|
|
18
18
|
"FAILED",
|
|
19
19
|
"WAIVED"
|
|
20
|
-
],
|
|
20
|
+
], U = [
|
|
21
21
|
"CLIENT",
|
|
22
22
|
"ENGAGEMENT",
|
|
23
23
|
"MATTER"
|
|
24
|
-
],
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
], W = {
|
|
25
|
+
ENGAGEMENT_ACCEPTANCE: /* @__PURE__ */ R(A, { className: "h-3.5 w-3.5" }),
|
|
26
|
+
INDEPENDENCE: /* @__PURE__ */ R(F, { className: "h-3.5 w-3.5" }),
|
|
27
|
+
LICENSING: /* @__PURE__ */ R(E, { className: "h-3.5 w-3.5" }),
|
|
28
|
+
CONTINUING_EDUCATION: /* @__PURE__ */ R(j, { className: "h-3.5 w-3.5" }),
|
|
29
|
+
DATA_RETENTION: /* @__PURE__ */ R(k, { className: "h-3.5 w-3.5" }),
|
|
30
|
+
LEGAL_HOLD: /* @__PURE__ */ R(N, { className: "h-3.5 w-3.5" })
|
|
31
|
+
}, G = () => {
|
|
32
|
+
let [e, n] = T(""), [r, i] = T(!1), [a, l] = T(null), [f, y] = T(null), { data: b, isLoading: E, error: k, refetch: A } = t({ status: e || void 0 }), j = b ?? [], N = j.filter((e) => e.status === "PENDING").length, F = j.filter((e) => e.status === "IN_REVIEW").length, L = j.filter((e) => e.status === "PASSED" || e.status === "FAILED" || e.status === "WAIVED").length;
|
|
33
|
+
return /* @__PURE__ */ z("div", {
|
|
27
34
|
className: "space-y-6",
|
|
28
35
|
children: [
|
|
29
|
-
/* @__PURE__ */
|
|
36
|
+
/* @__PURE__ */ R(m, {
|
|
30
37
|
title: "Compliance",
|
|
31
38
|
subtitle: "The duties that travel with the work — acceptance, independence, licensing, CE, retention and legal hold — as gates, not afterthoughts.",
|
|
32
|
-
icon: /* @__PURE__ */
|
|
33
|
-
actions: /* @__PURE__ */
|
|
39
|
+
icon: /* @__PURE__ */ R(I, { className: "h-6 w-6" }),
|
|
40
|
+
actions: /* @__PURE__ */ z(B, {
|
|
34
41
|
onClick: () => i(!0),
|
|
35
|
-
children: [/* @__PURE__ */
|
|
42
|
+
children: [/* @__PURE__ */ R(P, { className: "mr-1.5 h-4 w-4" }), "New check"]
|
|
36
43
|
})
|
|
37
44
|
}),
|
|
38
|
-
|
|
45
|
+
f && /* @__PURE__ */ R(o, {
|
|
39
46
|
tone: "success",
|
|
40
|
-
onClose: () =>
|
|
41
|
-
children:
|
|
47
|
+
onClose: () => y(null),
|
|
48
|
+
children: f
|
|
42
49
|
}),
|
|
43
|
-
/* @__PURE__ */
|
|
50
|
+
b && b.length > 0 && /* @__PURE__ */ z("div", {
|
|
51
|
+
className: "grid grid-cols-2 gap-3 lg:grid-cols-4",
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ R(d, {
|
|
54
|
+
label: "Checks",
|
|
55
|
+
value: j.length,
|
|
56
|
+
icon: /* @__PURE__ */ R(M, { className: "h-4 w-4" })
|
|
57
|
+
}),
|
|
58
|
+
/* @__PURE__ */ R(d, {
|
|
59
|
+
label: "Pending",
|
|
60
|
+
value: N,
|
|
61
|
+
icon: /* @__PURE__ */ R(O, { className: "h-4 w-4" }),
|
|
62
|
+
tone: N ? "warning" : "neutral"
|
|
63
|
+
}),
|
|
64
|
+
/* @__PURE__ */ R(d, {
|
|
65
|
+
label: "In review",
|
|
66
|
+
value: F,
|
|
67
|
+
icon: /* @__PURE__ */ R(I, { className: "h-4 w-4" }),
|
|
68
|
+
tone: "info"
|
|
69
|
+
}),
|
|
70
|
+
/* @__PURE__ */ R(d, {
|
|
71
|
+
label: "Resolved",
|
|
72
|
+
value: L,
|
|
73
|
+
icon: /* @__PURE__ */ R(D, { className: "h-4 w-4" }),
|
|
74
|
+
tone: "success"
|
|
75
|
+
})
|
|
76
|
+
]
|
|
77
|
+
}),
|
|
78
|
+
/* @__PURE__ */ R("div", {
|
|
44
79
|
className: "flex justify-end",
|
|
45
|
-
children: /* @__PURE__ */
|
|
80
|
+
children: /* @__PURE__ */ z(p, {
|
|
46
81
|
value: e,
|
|
47
82
|
onChange: (e) => n(e.target.value),
|
|
48
83
|
className: "sm:w-52",
|
|
49
|
-
children: [/* @__PURE__ */
|
|
84
|
+
children: [/* @__PURE__ */ R("option", {
|
|
50
85
|
value: "",
|
|
51
86
|
children: "All statuses"
|
|
52
|
-
}),
|
|
87
|
+
}), S([
|
|
53
88
|
"PENDING",
|
|
54
89
|
"IN_REVIEW",
|
|
55
90
|
"PASSED",
|
|
@@ -58,43 +93,52 @@ var j = [
|
|
|
58
93
|
])]
|
|
59
94
|
})
|
|
60
95
|
}),
|
|
61
|
-
|
|
62
|
-
error:
|
|
63
|
-
onRetry: () => void
|
|
64
|
-
}) : !
|
|
96
|
+
E ? /* @__PURE__ */ R(u, {}) : k ? /* @__PURE__ */ R(c, {
|
|
97
|
+
error: k,
|
|
98
|
+
onRetry: () => void A()
|
|
99
|
+
}) : !b || b.length === 0 ? /* @__PURE__ */ R(s, {
|
|
65
100
|
title: "No compliance checks",
|
|
66
101
|
description: "Raise a check to gate acceptance or track a professional obligation.",
|
|
67
|
-
icon: /* @__PURE__ */
|
|
68
|
-
action: /* @__PURE__ */
|
|
102
|
+
icon: /* @__PURE__ */ R(I, { className: "h-8 w-8" }),
|
|
103
|
+
action: /* @__PURE__ */ z(B, {
|
|
69
104
|
onClick: () => i(!0),
|
|
70
|
-
children: [/* @__PURE__ */
|
|
105
|
+
children: [/* @__PURE__ */ R(P, { className: "mr-1.5 h-4 w-4" }), "New check"]
|
|
71
106
|
})
|
|
72
|
-
}) : /* @__PURE__ */
|
|
73
|
-
title: `${
|
|
74
|
-
children: /* @__PURE__ */
|
|
75
|
-
/* @__PURE__ */
|
|
76
|
-
/* @__PURE__ */
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
-
/* @__PURE__ */
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
/* @__PURE__ */
|
|
107
|
+
}) : /* @__PURE__ */ R(h, {
|
|
108
|
+
title: `${b.length} check${b.length === 1 ? "" : "s"}`,
|
|
109
|
+
children: /* @__PURE__ */ z(_, { children: [/* @__PURE__ */ R("thead", { children: /* @__PURE__ */ z("tr", { children: [
|
|
110
|
+
/* @__PURE__ */ R(x, { children: "Title" }),
|
|
111
|
+
/* @__PURE__ */ R(x, { children: "Type" }),
|
|
112
|
+
/* @__PURE__ */ R(x, { children: "Subject" }),
|
|
113
|
+
/* @__PURE__ */ R(x, { children: "Due" }),
|
|
114
|
+
/* @__PURE__ */ R(x, { children: "Status" }),
|
|
115
|
+
/* @__PURE__ */ R(x, {
|
|
81
116
|
className: "text-right",
|
|
82
117
|
children: "Actions"
|
|
83
118
|
})
|
|
84
|
-
] }) }), /* @__PURE__ */
|
|
85
|
-
className: "hover:bg-bg-sunken/
|
|
119
|
+
] }) }), /* @__PURE__ */ R("tbody", { children: b.map((e) => /* @__PURE__ */ z("tr", {
|
|
120
|
+
className: "transition-colors hover:bg-bg-sunken/60",
|
|
86
121
|
children: [
|
|
87
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ R(v, { children: /* @__PURE__ */ R("span", {
|
|
88
123
|
className: "font-medium text-text-primary",
|
|
89
124
|
children: e.title
|
|
90
125
|
}) }),
|
|
91
|
-
/* @__PURE__ */
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
126
|
+
/* @__PURE__ */ R(v, { children: /* @__PURE__ */ z("span", {
|
|
127
|
+
className: "inline-flex items-center gap-2 whitespace-nowrap",
|
|
128
|
+
children: [/* @__PURE__ */ R("span", {
|
|
129
|
+
className: "flex h-6 w-6 items-center justify-center rounded-md bg-bg-sunken text-accent",
|
|
130
|
+
children: W[e.type]
|
|
131
|
+
}), w(e.type)]
|
|
132
|
+
}) }),
|
|
133
|
+
/* @__PURE__ */ R(v, { children: w(e.subjectType) }),
|
|
134
|
+
/* @__PURE__ */ R(v, {
|
|
135
|
+
className: "whitespace-nowrap",
|
|
136
|
+
children: C(e.dueDate)
|
|
137
|
+
}),
|
|
138
|
+
/* @__PURE__ */ R(v, { children: /* @__PURE__ */ R(g, { status: e.status }) }),
|
|
139
|
+
/* @__PURE__ */ R(v, {
|
|
96
140
|
className: "text-right",
|
|
97
|
-
children: e.status === "PENDING" || e.status === "IN_REVIEW" ? /* @__PURE__ */
|
|
141
|
+
children: e.status === "PENDING" || e.status === "IN_REVIEW" ? /* @__PURE__ */ R(B, {
|
|
98
142
|
variant: "ghost",
|
|
99
143
|
size: "sm",
|
|
100
144
|
onClick: () => l({
|
|
@@ -102,60 +146,60 @@ var j = [
|
|
|
102
146
|
title: e.title
|
|
103
147
|
}),
|
|
104
148
|
children: "Resolve"
|
|
105
|
-
}) : /* @__PURE__ */
|
|
149
|
+
}) : /* @__PURE__ */ R("span", {
|
|
106
150
|
className: "text-xs text-text-tertiary",
|
|
107
|
-
children: e.resolvedAt ?
|
|
151
|
+
children: e.resolvedAt ? C(e.resolvedAt) : ""
|
|
108
152
|
})
|
|
109
153
|
})
|
|
110
154
|
]
|
|
111
155
|
}, e.id)) })] })
|
|
112
156
|
}),
|
|
113
|
-
r && /* @__PURE__ */
|
|
157
|
+
r && /* @__PURE__ */ R(K, {
|
|
114
158
|
onClose: () => i(!1),
|
|
115
159
|
onDone: () => {
|
|
116
|
-
|
|
160
|
+
A(), y("Compliance check created.");
|
|
117
161
|
}
|
|
118
162
|
}),
|
|
119
|
-
a && /* @__PURE__ */
|
|
163
|
+
a && /* @__PURE__ */ R(q, {
|
|
120
164
|
check: a,
|
|
121
165
|
onClose: () => l(null),
|
|
122
166
|
onDone: () => {
|
|
123
|
-
|
|
167
|
+
A(), y("Compliance check resolved.");
|
|
124
168
|
}
|
|
125
169
|
})
|
|
126
170
|
]
|
|
127
171
|
});
|
|
128
|
-
},
|
|
129
|
-
let s = n(), [c, u] =
|
|
172
|
+
}, K = ({ onClose: t, onDone: a }) => {
|
|
173
|
+
let s = n(), [c, u] = T({
|
|
130
174
|
type: "ENGAGEMENT_ACCEPTANCE",
|
|
131
175
|
subjectType: "ENGAGEMENT",
|
|
132
176
|
subjectId: "",
|
|
133
177
|
title: "",
|
|
134
178
|
dueDate: "",
|
|
135
179
|
details: ""
|
|
136
|
-
}), [
|
|
180
|
+
}), [d, m] = T(null), h = (e) => (t) => u((n) => ({
|
|
137
181
|
...n,
|
|
138
182
|
[e]: t.target.value
|
|
139
|
-
})), g = e({ pagination: { limit: 100 } }), _ = r({ pagination: { limit: 100 } }),
|
|
183
|
+
})), g = e({ pagination: { limit: 100 } }), _ = r({ pagination: { limit: 100 } }), v = i({ pagination: { limit: 100 } }), x = c.subjectType === "CLIENT" ? (g.data?.items ?? []).map((e) => ({
|
|
140
184
|
id: e.id,
|
|
141
185
|
label: e.name
|
|
142
186
|
})) : c.subjectType === "ENGAGEMENT" ? (_.data?.items ?? []).map((e) => ({
|
|
143
187
|
id: e.id,
|
|
144
188
|
label: e.name
|
|
145
|
-
})) : (
|
|
189
|
+
})) : (v.data?.items ?? []).map((e) => ({
|
|
146
190
|
id: e.id,
|
|
147
191
|
label: e.title
|
|
148
192
|
}));
|
|
149
|
-
return /* @__PURE__ */
|
|
193
|
+
return /* @__PURE__ */ R(f, {
|
|
150
194
|
open: !0,
|
|
151
195
|
onClose: t,
|
|
152
196
|
title: "New compliance check",
|
|
153
|
-
footer: /* @__PURE__ */
|
|
197
|
+
footer: /* @__PURE__ */ z(L, { children: [/* @__PURE__ */ R(B, {
|
|
154
198
|
variant: "outline",
|
|
155
199
|
onClick: t,
|
|
156
200
|
disabled: s.isPending,
|
|
157
201
|
children: "Cancel"
|
|
158
|
-
}), /* @__PURE__ */
|
|
202
|
+
}), /* @__PURE__ */ R(B, {
|
|
159
203
|
onClick: () => {
|
|
160
204
|
if (m(null), !c.title.trim()) return m("Title is required.");
|
|
161
205
|
if (!c.subjectId) return m("Select a subject.");
|
|
@@ -176,70 +220,70 @@ var j = [
|
|
|
176
220
|
disabled: s.isPending,
|
|
177
221
|
children: s.isPending ? "Creating…" : "Create check"
|
|
178
222
|
})] }),
|
|
179
|
-
children: /* @__PURE__ */
|
|
223
|
+
children: /* @__PURE__ */ z("div", {
|
|
180
224
|
className: "space-y-3",
|
|
181
225
|
children: [
|
|
182
|
-
|
|
226
|
+
d && /* @__PURE__ */ R(o, {
|
|
183
227
|
tone: "danger",
|
|
184
|
-
children:
|
|
228
|
+
children: d
|
|
185
229
|
}),
|
|
186
|
-
/* @__PURE__ */
|
|
230
|
+
/* @__PURE__ */ R(l, {
|
|
187
231
|
label: "Title",
|
|
188
232
|
required: !0,
|
|
189
|
-
children: /* @__PURE__ */
|
|
233
|
+
children: /* @__PURE__ */ R(b, {
|
|
190
234
|
value: c.title,
|
|
191
235
|
onChange: h("title"),
|
|
192
236
|
placeholder: "Independence confirmation — FY26 audit"
|
|
193
237
|
})
|
|
194
238
|
}),
|
|
195
|
-
/* @__PURE__ */
|
|
239
|
+
/* @__PURE__ */ R(l, {
|
|
196
240
|
label: "Type",
|
|
197
|
-
children: /* @__PURE__ */
|
|
241
|
+
children: /* @__PURE__ */ R(p, {
|
|
198
242
|
value: c.type,
|
|
199
243
|
onChange: h("type"),
|
|
200
|
-
children:
|
|
244
|
+
children: S(V)
|
|
201
245
|
})
|
|
202
246
|
}),
|
|
203
|
-
/* @__PURE__ */
|
|
247
|
+
/* @__PURE__ */ z("div", {
|
|
204
248
|
className: "grid grid-cols-2 gap-3",
|
|
205
|
-
children: [/* @__PURE__ */
|
|
249
|
+
children: [/* @__PURE__ */ R(l, {
|
|
206
250
|
label: "Subject type",
|
|
207
|
-
children: /* @__PURE__ */
|
|
251
|
+
children: /* @__PURE__ */ R(p, {
|
|
208
252
|
value: c.subjectType,
|
|
209
253
|
onChange: (e) => u((t) => ({
|
|
210
254
|
...t,
|
|
211
255
|
subjectType: e.target.value,
|
|
212
256
|
subjectId: ""
|
|
213
257
|
})),
|
|
214
|
-
children:
|
|
258
|
+
children: S(U)
|
|
215
259
|
})
|
|
216
|
-
}), /* @__PURE__ */
|
|
260
|
+
}), /* @__PURE__ */ R(l, {
|
|
217
261
|
label: "Subject",
|
|
218
262
|
required: !0,
|
|
219
|
-
children: /* @__PURE__ */
|
|
263
|
+
children: /* @__PURE__ */ z(p, {
|
|
220
264
|
value: c.subjectId,
|
|
221
265
|
onChange: h("subjectId"),
|
|
222
|
-
children: [/* @__PURE__ */
|
|
266
|
+
children: [/* @__PURE__ */ R("option", {
|
|
223
267
|
value: "",
|
|
224
268
|
children: "Select…"
|
|
225
|
-
}),
|
|
269
|
+
}), x.map((e) => /* @__PURE__ */ R("option", {
|
|
226
270
|
value: e.id,
|
|
227
271
|
children: e.label
|
|
228
272
|
}, e.id))]
|
|
229
273
|
})
|
|
230
274
|
})]
|
|
231
275
|
}),
|
|
232
|
-
/* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ R(l, {
|
|
233
277
|
label: "Due date",
|
|
234
|
-
children: /* @__PURE__ */
|
|
278
|
+
children: /* @__PURE__ */ R(b, {
|
|
235
279
|
type: "date",
|
|
236
280
|
value: c.dueDate,
|
|
237
281
|
onChange: h("dueDate")
|
|
238
282
|
})
|
|
239
283
|
}),
|
|
240
|
-
/* @__PURE__ */
|
|
284
|
+
/* @__PURE__ */ R(l, {
|
|
241
285
|
label: "Details",
|
|
242
|
-
children: /* @__PURE__ */
|
|
286
|
+
children: /* @__PURE__ */ R(y, {
|
|
243
287
|
value: c.details,
|
|
244
288
|
onChange: h("details")
|
|
245
289
|
})
|
|
@@ -247,18 +291,18 @@ var j = [
|
|
|
247
291
|
]
|
|
248
292
|
})
|
|
249
293
|
});
|
|
250
|
-
},
|
|
251
|
-
let r = a(), [i, s] =
|
|
252
|
-
return /* @__PURE__ */
|
|
294
|
+
}, q = ({ check: e, onClose: t, onDone: n }) => {
|
|
295
|
+
let r = a(), [i, s] = T("PASSED"), [c, u] = T(""), [d, m] = T(null);
|
|
296
|
+
return /* @__PURE__ */ R(f, {
|
|
253
297
|
open: !0,
|
|
254
298
|
onClose: t,
|
|
255
299
|
title: `Resolve: ${e.title}`,
|
|
256
|
-
footer: /* @__PURE__ */
|
|
300
|
+
footer: /* @__PURE__ */ z(L, { children: [/* @__PURE__ */ R(B, {
|
|
257
301
|
variant: "outline",
|
|
258
302
|
onClick: t,
|
|
259
303
|
disabled: r.isPending,
|
|
260
304
|
children: "Cancel"
|
|
261
|
-
}), /* @__PURE__ */
|
|
305
|
+
}), /* @__PURE__ */ R(B, {
|
|
262
306
|
onClick: () => r.mutate({
|
|
263
307
|
id: e.id,
|
|
264
308
|
status: i,
|
|
@@ -272,27 +316,27 @@ var j = [
|
|
|
272
316
|
disabled: r.isPending,
|
|
273
317
|
children: r.isPending ? "Saving…" : "Resolve"
|
|
274
318
|
})] }),
|
|
275
|
-
children: /* @__PURE__ */
|
|
319
|
+
children: /* @__PURE__ */ z("div", {
|
|
276
320
|
className: "space-y-3",
|
|
277
321
|
children: [
|
|
278
|
-
|
|
322
|
+
d && /* @__PURE__ */ R(o, {
|
|
279
323
|
tone: "danger",
|
|
280
|
-
children:
|
|
324
|
+
children: d
|
|
281
325
|
}),
|
|
282
|
-
/* @__PURE__ */
|
|
326
|
+
/* @__PURE__ */ R(l, {
|
|
283
327
|
label: "Outcome",
|
|
284
|
-
children: /* @__PURE__ */
|
|
328
|
+
children: /* @__PURE__ */ R(p, {
|
|
285
329
|
value: i,
|
|
286
330
|
onChange: (e) => s(e.target.value),
|
|
287
|
-
children:
|
|
331
|
+
children: H.map((e) => /* @__PURE__ */ R("option", {
|
|
288
332
|
value: e,
|
|
289
|
-
children:
|
|
333
|
+
children: w(e)
|
|
290
334
|
}, e))
|
|
291
335
|
})
|
|
292
336
|
}),
|
|
293
|
-
/* @__PURE__ */
|
|
337
|
+
/* @__PURE__ */ R(l, {
|
|
294
338
|
label: "Notes",
|
|
295
|
-
children: /* @__PURE__ */
|
|
339
|
+
children: /* @__PURE__ */ R(y, {
|
|
296
340
|
value: c,
|
|
297
341
|
onChange: (e) => u(e.target.value)
|
|
298
342
|
})
|
|
@@ -302,6 +346,6 @@ var j = [
|
|
|
302
346
|
});
|
|
303
347
|
};
|
|
304
348
|
//#endregion
|
|
305
|
-
export {
|
|
349
|
+
export { G as CompliancePage };
|
|
306
350
|
|
|
307
351
|
//# sourceMappingURL=CompliancePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CompliancePage.js","names":[],"sources":["../../../src/proserviceworld/pages/CompliancePage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Plus, ShieldCheck } from 'lucide-react';\nimport {\n useComplianceChecks,\n useCreateComplianceCheck,\n useResolveComplianceCheck,\n useClients,\n useEngagements,\n useMatters,\n type PswComplianceStatus,\n} from '../hooks/useProServiceWorldApi';\nimport {\n PageHeader,\n SectionCard,\n LoadingBlock,\n ErrorState,\n Empty,\n StatusPill,\n Modal,\n Field,\n TextInput,\n TextArea,\n NativeSelect,\n Banner,\n TableWrap,\n Th,\n Td,\n enumOptions,\n fmtDate,\n humanize,\n} from '../components/ui';\n\nconst TYPES = [\n 'ENGAGEMENT_ACCEPTANCE',\n 'INDEPENDENCE',\n 'LICENSING',\n 'CONTINUING_EDUCATION',\n 'DATA_RETENTION',\n 'LEGAL_HOLD',\n] as const;\nconst RESOLVE_STATUSES: PswComplianceStatus[] = ['IN_REVIEW', 'PASSED', 'FAILED', 'WAIVED'];\nconst SUBJECT_TYPES = ['CLIENT', 'ENGAGEMENT', 'MATTER'] as const;\n\nexport const CompliancePage: FC = () => {\n const [statusFilter, setStatusFilter] = useState<PswComplianceStatus | ''>('');\n const [creating, setCreating] = useState(false);\n const [resolving, setResolving] = useState<{ id: string; title: string } | null>(null);\n const [banner, setBanner] = useState<string | null>(null);\n const { data, isLoading, error, refetch } = useComplianceChecks({\n status: statusFilter || undefined,\n });\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Compliance\"\n subtitle=\"The duties that travel with the work — acceptance, independence, licensing, CE, retention and legal hold — as gates, not afterthoughts.\"\n icon={<ShieldCheck className=\"h-6 w-6\" />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New check\n </Button>\n }\n />\n\n {banner && (\n <Banner tone=\"success\" onClose={() => setBanner(null)}>\n {banner}\n </Banner>\n )}\n\n <div className=\"flex justify-end\">\n <NativeSelect\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value as PswComplianceStatus | '')}\n className=\"sm:w-52\"\n >\n <option value=\"\">All statuses</option>\n {enumOptions(['PENDING', 'IN_REVIEW', 'PASSED', 'FAILED', 'WAIVED'])}\n </NativeSelect>\n </div>\n\n {isLoading ? (\n <LoadingBlock />\n ) : error ? (\n <ErrorState error={error} onRetry={() => void refetch()} />\n ) : !data || data.length === 0 ? (\n <Empty\n title=\"No compliance checks\"\n description=\"Raise a check to gate acceptance or track a professional obligation.\"\n icon={<ShieldCheck className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New check\n </Button>\n }\n />\n ) : (\n <SectionCard title={`${data.length} check${data.length === 1 ? '' : 's'}`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Title</Th>\n <Th>Type</Th>\n <Th>Subject</Th>\n <Th>Due</Th>\n <Th>Status</Th>\n <Th className=\"text-right\">Actions</Th>\n </tr>\n </thead>\n <tbody>\n {data.map((c) => (\n <tr key={c.id} className=\"hover:bg-bg-sunken/50\">\n <Td>\n <span className=\"font-medium text-text-primary\">{c.title}</span>\n </Td>\n <Td>{humanize(c.type)}</Td>\n <Td>{humanize(c.subjectType)}</Td>\n <Td>{fmtDate(c.dueDate)}</Td>\n <Td>\n <StatusPill status={c.status} />\n </Td>\n <Td className=\"text-right\">\n {c.status === 'PENDING' || c.status === 'IN_REVIEW' ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setResolving({ id: c.id, title: c.title })}\n >\n Resolve\n </Button>\n ) : (\n <span className=\"text-xs text-text-tertiary\">\n {c.resolvedAt ? fmtDate(c.resolvedAt) : ''}\n </span>\n )}\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n </SectionCard>\n )}\n\n {creating && (\n <ComplianceModal\n onClose={() => setCreating(false)}\n onDone={() => {\n void refetch();\n setBanner('Compliance check created.');\n }}\n />\n )}\n {resolving && (\n <ResolveModal\n check={resolving}\n onClose={() => setResolving(null)}\n onDone={() => {\n void refetch();\n setBanner('Compliance check resolved.');\n }}\n />\n )}\n </div>\n );\n};\n\nconst ComplianceModal: FC<{ onClose: () => void; onDone: () => void }> = ({ onClose, onDone }) => {\n const create = useCreateComplianceCheck();\n const [form, setForm] = useState({\n type: 'ENGAGEMENT_ACCEPTANCE',\n subjectType: 'ENGAGEMENT',\n subjectId: '',\n title: '',\n dueDate: '',\n details: '',\n });\n const [err, setErr] = useState<string | null>(null);\n const set = (k: keyof typeof form) => (e: { target: { value: string } }) =>\n setForm((f) => ({ ...f, [k]: e.target.value }));\n\n const clients = useClients({ pagination: { limit: 100 } });\n const engagements = useEngagements({ pagination: { limit: 100 } });\n const matters = useMatters({ pagination: { limit: 100 } });\n const subjects =\n form.subjectType === 'CLIENT'\n ? (clients.data?.items ?? []).map((c) => ({ id: c.id, label: c.name }))\n : form.subjectType === 'ENGAGEMENT'\n ? (engagements.data?.items ?? []).map((e) => ({ id: e.id, label: e.name }))\n : (matters.data?.items ?? []).map((m) => ({ id: m.id, label: m.title }));\n\n const submit = () => {\n setErr(null);\n if (!form.title.trim()) return setErr('Title is required.');\n if (!form.subjectId) return setErr('Select a subject.');\n create.mutate(\n {\n type: form.type,\n subjectType: form.subjectType,\n subjectId: form.subjectId,\n title: form.title.trim(),\n dueDate: form.dueDate ? new Date(form.dueDate).toISOString() : null,\n details: form.details.trim() || null,\n },\n {\n onSuccess: () => {\n onDone();\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title=\"New compliance check\"\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={create.isPending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={create.isPending}>\n {create.isPending ? 'Creating…' : 'Create check'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Title\" required>\n <TextInput\n value={form.title}\n onChange={set('title')}\n placeholder=\"Independence confirmation — FY26 audit\"\n />\n </Field>\n <Field label=\"Type\">\n <NativeSelect value={form.type} onChange={set('type')}>\n {enumOptions(TYPES)}\n </NativeSelect>\n </Field>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Subject type\">\n <NativeSelect\n value={form.subjectType}\n onChange={(e) =>\n setForm((f) => ({ ...f, subjectType: e.target.value, subjectId: '' }))\n }\n >\n {enumOptions(SUBJECT_TYPES)}\n </NativeSelect>\n </Field>\n <Field label=\"Subject\" required>\n <NativeSelect value={form.subjectId} onChange={set('subjectId')}>\n <option value=\"\">Select…</option>\n {subjects.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label}\n </option>\n ))}\n </NativeSelect>\n </Field>\n </div>\n <Field label=\"Due date\">\n <TextInput type=\"date\" value={form.dueDate} onChange={set('dueDate')} />\n </Field>\n <Field label=\"Details\">\n <TextArea value={form.details} onChange={set('details')} />\n </Field>\n </div>\n </Modal>\n );\n};\n\nconst ResolveModal: FC<{\n check: { id: string; title: string };\n onClose: () => void;\n onDone: () => void;\n}> = ({ check, onClose, onDone }) => {\n const resolve = useResolveComplianceCheck();\n const [status, setStatus] = useState<PswComplianceStatus>('PASSED');\n const [details, setDetails] = useState('');\n const [err, setErr] = useState<string | null>(null);\n const submit = () =>\n resolve.mutate(\n { id: check.id, status, details: details.trim() || undefined },\n {\n onSuccess: () => {\n onDone();\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n return (\n <Modal\n open\n onClose={onClose}\n title={`Resolve: ${check.title}`}\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={resolve.isPending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={resolve.isPending}>\n {resolve.isPending ? 'Saving…' : 'Resolve'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Outcome\">\n <NativeSelect\n value={status}\n onChange={(e) => setStatus(e.target.value as PswComplianceStatus)}\n >\n {RESOLVE_STATUSES.map((s) => (\n <option key={s} value={s}>\n {humanize(s)}\n </option>\n ))}\n </NativeSelect>\n </Field>\n <Field label=\"Notes\">\n <TextArea value={details} onChange={(e) => setDetails(e.target.value)} />\n </Field>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CompliancePage.js","names":[],"sources":["../../../src/proserviceworld/pages/CompliancePage.tsx"],"sourcesContent":["import type { FC, ReactNode } from 'react';\nimport { useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n ShieldCheck,\n FileCheck,\n Scale,\n BadgeCheck,\n GraduationCap,\n Database,\n Lock,\n Clock,\n ListChecks,\n CheckCircle2,\n} from 'lucide-react';\nimport {\n useComplianceChecks,\n useCreateComplianceCheck,\n useResolveComplianceCheck,\n useClients,\n useEngagements,\n useMatters,\n type PswComplianceStatus,\n type PswComplianceType,\n} from '../hooks/useProServiceWorldApi';\nimport {\n PageHeader,\n SectionCard,\n MetricCard,\n LoadingBlock,\n ErrorState,\n Empty,\n StatusPill,\n Modal,\n Field,\n TextInput,\n TextArea,\n NativeSelect,\n Banner,\n TableWrap,\n Th,\n Td,\n enumOptions,\n fmtDate,\n humanize,\n} from '../components/ui';\n\nconst TYPES = [\n 'ENGAGEMENT_ACCEPTANCE',\n 'INDEPENDENCE',\n 'LICENSING',\n 'CONTINUING_EDUCATION',\n 'DATA_RETENTION',\n 'LEGAL_HOLD',\n] as const;\nconst RESOLVE_STATUSES: PswComplianceStatus[] = ['IN_REVIEW', 'PASSED', 'FAILED', 'WAIVED'];\nconst SUBJECT_TYPES = ['CLIENT', 'ENGAGEMENT', 'MATTER'] as const;\n\nconst TYPE_ICON: Record<PswComplianceType, ReactNode> = {\n ENGAGEMENT_ACCEPTANCE: <FileCheck className=\"h-3.5 w-3.5\" />,\n INDEPENDENCE: <Scale className=\"h-3.5 w-3.5\" />,\n LICENSING: <BadgeCheck className=\"h-3.5 w-3.5\" />,\n CONTINUING_EDUCATION: <GraduationCap className=\"h-3.5 w-3.5\" />,\n DATA_RETENTION: <Database className=\"h-3.5 w-3.5\" />,\n LEGAL_HOLD: <Lock className=\"h-3.5 w-3.5\" />,\n};\n\nexport const CompliancePage: FC = () => {\n const [statusFilter, setStatusFilter] = useState<PswComplianceStatus | ''>('');\n const [creating, setCreating] = useState(false);\n const [resolving, setResolving] = useState<{ id: string; title: string } | null>(null);\n const [banner, setBanner] = useState<string | null>(null);\n const { data, isLoading, error, refetch } = useComplianceChecks({\n status: statusFilter || undefined,\n });\n\n const checks = data ?? [];\n const pendingCount = checks.filter((c) => c.status === 'PENDING').length;\n const inReviewCount = checks.filter((c) => c.status === 'IN_REVIEW').length;\n const resolvedCount = checks.filter(\n (c) => c.status === 'PASSED' || c.status === 'FAILED' || c.status === 'WAIVED'\n ).length;\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Compliance\"\n subtitle=\"The duties that travel with the work — acceptance, independence, licensing, CE, retention and legal hold — as gates, not afterthoughts.\"\n icon={<ShieldCheck className=\"h-6 w-6\" />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New check\n </Button>\n }\n />\n\n {banner && (\n <Banner tone=\"success\" onClose={() => setBanner(null)}>\n {banner}\n </Banner>\n )}\n\n {data && data.length > 0 && (\n <div className=\"grid grid-cols-2 gap-3 lg:grid-cols-4\">\n <MetricCard\n label=\"Checks\"\n value={checks.length}\n icon={<ListChecks className=\"h-4 w-4\" />}\n />\n <MetricCard\n label=\"Pending\"\n value={pendingCount}\n icon={<Clock className=\"h-4 w-4\" />}\n tone={pendingCount ? 'warning' : 'neutral'}\n />\n <MetricCard\n label=\"In review\"\n value={inReviewCount}\n icon={<ShieldCheck className=\"h-4 w-4\" />}\n tone=\"info\"\n />\n <MetricCard\n label=\"Resolved\"\n value={resolvedCount}\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n tone=\"success\"\n />\n </div>\n )}\n\n <div className=\"flex justify-end\">\n <NativeSelect\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value as PswComplianceStatus | '')}\n className=\"sm:w-52\"\n >\n <option value=\"\">All statuses</option>\n {enumOptions(['PENDING', 'IN_REVIEW', 'PASSED', 'FAILED', 'WAIVED'])}\n </NativeSelect>\n </div>\n\n {isLoading ? (\n <LoadingBlock />\n ) : error ? (\n <ErrorState error={error} onRetry={() => void refetch()} />\n ) : !data || data.length === 0 ? (\n <Empty\n title=\"No compliance checks\"\n description=\"Raise a check to gate acceptance or track a professional obligation.\"\n icon={<ShieldCheck className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New check\n </Button>\n }\n />\n ) : (\n <SectionCard title={`${data.length} check${data.length === 1 ? '' : 's'}`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Title</Th>\n <Th>Type</Th>\n <Th>Subject</Th>\n <Th>Due</Th>\n <Th>Status</Th>\n <Th className=\"text-right\">Actions</Th>\n </tr>\n </thead>\n <tbody>\n {data.map((c) => (\n <tr key={c.id} className=\"transition-colors hover:bg-bg-sunken/60\">\n <Td>\n <span className=\"font-medium text-text-primary\">{c.title}</span>\n </Td>\n <Td>\n <span className=\"inline-flex items-center gap-2 whitespace-nowrap\">\n <span className=\"flex h-6 w-6 items-center justify-center rounded-md bg-bg-sunken text-accent\">\n {TYPE_ICON[c.type]}\n </span>\n {humanize(c.type)}\n </span>\n </Td>\n <Td>{humanize(c.subjectType)}</Td>\n <Td className=\"whitespace-nowrap\">{fmtDate(c.dueDate)}</Td>\n <Td>\n <StatusPill status={c.status} />\n </Td>\n <Td className=\"text-right\">\n {c.status === 'PENDING' || c.status === 'IN_REVIEW' ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setResolving({ id: c.id, title: c.title })}\n >\n Resolve\n </Button>\n ) : (\n <span className=\"text-xs text-text-tertiary\">\n {c.resolvedAt ? fmtDate(c.resolvedAt) : ''}\n </span>\n )}\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n </SectionCard>\n )}\n\n {creating && (\n <ComplianceModal\n onClose={() => setCreating(false)}\n onDone={() => {\n void refetch();\n setBanner('Compliance check created.');\n }}\n />\n )}\n {resolving && (\n <ResolveModal\n check={resolving}\n onClose={() => setResolving(null)}\n onDone={() => {\n void refetch();\n setBanner('Compliance check resolved.');\n }}\n />\n )}\n </div>\n );\n};\n\nconst ComplianceModal: FC<{ onClose: () => void; onDone: () => void }> = ({ onClose, onDone }) => {\n const create = useCreateComplianceCheck();\n const [form, setForm] = useState({\n type: 'ENGAGEMENT_ACCEPTANCE',\n subjectType: 'ENGAGEMENT',\n subjectId: '',\n title: '',\n dueDate: '',\n details: '',\n });\n const [err, setErr] = useState<string | null>(null);\n const set = (k: keyof typeof form) => (e: { target: { value: string } }) =>\n setForm((f) => ({ ...f, [k]: e.target.value }));\n\n const clients = useClients({ pagination: { limit: 100 } });\n const engagements = useEngagements({ pagination: { limit: 100 } });\n const matters = useMatters({ pagination: { limit: 100 } });\n const subjects =\n form.subjectType === 'CLIENT'\n ? (clients.data?.items ?? []).map((c) => ({ id: c.id, label: c.name }))\n : form.subjectType === 'ENGAGEMENT'\n ? (engagements.data?.items ?? []).map((e) => ({ id: e.id, label: e.name }))\n : (matters.data?.items ?? []).map((m) => ({ id: m.id, label: m.title }));\n\n const submit = () => {\n setErr(null);\n if (!form.title.trim()) return setErr('Title is required.');\n if (!form.subjectId) return setErr('Select a subject.');\n create.mutate(\n {\n type: form.type,\n subjectType: form.subjectType,\n subjectId: form.subjectId,\n title: form.title.trim(),\n dueDate: form.dueDate ? new Date(form.dueDate).toISOString() : null,\n details: form.details.trim() || null,\n },\n {\n onSuccess: () => {\n onDone();\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title=\"New compliance check\"\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={create.isPending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={create.isPending}>\n {create.isPending ? 'Creating…' : 'Create check'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Title\" required>\n <TextInput\n value={form.title}\n onChange={set('title')}\n placeholder=\"Independence confirmation — FY26 audit\"\n />\n </Field>\n <Field label=\"Type\">\n <NativeSelect value={form.type} onChange={set('type')}>\n {enumOptions(TYPES)}\n </NativeSelect>\n </Field>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Subject type\">\n <NativeSelect\n value={form.subjectType}\n onChange={(e) =>\n setForm((f) => ({ ...f, subjectType: e.target.value, subjectId: '' }))\n }\n >\n {enumOptions(SUBJECT_TYPES)}\n </NativeSelect>\n </Field>\n <Field label=\"Subject\" required>\n <NativeSelect value={form.subjectId} onChange={set('subjectId')}>\n <option value=\"\">Select…</option>\n {subjects.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label}\n </option>\n ))}\n </NativeSelect>\n </Field>\n </div>\n <Field label=\"Due date\">\n <TextInput type=\"date\" value={form.dueDate} onChange={set('dueDate')} />\n </Field>\n <Field label=\"Details\">\n <TextArea value={form.details} onChange={set('details')} />\n </Field>\n </div>\n </Modal>\n );\n};\n\nconst ResolveModal: FC<{\n check: { id: string; title: string };\n onClose: () => void;\n onDone: () => void;\n}> = ({ check, onClose, onDone }) => {\n const resolve = useResolveComplianceCheck();\n const [status, setStatus] = useState<PswComplianceStatus>('PASSED');\n const [details, setDetails] = useState('');\n const [err, setErr] = useState<string | null>(null);\n const submit = () =>\n resolve.mutate(\n { id: check.id, status, details: details.trim() || undefined },\n {\n onSuccess: () => {\n onDone();\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n return (\n <Modal\n open\n onClose={onClose}\n title={`Resolve: ${check.title}`}\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={resolve.isPending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={resolve.isPending}>\n {resolve.isPending ? 'Saving…' : 'Resolve'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Outcome\">\n <NativeSelect\n value={status}\n onChange={(e) => setStatus(e.target.value as PswComplianceStatus)}\n >\n {RESOLVE_STATUSES.map((s) => (\n <option key={s} value={s}>\n {humanize(s)}\n </option>\n ))}\n </NativeSelect>\n </Field>\n <Field label=\"Notes\">\n <TextArea value={details} onChange={(e) => setDetails(e.target.value)} />\n </Field>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|