@burdenoff/microfe-proserviceworld 2026.706.1 → 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 +76 -0
- package/dist/proserviceworld/components/DiscussionThread.js.map +1 -0
- package/dist/proserviceworld/components/ui.js +18 -18
- package/dist/proserviceworld/components/ui.js.map +1 -1
- package/dist/proserviceworld/hooks/useEntityComments.js +56 -0
- package/dist/proserviceworld/hooks/useEntityComments.js.map +1 -0
- package/dist/proserviceworld/pages/AnalyticsPage.js +277 -111
- package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
- package/dist/proserviceworld/pages/ClientDetailPage.js +222 -149
- 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 +217 -182
- 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,229 +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 {
|
|
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";
|
|
9
11
|
//#region src/proserviceworld/pages/ClientDetailPage.tsx
|
|
10
|
-
var
|
|
11
|
-
let { id: n = "" } =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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", {
|
|
16
25
|
className: "space-y-6",
|
|
17
26
|
children: [
|
|
18
|
-
/* @__PURE__ */
|
|
27
|
+
/* @__PURE__ */ L("button", {
|
|
19
28
|
type: "button",
|
|
20
29
|
onClick: () => i("clients"),
|
|
21
|
-
className: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-accent",
|
|
22
|
-
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"]
|
|
23
32
|
}),
|
|
24
|
-
/* @__PURE__ */
|
|
25
|
-
title:
|
|
26
|
-
subtitle: [
|
|
27
|
-
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 })
|
|
28
37
|
}),
|
|
29
|
-
/* @__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", {
|
|
30
46
|
className: "grid grid-cols-1 gap-4 lg:grid-cols-3",
|
|
31
|
-
children: [/* @__PURE__ */
|
|
47
|
+
children: [/* @__PURE__ */ I(f, {
|
|
32
48
|
title: "Contact",
|
|
33
49
|
className: "lg:col-span-1",
|
|
34
|
-
children: /* @__PURE__ */
|
|
35
|
-
className: "space-y-
|
|
36
|
-
children: [
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
})]
|
|
58
93
|
})
|
|
59
|
-
}), /* @__PURE__ */
|
|
94
|
+
}), /* @__PURE__ */ I(f, {
|
|
60
95
|
title: "Conflict checks",
|
|
61
96
|
className: "lg:col-span-2",
|
|
62
|
-
action: /* @__PURE__ */
|
|
97
|
+
action: /* @__PURE__ */ L(R, {
|
|
63
98
|
size: "sm",
|
|
64
99
|
variant: "outline",
|
|
65
|
-
onClick: () =>
|
|
66
|
-
children: [/* @__PURE__ */ O
|
|
100
|
+
onClick: () => B(!0),
|
|
101
|
+
children: [/* @__PURE__ */ I(O, { className: "mr-1.5 h-4 w-4" }), " Run check"]
|
|
67
102
|
}),
|
|
68
|
-
children:
|
|
103
|
+
children: _.isLoading ? /* @__PURE__ */ I(l, { label: "Loading…" }) : !_.data || _.data.length === 0 ? /* @__PURE__ */ I(o, {
|
|
69
104
|
title: "No conflict checks",
|
|
70
|
-
description: "Run a conflict check before accepting new work for this client."
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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",
|
|
77
119
|
children: e.searchedParties.join(", ") || "Conflict search"
|
|
78
|
-
}), /* @__PURE__ */
|
|
120
|
+
}), e.findings ? /* @__PURE__ */ I("div", {
|
|
79
121
|
className: "text-xs text-text-tertiary",
|
|
80
|
-
children:
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
|
|
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)) })] })
|
|
84
134
|
})]
|
|
85
135
|
}),
|
|
86
|
-
/* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ I(f, {
|
|
87
137
|
title: "Engagements",
|
|
88
|
-
|
|
138
|
+
description: `${a.engagements.length} scoped for this client`,
|
|
139
|
+
action: /* @__PURE__ */ L(R, {
|
|
89
140
|
size: "sm",
|
|
90
141
|
variant: "outline",
|
|
91
142
|
onClick: () => i("engagements"),
|
|
92
|
-
children: [/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ I(M, { className: "mr-1.5 h-4 w-4" }), "Manage"]
|
|
93
144
|
}),
|
|
94
|
-
children:
|
|
145
|
+
children: a.engagements.length === 0 ? /* @__PURE__ */ I(o, {
|
|
95
146
|
title: "No engagements",
|
|
96
147
|
description: "Scope the first engagement for this client.",
|
|
97
|
-
icon: /* @__PURE__ */
|
|
98
|
-
}) : /* @__PURE__ */
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
className: "
|
|
104
|
-
children:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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",
|
|
109
167
|
children: [
|
|
110
|
-
|
|
111
|
-
"
|
|
112
|
-
|
|
168
|
+
b(e.feeAmount, e.currency),
|
|
169
|
+
" ",
|
|
170
|
+
/* @__PURE__ */ L("span", {
|
|
171
|
+
className: "text-xs text-text-tertiary",
|
|
172
|
+
children: ["/ ", x(e.feeArrangement)]
|
|
173
|
+
})
|
|
113
174
|
]
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
|
|
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)) })] })
|
|
117
186
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ I(f, {
|
|
119
188
|
title: "Matters",
|
|
120
|
-
|
|
189
|
+
description: `${a.matters.length} tracked for this client`,
|
|
190
|
+
action: /* @__PURE__ */ L(R, {
|
|
121
191
|
size: "sm",
|
|
122
192
|
variant: "outline",
|
|
123
193
|
onClick: () => i("matters"),
|
|
124
|
-
children: [/* @__PURE__ */
|
|
194
|
+
children: [/* @__PURE__ */ I(M, { className: "mr-1.5 h-4 w-4" }), "Manage"]
|
|
125
195
|
}),
|
|
126
|
-
children:
|
|
196
|
+
children: a.matters.length === 0 ? /* @__PURE__ */ I(o, {
|
|
127
197
|
title: "No matters",
|
|
128
198
|
description: "Open a matter to track regulated work for this client.",
|
|
129
|
-
icon: /* @__PURE__ */
|
|
130
|
-
}) : /* @__PURE__ */
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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)) })] })
|
|
228
|
+
}),
|
|
229
|
+
/* @__PURE__ */ I(S, {
|
|
230
|
+
entityType: "proserviceworld-client",
|
|
231
|
+
entityId: n
|
|
150
232
|
}),
|
|
151
|
-
|
|
233
|
+
F && /* @__PURE__ */ I(H, {
|
|
152
234
|
clientId: n,
|
|
153
|
-
onClose: () =>
|
|
154
|
-
onDone: () => void
|
|
235
|
+
onClose: () => B(!1),
|
|
236
|
+
onDone: () => void _.refetch()
|
|
155
237
|
})
|
|
156
238
|
]
|
|
157
|
-
}) : /* @__PURE__ */ O(a, {
|
|
158
|
-
title: "Client not found",
|
|
159
|
-
description: "It may have been archived or belongs to another workspace."
|
|
160
239
|
});
|
|
161
|
-
},
|
|
162
|
-
className: "flex
|
|
163
|
-
children: [/* @__PURE__ */
|
|
164
|
-
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",
|
|
165
244
|
children: e
|
|
166
|
-
}), /* @__PURE__ */
|
|
167
|
-
className: "
|
|
245
|
+
}), /* @__PURE__ */ I("span", {
|
|
246
|
+
className: i("min-w-0 break-words", n ? "leading-relaxed" : "truncate"),
|
|
168
247
|
children: t
|
|
169
248
|
})]
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
className: "text-text-tertiary",
|
|
174
|
-
children: e
|
|
175
|
-
}), t]
|
|
176
|
-
}), P = ({ clientId: e, onClose: t, onDone: r }) => {
|
|
177
|
-
let a = n(), [o, c] = _(""), [u, d] = _(""), [f, h] = _(null);
|
|
178
|
-
return /* @__PURE__ */ O(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, {
|
|
179
252
|
open: !0,
|
|
180
253
|
onClose: t,
|
|
181
254
|
title: "Run conflict check",
|
|
182
|
-
footer: /* @__PURE__ */
|
|
255
|
+
footer: /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ I(R, {
|
|
183
256
|
variant: "outline",
|
|
184
257
|
onClick: t,
|
|
185
|
-
disabled:
|
|
258
|
+
disabled: i.isPending,
|
|
186
259
|
children: "Cancel"
|
|
187
|
-
}), /* @__PURE__ */
|
|
260
|
+
}), /* @__PURE__ */ I(R, {
|
|
188
261
|
onClick: () => {
|
|
189
|
-
|
|
262
|
+
p(null);
|
|
190
263
|
let n = o.split(",").map((e) => e.trim()).filter(Boolean);
|
|
191
|
-
if (n.length === 0) return
|
|
192
|
-
|
|
264
|
+
if (n.length === 0) return p("Add at least one party to search.");
|
|
265
|
+
i.mutate({
|
|
193
266
|
clientId: e,
|
|
194
267
|
searchedParties: n,
|
|
195
|
-
findings:
|
|
268
|
+
findings: l.trim() || null
|
|
196
269
|
}, {
|
|
197
270
|
onSuccess: () => {
|
|
198
271
|
r(), t();
|
|
199
272
|
},
|
|
200
|
-
onError: (e) =>
|
|
273
|
+
onError: (e) => p(e instanceof Error ? e.message : "Failed.")
|
|
201
274
|
});
|
|
202
275
|
},
|
|
203
|
-
disabled:
|
|
204
|
-
children:
|
|
276
|
+
disabled: i.isPending,
|
|
277
|
+
children: i.isPending ? "Running…" : "Record check"
|
|
205
278
|
})] }),
|
|
206
|
-
children: /* @__PURE__ */
|
|
279
|
+
children: /* @__PURE__ */ L("div", {
|
|
207
280
|
className: "space-y-3",
|
|
208
281
|
children: [
|
|
209
|
-
f && /* @__PURE__ */
|
|
282
|
+
f && /* @__PURE__ */ I(a, {
|
|
210
283
|
tone: "danger",
|
|
211
284
|
children: f
|
|
212
285
|
}),
|
|
213
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ I(c, {
|
|
214
287
|
label: "Parties searched",
|
|
215
288
|
required: !0,
|
|
216
289
|
hint: "Comma-separated — counterparties, related entities, principals.",
|
|
217
|
-
children: /* @__PURE__ */
|
|
290
|
+
children: /* @__PURE__ */ I(_, {
|
|
218
291
|
value: o,
|
|
219
|
-
onChange: (e) =>
|
|
292
|
+
onChange: (e) => s(e.target.value),
|
|
220
293
|
placeholder: "Beta Corp, John Roe, Gamma LLP"
|
|
221
294
|
})
|
|
222
295
|
}),
|
|
223
|
-
/* @__PURE__ */
|
|
296
|
+
/* @__PURE__ */ I(c, {
|
|
224
297
|
label: "Findings",
|
|
225
|
-
children: /* @__PURE__ */
|
|
226
|
-
value:
|
|
298
|
+
children: /* @__PURE__ */ I(g, {
|
|
299
|
+
value: l,
|
|
227
300
|
onChange: (e) => d(e.target.value),
|
|
228
301
|
placeholder: "Notes on any potential conflicts…"
|
|
229
302
|
})
|
|
@@ -233,6 +306,6 @@ var j = () => {
|
|
|
233
306
|
});
|
|
234
307
|
};
|
|
235
308
|
//#endregion
|
|
236
|
-
export {
|
|
309
|
+
export { B as ClientDetailPage };
|
|
237
310
|
|
|
238
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 {\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 {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"}
|