@burdenoff/microfe-proserviceworld 2026.626.2 → 2026.706.1

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 (75) hide show
  1. package/dist/index.js +2 -3
  2. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  3. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  4. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  5. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  6. package/dist/proserviceworld/ProServiceWorldRoot.js +92 -136
  7. package/dist/proserviceworld/ProServiceWorldRoot.js.map +1 -1
  8. package/dist/proserviceworld/ProServiceWorldRoutes.js +18 -26
  9. package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
  10. package/dist/proserviceworld/components/ui.js +273 -0
  11. package/dist/proserviceworld/components/ui.js.map +1 -0
  12. package/dist/proserviceworld/hooks/useFiles.js +45 -0
  13. package/dist/proserviceworld/hooks/useFiles.js.map +1 -0
  14. package/dist/proserviceworld/hooks/useProServiceWorldApi.js +416 -0
  15. package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -0
  16. package/dist/proserviceworld/index.js +0 -1
  17. package/dist/proserviceworld/pages/AnalyticsPage.js +163 -475
  18. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  19. package/dist/proserviceworld/pages/ClientDetailPage.js +238 -0
  20. package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -0
  21. package/dist/proserviceworld/pages/ClientsPage.js +295 -0
  22. package/dist/proserviceworld/pages/ClientsPage.js.map +1 -0
  23. package/dist/proserviceworld/pages/CompliancePage.js +307 -0
  24. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -0
  25. package/dist/proserviceworld/pages/ConflictsPage.js +234 -0
  26. package/dist/proserviceworld/pages/ConflictsPage.js.map +1 -0
  27. package/dist/proserviceworld/pages/DashboardPage.js +179 -632
  28. package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
  29. package/dist/proserviceworld/pages/DocumentsPage.js +235 -539
  30. package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
  31. package/dist/proserviceworld/pages/EngagementDetailPage.js +444 -0
  32. package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -0
  33. package/dist/proserviceworld/pages/EngagementsPage.js +256 -0
  34. package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -0
  35. package/dist/proserviceworld/pages/InvoicesPage.js +303 -0
  36. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -0
  37. package/dist/proserviceworld/pages/MattersPage.js +275 -0
  38. package/dist/proserviceworld/pages/MattersPage.js.map +1 -0
  39. package/dist/proserviceworld/pages/PracticeAreasPage.js +176 -0
  40. package/dist/proserviceworld/pages/PracticeAreasPage.js.map +1 -0
  41. package/dist/proserviceworld/pages/TimePage.js +310 -0
  42. package/dist/proserviceworld/pages/TimePage.js.map +1 -0
  43. package/dist/proserviceworld/utils/cn.js +10 -0
  44. package/dist/proserviceworld/utils/cn.js.map +1 -0
  45. package/dist/proserviceworld/utils/nav.js +11 -0
  46. package/dist/proserviceworld/utils/nav.js.map +1 -0
  47. package/package.json +3 -2
  48. package/dist/proserviceworld/pages/AdminReportsPage.js +0 -579
  49. package/dist/proserviceworld/pages/AdminReportsPage.js.map +0 -1
  50. package/dist/proserviceworld/pages/AdminUsersPage.js +0 -468
  51. package/dist/proserviceworld/pages/AdminUsersPage.js.map +0 -1
  52. package/dist/proserviceworld/pages/BookingsPage.js +0 -446
  53. package/dist/proserviceworld/pages/BookingsPage.js.map +0 -1
  54. package/dist/proserviceworld/pages/MessagesPage.js +0 -238
  55. package/dist/proserviceworld/pages/MessagesPage.js.map +0 -1
  56. package/dist/proserviceworld/pages/PaymentsPage.js +0 -537
  57. package/dist/proserviceworld/pages/PaymentsPage.js.map +0 -1
  58. package/dist/proserviceworld/pages/ProjectsPage.js +0 -627
  59. package/dist/proserviceworld/pages/ProjectsPage.js.map +0 -1
  60. package/dist/proserviceworld/pages/ProviderDetailPage.js +0 -538
  61. package/dist/proserviceworld/pages/ProviderDetailPage.js.map +0 -1
  62. package/dist/proserviceworld/pages/ProvidersPage.js +0 -347
  63. package/dist/proserviceworld/pages/ProvidersPage.js.map +0 -1
  64. package/dist/proserviceworld/pages/ReviewsPage.js +0 -356
  65. package/dist/proserviceworld/pages/ReviewsPage.js.map +0 -1
  66. package/dist/proserviceworld/pages/ServiceDetailsPage.js +0 -631
  67. package/dist/proserviceworld/pages/ServiceDetailsPage.js.map +0 -1
  68. package/dist/proserviceworld/pages/ServicesPage.js +0 -344
  69. package/dist/proserviceworld/pages/ServicesPage.js.map +0 -1
  70. package/dist/proserviceworld/pages/VerificationPage.js +0 -370
  71. package/dist/proserviceworld/pages/VerificationPage.js.map +0 -1
  72. package/dist/proserviceworld/store/proserviceworldStore.js +0 -2490
  73. package/dist/proserviceworld/store/proserviceworldStore.js.map +0 -1
  74. package/dist/proserviceworld/utils/i18n.js +0 -15
  75. package/dist/proserviceworld/utils/i18n.js.map +0 -1
@@ -0,0 +1,295 @@
1
+ import { useArchiveClient as e, useClients as t, useCreateClient as n, useUpdateClient as r } from "../hooks/useProServiceWorldApi.js";
2
+ import { useNav as i } from "../utils/nav.js";
3
+ import { Banner as a, Empty as o, ErrorState as s, Field as c, LoadingBlock as l, Modal as u, NativeSelect as d, PageHeader as f, SectionCard as p, StatusPill as m, TableWrap as h, Td as g, TextArea as _, TextInput as v, Th as y, enumOptions as b, fmtDate as x } from "../components/ui.js";
4
+ import { useMemo as S, useState as C } from "react";
5
+ import { Archive as w, Pencil as T, Plus as E, Search as D, Users as O } from "lucide-react";
6
+ import { Fragment as k, jsx as A, jsxs as j } from "react/jsx-runtime";
7
+ import { Button as M } from "@burdenoff/fe-libs/ui";
8
+ //#region src/proserviceworld/pages/ClientsPage.tsx
9
+ var N = ["ORGANIZATION", "INDIVIDUAL"], P = [
10
+ "PROSPECT",
11
+ "ACTIVE",
12
+ "INACTIVE",
13
+ "ARCHIVED"
14
+ ], F = {
15
+ name: "",
16
+ type: "ORGANIZATION",
17
+ status: "PROSPECT",
18
+ industry: "",
19
+ contactName: "",
20
+ contactEmail: "",
21
+ contactPhone: "",
22
+ notes: ""
23
+ }, I = () => {
24
+ let e = i(), [n, r] = C(""), [c, u] = C(""), [_, S] = C(null), [w, k] = C(!1), [N, F] = C(null), { data: I, isLoading: z, error: B, refetch: V } = t({
25
+ search: n.trim() || void 0,
26
+ status: c || void 0
27
+ });
28
+ return /* @__PURE__ */ j("div", {
29
+ className: "space-y-6",
30
+ children: [
31
+ /* @__PURE__ */ A(f, {
32
+ title: "Clients",
33
+ subtitle: "Every person or organization your firm serves — the record engagements, matters, documents and invoices hang off.",
34
+ icon: /* @__PURE__ */ A(O, { className: "h-6 w-6" }),
35
+ actions: /* @__PURE__ */ j(M, {
36
+ onClick: () => k(!0),
37
+ children: [/* @__PURE__ */ A(E, { className: "mr-1.5 h-4 w-4" }), " New client"]
38
+ })
39
+ }),
40
+ N && /* @__PURE__ */ A(a, {
41
+ tone: N.tone,
42
+ onClose: () => F(null),
43
+ children: N.text
44
+ }),
45
+ /* @__PURE__ */ j("div", {
46
+ className: "flex flex-col gap-2 sm:flex-row sm:items-center",
47
+ children: [/* @__PURE__ */ j("div", {
48
+ className: "relative flex-1",
49
+ children: [/* @__PURE__ */ A(D, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ A(v, {
50
+ placeholder: "Search clients…",
51
+ value: n,
52
+ onChange: (e) => r(e.target.value),
53
+ className: "pl-9"
54
+ })]
55
+ }), /* @__PURE__ */ j(d, {
56
+ value: c,
57
+ onChange: (e) => u(e.target.value),
58
+ className: "sm:w-48",
59
+ children: [/* @__PURE__ */ A("option", {
60
+ value: "",
61
+ children: "All statuses"
62
+ }), b(P)]
63
+ })]
64
+ }),
65
+ z ? /* @__PURE__ */ A(l, {}) : B ? /* @__PURE__ */ A(s, {
66
+ error: B,
67
+ onRetry: () => void V()
68
+ }) : !I || I.items.length === 0 ? /* @__PURE__ */ A(o, {
69
+ title: "No clients yet",
70
+ description: "Add your first client to start scoping engagements and matters.",
71
+ icon: /* @__PURE__ */ A(O, { className: "h-8 w-8" }),
72
+ action: /* @__PURE__ */ j(M, {
73
+ onClick: () => k(!0),
74
+ children: [/* @__PURE__ */ A(E, { className: "mr-1.5 h-4 w-4" }), " New client"]
75
+ })
76
+ }) : /* @__PURE__ */ A(p, {
77
+ title: `${I.totalCount} client${I.totalCount === 1 ? "" : "s"}`,
78
+ children: /* @__PURE__ */ j(h, { children: [/* @__PURE__ */ A("thead", { children: /* @__PURE__ */ j("tr", { children: [
79
+ /* @__PURE__ */ A(y, { children: "Name" }),
80
+ /* @__PURE__ */ A(y, { children: "Type" }),
81
+ /* @__PURE__ */ A(y, { children: "Industry" }),
82
+ /* @__PURE__ */ A(y, { children: "Status" }),
83
+ /* @__PURE__ */ A(y, { children: "Added" }),
84
+ /* @__PURE__ */ A(y, {
85
+ className: "text-right",
86
+ children: "Actions"
87
+ })
88
+ ] }) }), /* @__PURE__ */ A("tbody", { children: I.items.map((t) => /* @__PURE__ */ j("tr", {
89
+ className: "hover:bg-bg-sunken/50",
90
+ children: [
91
+ /* @__PURE__ */ j(g, { children: [/* @__PURE__ */ A("button", {
92
+ type: "button",
93
+ className: "text-left font-medium text-text-primary hover:text-accent",
94
+ onClick: () => e(`clients/${t.id}`),
95
+ children: t.name
96
+ }), t.contactName ? /* @__PURE__ */ A("div", {
97
+ className: "text-xs text-text-tertiary",
98
+ children: t.contactName
99
+ }) : null] }),
100
+ /* @__PURE__ */ A(g, { children: t.type === "ORGANIZATION" ? "Organization" : "Individual" }),
101
+ /* @__PURE__ */ A(g, { children: t.industry || "—" }),
102
+ /* @__PURE__ */ A(g, { children: /* @__PURE__ */ A(m, { status: t.status }) }),
103
+ /* @__PURE__ */ A(g, { children: x(t.createdAt) }),
104
+ /* @__PURE__ */ A(g, {
105
+ className: "text-right",
106
+ children: /* @__PURE__ */ j("div", {
107
+ className: "flex justify-end gap-1",
108
+ children: [/* @__PURE__ */ A(M, {
109
+ variant: "ghost",
110
+ size: "sm",
111
+ onClick: () => S(t),
112
+ "aria-label": "Edit",
113
+ children: /* @__PURE__ */ A(T, { className: "h-4 w-4" })
114
+ }), t.status !== "ARCHIVED" && /* @__PURE__ */ A(L, {
115
+ id: t.id,
116
+ onDone: (e) => F(e ? {
117
+ tone: "success",
118
+ text: `${t.name} archived.`
119
+ } : {
120
+ tone: "danger",
121
+ text: "Could not archive client."
122
+ })
123
+ })]
124
+ })
125
+ })
126
+ ]
127
+ }, t.id)) })] })
128
+ }),
129
+ w && /* @__PURE__ */ A(R, {
130
+ onClose: () => k(!1),
131
+ onSaved: (e) => F({
132
+ tone: "success",
133
+ text: `${e} created.`
134
+ })
135
+ }),
136
+ _ && /* @__PURE__ */ A(R, {
137
+ client: _,
138
+ onClose: () => S(null),
139
+ onSaved: (e) => F({
140
+ tone: "success",
141
+ text: `${e} updated.`
142
+ })
143
+ })
144
+ ]
145
+ });
146
+ }, L = ({ id: t, onDone: n }) => {
147
+ let r = e();
148
+ return /* @__PURE__ */ A(M, {
149
+ variant: "ghost",
150
+ size: "sm",
151
+ "aria-label": "Archive",
152
+ disabled: r.isPending,
153
+ onClick: () => {
154
+ window.confirm("Archive this client? Their engagements and matters remain.") && r.mutate(t, {
155
+ onSuccess: (e) => n(!!e),
156
+ onError: () => n(!1)
157
+ });
158
+ },
159
+ children: /* @__PURE__ */ A(w, { className: "h-4 w-4" })
160
+ });
161
+ }, R = ({ client: e, onClose: t, onSaved: i }) => {
162
+ let o = n(), s = r(), [l, f] = C(e ? {
163
+ name: e.name,
164
+ type: e.type,
165
+ status: e.status,
166
+ industry: e.industry ?? "",
167
+ contactName: e.contactName ?? "",
168
+ contactEmail: e.contactEmail ?? "",
169
+ contactPhone: e.contactPhone ?? "",
170
+ notes: e.notes ?? ""
171
+ } : F), [p, m] = C(null), h = (e) => (t) => f((n) => ({
172
+ ...n,
173
+ [e]: t.target.value
174
+ })), g = o.isPending || s.isPending, y = S(() => ({
175
+ name: l.name.trim(),
176
+ type: l.type,
177
+ status: l.status,
178
+ industry: l.industry.trim() || null,
179
+ contactName: l.contactName.trim() || null,
180
+ contactEmail: l.contactEmail.trim() || null,
181
+ contactPhone: l.contactPhone.trim() || null,
182
+ notes: l.notes.trim() || null
183
+ }), [l]);
184
+ return /* @__PURE__ */ A(u, {
185
+ open: !0,
186
+ onClose: t,
187
+ title: e ? "Edit client" : "New client",
188
+ footer: /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(M, {
189
+ variant: "outline",
190
+ onClick: t,
191
+ disabled: g,
192
+ children: "Cancel"
193
+ }), /* @__PURE__ */ A(M, {
194
+ onClick: () => {
195
+ if (m(null), !y.name) return m("Client name is required.");
196
+ let n = (e) => m(e instanceof Error ? e.message : "Save failed.");
197
+ e ? s.mutate({
198
+ id: e.id,
199
+ input: y
200
+ }, {
201
+ onSuccess: () => {
202
+ i(y.name), t();
203
+ },
204
+ onError: n
205
+ }) : o.mutate(y, {
206
+ onSuccess: () => {
207
+ i(y.name), t();
208
+ },
209
+ onError: n
210
+ });
211
+ },
212
+ disabled: g,
213
+ children: g ? "Saving…" : e ? "Save changes" : "Create client"
214
+ })] }),
215
+ children: /* @__PURE__ */ j("div", {
216
+ className: "space-y-3",
217
+ children: [
218
+ p && /* @__PURE__ */ A(a, {
219
+ tone: "danger",
220
+ children: p
221
+ }),
222
+ /* @__PURE__ */ A(c, {
223
+ label: "Name",
224
+ required: !0,
225
+ children: /* @__PURE__ */ A(v, {
226
+ value: l.name,
227
+ onChange: h("name"),
228
+ placeholder: "Acme Holdings Ltd."
229
+ })
230
+ }),
231
+ /* @__PURE__ */ j("div", {
232
+ className: "grid grid-cols-2 gap-3",
233
+ children: [/* @__PURE__ */ A(c, {
234
+ label: "Type",
235
+ children: /* @__PURE__ */ A(d, {
236
+ value: l.type,
237
+ onChange: h("type"),
238
+ children: b(N)
239
+ })
240
+ }), /* @__PURE__ */ A(c, {
241
+ label: "Status",
242
+ children: /* @__PURE__ */ A(d, {
243
+ value: l.status,
244
+ onChange: h("status"),
245
+ children: b(P)
246
+ })
247
+ })]
248
+ }),
249
+ /* @__PURE__ */ A(c, {
250
+ label: "Industry",
251
+ children: /* @__PURE__ */ A(v, {
252
+ value: l.industry,
253
+ onChange: h("industry"),
254
+ placeholder: "Financial services"
255
+ })
256
+ }),
257
+ /* @__PURE__ */ j("div", {
258
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
259
+ children: [/* @__PURE__ */ A(c, {
260
+ label: "Contact name",
261
+ children: /* @__PURE__ */ A(v, {
262
+ value: l.contactName,
263
+ onChange: h("contactName")
264
+ })
265
+ }), /* @__PURE__ */ A(c, {
266
+ label: "Contact email",
267
+ children: /* @__PURE__ */ A(v, {
268
+ type: "email",
269
+ value: l.contactEmail,
270
+ onChange: h("contactEmail")
271
+ })
272
+ })]
273
+ }),
274
+ /* @__PURE__ */ A(c, {
275
+ label: "Contact phone",
276
+ children: /* @__PURE__ */ A(v, {
277
+ value: l.contactPhone,
278
+ onChange: h("contactPhone")
279
+ })
280
+ }),
281
+ /* @__PURE__ */ A(c, {
282
+ label: "Notes",
283
+ children: /* @__PURE__ */ A(_, {
284
+ value: l.notes,
285
+ onChange: h("notes")
286
+ })
287
+ })
288
+ ]
289
+ })
290
+ });
291
+ };
292
+ //#endregion
293
+ export { I as ClientsPage };
294
+
295
+ //# sourceMappingURL=ClientsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClientsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/ClientsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Plus, Search, Users, Pencil, Archive } from 'lucide-react';\nimport {\n useClients,\n useCreateClient,\n useUpdateClient,\n useArchiveClient,\n type PswClient,\n type PswClientStatus,\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 NativeSelect,\n Banner,\n TableWrap,\n Th,\n Td,\n enumOptions,\n fmtDate,\n} from '../components/ui';\n\nconst CLIENT_TYPES = ['ORGANIZATION', 'INDIVIDUAL'] as const;\nconst CLIENT_STATUSES: PswClientStatus[] = ['PROSPECT', 'ACTIVE', 'INACTIVE', 'ARCHIVED'];\n\ninterface FormState {\n name: string;\n type: string;\n status: string;\n industry: string;\n contactName: string;\n contactEmail: string;\n contactPhone: string;\n notes: string;\n}\nconst emptyForm: FormState = {\n name: '',\n type: 'ORGANIZATION',\n status: 'PROSPECT',\n industry: '',\n contactName: '',\n contactEmail: '',\n contactPhone: '',\n notes: '',\n};\n\nexport const ClientsPage: FC = () => {\n const nav = useNav();\n const [search, setSearch] = useState('');\n const [statusFilter, setStatusFilter] = useState<PswClientStatus | ''>('');\n const [editing, setEditing] = useState<PswClient | null>(null);\n const [creating, setCreating] = useState(false);\n const [banner, setBanner] = useState<{ tone: 'success' | 'danger'; text: string } | null>(null);\n\n const { data, isLoading, error, refetch } = useClients({\n search: search.trim() || undefined,\n status: statusFilter || undefined,\n });\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Clients\"\n subtitle=\"Every person or organization your firm serves — the record engagements, matters, documents and invoices hang off.\"\n icon={<Users className=\"h-6 w-6\" />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New client\n </Button>\n }\n />\n\n {banner && (\n <Banner tone={banner.tone} onClose={() => setBanner(null)}>\n {banner.text}\n </Banner>\n )}\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary\" />\n <TextInput\n placeholder=\"Search clients…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <NativeSelect\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value as PswClientStatus | '')}\n className=\"sm:w-48\"\n >\n <option value=\"\">All statuses</option>\n {enumOptions(CLIENT_STATUSES)}\n </NativeSelect>\n </div>\n\n {isLoading ? (\n <LoadingBlock />\n ) : error ? (\n <ErrorState error={error} onRetry={() => void refetch()} />\n ) : !data || data.items.length === 0 ? (\n <Empty\n title=\"No clients yet\"\n description=\"Add your first client to start scoping engagements and matters.\"\n icon={<Users className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> New client\n </Button>\n }\n />\n ) : (\n <SectionCard title={`${data.totalCount} client${data.totalCount === 1 ? '' : 's'}`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Name</Th>\n <Th>Type</Th>\n <Th>Industry</Th>\n <Th>Status</Th>\n <Th>Added</Th>\n <Th className=\"text-right\">Actions</Th>\n </tr>\n </thead>\n <tbody>\n {data.items.map((c) => (\n <tr key={c.id} className=\"hover:bg-bg-sunken/50\">\n <Td>\n <button\n type=\"button\"\n className=\"text-left font-medium text-text-primary hover:text-accent\"\n onClick={() => nav(`clients/${c.id}`)}\n >\n {c.name}\n </button>\n {c.contactName ? (\n <div className=\"text-xs text-text-tertiary\">{c.contactName}</div>\n ) : null}\n </Td>\n <Td>{c.type === 'ORGANIZATION' ? 'Organization' : 'Individual'}</Td>\n <Td>{c.industry || '—'}</Td>\n <Td>\n <StatusPill status={c.status} />\n </Td>\n <Td>{fmtDate(c.createdAt)}</Td>\n <Td className=\"text-right\">\n <div className=\"flex justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setEditing(c)}\n aria-label=\"Edit\"\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n {c.status !== 'ARCHIVED' && (\n <ArchiveButton\n id={c.id}\n onDone={(ok) =>\n setBanner(\n ok\n ? { tone: 'success', text: `${c.name} archived.` }\n : { tone: 'danger', text: 'Could not archive client.' }\n )\n }\n />\n )}\n </div>\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n </SectionCard>\n )}\n\n {creating && (\n <ClientModal\n onClose={() => setCreating(false)}\n onSaved={(name) => setBanner({ tone: 'success', text: `${name} created.` })}\n />\n )}\n {editing && (\n <ClientModal\n client={editing}\n onClose={() => setEditing(null)}\n onSaved={(name) => setBanner({ tone: 'success', text: `${name} updated.` })}\n />\n )}\n </div>\n );\n};\n\nconst ArchiveButton: FC<{ id: string; onDone: (ok: boolean) => void }> = ({ id, onDone }) => {\n const archive = useArchiveClient();\n return (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Archive\"\n disabled={archive.isPending}\n onClick={() => {\n if (!window.confirm('Archive this client? Their engagements and matters remain.')) return;\n archive.mutate(id, { onSuccess: (r) => onDone(Boolean(r)), onError: () => onDone(false) });\n }}\n >\n <Archive className=\"h-4 w-4\" />\n </Button>\n );\n};\n\nconst ClientModal: FC<{\n client?: PswClient;\n onClose: () => void;\n onSaved: (name: string) => void;\n}> = ({ client, onClose, onSaved }) => {\n const create = useCreateClient();\n const update = useUpdateClient();\n const [form, setForm] = useState<FormState>(\n client\n ? {\n name: client.name,\n type: client.type,\n status: client.status,\n industry: client.industry ?? '',\n contactName: client.contactName ?? '',\n contactEmail: client.contactEmail ?? '',\n contactPhone: client.contactPhone ?? '',\n notes: client.notes ?? '',\n }\n : emptyForm\n );\n const [err, setErr] = useState<string | null>(null);\n const set = (k: keyof FormState) => (e: { target: { value: string } }) =>\n setForm((f) => ({ ...f, [k]: e.target.value }));\n const pending = create.isPending || update.isPending;\n\n const payload = useMemo(\n () => ({\n name: form.name.trim(),\n type: form.type,\n status: form.status,\n industry: form.industry.trim() || null,\n contactName: form.contactName.trim() || null,\n contactEmail: form.contactEmail.trim() || null,\n contactPhone: form.contactPhone.trim() || null,\n notes: form.notes.trim() || null,\n }),\n [form]\n );\n\n const submit = () => {\n setErr(null);\n if (!payload.name) return setErr('Client name is required.');\n const onError = (e: unknown) => setErr(e instanceof Error ? e.message : 'Save failed.');\n if (client) {\n update.mutate(\n { id: client.id, input: payload },\n {\n onSuccess: () => {\n onSaved(payload.name);\n onClose();\n },\n onError,\n }\n );\n } else {\n create.mutate(payload, {\n onSuccess: () => {\n onSaved(payload.name);\n onClose();\n },\n onError,\n });\n }\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title={client ? 'Edit client' : 'New client'}\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={pending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={pending}>\n {pending ? 'Saving…' : client ? 'Save changes' : 'Create client'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Name\" required>\n <TextInput value={form.name} onChange={set('name')} placeholder=\"Acme Holdings Ltd.\" />\n </Field>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Type\">\n <NativeSelect value={form.type} onChange={set('type')}>\n {enumOptions(CLIENT_TYPES)}\n </NativeSelect>\n </Field>\n <Field label=\"Status\">\n <NativeSelect value={form.status} onChange={set('status')}>\n {enumOptions(CLIENT_STATUSES)}\n </NativeSelect>\n </Field>\n </div>\n <Field label=\"Industry\">\n <TextInput\n value={form.industry}\n onChange={set('industry')}\n placeholder=\"Financial services\"\n />\n </Field>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <Field label=\"Contact name\">\n <TextInput value={form.contactName} onChange={set('contactName')} />\n </Field>\n <Field label=\"Contact email\">\n <TextInput type=\"email\" value={form.contactEmail} onChange={set('contactEmail')} />\n </Field>\n </div>\n <Field label=\"Contact phone\">\n <TextInput value={form.contactPhone} onChange={set('contactPhone')} />\n </Field>\n <Field label=\"Notes\">\n <TextArea value={form.notes} onChange={set('notes')} />\n </Field>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,307 @@
1
+ import { useClients as e, useComplianceChecks as t, useCreateComplianceCheck as n, useEngagements as r, useMatters as i, useResolveComplianceCheck as a } from "../hooks/useProServiceWorldApi.js";
2
+ import { Banner as o, Empty as s, ErrorState as c, Field as l, LoadingBlock as u, Modal as d, NativeSelect as f, PageHeader as p, SectionCard as m, StatusPill as h, TableWrap as g, Td as _, TextArea as v, TextInput as y, Th as b, enumOptions as x, fmtDate as S, humanize as C } from "../components/ui.js";
3
+ import { useState as w } from "react";
4
+ import { Plus as T, ShieldCheck as E } from "lucide-react";
5
+ import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
6
+ import { Button as A } from "@burdenoff/fe-libs/ui";
7
+ //#region src/proserviceworld/pages/CompliancePage.tsx
8
+ var j = [
9
+ "ENGAGEMENT_ACCEPTANCE",
10
+ "INDEPENDENCE",
11
+ "LICENSING",
12
+ "CONTINUING_EDUCATION",
13
+ "DATA_RETENTION",
14
+ "LEGAL_HOLD"
15
+ ], M = [
16
+ "IN_REVIEW",
17
+ "PASSED",
18
+ "FAILED",
19
+ "WAIVED"
20
+ ], N = [
21
+ "CLIENT",
22
+ "ENGAGEMENT",
23
+ "MATTER"
24
+ ], P = () => {
25
+ let [e, n] = w(""), [r, i] = w(!1), [a, l] = w(null), [d, v] = w(null), { data: y, isLoading: D, error: j, refetch: M } = t({ status: e || void 0 });
26
+ return /* @__PURE__ */ k("div", {
27
+ className: "space-y-6",
28
+ children: [
29
+ /* @__PURE__ */ O(p, {
30
+ title: "Compliance",
31
+ subtitle: "The duties that travel with the work — acceptance, independence, licensing, CE, retention and legal hold — as gates, not afterthoughts.",
32
+ icon: /* @__PURE__ */ O(E, { className: "h-6 w-6" }),
33
+ actions: /* @__PURE__ */ k(A, {
34
+ onClick: () => i(!0),
35
+ children: [/* @__PURE__ */ O(T, { className: "mr-1.5 h-4 w-4" }), "New check"]
36
+ })
37
+ }),
38
+ d && /* @__PURE__ */ O(o, {
39
+ tone: "success",
40
+ onClose: () => v(null),
41
+ children: d
42
+ }),
43
+ /* @__PURE__ */ O("div", {
44
+ className: "flex justify-end",
45
+ children: /* @__PURE__ */ k(f, {
46
+ value: e,
47
+ onChange: (e) => n(e.target.value),
48
+ className: "sm:w-52",
49
+ children: [/* @__PURE__ */ O("option", {
50
+ value: "",
51
+ children: "All statuses"
52
+ }), x([
53
+ "PENDING",
54
+ "IN_REVIEW",
55
+ "PASSED",
56
+ "FAILED",
57
+ "WAIVED"
58
+ ])]
59
+ })
60
+ }),
61
+ D ? /* @__PURE__ */ O(u, {}) : j ? /* @__PURE__ */ O(c, {
62
+ error: j,
63
+ onRetry: () => void M()
64
+ }) : !y || y.length === 0 ? /* @__PURE__ */ O(s, {
65
+ title: "No compliance checks",
66
+ description: "Raise a check to gate acceptance or track a professional obligation.",
67
+ icon: /* @__PURE__ */ O(E, { className: "h-8 w-8" }),
68
+ action: /* @__PURE__ */ k(A, {
69
+ onClick: () => i(!0),
70
+ children: [/* @__PURE__ */ O(T, { className: "mr-1.5 h-4 w-4" }), "New check"]
71
+ })
72
+ }) : /* @__PURE__ */ O(m, {
73
+ title: `${y.length} check${y.length === 1 ? "" : "s"}`,
74
+ children: /* @__PURE__ */ k(g, { children: [/* @__PURE__ */ O("thead", { children: /* @__PURE__ */ k("tr", { children: [
75
+ /* @__PURE__ */ O(b, { children: "Title" }),
76
+ /* @__PURE__ */ O(b, { children: "Type" }),
77
+ /* @__PURE__ */ O(b, { children: "Subject" }),
78
+ /* @__PURE__ */ O(b, { children: "Due" }),
79
+ /* @__PURE__ */ O(b, { children: "Status" }),
80
+ /* @__PURE__ */ O(b, {
81
+ className: "text-right",
82
+ children: "Actions"
83
+ })
84
+ ] }) }), /* @__PURE__ */ O("tbody", { children: y.map((e) => /* @__PURE__ */ k("tr", {
85
+ className: "hover:bg-bg-sunken/50",
86
+ children: [
87
+ /* @__PURE__ */ O(_, { children: /* @__PURE__ */ O("span", {
88
+ className: "font-medium text-text-primary",
89
+ children: e.title
90
+ }) }),
91
+ /* @__PURE__ */ O(_, { children: C(e.type) }),
92
+ /* @__PURE__ */ O(_, { children: C(e.subjectType) }),
93
+ /* @__PURE__ */ O(_, { children: S(e.dueDate) }),
94
+ /* @__PURE__ */ O(_, { children: /* @__PURE__ */ O(h, { status: e.status }) }),
95
+ /* @__PURE__ */ O(_, {
96
+ className: "text-right",
97
+ children: e.status === "PENDING" || e.status === "IN_REVIEW" ? /* @__PURE__ */ O(A, {
98
+ variant: "ghost",
99
+ size: "sm",
100
+ onClick: () => l({
101
+ id: e.id,
102
+ title: e.title
103
+ }),
104
+ children: "Resolve"
105
+ }) : /* @__PURE__ */ O("span", {
106
+ className: "text-xs text-text-tertiary",
107
+ children: e.resolvedAt ? S(e.resolvedAt) : ""
108
+ })
109
+ })
110
+ ]
111
+ }, e.id)) })] })
112
+ }),
113
+ r && /* @__PURE__ */ O(F, {
114
+ onClose: () => i(!1),
115
+ onDone: () => {
116
+ M(), v("Compliance check created.");
117
+ }
118
+ }),
119
+ a && /* @__PURE__ */ O(I, {
120
+ check: a,
121
+ onClose: () => l(null),
122
+ onDone: () => {
123
+ M(), v("Compliance check resolved.");
124
+ }
125
+ })
126
+ ]
127
+ });
128
+ }, F = ({ onClose: t, onDone: a }) => {
129
+ let s = n(), [c, u] = w({
130
+ type: "ENGAGEMENT_ACCEPTANCE",
131
+ subjectType: "ENGAGEMENT",
132
+ subjectId: "",
133
+ title: "",
134
+ dueDate: "",
135
+ details: ""
136
+ }), [p, m] = w(null), h = (e) => (t) => u((n) => ({
137
+ ...n,
138
+ [e]: t.target.value
139
+ })), g = e({ pagination: { limit: 100 } }), _ = r({ pagination: { limit: 100 } }), b = i({ pagination: { limit: 100 } }), S = c.subjectType === "CLIENT" ? (g.data?.items ?? []).map((e) => ({
140
+ id: e.id,
141
+ label: e.name
142
+ })) : c.subjectType === "ENGAGEMENT" ? (_.data?.items ?? []).map((e) => ({
143
+ id: e.id,
144
+ label: e.name
145
+ })) : (b.data?.items ?? []).map((e) => ({
146
+ id: e.id,
147
+ label: e.title
148
+ }));
149
+ return /* @__PURE__ */ O(d, {
150
+ open: !0,
151
+ onClose: t,
152
+ title: "New compliance check",
153
+ footer: /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ O(A, {
154
+ variant: "outline",
155
+ onClick: t,
156
+ disabled: s.isPending,
157
+ children: "Cancel"
158
+ }), /* @__PURE__ */ O(A, {
159
+ onClick: () => {
160
+ if (m(null), !c.title.trim()) return m("Title is required.");
161
+ if (!c.subjectId) return m("Select a subject.");
162
+ s.mutate({
163
+ type: c.type,
164
+ subjectType: c.subjectType,
165
+ subjectId: c.subjectId,
166
+ title: c.title.trim(),
167
+ dueDate: c.dueDate ? new Date(c.dueDate).toISOString() : null,
168
+ details: c.details.trim() || null
169
+ }, {
170
+ onSuccess: () => {
171
+ a(), t();
172
+ },
173
+ onError: (e) => m(e instanceof Error ? e.message : "Failed.")
174
+ });
175
+ },
176
+ disabled: s.isPending,
177
+ children: s.isPending ? "Creating…" : "Create check"
178
+ })] }),
179
+ children: /* @__PURE__ */ k("div", {
180
+ className: "space-y-3",
181
+ children: [
182
+ p && /* @__PURE__ */ O(o, {
183
+ tone: "danger",
184
+ children: p
185
+ }),
186
+ /* @__PURE__ */ O(l, {
187
+ label: "Title",
188
+ required: !0,
189
+ children: /* @__PURE__ */ O(y, {
190
+ value: c.title,
191
+ onChange: h("title"),
192
+ placeholder: "Independence confirmation — FY26 audit"
193
+ })
194
+ }),
195
+ /* @__PURE__ */ O(l, {
196
+ label: "Type",
197
+ children: /* @__PURE__ */ O(f, {
198
+ value: c.type,
199
+ onChange: h("type"),
200
+ children: x(j)
201
+ })
202
+ }),
203
+ /* @__PURE__ */ k("div", {
204
+ className: "grid grid-cols-2 gap-3",
205
+ children: [/* @__PURE__ */ O(l, {
206
+ label: "Subject type",
207
+ children: /* @__PURE__ */ O(f, {
208
+ value: c.subjectType,
209
+ onChange: (e) => u((t) => ({
210
+ ...t,
211
+ subjectType: e.target.value,
212
+ subjectId: ""
213
+ })),
214
+ children: x(N)
215
+ })
216
+ }), /* @__PURE__ */ O(l, {
217
+ label: "Subject",
218
+ required: !0,
219
+ children: /* @__PURE__ */ k(f, {
220
+ value: c.subjectId,
221
+ onChange: h("subjectId"),
222
+ children: [/* @__PURE__ */ O("option", {
223
+ value: "",
224
+ children: "Select…"
225
+ }), S.map((e) => /* @__PURE__ */ O("option", {
226
+ value: e.id,
227
+ children: e.label
228
+ }, e.id))]
229
+ })
230
+ })]
231
+ }),
232
+ /* @__PURE__ */ O(l, {
233
+ label: "Due date",
234
+ children: /* @__PURE__ */ O(y, {
235
+ type: "date",
236
+ value: c.dueDate,
237
+ onChange: h("dueDate")
238
+ })
239
+ }),
240
+ /* @__PURE__ */ O(l, {
241
+ label: "Details",
242
+ children: /* @__PURE__ */ O(v, {
243
+ value: c.details,
244
+ onChange: h("details")
245
+ })
246
+ })
247
+ ]
248
+ })
249
+ });
250
+ }, I = ({ check: e, onClose: t, onDone: n }) => {
251
+ let r = a(), [i, s] = w("PASSED"), [c, u] = w(""), [p, m] = w(null);
252
+ return /* @__PURE__ */ O(d, {
253
+ open: !0,
254
+ onClose: t,
255
+ title: `Resolve: ${e.title}`,
256
+ footer: /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ O(A, {
257
+ variant: "outline",
258
+ onClick: t,
259
+ disabled: r.isPending,
260
+ children: "Cancel"
261
+ }), /* @__PURE__ */ O(A, {
262
+ onClick: () => r.mutate({
263
+ id: e.id,
264
+ status: i,
265
+ details: c.trim() || void 0
266
+ }, {
267
+ onSuccess: () => {
268
+ n(), t();
269
+ },
270
+ onError: (e) => m(e instanceof Error ? e.message : "Failed.")
271
+ }),
272
+ disabled: r.isPending,
273
+ children: r.isPending ? "Saving…" : "Resolve"
274
+ })] }),
275
+ children: /* @__PURE__ */ k("div", {
276
+ className: "space-y-3",
277
+ children: [
278
+ p && /* @__PURE__ */ O(o, {
279
+ tone: "danger",
280
+ children: p
281
+ }),
282
+ /* @__PURE__ */ O(l, {
283
+ label: "Outcome",
284
+ children: /* @__PURE__ */ O(f, {
285
+ value: i,
286
+ onChange: (e) => s(e.target.value),
287
+ children: M.map((e) => /* @__PURE__ */ O("option", {
288
+ value: e,
289
+ children: C(e)
290
+ }, e))
291
+ })
292
+ }),
293
+ /* @__PURE__ */ O(l, {
294
+ label: "Notes",
295
+ children: /* @__PURE__ */ O(v, {
296
+ value: c,
297
+ onChange: (e) => u(e.target.value)
298
+ })
299
+ })
300
+ ]
301
+ })
302
+ });
303
+ };
304
+ //#endregion
305
+ export { P as CompliancePage };
306
+
307
+ //# sourceMappingURL=CompliancePage.js.map