@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,234 +1,302 @@
|
|
|
1
1
|
import { useClient as e, useConflictChecks as t, useCreateConflictCheck as n } from "../hooks/useProServiceWorldApi.js";
|
|
2
2
|
import { useNav as r } from "../utils/nav.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { cn as i } from "../utils/cn.js";
|
|
4
|
+
import { Banner as a, Empty as o, ErrorState as s, Field as c, LoadingBlock as l, Modal as u, PageHeader as d, SectionCard as f, StatusPill as p, TableWrap as m, Td as h, TextArea as g, TextInput as _, Th as v, fmtDate as y, fmtMoney as b, humanize as x } from "../components/ui.js";
|
|
5
|
+
import { DiscussionThread as S } from "../components/DiscussionThread.js";
|
|
6
|
+
import { useState as C } from "react";
|
|
7
|
+
import { ArrowLeft as w, Briefcase as T, ChevronRight as E, FolderKanban as D, GitBranch as O, Mail as k, MapPin as A, Phone as j, Plus as M, StickyNote as N } from "lucide-react";
|
|
8
|
+
import { useParams as P } from "react-router-dom";
|
|
9
|
+
import { Fragment as F, jsx as I, jsxs as L } from "react/jsx-runtime";
|
|
10
|
+
import { Button as R } from "@burdenoff/fe-libs/ui";
|
|
10
11
|
//#region src/proserviceworld/pages/ClientDetailPage.tsx
|
|
11
|
-
var
|
|
12
|
-
let { id: n = "" } =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
var z = (e) => e.split(/\s+/).filter(Boolean).slice(0, 2).map((e) => e[0]?.toUpperCase() ?? "").join("") || "?", B = () => {
|
|
13
|
+
let { id: n = "" } = P(), i = r(), { data: a, isLoading: c, error: u, refetch: g } = e(n), _ = t({ clientId: n }), [F, B] = C(!1);
|
|
14
|
+
if (c) return /* @__PURE__ */ I(l, {});
|
|
15
|
+
if (u) return /* @__PURE__ */ I(s, {
|
|
16
|
+
error: u,
|
|
17
|
+
onRetry: () => void g()
|
|
18
|
+
});
|
|
19
|
+
if (!a) return /* @__PURE__ */ I(o, {
|
|
20
|
+
title: "Client not found",
|
|
21
|
+
description: "It may have been archived or belongs to another workspace."
|
|
22
|
+
});
|
|
23
|
+
let U = a.contactName || a.name;
|
|
24
|
+
return /* @__PURE__ */ L("div", {
|
|
17
25
|
className: "space-y-6",
|
|
18
26
|
children: [
|
|
19
|
-
/* @__PURE__ */
|
|
27
|
+
/* @__PURE__ */ L("button", {
|
|
20
28
|
type: "button",
|
|
21
29
|
onClick: () => i("clients"),
|
|
22
|
-
className: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-accent",
|
|
23
|
-
children: [/* @__PURE__ */
|
|
30
|
+
className: "flex items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-accent",
|
|
31
|
+
children: [/* @__PURE__ */ I(w, { className: "h-4 w-4" }), " Back to clients"]
|
|
24
32
|
}),
|
|
25
|
-
/* @__PURE__ */
|
|
26
|
-
title:
|
|
27
|
-
subtitle: [
|
|
28
|
-
actions: /* @__PURE__ */
|
|
33
|
+
/* @__PURE__ */ I(d, {
|
|
34
|
+
title: a.name,
|
|
35
|
+
subtitle: [a.type === "ORGANIZATION" ? "Organization" : "Individual", a.industry].filter(Boolean).join(" · "),
|
|
36
|
+
actions: /* @__PURE__ */ I(p, { status: a.status })
|
|
29
37
|
}),
|
|
30
|
-
/* @__PURE__ */
|
|
38
|
+
a.tags.length > 0 && /* @__PURE__ */ I("div", {
|
|
39
|
+
className: "flex flex-wrap gap-2",
|
|
40
|
+
children: a.tags.map((e) => /* @__PURE__ */ I("span", {
|
|
41
|
+
className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
|
|
42
|
+
children: e
|
|
43
|
+
}, e))
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ L("div", {
|
|
31
46
|
className: "grid grid-cols-1 gap-4 lg:grid-cols-3",
|
|
32
|
-
children: [/* @__PURE__ */
|
|
47
|
+
children: [/* @__PURE__ */ I(f, {
|
|
33
48
|
title: "Contact",
|
|
34
49
|
className: "lg:col-span-1",
|
|
35
|
-
children: /* @__PURE__ */
|
|
36
|
-
className: "space-y-
|
|
37
|
-
children: [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
children: /* @__PURE__ */ L("div", {
|
|
51
|
+
className: "space-y-4",
|
|
52
|
+
children: [/* @__PURE__ */ L("div", {
|
|
53
|
+
className: "flex items-center gap-3",
|
|
54
|
+
children: [/* @__PURE__ */ I("span", {
|
|
55
|
+
className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-accent/10 text-sm font-semibold text-accent ring-1 ring-inset ring-accent/15",
|
|
56
|
+
children: z(U)
|
|
57
|
+
}), /* @__PURE__ */ L("div", {
|
|
58
|
+
className: "min-w-0",
|
|
59
|
+
children: [/* @__PURE__ */ I("div", {
|
|
60
|
+
className: "truncate text-sm font-semibold text-text-primary",
|
|
61
|
+
children: a.contactName || a.name
|
|
62
|
+
}), /* @__PURE__ */ I("div", {
|
|
63
|
+
className: "truncate text-xs text-text-tertiary",
|
|
64
|
+
children: a.contactName ? "Primary contact" : "Client record"
|
|
65
|
+
})]
|
|
66
|
+
})]
|
|
67
|
+
}), /* @__PURE__ */ L("dl", {
|
|
68
|
+
className: "space-y-2.5 text-sm",
|
|
69
|
+
children: [
|
|
70
|
+
a.contactEmail && /* @__PURE__ */ I(V, {
|
|
71
|
+
icon: /* @__PURE__ */ I(k, { className: "h-4 w-4" }),
|
|
72
|
+
value: a.contactEmail
|
|
73
|
+
}),
|
|
74
|
+
a.contactPhone && /* @__PURE__ */ I(V, {
|
|
75
|
+
icon: /* @__PURE__ */ I(j, { className: "h-4 w-4" }),
|
|
76
|
+
value: a.contactPhone
|
|
77
|
+
}),
|
|
78
|
+
a.address && /* @__PURE__ */ I(V, {
|
|
79
|
+
icon: /* @__PURE__ */ I(A, { className: "h-4 w-4" }),
|
|
80
|
+
value: a.address
|
|
81
|
+
}),
|
|
82
|
+
a.notes && /* @__PURE__ */ I(V, {
|
|
83
|
+
icon: /* @__PURE__ */ I(N, { className: "h-4 w-4" }),
|
|
84
|
+
value: a.notes,
|
|
85
|
+
multiline: !0
|
|
86
|
+
}),
|
|
87
|
+
!a.contactEmail && !a.contactPhone && !a.address && !a.notes && /* @__PURE__ */ I("p", {
|
|
88
|
+
className: "text-sm text-text-tertiary",
|
|
89
|
+
children: "No contact details recorded yet."
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
})]
|
|
59
93
|
})
|
|
60
|
-
}), /* @__PURE__ */
|
|
94
|
+
}), /* @__PURE__ */ I(f, {
|
|
61
95
|
title: "Conflict checks",
|
|
62
96
|
className: "lg:col-span-2",
|
|
63
|
-
action: /* @__PURE__ */
|
|
97
|
+
action: /* @__PURE__ */ L(R, {
|
|
64
98
|
size: "sm",
|
|
65
99
|
variant: "outline",
|
|
66
|
-
onClick: () =>
|
|
67
|
-
children: [/* @__PURE__ */
|
|
100
|
+
onClick: () => B(!0),
|
|
101
|
+
children: [/* @__PURE__ */ I(O, { className: "mr-1.5 h-4 w-4" }), " Run check"]
|
|
68
102
|
}),
|
|
69
|
-
children:
|
|
103
|
+
children: _.isLoading ? /* @__PURE__ */ I(l, { label: "Loading…" }) : !_.data || _.data.length === 0 ? /* @__PURE__ */ I(o, {
|
|
70
104
|
title: "No conflict checks",
|
|
71
|
-
description: "Run a conflict check before accepting new work for this client."
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
105
|
+
description: "Run a conflict check before accepting new work for this client.",
|
|
106
|
+
icon: /* @__PURE__ */ I(O, { className: "h-7 w-7" })
|
|
107
|
+
}) : /* @__PURE__ */ L(m, { children: [/* @__PURE__ */ I("thead", { children: /* @__PURE__ */ L("tr", { children: [
|
|
108
|
+
/* @__PURE__ */ I(v, { children: "Parties searched" }),
|
|
109
|
+
/* @__PURE__ */ I(v, { children: "Date" }),
|
|
110
|
+
/* @__PURE__ */ I(v, {
|
|
111
|
+
className: "text-right",
|
|
112
|
+
children: "Status"
|
|
113
|
+
})
|
|
114
|
+
] }) }), /* @__PURE__ */ I("tbody", { children: _.data.map((e) => /* @__PURE__ */ L("tr", {
|
|
115
|
+
className: "transition-colors hover:bg-bg-sunken/60",
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ L(h, { children: [/* @__PURE__ */ I("div", {
|
|
118
|
+
className: "font-medium text-text-primary",
|
|
78
119
|
children: e.searchedParties.join(", ") || "Conflict search"
|
|
79
|
-
}), /* @__PURE__ */
|
|
120
|
+
}), e.findings ? /* @__PURE__ */ I("div", {
|
|
80
121
|
className: "text-xs text-text-tertiary",
|
|
81
|
-
children:
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
|
|
122
|
+
children: e.findings
|
|
123
|
+
}) : null] }),
|
|
124
|
+
/* @__PURE__ */ I(h, {
|
|
125
|
+
className: "whitespace-nowrap",
|
|
126
|
+
children: y(e.createdAt)
|
|
127
|
+
}),
|
|
128
|
+
/* @__PURE__ */ I(h, {
|
|
129
|
+
className: "text-right",
|
|
130
|
+
children: /* @__PURE__ */ I(p, { status: e.status })
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
}, e.id)) })] })
|
|
85
134
|
})]
|
|
86
135
|
}),
|
|
87
|
-
/* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ I(f, {
|
|
88
137
|
title: "Engagements",
|
|
89
|
-
|
|
138
|
+
description: `${a.engagements.length} scoped for this client`,
|
|
139
|
+
action: /* @__PURE__ */ L(R, {
|
|
90
140
|
size: "sm",
|
|
91
141
|
variant: "outline",
|
|
92
142
|
onClick: () => i("engagements"),
|
|
93
|
-
children: [/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ I(M, { className: "mr-1.5 h-4 w-4" }), "Manage"]
|
|
94
144
|
}),
|
|
95
|
-
children:
|
|
145
|
+
children: a.engagements.length === 0 ? /* @__PURE__ */ I(o, {
|
|
96
146
|
title: "No engagements",
|
|
97
147
|
description: "Scope the first engagement for this client.",
|
|
98
|
-
icon: /* @__PURE__ */
|
|
99
|
-
}) : /* @__PURE__ */
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
className: "
|
|
105
|
-
children:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
icon: /* @__PURE__ */ I(T, { className: "h-7 w-7" })
|
|
149
|
+
}) : /* @__PURE__ */ L(m, { children: [/* @__PURE__ */ I("thead", { children: /* @__PURE__ */ L("tr", { children: [
|
|
150
|
+
/* @__PURE__ */ I(v, { children: "Engagement" }),
|
|
151
|
+
/* @__PURE__ */ I(v, { children: "Fee" }),
|
|
152
|
+
/* @__PURE__ */ I(v, { children: "Started" }),
|
|
153
|
+
/* @__PURE__ */ I(v, {
|
|
154
|
+
className: "text-right",
|
|
155
|
+
children: "Status"
|
|
156
|
+
})
|
|
157
|
+
] }) }), /* @__PURE__ */ I("tbody", { children: a.engagements.map((e) => /* @__PURE__ */ L("tr", {
|
|
158
|
+
className: "group cursor-pointer transition-colors hover:bg-bg-sunken/60",
|
|
159
|
+
onClick: () => i(`engagements/${e.id}`),
|
|
160
|
+
children: [
|
|
161
|
+
/* @__PURE__ */ I(h, { children: /* @__PURE__ */ L("div", {
|
|
162
|
+
className: "flex items-center gap-1 font-medium text-text-primary transition-colors group-hover:text-accent",
|
|
163
|
+
children: [/* @__PURE__ */ I("span", { children: e.name }), /* @__PURE__ */ I(E, { className: "h-3.5 w-3.5 shrink-0 text-text-tertiary opacity-0 transition-opacity group-hover:opacity-100" })]
|
|
164
|
+
}) }),
|
|
165
|
+
/* @__PURE__ */ L(h, {
|
|
166
|
+
className: "whitespace-nowrap",
|
|
110
167
|
children: [
|
|
111
|
-
|
|
112
|
-
"
|
|
113
|
-
|
|
168
|
+
b(e.feeAmount, e.currency),
|
|
169
|
+
" ",
|
|
170
|
+
/* @__PURE__ */ L("span", {
|
|
171
|
+
className: "text-xs text-text-tertiary",
|
|
172
|
+
children: ["/ ", x(e.feeArrangement)]
|
|
173
|
+
})
|
|
114
174
|
]
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
|
|
175
|
+
}),
|
|
176
|
+
/* @__PURE__ */ I(h, {
|
|
177
|
+
className: "whitespace-nowrap",
|
|
178
|
+
children: y(e.startDate)
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ I(h, {
|
|
181
|
+
className: "text-right",
|
|
182
|
+
children: /* @__PURE__ */ I(p, { status: e.status })
|
|
183
|
+
})
|
|
184
|
+
]
|
|
185
|
+
}, e.id)) })] })
|
|
118
186
|
}),
|
|
119
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ I(f, {
|
|
120
188
|
title: "Matters",
|
|
121
|
-
|
|
189
|
+
description: `${a.matters.length} tracked for this client`,
|
|
190
|
+
action: /* @__PURE__ */ L(R, {
|
|
122
191
|
size: "sm",
|
|
123
192
|
variant: "outline",
|
|
124
193
|
onClick: () => i("matters"),
|
|
125
|
-
children: [/* @__PURE__ */
|
|
194
|
+
children: [/* @__PURE__ */ I(M, { className: "mr-1.5 h-4 w-4" }), "Manage"]
|
|
126
195
|
}),
|
|
127
|
-
children:
|
|
196
|
+
children: a.matters.length === 0 ? /* @__PURE__ */ I(o, {
|
|
128
197
|
title: "No matters",
|
|
129
198
|
description: "Open a matter to track regulated work for this client.",
|
|
130
|
-
icon: /* @__PURE__ */
|
|
131
|
-
}) : /* @__PURE__ */
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
199
|
+
icon: /* @__PURE__ */ I(D, { className: "h-7 w-7" })
|
|
200
|
+
}) : /* @__PURE__ */ L(m, { children: [/* @__PURE__ */ I("thead", { children: /* @__PURE__ */ L("tr", { children: [
|
|
201
|
+
/* @__PURE__ */ I(v, { children: "Reference" }),
|
|
202
|
+
/* @__PURE__ */ I(v, { children: "Title" }),
|
|
203
|
+
/* @__PURE__ */ I(v, { children: "Due" }),
|
|
204
|
+
/* @__PURE__ */ I(v, { children: "Priority" }),
|
|
205
|
+
/* @__PURE__ */ I(v, {
|
|
206
|
+
className: "text-right",
|
|
207
|
+
children: "Status"
|
|
208
|
+
})
|
|
209
|
+
] }) }), /* @__PURE__ */ I("tbody", { children: a.matters.map((e) => /* @__PURE__ */ L("tr", {
|
|
210
|
+
className: "transition-colors hover:bg-bg-sunken/60",
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ I(h, {
|
|
213
|
+
className: "whitespace-nowrap font-medium text-text-primary",
|
|
214
|
+
children: e.reference || "—"
|
|
215
|
+
}),
|
|
216
|
+
/* @__PURE__ */ I(h, { children: e.title }),
|
|
217
|
+
/* @__PURE__ */ I(h, {
|
|
218
|
+
className: "whitespace-nowrap",
|
|
219
|
+
children: y(e.dueDate)
|
|
220
|
+
}),
|
|
221
|
+
/* @__PURE__ */ I(h, { children: /* @__PURE__ */ I(p, { status: e.priority }) }),
|
|
222
|
+
/* @__PURE__ */ I(h, {
|
|
223
|
+
className: "text-right",
|
|
224
|
+
children: /* @__PURE__ */ I(p, { status: e.status })
|
|
225
|
+
})
|
|
226
|
+
]
|
|
227
|
+
}, e.id)) })] })
|
|
151
228
|
}),
|
|
152
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ I(S, {
|
|
153
230
|
entityType: "proserviceworld-client",
|
|
154
231
|
entityId: n
|
|
155
232
|
}),
|
|
156
|
-
|
|
233
|
+
F && /* @__PURE__ */ I(H, {
|
|
157
234
|
clientId: n,
|
|
158
|
-
onClose: () =>
|
|
159
|
-
onDone: () => void
|
|
235
|
+
onClose: () => B(!1),
|
|
236
|
+
onDone: () => void _.refetch()
|
|
160
237
|
})
|
|
161
238
|
]
|
|
162
|
-
}) : /* @__PURE__ */ k(a, {
|
|
163
|
-
title: "Client not found",
|
|
164
|
-
description: "It may have been archived or belongs to another workspace."
|
|
165
239
|
});
|
|
166
|
-
},
|
|
167
|
-
className: "flex
|
|
168
|
-
children: [/* @__PURE__ */
|
|
169
|
-
className: "text-text-tertiary",
|
|
240
|
+
}, V = ({ icon: e, value: t, multiline: n }) => /* @__PURE__ */ L("div", {
|
|
241
|
+
className: i("flex gap-2.5 text-text-secondary", n ? "items-start" : "items-center"),
|
|
242
|
+
children: [/* @__PURE__ */ I("span", {
|
|
243
|
+
className: "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-tertiary",
|
|
170
244
|
children: e
|
|
171
|
-
}), /* @__PURE__ */
|
|
172
|
-
className: "
|
|
245
|
+
}), /* @__PURE__ */ I("span", {
|
|
246
|
+
className: i("min-w-0 break-words", n ? "leading-relaxed" : "truncate"),
|
|
173
247
|
children: t
|
|
174
248
|
})]
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
className: "text-text-tertiary",
|
|
179
|
-
children: e
|
|
180
|
-
}), t]
|
|
181
|
-
}), F = ({ clientId: e, onClose: t, onDone: r }) => {
|
|
182
|
-
let a = n(), [o, c] = v(""), [u, d] = v(""), [f, h] = v(null);
|
|
183
|
-
return /* @__PURE__ */ k(l, {
|
|
249
|
+
}), H = ({ clientId: e, onClose: t, onDone: r }) => {
|
|
250
|
+
let i = n(), [o, s] = C(""), [l, d] = C(""), [f, p] = C(null);
|
|
251
|
+
return /* @__PURE__ */ I(u, {
|
|
184
252
|
open: !0,
|
|
185
253
|
onClose: t,
|
|
186
254
|
title: "Run conflict check",
|
|
187
|
-
footer: /* @__PURE__ */
|
|
255
|
+
footer: /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ I(R, {
|
|
188
256
|
variant: "outline",
|
|
189
257
|
onClick: t,
|
|
190
|
-
disabled:
|
|
258
|
+
disabled: i.isPending,
|
|
191
259
|
children: "Cancel"
|
|
192
|
-
}), /* @__PURE__ */
|
|
260
|
+
}), /* @__PURE__ */ I(R, {
|
|
193
261
|
onClick: () => {
|
|
194
|
-
|
|
262
|
+
p(null);
|
|
195
263
|
let n = o.split(",").map((e) => e.trim()).filter(Boolean);
|
|
196
|
-
if (n.length === 0) return
|
|
197
|
-
|
|
264
|
+
if (n.length === 0) return p("Add at least one party to search.");
|
|
265
|
+
i.mutate({
|
|
198
266
|
clientId: e,
|
|
199
267
|
searchedParties: n,
|
|
200
|
-
findings:
|
|
268
|
+
findings: l.trim() || null
|
|
201
269
|
}, {
|
|
202
270
|
onSuccess: () => {
|
|
203
271
|
r(), t();
|
|
204
272
|
},
|
|
205
|
-
onError: (e) =>
|
|
273
|
+
onError: (e) => p(e instanceof Error ? e.message : "Failed.")
|
|
206
274
|
});
|
|
207
275
|
},
|
|
208
|
-
disabled:
|
|
209
|
-
children:
|
|
276
|
+
disabled: i.isPending,
|
|
277
|
+
children: i.isPending ? "Running…" : "Record check"
|
|
210
278
|
})] }),
|
|
211
|
-
children: /* @__PURE__ */
|
|
279
|
+
children: /* @__PURE__ */ L("div", {
|
|
212
280
|
className: "space-y-3",
|
|
213
281
|
children: [
|
|
214
|
-
f && /* @__PURE__ */
|
|
282
|
+
f && /* @__PURE__ */ I(a, {
|
|
215
283
|
tone: "danger",
|
|
216
284
|
children: f
|
|
217
285
|
}),
|
|
218
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ I(c, {
|
|
219
287
|
label: "Parties searched",
|
|
220
288
|
required: !0,
|
|
221
289
|
hint: "Comma-separated — counterparties, related entities, principals.",
|
|
222
|
-
children: /* @__PURE__ */
|
|
290
|
+
children: /* @__PURE__ */ I(_, {
|
|
223
291
|
value: o,
|
|
224
|
-
onChange: (e) =>
|
|
292
|
+
onChange: (e) => s(e.target.value),
|
|
225
293
|
placeholder: "Beta Corp, John Roe, Gamma LLP"
|
|
226
294
|
})
|
|
227
295
|
}),
|
|
228
|
-
/* @__PURE__ */
|
|
296
|
+
/* @__PURE__ */ I(c, {
|
|
229
297
|
label: "Findings",
|
|
230
|
-
children: /* @__PURE__ */
|
|
231
|
-
value:
|
|
298
|
+
children: /* @__PURE__ */ I(g, {
|
|
299
|
+
value: l,
|
|
232
300
|
onChange: (e) => d(e.target.value),
|
|
233
301
|
placeholder: "Notes on any potential conflicts…"
|
|
234
302
|
})
|
|
@@ -238,6 +306,6 @@ var M = () => {
|
|
|
238
306
|
});
|
|
239
307
|
};
|
|
240
308
|
//#endregion
|
|
241
|
-
export {
|
|
309
|
+
export { B as ClientDetailPage };
|
|
242
310
|
|
|
243
311
|
//# sourceMappingURL=ClientDetailPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientDetailPage.js","names":[],"sources":["../../../src/proserviceworld/pages/ClientDetailPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeft,\n Briefcase,\n FolderKanban,\n GitBranch,\n Mail,\n Phone,\n MapPin,\n Plus,\n} from 'lucide-react';\nimport {\n useClient,\n useConflictChecks,\n useCreateConflictCheck,\n type PswEngagement,\n type PswMatter,\n} from '../hooks/useProServiceWorldApi';\nimport { useNav } from '../utils/nav';\nimport { DiscussionThread } from '../components/DiscussionThread';\nimport {\n PageHeader,\n SectionCard,\n LoadingBlock,\n ErrorState,\n Empty,\n StatusPill,\n Modal,\n Field,\n TextInput,\n TextArea,\n Banner,\n fmtDate,\n fmtMoney,\n} from '../components/ui';\n\nexport const ClientDetailPage: FC = () => {\n const { id = '' } = useParams();\n const nav = useNav();\n const { data: client, isLoading, error, refetch } = useClient(id);\n const conflicts = useConflictChecks({ clientId: id });\n const [runConflict, setRunConflict] = useState(false);\n\n if (isLoading) return <LoadingBlock />;\n if (error) return <ErrorState error={error} onRetry={() => void refetch()} />;\n if (!client)\n return (\n <Empty\n title=\"Client not found\"\n description=\"It may have been archived or belongs to another workspace.\"\n />\n );\n\n return (\n <div className=\"space-y-6\">\n <button\n type=\"button\"\n onClick={() => nav('clients')}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary hover:text-accent\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back to clients\n </button>\n\n <PageHeader\n title={client.name}\n subtitle={[client.type === 'ORGANIZATION' ? 'Organization' : 'Individual', client.industry]\n .filter(Boolean)\n .join(' · ')}\n actions={<StatusPill status={client.status} />}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <SectionCard title=\"Contact\" className=\"lg:col-span-1\">\n <dl className=\"space-y-2 text-sm\">\n <Row label=\"Contact\" value={client.contactName} />\n {client.contactEmail && (\n <IconRow icon={<Mail className=\"h-3.5 w-3.5\" />} value={client.contactEmail} />\n )}\n {client.contactPhone && (\n <IconRow icon={<Phone className=\"h-3.5 w-3.5\" />} value={client.contactPhone} />\n )}\n {client.address && (\n <IconRow icon={<MapPin className=\"h-3.5 w-3.5\" />} value={client.address} />\n )}\n {client.notes && <p className=\"pt-2 text-text-secondary\">{client.notes}</p>}\n </dl>\n </SectionCard>\n\n <SectionCard\n title=\"Conflict checks\"\n className=\"lg:col-span-2\"\n action={\n <Button size=\"sm\" variant=\"outline\" onClick={() => setRunConflict(true)}>\n <GitBranch className=\"mr-1.5 h-4 w-4\" /> Run check\n </Button>\n }\n >\n {conflicts.isLoading ? (\n <LoadingBlock label=\"Loading…\" />\n ) : !conflicts.data || conflicts.data.length === 0 ? (\n <Empty\n title=\"No conflict checks\"\n description=\"Run a conflict check before accepting new work for this client.\"\n />\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {conflicts.data.map((c) => (\n <li key={c.id} className=\"flex items-center justify-between py-2.5\">\n <div>\n <div className=\"text-sm text-text-primary\">\n {c.searchedParties.join(', ') || 'Conflict search'}\n </div>\n <div className=\"text-xs text-text-tertiary\">\n {fmtDate(c.createdAt)}\n {c.findings ? ` · ${c.findings}` : ''}\n </div>\n </div>\n <StatusPill status={c.status} />\n </li>\n ))}\n </ul>\n )}\n </SectionCard>\n </div>\n\n <SectionCard\n title=\"Engagements\"\n action={\n <Button size=\"sm\" variant=\"outline\" onClick={() => nav('engagements')}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Manage\n </Button>\n }\n >\n {client.engagements.length === 0 ? (\n <Empty\n title=\"No engagements\"\n description=\"Scope the first engagement for this client.\"\n icon={<Briefcase className=\"h-7 w-7\" />}\n />\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {client.engagements.map((e: PswEngagement) => (\n <li key={e.id}>\n <button\n type=\"button\"\n onClick={() => nav(`engagements/${e.id}`)}\n className=\"flex w-full items-center justify-between py-2.5 text-left hover:text-accent\"\n >\n <div>\n <div className=\"text-sm font-medium text-text-primary\">{e.name}</div>\n <div className=\"text-xs text-text-tertiary\">\n {fmtMoney(e.feeAmount, e.currency)} · {e.feeArrangement.toLowerCase()}\n </div>\n </div>\n <StatusPill status={e.status} />\n </button>\n </li>\n ))}\n </ul>\n )}\n </SectionCard>\n\n <SectionCard\n title=\"Matters\"\n action={\n <Button size=\"sm\" variant=\"outline\" onClick={() => nav('matters')}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Manage\n </Button>\n }\n >\n {client.matters.length === 0 ? (\n <Empty\n title=\"No matters\"\n description=\"Open a matter to track regulated work for this client.\"\n icon={<FolderKanban className=\"h-7 w-7\" />}\n />\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {client.matters.map((m: PswMatter) => (\n <li key={m.id} className=\"flex items-center justify-between py-2.5\">\n <div>\n <div className=\"text-sm font-medium text-text-primary\">{m.title}</div>\n <div className=\"text-xs text-text-tertiary\">\n {m.reference || 'No reference'} · Due {fmtDate(m.dueDate)}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <StatusPill status={m.priority} />\n <StatusPill status={m.status} />\n </div>\n </li>\n ))}\n </ul>\n )}\n </SectionCard>\n\n <DiscussionThread entityType=\"proserviceworld-client\" entityId={id} />\n\n {runConflict && (\n <ConflictModal\n clientId={id}\n onClose={() => setRunConflict(false)}\n onDone={() => void conflicts.refetch()}\n />\n )}\n </div>\n );\n};\n\nconst Row: FC<{ label: string; value: string | null }> = ({ label, value }) =>\n value ? (\n <div className=\"flex justify-between gap-4\">\n <dt className=\"text-text-tertiary\">{label}</dt>\n <dd className=\"text-right text-text-primary\">{value}</dd>\n </div>\n ) : null;\n\nconst IconRow: FC<{ icon: React.ReactNode; value: string }> = ({ icon, value }) => (\n <div className=\"flex items-center gap-2 text-text-secondary\">\n <span className=\"text-text-tertiary\">{icon}</span>\n {value}\n </div>\n);\n\nconst ConflictModal: FC<{ clientId: string; onClose: () => void; onDone: () => void }> = ({\n clientId,\n onClose,\n onDone,\n}) => {\n const create = useCreateConflictCheck();\n const [parties, setParties] = useState('');\n const [findings, setFindings] = useState('');\n const [err, setErr] = useState<string | null>(null);\n\n const submit = () => {\n setErr(null);\n const searchedParties = parties\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n if (searchedParties.length === 0) return setErr('Add at least one party to search.');\n create.mutate(\n { clientId, searchedParties, findings: findings.trim() || null },\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=\"Run conflict 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 ? 'Running…' : 'Record check'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field\n label=\"Parties searched\"\n required\n hint=\"Comma-separated — counterparties, related entities, principals.\"\n >\n <TextInput\n value={parties}\n onChange={(e) => setParties(e.target.value)}\n placeholder=\"Beta Corp, John Roe, Gamma LLP\"\n />\n </Field>\n <Field label=\"Findings\">\n <TextArea\n value={findings}\n onChange={(e) => setFindings(e.target.value)}\n placeholder=\"Notes on any potential conflicts…\"\n />\n </Field>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ClientDetailPage.js","names":[],"sources":["../../../src/proserviceworld/pages/ClientDetailPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeft,\n Briefcase,\n FolderKanban,\n GitBranch,\n Mail,\n Phone,\n MapPin,\n Plus,\n StickyNote,\n ChevronRight,\n} from 'lucide-react';\nimport {\n useClient,\n useConflictChecks,\n useCreateConflictCheck,\n type PswEngagement,\n type PswMatter,\n} from '../hooks/useProServiceWorldApi';\nimport { useNav } from '../utils/nav';\nimport { cn } from '../utils/cn';\nimport { DiscussionThread } from '../components/DiscussionThread';\nimport {\n PageHeader,\n SectionCard,\n LoadingBlock,\n ErrorState,\n Empty,\n StatusPill,\n Modal,\n Field,\n TextInput,\n TextArea,\n Banner,\n TableWrap,\n Th,\n Td,\n fmtDate,\n fmtMoney,\n humanize,\n} from '../components/ui';\n\nconst initials = (name: string): string =>\n name\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((w) => w[0]?.toUpperCase() ?? '')\n .join('') || '?';\n\nexport const ClientDetailPage: FC = () => {\n const { id = '' } = useParams();\n const nav = useNav();\n const { data: client, isLoading, error, refetch } = useClient(id);\n const conflicts = useConflictChecks({ clientId: id });\n const [runConflict, setRunConflict] = useState(false);\n\n if (isLoading) return <LoadingBlock />;\n if (error) return <ErrorState error={error} onRetry={() => void refetch()} />;\n if (!client)\n return (\n <Empty\n title=\"Client not found\"\n description=\"It may have been archived or belongs to another workspace.\"\n />\n );\n\n const avatarName = client.contactName || client.name;\n\n return (\n <div className=\"space-y-6\">\n <button\n type=\"button\"\n onClick={() => nav('clients')}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-accent\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back to clients\n </button>\n\n <PageHeader\n title={client.name}\n subtitle={[client.type === 'ORGANIZATION' ? 'Organization' : 'Individual', client.industry]\n .filter(Boolean)\n .join(' · ')}\n actions={<StatusPill status={client.status} />}\n />\n\n {client.tags.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {client.tags.map((t) => (\n <span\n key={t}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {t}\n </span>\n ))}\n </div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <SectionCard title=\"Contact\" className=\"lg:col-span-1\">\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-3\">\n <span className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-accent/10 text-sm font-semibold text-accent ring-1 ring-inset ring-accent/15\">\n {initials(avatarName)}\n </span>\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-semibold text-text-primary\">\n {client.contactName || client.name}\n </div>\n <div className=\"truncate text-xs text-text-tertiary\">\n {client.contactName ? 'Primary contact' : 'Client record'}\n </div>\n </div>\n </div>\n\n <dl className=\"space-y-2.5 text-sm\">\n {client.contactEmail && (\n <IconRow icon={<Mail className=\"h-4 w-4\" />} value={client.contactEmail} />\n )}\n {client.contactPhone && (\n <IconRow icon={<Phone className=\"h-4 w-4\" />} value={client.contactPhone} />\n )}\n {client.address && (\n <IconRow icon={<MapPin className=\"h-4 w-4\" />} value={client.address} />\n )}\n {client.notes && (\n <IconRow icon={<StickyNote className=\"h-4 w-4\" />} value={client.notes} multiline />\n )}\n {!client.contactEmail && !client.contactPhone && !client.address && !client.notes && (\n <p className=\"text-sm text-text-tertiary\">No contact details recorded yet.</p>\n )}\n </dl>\n </div>\n </SectionCard>\n\n <SectionCard\n title=\"Conflict checks\"\n className=\"lg:col-span-2\"\n action={\n <Button size=\"sm\" variant=\"outline\" onClick={() => setRunConflict(true)}>\n <GitBranch className=\"mr-1.5 h-4 w-4\" /> Run check\n </Button>\n }\n >\n {conflicts.isLoading ? (\n <LoadingBlock label=\"Loading…\" />\n ) : !conflicts.data || conflicts.data.length === 0 ? (\n <Empty\n title=\"No conflict checks\"\n description=\"Run a conflict check before accepting new work for this client.\"\n icon={<GitBranch className=\"h-7 w-7\" />}\n />\n ) : (\n <TableWrap>\n <thead>\n <tr>\n <Th>Parties searched</Th>\n <Th>Date</Th>\n <Th className=\"text-right\">Status</Th>\n </tr>\n </thead>\n <tbody>\n {conflicts.data.map((c) => (\n <tr key={c.id} className=\"transition-colors hover:bg-bg-sunken/60\">\n <Td>\n <div className=\"font-medium text-text-primary\">\n {c.searchedParties.join(', ') || 'Conflict search'}\n </div>\n {c.findings ? (\n <div className=\"text-xs text-text-tertiary\">{c.findings}</div>\n ) : null}\n </Td>\n <Td className=\"whitespace-nowrap\">{fmtDate(c.createdAt)}</Td>\n <Td className=\"text-right\">\n <StatusPill status={c.status} />\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n )}\n </SectionCard>\n </div>\n\n <SectionCard\n title=\"Engagements\"\n description={`${client.engagements.length} scoped for this client`}\n action={\n <Button size=\"sm\" variant=\"outline\" onClick={() => nav('engagements')}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Manage\n </Button>\n }\n >\n {client.engagements.length === 0 ? (\n <Empty\n title=\"No engagements\"\n description=\"Scope the first engagement for this client.\"\n icon={<Briefcase className=\"h-7 w-7\" />}\n />\n ) : (\n <TableWrap>\n <thead>\n <tr>\n <Th>Engagement</Th>\n <Th>Fee</Th>\n <Th>Started</Th>\n <Th className=\"text-right\">Status</Th>\n </tr>\n </thead>\n <tbody>\n {client.engagements.map((e: PswEngagement) => (\n <tr\n key={e.id}\n className=\"group cursor-pointer transition-colors hover:bg-bg-sunken/60\"\n onClick={() => nav(`engagements/${e.id}`)}\n >\n <Td>\n <div className=\"flex items-center gap-1 font-medium text-text-primary transition-colors group-hover:text-accent\">\n <span>{e.name}</span>\n <ChevronRight className=\"h-3.5 w-3.5 shrink-0 text-text-tertiary opacity-0 transition-opacity group-hover:opacity-100\" />\n </div>\n </Td>\n <Td className=\"whitespace-nowrap\">\n {fmtMoney(e.feeAmount, e.currency)}{' '}\n <span className=\"text-xs text-text-tertiary\">\n / {humanize(e.feeArrangement)}\n </span>\n </Td>\n <Td className=\"whitespace-nowrap\">{fmtDate(e.startDate)}</Td>\n <Td className=\"text-right\">\n <StatusPill status={e.status} />\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n )}\n </SectionCard>\n\n <SectionCard\n title=\"Matters\"\n description={`${client.matters.length} tracked for this client`}\n action={\n <Button size=\"sm\" variant=\"outline\" onClick={() => nav('matters')}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Manage\n </Button>\n }\n >\n {client.matters.length === 0 ? (\n <Empty\n title=\"No matters\"\n description=\"Open a matter to track regulated work for this client.\"\n icon={<FolderKanban className=\"h-7 w-7\" />}\n />\n ) : (\n <TableWrap>\n <thead>\n <tr>\n <Th>Reference</Th>\n <Th>Title</Th>\n <Th>Due</Th>\n <Th>Priority</Th>\n <Th className=\"text-right\">Status</Th>\n </tr>\n </thead>\n <tbody>\n {client.matters.map((m: PswMatter) => (\n <tr key={m.id} className=\"transition-colors hover:bg-bg-sunken/60\">\n <Td className=\"whitespace-nowrap font-medium text-text-primary\">\n {m.reference || '—'}\n </Td>\n <Td>{m.title}</Td>\n <Td className=\"whitespace-nowrap\">{fmtDate(m.dueDate)}</Td>\n <Td>\n <StatusPill status={m.priority} />\n </Td>\n <Td className=\"text-right\">\n <StatusPill status={m.status} />\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n )}\n </SectionCard>\n\n <DiscussionThread entityType=\"proserviceworld-client\" entityId={id} />\n\n {runConflict && (\n <ConflictModal\n clientId={id}\n onClose={() => setRunConflict(false)}\n onDone={() => void conflicts.refetch()}\n />\n )}\n </div>\n );\n};\n\nconst IconRow: FC<{ icon: React.ReactNode; value: string; multiline?: boolean }> = ({\n icon,\n value,\n multiline,\n}) => (\n <div\n className={cn('flex gap-2.5 text-text-secondary', multiline ? 'items-start' : 'items-center')}\n >\n <span className=\"mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-tertiary\">\n {icon}\n </span>\n <span className={cn('min-w-0 break-words', multiline ? 'leading-relaxed' : 'truncate')}>\n {value}\n </span>\n </div>\n);\n\nconst ConflictModal: FC<{ clientId: string; onClose: () => void; onDone: () => void }> = ({\n clientId,\n onClose,\n onDone,\n}) => {\n const create = useCreateConflictCheck();\n const [parties, setParties] = useState('');\n const [findings, setFindings] = useState('');\n const [err, setErr] = useState<string | null>(null);\n\n const submit = () => {\n setErr(null);\n const searchedParties = parties\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n if (searchedParties.length === 0) return setErr('Add at least one party to search.');\n create.mutate(\n { clientId, searchedParties, findings: findings.trim() || null },\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=\"Run conflict 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 ? 'Running…' : 'Record check'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field\n label=\"Parties searched\"\n required\n hint=\"Comma-separated — counterparties, related entities, principals.\"\n >\n <TextInput\n value={parties}\n onChange={(e) => setParties(e.target.value)}\n placeholder=\"Beta Corp, John Roe, Gamma LLP\"\n />\n </Field>\n <Field label=\"Findings\">\n <TextArea\n value={findings}\n onChange={(e) => setFindings(e.target.value)}\n placeholder=\"Notes on any potential conflicts…\"\n />\n </Field>\n </div>\n </Modal>\n );\n};\n"],"mappings":";;;;;;;;;;;AA8CA,IAAM,KAAY,MAChB,EACG,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,MAAM,GAAG,EAAE,CACX,KAAK,MAAM,EAAE,IAAI,aAAa,IAAI,GAAG,CACrC,KAAK,GAAG,IAAI,KAEJ,UAA6B;CACxC,IAAM,EAAE,QAAK,OAAO,GAAW,EACzB,IAAM,GAAQ,EACd,EAAE,MAAM,GAAQ,cAAW,UAAO,eAAY,EAAU,EAAG,EAC3D,IAAY,EAAkB,EAAE,UAAU,GAAI,CAAC,EAC/C,CAAC,GAAa,KAAkB,EAAS,GAAM;AAErD,KAAI,EAAW,QAAO,kBAAC,GAAD,EAAgB,CAAA;AACtC,KAAI,EAAO,QAAO,kBAAC,GAAD;EAAmB;EAAO,eAAe,KAAK,GAAS;EAAI,CAAA;AAC7E,KAAI,CAAC,EACH,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,CAAA;CAGN,IAAM,IAAa,EAAO,eAAe,EAAO;AAEhD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAI,UAAU;IAC7B,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,mBAC1B;;GAET,kBAAC,GAAD;IACE,OAAO,EAAO;IACd,UAAU,CAAC,EAAO,SAAS,iBAAiB,iBAAiB,cAAc,EAAO,SAAS,CACxF,OAAO,QAAQ,CACf,KAAK,MAAM;IACd,SAAS,kBAAC,GAAD,EAAY,QAAQ,EAAO,QAAU,CAAA;IAC9C,CAAA;GAED,EAAO,KAAK,SAAS,KACpB,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAO,KAAK,KAAK,MAChB,kBAAC,QAAD;KAEE,WAAU;eAET;KACI,EAJA,EAIA,CACP;IACE,CAAA;GAGR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAa,OAAM;KAAU,WAAU;eACrC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAS,EAAW;QAChB,CAAA,EACP,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAO,eAAe,EAAO;SAC1B,CAAA,EACN,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAO,cAAc,oBAAoB;SACtC,CAAA,CACF;UACF;UAEN,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACG,EAAO,gBACN,kBAAC,GAAD;SAAS,MAAM,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;SAAE,OAAO,EAAO;SAAgB,CAAA;QAE5E,EAAO,gBACN,kBAAC,GAAD;SAAS,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;SAAE,OAAO,EAAO;SAAgB,CAAA;QAE7E,EAAO,WACN,kBAAC,GAAD;SAAS,MAAM,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;SAAE,OAAO,EAAO;SAAW,CAAA;QAEzE,EAAO,SACN,kBAAC,GAAD;SAAS,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;SAAE,OAAO,EAAO;SAAO,WAAA;SAAY,CAAA;QAErF,CAAC,EAAO,gBAAgB,CAAC,EAAO,gBAAgB,CAAC,EAAO,WAAW,CAAC,EAAO,SAC1E,kBAAC,KAAD;SAAG,WAAU;mBAA6B;SAAoC,CAAA;QAE7E;SACD;;KACM,CAAA,EAEd,kBAAC,GAAD;KACE,OAAM;KACN,WAAU;KACV,QACE,kBAAC,GAAD;MAAQ,MAAK;MAAK,SAAQ;MAAU,eAAe,EAAe,GAAK;gBAAvE,CACE,kBAAC,GAAD,EAAW,WAAU,kBAAmB,CAAA,EAAA,aACjC;;eAGV,EAAU,YACT,kBAAC,GAAD,EAAc,OAAM,YAAa,CAAA,GAC/B,CAAC,EAAU,QAAQ,EAAU,KAAK,WAAW,IAC/C,kBAAC,GAAD;MACE,OAAM;MACN,aAAY;MACZ,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;MACvC,CAAA,GAEF,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD,EAAA,UAAA;MACE,kBAAC,GAAD,EAAA,UAAI,oBAAqB,CAAA;MACzB,kBAAC,GAAD,EAAA,UAAI,QAAS,CAAA;MACb,kBAAC,GAAD;OAAI,WAAU;iBAAa;OAAW,CAAA;MACnC,EAAA,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAU,KAAK,KAAK,MACnB,kBAAC,MAAD;MAAe,WAAU;gBAAzB;OACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAE,gBAAgB,KAAK,KAAK,IAAI;QAC7B,CAAA,EACL,EAAE,WACD,kBAAC,OAAD;QAAK,WAAU;kBAA8B,EAAE;QAAe,CAAA,GAC5D,KACD,EAAA,CAAA;OACL,kBAAC,GAAD;QAAI,WAAU;kBAAqB,EAAQ,EAAE,UAAU;QAAM,CAAA;OAC7D,kBAAC,GAAD;QAAI,WAAU;kBACZ,kBAAC,GAAD,EAAY,QAAQ,EAAE,QAAU,CAAA;QAC7B,CAAA;OACF;QAbI,EAAE,GAaN,CACL,EACI,CAAA,CACE,EAAA,CAAA;KAEF,CAAA,CACV;;GAEN,kBAAC,GAAD;IACE,OAAM;IACN,aAAa,GAAG,EAAO,YAAY,OAAO;IAC1C,QACE,kBAAC,GAAD;KAAQ,MAAK;KAAK,SAAQ;KAAU,eAAe,EAAI,cAAc;eAArE,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,SAE5B;;cAGV,EAAO,YAAY,WAAW,IAC7B,kBAAC,GAAD;KACE,OAAM;KACN,aAAY;KACZ,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;KACvC,CAAA,GAEF,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD,EAAA,UAAA;KACE,kBAAC,GAAD,EAAA,UAAI,cAAe,CAAA;KACnB,kBAAC,GAAD,EAAA,UAAI,OAAQ,CAAA;KACZ,kBAAC,GAAD,EAAA,UAAI,WAAY,CAAA;KAChB,kBAAC,GAAD;MAAI,WAAU;gBAAa;MAAW,CAAA;KACnC,EAAA,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAO,YAAY,KAAK,MACvB,kBAAC,MAAD;KAEE,WAAU;KACV,eAAe,EAAI,eAAe,EAAE,KAAK;eAH3C;MAKE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD,EAAA,UAAO,EAAE,MAAY,CAAA,EACrB,kBAAC,GAAD,EAAc,WAAU,gGAAiG,CAAA,CACrH;UACH,CAAA;MACL,kBAAC,GAAD;OAAI,WAAU;iBAAd;QACG,EAAS,EAAE,WAAW,EAAE,SAAS;QAAE;QACpC,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CAA6C,MACxC,EAAS,EAAE,eAAe,CACxB;;QACJ;;MACL,kBAAC,GAAD;OAAI,WAAU;iBAAqB,EAAQ,EAAE,UAAU;OAAM,CAAA;MAC7D,kBAAC,GAAD;OAAI,WAAU;iBACZ,kBAAC,GAAD,EAAY,QAAQ,EAAE,QAAU,CAAA;OAC7B,CAAA;MACF;OApBE,EAAE,GAoBJ,CACL,EACI,CAAA,CACE,EAAA,CAAA;IAEF,CAAA;GAEd,kBAAC,GAAD;IACE,OAAM;IACN,aAAa,GAAG,EAAO,QAAQ,OAAO;IACtC,QACE,kBAAC,GAAD;KAAQ,MAAK;KAAK,SAAQ;KAAU,eAAe,EAAI,UAAU;eAAjE,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,SAE5B;;cAGV,EAAO,QAAQ,WAAW,IACzB,kBAAC,GAAD;KACE,OAAM;KACN,aAAY;KACZ,MAAM,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA;KAC1C,CAAA,GAEF,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD,EAAA,UAAA;KACE,kBAAC,GAAD,EAAA,UAAI,aAAc,CAAA;KAClB,kBAAC,GAAD,EAAA,UAAI,SAAU,CAAA;KACd,kBAAC,GAAD,EAAA,UAAI,OAAQ,CAAA;KACZ,kBAAC,GAAD,EAAA,UAAI,YAAa,CAAA;KACjB,kBAAC,GAAD;MAAI,WAAU;gBAAa;MAAW,CAAA;KACnC,EAAA,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAO,QAAQ,KAAK,MACnB,kBAAC,MAAD;KAAe,WAAU;eAAzB;MACE,kBAAC,GAAD;OAAI,WAAU;iBACX,EAAE,aAAa;OACb,CAAA;MACL,kBAAC,GAAD,EAAA,UAAK,EAAE,OAAW,CAAA;MAClB,kBAAC,GAAD;OAAI,WAAU;iBAAqB,EAAQ,EAAE,QAAQ;OAAM,CAAA;MAC3D,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAY,QAAQ,EAAE,UAAY,CAAA,EAC/B,CAAA;MACL,kBAAC,GAAD;OAAI,WAAU;iBACZ,kBAAC,GAAD,EAAY,QAAQ,EAAE,QAAU,CAAA;OAC7B,CAAA;MACF;OAZI,EAAE,GAYN,CACL,EACI,CAAA,CACE,EAAA,CAAA;IAEF,CAAA;GAEd,kBAAC,GAAD;IAAkB,YAAW;IAAyB,UAAU;IAAM,CAAA;GAErE,KACC,kBAAC,GAAD;IACE,UAAU;IACV,eAAe,EAAe,GAAM;IACpC,cAAc,KAAK,EAAU,SAAS;IACtC,CAAA;GAEA;;GAIJ,KAA8E,EAClF,SACA,UACA,mBAEA,kBAAC,OAAD;CACE,WAAW,EAAG,oCAAoC,IAAY,gBAAgB,eAAe;WAD/F,CAGE,kBAAC,QAAD;EAAM,WAAU;YACb;EACI,CAAA,EACP,kBAAC,QAAD;EAAM,WAAW,EAAG,uBAAuB,IAAY,oBAAoB,WAAW;YACnF;EACI,CAAA,CACH;IAGF,KAAoF,EACxF,aACA,YACA,gBACI;CACJ,IAAM,IAAS,GAAwB,EACjC,CAAC,GAAS,KAAc,EAAS,GAAG,EACpC,CAAC,GAAU,KAAe,EAAS,GAAG,EACtC,CAAC,GAAK,KAAU,EAAwB,KAAK;AAqBnD,QACE,kBAAC,GAAD;EACE,MAAA;EACS;EACT,OAAM;EACN,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAQ,SAAQ;GAAU,SAAS;GAAS,UAAU,EAAO;aAAW;GAE/D,CAAA,EACT,kBAAC,GAAD;GAAQ,eA7BK;AACnB,MAAO,KAAK;IACZ,IAAM,IAAkB,EACrB,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ;AAClB,QAAI,EAAgB,WAAW,EAAG,QAAO,EAAO,oCAAoC;AACpF,MAAO,OACL;KAAE;KAAU;KAAiB,UAAU,EAAS,MAAM,IAAI;KAAM,EAChE;KACE,iBAAiB;AAEf,MADA,GAAQ,EACR,GAAS;;KAEX,UAAU,MAAM,EAAO,aAAa,QAAQ,EAAE,UAAU,UAAU;KACnE,CACF;;GAa8B,UAAU,EAAO;aACvC,EAAO,YAAY,aAAa;GAC1B,CAAA,CACR,EAAA,CAAA;YAGL,kBAAC,OAAD;GAAK,WAAU;aAAf;IACG,KAAO,kBAAC,GAAD;KAAQ,MAAK;eAAU;KAAa,CAAA;IAC5C,kBAAC,GAAD;KACE,OAAM;KACN,UAAA;KACA,MAAK;eAEL,kBAAC,GAAD;MACE,OAAO;MACP,WAAW,MAAM,EAAW,EAAE,OAAO,MAAM;MAC3C,aAAY;MACZ,CAAA;KACI,CAAA;IACR,kBAAC,GAAD;KAAO,OAAM;eACX,kBAAC,GAAD;MACE,OAAO;MACP,WAAW,MAAM,EAAY,EAAE,OAAO,MAAM;MAC5C,aAAY;MACZ,CAAA;KACI,CAAA;IACJ;;EACA,CAAA"}
|