@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.
Files changed (26) hide show
  1. package/dist/proserviceworld/components/DiscussionThread.js +1 -1
  2. package/dist/proserviceworld/components/DiscussionThread.js.map +1 -1
  3. package/dist/proserviceworld/components/ui.js +18 -18
  4. package/dist/proserviceworld/components/ui.js.map +1 -1
  5. package/dist/proserviceworld/hooks/useEntityComments.js.map +1 -1
  6. package/dist/proserviceworld/pages/AnalyticsPage.js +277 -111
  7. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  8. package/dist/proserviceworld/pages/ClientDetailPage.js +219 -151
  9. package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -1
  10. package/dist/proserviceworld/pages/ClientsPage.js +148 -127
  11. package/dist/proserviceworld/pages/ClientsPage.js.map +1 -1
  12. package/dist/proserviceworld/pages/CompliancePage.js +140 -96
  13. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -1
  14. package/dist/proserviceworld/pages/DashboardPage.js +221 -104
  15. package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
  16. package/dist/proserviceworld/pages/EngagementDetailPage.js +211 -181
  17. package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -1
  18. package/dist/proserviceworld/pages/EngagementsPage.js +144 -106
  19. package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -1
  20. package/dist/proserviceworld/pages/InvoicesPage.js +144 -129
  21. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
  22. package/dist/proserviceworld/pages/MattersPage.js +163 -122
  23. package/dist/proserviceworld/pages/MattersPage.js.map +1 -1
  24. package/dist/proserviceworld/pages/TimePage.js +112 -92
  25. package/dist/proserviceworld/pages/TimePage.js.map +1 -1
  26. 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 { Banner as i, Empty as a, ErrorState as o, Field as s, LoadingBlock as c, Modal as l, PageHeader as u, SectionCard as d, StatusPill as f, TextArea as p, TextInput as m, fmtDate as h, fmtMoney as g } from "../components/ui.js";
4
- import { DiscussionThread as _ } from "../components/DiscussionThread.js";
5
- import { useState as v } from "react";
6
- import { ArrowLeft as y, Briefcase as b, FolderKanban as x, GitBranch as S, Mail as C, MapPin as w, Phone as T, Plus as E } from "lucide-react";
7
- import { useParams as D } from "react-router-dom";
8
- import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
9
- import { Button as j } from "@burdenoff/fe-libs/ui";
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 M = () => {
12
- let { id: n = "" } = D(), i = r(), { data: s, isLoading: l, error: p, refetch: m } = e(n), O = t({ clientId: n }), [M, I] = v(!1);
13
- return l ? /* @__PURE__ */ k(c, {}) : p ? /* @__PURE__ */ k(o, {
14
- error: p,
15
- onRetry: () => void m()
16
- }) : s ? /* @__PURE__ */ A("div", {
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__ */ A("button", {
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__ */ k(y, { className: "h-4 w-4" }), " Back to clients"]
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__ */ k(u, {
26
- title: s.name,
27
- subtitle: [s.type === "ORGANIZATION" ? "Organization" : "Individual", s.industry].filter(Boolean).join(" · "),
28
- actions: /* @__PURE__ */ k(f, { status: s.status })
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__ */ A("div", {
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__ */ k(d, {
47
+ children: [/* @__PURE__ */ I(f, {
33
48
  title: "Contact",
34
49
  className: "lg:col-span-1",
35
- children: /* @__PURE__ */ A("dl", {
36
- className: "space-y-2 text-sm",
37
- children: [
38
- /* @__PURE__ */ k(N, {
39
- label: "Contact",
40
- value: s.contactName
41
- }),
42
- s.contactEmail && /* @__PURE__ */ k(P, {
43
- icon: /* @__PURE__ */ k(C, { className: "h-3.5 w-3.5" }),
44
- value: s.contactEmail
45
- }),
46
- s.contactPhone && /* @__PURE__ */ k(P, {
47
- icon: /* @__PURE__ */ k(T, { className: "h-3.5 w-3.5" }),
48
- value: s.contactPhone
49
- }),
50
- s.address && /* @__PURE__ */ k(P, {
51
- icon: /* @__PURE__ */ k(w, { className: "h-3.5 w-3.5" }),
52
- value: s.address
53
- }),
54
- s.notes && /* @__PURE__ */ k("p", {
55
- className: "pt-2 text-text-secondary",
56
- children: s.notes
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__ */ k(d, {
94
+ }), /* @__PURE__ */ I(f, {
61
95
  title: "Conflict checks",
62
96
  className: "lg:col-span-2",
63
- action: /* @__PURE__ */ A(j, {
97
+ action: /* @__PURE__ */ L(R, {
64
98
  size: "sm",
65
99
  variant: "outline",
66
- onClick: () => I(!0),
67
- children: [/* @__PURE__ */ k(S, { className: "mr-1.5 h-4 w-4" }), " Run check"]
100
+ onClick: () => B(!0),
101
+ children: [/* @__PURE__ */ I(O, { className: "mr-1.5 h-4 w-4" }), " Run check"]
68
102
  }),
69
- children: O.isLoading ? /* @__PURE__ */ k(c, { label: "Loading…" }) : !O.data || O.data.length === 0 ? /* @__PURE__ */ k(a, {
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
- }) : /* @__PURE__ */ k("ul", {
73
- className: "divide-y divide-border-seam",
74
- children: O.data.map((e) => /* @__PURE__ */ A("li", {
75
- className: "flex items-center justify-between py-2.5",
76
- children: [/* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
77
- className: "text-sm text-text-primary",
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__ */ A("div", {
120
+ }), e.findings ? /* @__PURE__ */ I("div", {
80
121
  className: "text-xs text-text-tertiary",
81
- children: [h(e.createdAt), e.findings ? ` · ${e.findings}` : ""]
82
- })] }), /* @__PURE__ */ k(f, { status: e.status })]
83
- }, e.id))
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__ */ k(d, {
136
+ /* @__PURE__ */ I(f, {
88
137
  title: "Engagements",
89
- action: /* @__PURE__ */ A(j, {
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__ */ k(E, { className: "mr-1.5 h-4 w-4" }), "Manage"]
143
+ children: [/* @__PURE__ */ I(M, { className: "mr-1.5 h-4 w-4" }), "Manage"]
94
144
  }),
95
- children: s.engagements.length === 0 ? /* @__PURE__ */ k(a, {
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__ */ k(b, { className: "h-7 w-7" })
99
- }) : /* @__PURE__ */ k("ul", {
100
- className: "divide-y divide-border-seam",
101
- children: s.engagements.map((e) => /* @__PURE__ */ k("li", { children: /* @__PURE__ */ A("button", {
102
- type: "button",
103
- onClick: () => i(`engagements/${e.id}`),
104
- className: "flex w-full items-center justify-between py-2.5 text-left hover:text-accent",
105
- children: [/* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
106
- className: "text-sm font-medium text-text-primary",
107
- children: e.name
108
- }), /* @__PURE__ */ A("div", {
109
- className: "text-xs text-text-tertiary",
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
- g(e.feeAmount, e.currency),
112
- " · ",
113
- e.feeArrangement.toLowerCase()
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
- })] }), /* @__PURE__ */ k(f, { status: e.status })]
116
- }) }, e.id))
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__ */ k(d, {
187
+ /* @__PURE__ */ I(f, {
120
188
  title: "Matters",
121
- action: /* @__PURE__ */ A(j, {
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__ */ k(E, { className: "mr-1.5 h-4 w-4" }), "Manage"]
194
+ children: [/* @__PURE__ */ I(M, { className: "mr-1.5 h-4 w-4" }), "Manage"]
126
195
  }),
127
- children: s.matters.length === 0 ? /* @__PURE__ */ k(a, {
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__ */ k(x, { className: "h-7 w-7" })
131
- }) : /* @__PURE__ */ k("ul", {
132
- className: "divide-y divide-border-seam",
133
- children: s.matters.map((e) => /* @__PURE__ */ A("li", {
134
- className: "flex items-center justify-between py-2.5",
135
- children: [/* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("div", {
136
- className: "text-sm font-medium text-text-primary",
137
- children: e.title
138
- }), /* @__PURE__ */ A("div", {
139
- className: "text-xs text-text-tertiary",
140
- children: [
141
- e.reference || "No reference",
142
- " · Due ",
143
- h(e.dueDate)
144
- ]
145
- })] }), /* @__PURE__ */ A("div", {
146
- className: "flex items-center gap-2",
147
- children: [/* @__PURE__ */ k(f, { status: e.priority }), /* @__PURE__ */ k(f, { status: e.status })]
148
- })]
149
- }, e.id))
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__ */ k(_, {
229
+ /* @__PURE__ */ I(S, {
153
230
  entityType: "proserviceworld-client",
154
231
  entityId: n
155
232
  }),
156
- M && /* @__PURE__ */ k(F, {
233
+ F && /* @__PURE__ */ I(H, {
157
234
  clientId: n,
158
- onClose: () => I(!1),
159
- onDone: () => void O.refetch()
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
- }, N = ({ label: e, value: t }) => t ? /* @__PURE__ */ A("div", {
167
- className: "flex justify-between gap-4",
168
- children: [/* @__PURE__ */ k("dt", {
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__ */ k("dd", {
172
- className: "text-right text-text-primary",
245
+ }), /* @__PURE__ */ I("span", {
246
+ className: i("min-w-0 break-words", n ? "leading-relaxed" : "truncate"),
173
247
  children: t
174
248
  })]
175
- }) : null, P = ({ icon: e, value: t }) => /* @__PURE__ */ A("div", {
176
- className: "flex items-center gap-2 text-text-secondary",
177
- children: [/* @__PURE__ */ k("span", {
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__ */ A(O, { children: [/* @__PURE__ */ k(j, {
255
+ footer: /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ I(R, {
188
256
  variant: "outline",
189
257
  onClick: t,
190
- disabled: a.isPending,
258
+ disabled: i.isPending,
191
259
  children: "Cancel"
192
- }), /* @__PURE__ */ k(j, {
260
+ }), /* @__PURE__ */ I(R, {
193
261
  onClick: () => {
194
- h(null);
262
+ p(null);
195
263
  let n = o.split(",").map((e) => e.trim()).filter(Boolean);
196
- if (n.length === 0) return h("Add at least one party to search.");
197
- a.mutate({
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: u.trim() || null
268
+ findings: l.trim() || null
201
269
  }, {
202
270
  onSuccess: () => {
203
271
  r(), t();
204
272
  },
205
- onError: (e) => h(e instanceof Error ? e.message : "Failed.")
273
+ onError: (e) => p(e instanceof Error ? e.message : "Failed.")
206
274
  });
207
275
  },
208
- disabled: a.isPending,
209
- children: a.isPending ? "Running…" : "Record check"
276
+ disabled: i.isPending,
277
+ children: i.isPending ? "Running…" : "Record check"
210
278
  })] }),
211
- children: /* @__PURE__ */ A("div", {
279
+ children: /* @__PURE__ */ L("div", {
212
280
  className: "space-y-3",
213
281
  children: [
214
- f && /* @__PURE__ */ k(i, {
282
+ f && /* @__PURE__ */ I(a, {
215
283
  tone: "danger",
216
284
  children: f
217
285
  }),
218
- /* @__PURE__ */ k(s, {
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__ */ k(m, {
290
+ children: /* @__PURE__ */ I(_, {
223
291
  value: o,
224
- onChange: (e) => c(e.target.value),
292
+ onChange: (e) => s(e.target.value),
225
293
  placeholder: "Beta Corp, John Roe, Gamma LLP"
226
294
  })
227
295
  }),
228
- /* @__PURE__ */ k(s, {
296
+ /* @__PURE__ */ I(c, {
229
297
  label: "Findings",
230
- children: /* @__PURE__ */ k(p, {
231
- value: u,
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 { M as ClientDetailPage };
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":"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"}