@burdenoff/microfe-proserviceworld 2026.706.2 → 2026.709.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 (108) hide show
  1. package/dist/dev/main.d.ts +2 -0
  2. package/dist/dev/main.d.ts.map +1 -0
  3. package/dist/generated/global-operations.d.ts +2 -0
  4. package/dist/generated/global-operations.d.ts.map +1 -0
  5. package/dist/generated/global-types.d.ts +18199 -0
  6. package/dist/generated/global-types.d.ts.map +1 -0
  7. package/dist/generated/wspace-operations.d.ts +2 -0
  8. package/dist/generated/wspace-operations.d.ts.map +1 -0
  9. package/dist/generated/wspace-types.d.ts +43046 -0
  10. package/dist/generated/wspace-types.d.ts.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +2 -1
  14. package/dist/proserviceworld/ProServiceWorldRoot.d.ts +5 -0
  15. package/dist/proserviceworld/ProServiceWorldRoot.d.ts.map +1 -0
  16. package/dist/proserviceworld/ProServiceWorldRoutes.d.ts +2 -0
  17. package/dist/proserviceworld/ProServiceWorldRoutes.d.ts.map +1 -0
  18. package/dist/proserviceworld/components/DiscussionThread.d.ts +12 -0
  19. package/dist/proserviceworld/components/DiscussionThread.d.ts.map +1 -0
  20. package/dist/proserviceworld/components/DiscussionThread.js +1 -1
  21. package/dist/proserviceworld/components/DiscussionThread.js.map +1 -1
  22. package/dist/proserviceworld/components/ui.d.ts +82 -0
  23. package/dist/proserviceworld/components/ui.d.ts.map +1 -0
  24. package/dist/proserviceworld/components/ui.js +18 -18
  25. package/dist/proserviceworld/components/ui.js.map +1 -1
  26. package/dist/proserviceworld/hooks/useAnalytics.d.ts +18 -0
  27. package/dist/proserviceworld/hooks/useAnalytics.d.ts.map +1 -0
  28. package/dist/proserviceworld/hooks/useAnalytics.js +21 -0
  29. package/dist/proserviceworld/hooks/useAnalytics.js.map +1 -0
  30. package/dist/proserviceworld/hooks/useEntityComments.d.ts +27 -0
  31. package/dist/proserviceworld/hooks/useEntityComments.d.ts.map +1 -0
  32. package/dist/proserviceworld/hooks/useEntityComments.js.map +1 -1
  33. package/dist/proserviceworld/hooks/useFiles.d.ts +23 -0
  34. package/dist/proserviceworld/hooks/useFiles.d.ts.map +1 -0
  35. package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts +351 -0
  36. package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts.map +1 -0
  37. package/dist/proserviceworld/index.d.ts +5 -0
  38. package/dist/proserviceworld/index.d.ts.map +1 -0
  39. package/dist/proserviceworld/index.js +1 -0
  40. package/dist/proserviceworld/pages/AnalyticsPage.d.ts +4 -0
  41. package/dist/proserviceworld/pages/AnalyticsPage.d.ts.map +1 -0
  42. package/dist/proserviceworld/pages/AnalyticsPage.js +277 -111
  43. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  44. package/dist/proserviceworld/pages/ClientDetailPage.d.ts +4 -0
  45. package/dist/proserviceworld/pages/ClientDetailPage.d.ts.map +1 -0
  46. package/dist/proserviceworld/pages/ClientDetailPage.js +219 -151
  47. package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -1
  48. package/dist/proserviceworld/pages/ClientsPage.d.ts +9 -0
  49. package/dist/proserviceworld/pages/ClientsPage.d.ts.map +1 -0
  50. package/dist/proserviceworld/pages/ClientsPage.js +180 -148
  51. package/dist/proserviceworld/pages/ClientsPage.js.map +1 -1
  52. package/dist/proserviceworld/pages/CompliancePage.d.ts +4 -0
  53. package/dist/proserviceworld/pages/CompliancePage.d.ts.map +1 -0
  54. package/dist/proserviceworld/pages/CompliancePage.js +140 -96
  55. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -1
  56. package/dist/proserviceworld/pages/ConflictsPage.d.ts +4 -0
  57. package/dist/proserviceworld/pages/ConflictsPage.d.ts.map +1 -0
  58. package/dist/proserviceworld/pages/DashboardPage.d.ts +4 -0
  59. package/dist/proserviceworld/pages/DashboardPage.d.ts.map +1 -0
  60. package/dist/proserviceworld/pages/DashboardPage.js +221 -104
  61. package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
  62. package/dist/proserviceworld/pages/DocumentsPage.d.ts +4 -0
  63. package/dist/proserviceworld/pages/DocumentsPage.d.ts.map +1 -0
  64. package/dist/proserviceworld/pages/EngagementDetailPage.d.ts +4 -0
  65. package/dist/proserviceworld/pages/EngagementDetailPage.d.ts.map +1 -0
  66. package/dist/proserviceworld/pages/EngagementDetailPage.js +233 -197
  67. package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -1
  68. package/dist/proserviceworld/pages/EngagementsPage.d.ts +4 -0
  69. package/dist/proserviceworld/pages/EngagementsPage.d.ts.map +1 -0
  70. package/dist/proserviceworld/pages/EngagementsPage.js +187 -136
  71. package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -1
  72. package/dist/proserviceworld/pages/InvoicesPage.d.ts +4 -0
  73. package/dist/proserviceworld/pages/InvoicesPage.d.ts.map +1 -0
  74. package/dist/proserviceworld/pages/InvoicesPage.js +144 -129
  75. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
  76. package/dist/proserviceworld/pages/MattersPage.d.ts +4 -0
  77. package/dist/proserviceworld/pages/MattersPage.d.ts.map +1 -0
  78. package/dist/proserviceworld/pages/MattersPage.js +198 -142
  79. package/dist/proserviceworld/pages/MattersPage.js.map +1 -1
  80. package/dist/proserviceworld/pages/PracticeAreasPage.d.ts +4 -0
  81. package/dist/proserviceworld/pages/PracticeAreasPage.d.ts.map +1 -0
  82. package/dist/proserviceworld/pages/TimePage.d.ts +4 -0
  83. package/dist/proserviceworld/pages/TimePage.d.ts.map +1 -0
  84. package/dist/proserviceworld/pages/TimePage.js +112 -92
  85. package/dist/proserviceworld/pages/TimePage.js.map +1 -1
  86. package/dist/proserviceworld/providers/ProServiceWorldProvider.d.ts +6 -0
  87. package/dist/proserviceworld/providers/ProServiceWorldProvider.d.ts.map +1 -0
  88. package/dist/proserviceworld/services/assistantApi.d.ts +74 -0
  89. package/dist/proserviceworld/services/assistantApi.d.ts.map +1 -0
  90. package/dist/proserviceworld/services/assistantApi.js +203 -0
  91. package/dist/proserviceworld/services/assistantApi.js.map +1 -0
  92. package/dist/proserviceworld/services/createSandboxAssistantTransport.d.ts +28 -0
  93. package/dist/proserviceworld/services/createSandboxAssistantTransport.d.ts.map +1 -0
  94. package/dist/proserviceworld/services/createSandboxAssistantTransport.js +120 -0
  95. package/dist/proserviceworld/services/createSandboxAssistantTransport.js.map +1 -0
  96. package/dist/proserviceworld/types/index.d.ts +57 -0
  97. package/dist/proserviceworld/types/index.d.ts.map +1 -0
  98. package/dist/proserviceworld/utils/cn.d.ts +4 -0
  99. package/dist/proserviceworld/utils/cn.d.ts.map +1 -0
  100. package/dist/proserviceworld/utils/nav.d.ts +6 -0
  101. package/dist/proserviceworld/utils/nav.d.ts.map +1 -0
  102. package/dist/proserviceworld/utils/navigation.d.ts +2 -0
  103. package/dist/proserviceworld/utils/navigation.d.ts.map +1 -0
  104. package/dist/proserviceworld/utils/pageContext.d.ts +12 -0
  105. package/dist/proserviceworld/utils/pageContext.d.ts.map +1 -0
  106. package/dist/proserviceworld/utils/pageContext.js +74 -0
  107. package/dist/proserviceworld/utils/pageContext.js.map +1 -0
  108. package/package.json +1 -1
@@ -1,17 +1,23 @@
1
1
  import { useArchiveClient as e, useClients as t, useCreateClient as n, useUpdateClient as r } from "../hooks/useProServiceWorldApi.js";
2
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";
3
+ import { cn as a } from "../utils/cn.js";
4
+ 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 } from "../components/ui.js";
5
+ import { useAnalytics as C } from "../hooks/useAnalytics.js";
6
+ import { useMemo as w, useState as T } from "react";
7
+ import { Archive as E, Building2 as D, ChevronRight as O, Pencil as k, Plus as A, Search as j, User as M, Users as N } from "lucide-react";
8
+ import { Fragment as P, jsx as F, jsxs as I } from "react/jsx-runtime";
9
+ import { Button as L } from "@burdenoff/fe-libs/ui";
8
10
  //#region src/proserviceworld/pages/ClientsPage.tsx
9
- var N = ["ORGANIZATION", "INDIVIDUAL"], P = [
11
+ var R = ["ORGANIZATION", "INDIVIDUAL"], z = [
10
12
  "PROSPECT",
11
13
  "ACTIVE",
12
14
  "INACTIVE",
13
15
  "ARCHIVED"
14
- ], F = {
16
+ ], B = (e) => e.split(/\s+/).filter(Boolean).slice(0, 2).map((e) => e[0]?.toUpperCase() ?? "").join("") || "?", V = ({ name: e, className: t }) => /* @__PURE__ */ F("span", {
17
+ className: a("flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent/10 text-xs font-semibold text-accent ring-1 ring-inset ring-accent/15", t),
18
+ "aria-hidden": !0,
19
+ children: B(e)
20
+ }), H = {
15
21
  name: "",
16
22
  type: "ORGANIZATION",
17
23
  status: "PROSPECT",
@@ -20,100 +26,124 @@ var N = ["ORGANIZATION", "INDIVIDUAL"], P = [
20
26
  contactEmail: "",
21
27
  contactPhone: "",
22
28
  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
29
+ }, U = () => {
30
+ let e = i(), { emitIntent: n, emitFact: r } = C(), [a, l] = T(""), [d, v] = T(""), [w, E] = T(null), [P, R] = T(!1), [B, H] = T(null), { data: U, isLoading: K, error: q, refetch: J } = t({
31
+ search: a.trim() || void 0,
32
+ status: d || void 0
27
33
  });
28
- return /* @__PURE__ */ j("div", {
34
+ return /* @__PURE__ */ I("div", {
29
35
  className: "space-y-6",
30
36
  children: [
31
- /* @__PURE__ */ A(f, {
37
+ /* @__PURE__ */ F(p, {
32
38
  title: "Clients",
33
39
  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"]
40
+ icon: /* @__PURE__ */ F(N, { className: "h-6 w-6" }),
41
+ actions: /* @__PURE__ */ I(L, {
42
+ onClick: () => {
43
+ n("psw.client.create_clicked"), R(!0);
44
+ },
45
+ children: [/* @__PURE__ */ F(A, { className: "mr-1.5 h-4 w-4" }), " New client"]
38
46
  })
39
47
  }),
40
- N && /* @__PURE__ */ A(a, {
41
- tone: N.tone,
42
- onClose: () => F(null),
43
- children: N.text
48
+ B && /* @__PURE__ */ F(o, {
49
+ tone: B.tone,
50
+ onClose: () => H(null),
51
+ children: B.text
44
52
  }),
45
- /* @__PURE__ */ j("div", {
53
+ /* @__PURE__ */ I("div", {
46
54
  className: "flex flex-col gap-2 sm:flex-row sm:items-center",
47
- children: [/* @__PURE__ */ j("div", {
55
+ children: [/* @__PURE__ */ I("div", {
48
56
  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, {
57
+ children: [/* @__PURE__ */ F(j, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ F(y, {
50
58
  placeholder: "Search clients…",
51
- value: n,
52
- onChange: (e) => r(e.target.value),
59
+ value: a,
60
+ onChange: (e) => l(e.target.value),
61
+ onKeyDown: (e) => {
62
+ e.key === "Enter" && a.trim() && r("psw.search.performed", {
63
+ entityType: "client",
64
+ queryLength: a.trim().length
65
+ });
66
+ },
53
67
  className: "pl-9"
54
68
  })]
55
- }), /* @__PURE__ */ j(d, {
56
- value: c,
57
- onChange: (e) => u(e.target.value),
69
+ }), /* @__PURE__ */ I(f, {
70
+ value: d,
71
+ onChange: (e) => v(e.target.value),
58
72
  className: "sm:w-48",
59
- children: [/* @__PURE__ */ A("option", {
73
+ children: [/* @__PURE__ */ F("option", {
60
74
  value: "",
61
75
  children: "All statuses"
62
- }), b(P)]
76
+ }), x(z)]
63
77
  })]
64
78
  }),
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, {
79
+ K ? /* @__PURE__ */ F(u, {}) : q ? /* @__PURE__ */ F(c, {
80
+ error: q,
81
+ onRetry: () => void J()
82
+ }) : !U || U.items.length === 0 ? /* @__PURE__ */ F(s, {
69
83
  title: "No clients yet",
70
84
  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"]
85
+ icon: /* @__PURE__ */ F(N, { className: "h-8 w-8" }),
86
+ action: /* @__PURE__ */ I(L, {
87
+ onClick: () => R(!0),
88
+ children: [/* @__PURE__ */ F(A, { className: "mr-1.5 h-4 w-4" }), " New client"]
75
89
  })
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, {
90
+ }) : /* @__PURE__ */ F(m, {
91
+ title: `${U.totalCount} client${U.totalCount === 1 ? "" : "s"}`,
92
+ children: /* @__PURE__ */ I(g, { children: [/* @__PURE__ */ F("thead", { children: /* @__PURE__ */ I("tr", { children: [
93
+ /* @__PURE__ */ F(b, { children: "Name" }),
94
+ /* @__PURE__ */ F(b, { children: "Type" }),
95
+ /* @__PURE__ */ F(b, { children: "Industry" }),
96
+ /* @__PURE__ */ F(b, { children: "Status" }),
97
+ /* @__PURE__ */ F(b, { children: "Added" }),
98
+ /* @__PURE__ */ F(b, {
85
99
  className: "text-right",
86
100
  children: "Actions"
87
101
  })
88
- ] }) }), /* @__PURE__ */ A("tbody", { children: I.items.map((t) => /* @__PURE__ */ j("tr", {
89
- className: "hover:bg-bg-sunken/50",
102
+ ] }) }), /* @__PURE__ */ F("tbody", { children: U.items.map((t) => /* @__PURE__ */ I("tr", {
103
+ className: "group cursor-pointer transition-colors hover:bg-bg-sunken/60",
104
+ onClick: () => e(`clients/${t.id}`),
90
105
  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, {
106
+ /* @__PURE__ */ F(_, { children: /* @__PURE__ */ I("div", {
107
+ className: "flex items-center gap-3",
108
+ children: [/* @__PURE__ */ F(V, { name: t.name }), /* @__PURE__ */ I("div", {
109
+ className: "min-w-0",
110
+ children: [/* @__PURE__ */ I("div", {
111
+ className: "flex items-center gap-1 font-medium text-text-primary transition-colors group-hover:text-accent",
112
+ children: [/* @__PURE__ */ F("span", {
113
+ className: "truncate",
114
+ children: t.name
115
+ }), /* @__PURE__ */ F(O, { className: "h-3.5 w-3.5 shrink-0 text-text-tertiary opacity-0 transition-opacity group-hover:opacity-100" })]
116
+ }), t.contactName ? /* @__PURE__ */ F("div", {
117
+ className: "truncate text-xs text-text-tertiary",
118
+ children: t.contactName
119
+ }) : null]
120
+ })]
121
+ }) }),
122
+ /* @__PURE__ */ F(_, { children: /* @__PURE__ */ I("span", {
123
+ className: "inline-flex items-center gap-1.5 text-text-secondary",
124
+ children: [t.type === "ORGANIZATION" ? /* @__PURE__ */ F(D, { className: "h-3.5 w-3.5 text-text-tertiary" }) : /* @__PURE__ */ F(M, { className: "h-3.5 w-3.5 text-text-tertiary" }), t.type === "ORGANIZATION" ? "Organization" : "Individual"]
125
+ }) }),
126
+ /* @__PURE__ */ F(_, { children: t.industry || "—" }),
127
+ /* @__PURE__ */ F(_, { children: /* @__PURE__ */ F(h, { status: t.status }) }),
128
+ /* @__PURE__ */ F(_, {
129
+ className: "whitespace-nowrap",
130
+ children: S(t.createdAt)
131
+ }),
132
+ /* @__PURE__ */ F(_, {
105
133
  className: "text-right",
106
- children: /* @__PURE__ */ j("div", {
134
+ children: /* @__PURE__ */ I("div", {
107
135
  className: "flex justify-end gap-1",
108
- children: [/* @__PURE__ */ A(M, {
136
+ onClick: (e) => e.stopPropagation(),
137
+ role: "presentation",
138
+ children: [/* @__PURE__ */ F(L, {
109
139
  variant: "ghost",
110
140
  size: "sm",
111
- onClick: () => S(t),
141
+ onClick: () => E(t),
112
142
  "aria-label": "Edit",
113
- children: /* @__PURE__ */ A(T, { className: "h-4 w-4" })
114
- }), t.status !== "ARCHIVED" && /* @__PURE__ */ A(L, {
143
+ children: /* @__PURE__ */ F(k, { className: "h-4 w-4" })
144
+ }), t.status !== "ARCHIVED" && /* @__PURE__ */ F(W, {
115
145
  id: t.id,
116
- onDone: (e) => F(e ? {
146
+ onDone: (e) => H(e ? {
117
147
  tone: "success",
118
148
  text: `${t.name} archived.`
119
149
  } : {
@@ -126,40 +156,42 @@ var N = ["ORGANIZATION", "INDIVIDUAL"], P = [
126
156
  ]
127
157
  }, t.id)) })] })
128
158
  }),
129
- w && /* @__PURE__ */ A(R, {
130
- onClose: () => k(!1),
131
- onSaved: (e) => F({
159
+ P && /* @__PURE__ */ F(G, {
160
+ onClose: () => R(!1),
161
+ onSaved: (e) => H({
132
162
  tone: "success",
133
163
  text: `${e} created.`
134
164
  })
135
165
  }),
136
- _ && /* @__PURE__ */ A(R, {
137
- client: _,
138
- onClose: () => S(null),
139
- onSaved: (e) => F({
166
+ w && /* @__PURE__ */ F(G, {
167
+ client: w,
168
+ onClose: () => E(null),
169
+ onSaved: (e) => H({
140
170
  tone: "success",
141
171
  text: `${e} updated.`
142
172
  })
143
173
  })
144
174
  ]
145
175
  });
146
- }, L = ({ id: t, onDone: n }) => {
147
- let r = e();
148
- return /* @__PURE__ */ A(M, {
176
+ }, W = ({ id: t, onDone: n }) => {
177
+ let r = e(), { emitFact: i } = C();
178
+ return /* @__PURE__ */ F(L, {
149
179
  variant: "ghost",
150
180
  size: "sm",
151
181
  "aria-label": "Archive",
152
182
  disabled: r.isPending,
153
183
  onClick: () => {
154
184
  window.confirm("Archive this client? Their engagements and matters remain.") && r.mutate(t, {
155
- onSuccess: (e) => n(!!e),
185
+ onSuccess: (e) => {
186
+ i("psw.client.archived", { clientId: t }), n(!!e);
187
+ },
156
188
  onError: () => n(!1)
157
189
  });
158
190
  },
159
- children: /* @__PURE__ */ A(w, { className: "h-4 w-4" })
191
+ children: /* @__PURE__ */ F(E, { className: "h-4 w-4" })
160
192
  });
161
- }, R = ({ client: e, onClose: t, onSaved: i }) => {
162
- let o = n(), s = r(), [l, f] = C(e ? {
193
+ }, G = ({ client: e, onClose: t, onSaved: i }) => {
194
+ let a = n(), s = r(), { emitFact: c } = C(), [u, p] = T(e ? {
163
195
  name: e.name,
164
196
  type: e.type,
165
197
  status: e.status,
@@ -168,121 +200,121 @@ var N = ["ORGANIZATION", "INDIVIDUAL"], P = [
168
200
  contactEmail: e.contactEmail ?? "",
169
201
  contactPhone: e.contactPhone ?? "",
170
202
  notes: e.notes ?? ""
171
- } : F), [p, m] = C(null), h = (e) => (t) => f((n) => ({
203
+ } : H), [m, h] = T(null), g = (e) => (t) => p((n) => ({
172
204
  ...n,
173
205
  [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, {
206
+ })), _ = a.isPending || s.isPending, b = w(() => ({
207
+ name: u.name.trim(),
208
+ type: u.type,
209
+ status: u.status,
210
+ industry: u.industry.trim() || null,
211
+ contactName: u.contactName.trim() || null,
212
+ contactEmail: u.contactEmail.trim() || null,
213
+ contactPhone: u.contactPhone.trim() || null,
214
+ notes: u.notes.trim() || null
215
+ }), [u]);
216
+ return /* @__PURE__ */ F(d, {
185
217
  open: !0,
186
218
  onClose: t,
187
219
  title: e ? "Edit client" : "New client",
188
- footer: /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(M, {
220
+ footer: /* @__PURE__ */ I(P, { children: [/* @__PURE__ */ F(L, {
189
221
  variant: "outline",
190
222
  onClick: t,
191
- disabled: g,
223
+ disabled: _,
192
224
  children: "Cancel"
193
- }), /* @__PURE__ */ A(M, {
225
+ }), /* @__PURE__ */ F(L, {
194
226
  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.");
227
+ if (h(null), !b.name) return h("Client name is required.");
228
+ let n = (e) => h(e instanceof Error ? e.message : "Save failed.");
197
229
  e ? s.mutate({
198
230
  id: e.id,
199
- input: y
231
+ input: b
200
232
  }, {
201
233
  onSuccess: () => {
202
- i(y.name), t();
234
+ c("psw.client.updated", { clientId: e.id }), i(b.name), t();
203
235
  },
204
236
  onError: n
205
- }) : o.mutate(y, {
206
- onSuccess: () => {
207
- i(y.name), t();
237
+ }) : a.mutate(b, {
238
+ onSuccess: (e) => {
239
+ c("psw.client.created", { clientId: e.pswCreateClient.id }), i(b.name), t();
208
240
  },
209
241
  onError: n
210
242
  });
211
243
  },
212
- disabled: g,
213
- children: g ? "Saving…" : e ? "Save changes" : "Create client"
244
+ disabled: _,
245
+ children: _ ? "Saving…" : e ? "Save changes" : "Create client"
214
246
  })] }),
215
- children: /* @__PURE__ */ j("div", {
247
+ children: /* @__PURE__ */ I("div", {
216
248
  className: "space-y-3",
217
249
  children: [
218
- p && /* @__PURE__ */ A(a, {
250
+ m && /* @__PURE__ */ F(o, {
219
251
  tone: "danger",
220
- children: p
252
+ children: m
221
253
  }),
222
- /* @__PURE__ */ A(c, {
254
+ /* @__PURE__ */ F(l, {
223
255
  label: "Name",
224
256
  required: !0,
225
- children: /* @__PURE__ */ A(v, {
226
- value: l.name,
227
- onChange: h("name"),
257
+ children: /* @__PURE__ */ F(y, {
258
+ value: u.name,
259
+ onChange: g("name"),
228
260
  placeholder: "Acme Holdings Ltd."
229
261
  })
230
262
  }),
231
- /* @__PURE__ */ j("div", {
263
+ /* @__PURE__ */ I("div", {
232
264
  className: "grid grid-cols-2 gap-3",
233
- children: [/* @__PURE__ */ A(c, {
265
+ children: [/* @__PURE__ */ F(l, {
234
266
  label: "Type",
235
- children: /* @__PURE__ */ A(d, {
236
- value: l.type,
237
- onChange: h("type"),
238
- children: b(N)
267
+ children: /* @__PURE__ */ F(f, {
268
+ value: u.type,
269
+ onChange: g("type"),
270
+ children: x(R)
239
271
  })
240
- }), /* @__PURE__ */ A(c, {
272
+ }), /* @__PURE__ */ F(l, {
241
273
  label: "Status",
242
- children: /* @__PURE__ */ A(d, {
243
- value: l.status,
244
- onChange: h("status"),
245
- children: b(P)
274
+ children: /* @__PURE__ */ F(f, {
275
+ value: u.status,
276
+ onChange: g("status"),
277
+ children: x(z)
246
278
  })
247
279
  })]
248
280
  }),
249
- /* @__PURE__ */ A(c, {
281
+ /* @__PURE__ */ F(l, {
250
282
  label: "Industry",
251
- children: /* @__PURE__ */ A(v, {
252
- value: l.industry,
253
- onChange: h("industry"),
283
+ children: /* @__PURE__ */ F(y, {
284
+ value: u.industry,
285
+ onChange: g("industry"),
254
286
  placeholder: "Financial services"
255
287
  })
256
288
  }),
257
- /* @__PURE__ */ j("div", {
289
+ /* @__PURE__ */ I("div", {
258
290
  className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
259
- children: [/* @__PURE__ */ A(c, {
291
+ children: [/* @__PURE__ */ F(l, {
260
292
  label: "Contact name",
261
- children: /* @__PURE__ */ A(v, {
262
- value: l.contactName,
263
- onChange: h("contactName")
293
+ children: /* @__PURE__ */ F(y, {
294
+ value: u.contactName,
295
+ onChange: g("contactName")
264
296
  })
265
- }), /* @__PURE__ */ A(c, {
297
+ }), /* @__PURE__ */ F(l, {
266
298
  label: "Contact email",
267
- children: /* @__PURE__ */ A(v, {
299
+ children: /* @__PURE__ */ F(y, {
268
300
  type: "email",
269
- value: l.contactEmail,
270
- onChange: h("contactEmail")
301
+ value: u.contactEmail,
302
+ onChange: g("contactEmail")
271
303
  })
272
304
  })]
273
305
  }),
274
- /* @__PURE__ */ A(c, {
306
+ /* @__PURE__ */ F(l, {
275
307
  label: "Contact phone",
276
- children: /* @__PURE__ */ A(v, {
277
- value: l.contactPhone,
278
- onChange: h("contactPhone")
308
+ children: /* @__PURE__ */ F(y, {
309
+ value: u.contactPhone,
310
+ onChange: g("contactPhone")
279
311
  })
280
312
  }),
281
- /* @__PURE__ */ A(c, {
313
+ /* @__PURE__ */ F(l, {
282
314
  label: "Notes",
283
- children: /* @__PURE__ */ A(_, {
284
- value: l.notes,
285
- onChange: h("notes")
315
+ children: /* @__PURE__ */ F(v, {
316
+ value: u.notes,
317
+ onChange: g("notes")
286
318
  })
287
319
  })
288
320
  ]
@@ -290,6 +322,6 @@ var N = ["ORGANIZATION", "INDIVIDUAL"], P = [
290
322
  });
291
323
  };
292
324
  //#endregion
293
- export { I as ClientsPage };
325
+ export { U as ClientsPage };
294
326
 
295
327
  //# sourceMappingURL=ClientsPage.js.map
@@ -1 +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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"}
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, Building2, User, ChevronRight } 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 { cn } from '../utils/cn';\nimport { useAnalytics } from '../hooks/useAnalytics';\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\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\n/** Tinted initials avatar (semantic tokens only). */\nexport const Avatar: FC<{ name: string; className?: string }> = ({ name, className }) => (\n <span\n className={cn(\n 'flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent/10 text-xs font-semibold text-accent ring-1 ring-inset ring-accent/15',\n className\n )}\n aria-hidden\n >\n {initials(name)}\n </span>\n);\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 { emitIntent, emitFact } = useAnalytics();\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\n onClick={() => {\n emitIntent('psw.client.create_clicked');\n setCreating(true);\n }}\n >\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 onKeyDown={(e) => {\n if (e.key === 'Enter' && search.trim()) {\n emitFact('psw.search.performed', {\n entityType: 'client',\n queryLength: search.trim().length,\n });\n }\n }}\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\n key={c.id}\n className=\"group cursor-pointer transition-colors hover:bg-bg-sunken/60\"\n onClick={() => nav(`clients/${c.id}`)}\n >\n <Td>\n <div className=\"flex items-center gap-3\">\n <Avatar name={c.name} />\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1 font-medium text-text-primary transition-colors group-hover:text-accent\">\n <span className=\"truncate\">{c.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 {c.contactName ? (\n <div className=\"truncate text-xs text-text-tertiary\">{c.contactName}</div>\n ) : null}\n </div>\n </div>\n </Td>\n <Td>\n <span className=\"inline-flex items-center gap-1.5 text-text-secondary\">\n {c.type === 'ORGANIZATION' ? (\n <Building2 className=\"h-3.5 w-3.5 text-text-tertiary\" />\n ) : (\n <User className=\"h-3.5 w-3.5 text-text-tertiary\" />\n )}\n {c.type === 'ORGANIZATION' ? 'Organization' : 'Individual'}\n </span>\n </Td>\n <Td>{c.industry || '—'}</Td>\n <Td>\n <StatusPill status={c.status} />\n </Td>\n <Td className=\"whitespace-nowrap\">{fmtDate(c.createdAt)}</Td>\n <Td className=\"text-right\">\n <div\n className=\"flex justify-end gap-1\"\n onClick={(ev) => ev.stopPropagation()}\n role=\"presentation\"\n >\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 const { emitFact } = useAnalytics();\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, {\n onSuccess: (r) => {\n emitFact('psw.client.archived', { clientId: id });\n onDone(Boolean(r));\n },\n onError: () => onDone(false),\n });\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 { emitFact } = useAnalytics();\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 emitFact('psw.client.updated', { clientId: client.id });\n onSaved(payload.name);\n onClose();\n },\n onError,\n }\n );\n } else {\n create.mutate(payload, {\n onSuccess: (created) => {\n emitFact('psw.client.created', { clientId: created.pswCreateClient.id });\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,4 @@
1
+ import { FC } from 'react';
2
+
3
+ export declare const CompliancePage: FC;
4
+ //# sourceMappingURL=CompliancePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompliancePage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/CompliancePage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AAoE3C,eAAO,MAAM,cAAc,EAAE,EAsK5B,CAAC"}