@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.
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +18199 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +43046 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -1
- package/dist/proserviceworld/ProServiceWorldRoot.d.ts +5 -0
- package/dist/proserviceworld/ProServiceWorldRoot.d.ts.map +1 -0
- package/dist/proserviceworld/ProServiceWorldRoutes.d.ts +2 -0
- package/dist/proserviceworld/ProServiceWorldRoutes.d.ts.map +1 -0
- package/dist/proserviceworld/components/DiscussionThread.d.ts +12 -0
- package/dist/proserviceworld/components/DiscussionThread.d.ts.map +1 -0
- package/dist/proserviceworld/components/DiscussionThread.js +1 -1
- package/dist/proserviceworld/components/DiscussionThread.js.map +1 -1
- package/dist/proserviceworld/components/ui.d.ts +82 -0
- package/dist/proserviceworld/components/ui.d.ts.map +1 -0
- package/dist/proserviceworld/components/ui.js +18 -18
- package/dist/proserviceworld/components/ui.js.map +1 -1
- package/dist/proserviceworld/hooks/useAnalytics.d.ts +18 -0
- package/dist/proserviceworld/hooks/useAnalytics.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/useAnalytics.js +21 -0
- package/dist/proserviceworld/hooks/useAnalytics.js.map +1 -0
- package/dist/proserviceworld/hooks/useEntityComments.d.ts +27 -0
- package/dist/proserviceworld/hooks/useEntityComments.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/useEntityComments.js.map +1 -1
- package/dist/proserviceworld/hooks/useFiles.d.ts +23 -0
- package/dist/proserviceworld/hooks/useFiles.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts +351 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts.map +1 -0
- package/dist/proserviceworld/index.d.ts +5 -0
- package/dist/proserviceworld/index.d.ts.map +1 -0
- package/dist/proserviceworld/index.js +1 -0
- package/dist/proserviceworld/pages/AnalyticsPage.d.ts +4 -0
- package/dist/proserviceworld/pages/AnalyticsPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/AnalyticsPage.js +277 -111
- package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
- package/dist/proserviceworld/pages/ClientDetailPage.d.ts +4 -0
- package/dist/proserviceworld/pages/ClientDetailPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/ClientDetailPage.js +219 -151
- package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -1
- package/dist/proserviceworld/pages/ClientsPage.d.ts +9 -0
- package/dist/proserviceworld/pages/ClientsPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/ClientsPage.js +180 -148
- package/dist/proserviceworld/pages/ClientsPage.js.map +1 -1
- package/dist/proserviceworld/pages/CompliancePage.d.ts +4 -0
- package/dist/proserviceworld/pages/CompliancePage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/CompliancePage.js +140 -96
- package/dist/proserviceworld/pages/CompliancePage.js.map +1 -1
- package/dist/proserviceworld/pages/ConflictsPage.d.ts +4 -0
- package/dist/proserviceworld/pages/ConflictsPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/DashboardPage.d.ts +4 -0
- package/dist/proserviceworld/pages/DashboardPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/DashboardPage.js +221 -104
- package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
- package/dist/proserviceworld/pages/DocumentsPage.d.ts +4 -0
- package/dist/proserviceworld/pages/DocumentsPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/EngagementDetailPage.d.ts +4 -0
- package/dist/proserviceworld/pages/EngagementDetailPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/EngagementDetailPage.js +233 -197
- package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -1
- package/dist/proserviceworld/pages/EngagementsPage.d.ts +4 -0
- package/dist/proserviceworld/pages/EngagementsPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/EngagementsPage.js +187 -136
- package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -1
- package/dist/proserviceworld/pages/InvoicesPage.d.ts +4 -0
- package/dist/proserviceworld/pages/InvoicesPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/InvoicesPage.js +144 -129
- package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
- package/dist/proserviceworld/pages/MattersPage.d.ts +4 -0
- package/dist/proserviceworld/pages/MattersPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/MattersPage.js +198 -142
- package/dist/proserviceworld/pages/MattersPage.js.map +1 -1
- package/dist/proserviceworld/pages/PracticeAreasPage.d.ts +4 -0
- package/dist/proserviceworld/pages/PracticeAreasPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/TimePage.d.ts +4 -0
- package/dist/proserviceworld/pages/TimePage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/TimePage.js +112 -92
- package/dist/proserviceworld/pages/TimePage.js.map +1 -1
- package/dist/proserviceworld/providers/ProServiceWorldProvider.d.ts +6 -0
- package/dist/proserviceworld/providers/ProServiceWorldProvider.d.ts.map +1 -0
- package/dist/proserviceworld/services/assistantApi.d.ts +74 -0
- package/dist/proserviceworld/services/assistantApi.d.ts.map +1 -0
- package/dist/proserviceworld/services/assistantApi.js +203 -0
- package/dist/proserviceworld/services/assistantApi.js.map +1 -0
- package/dist/proserviceworld/services/createSandboxAssistantTransport.d.ts +28 -0
- package/dist/proserviceworld/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/proserviceworld/services/createSandboxAssistantTransport.js +120 -0
- package/dist/proserviceworld/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/proserviceworld/types/index.d.ts +57 -0
- package/dist/proserviceworld/types/index.d.ts.map +1 -0
- package/dist/proserviceworld/utils/cn.d.ts +4 -0
- package/dist/proserviceworld/utils/cn.d.ts.map +1 -0
- package/dist/proserviceworld/utils/nav.d.ts +6 -0
- package/dist/proserviceworld/utils/nav.d.ts.map +1 -0
- package/dist/proserviceworld/utils/navigation.d.ts +2 -0
- package/dist/proserviceworld/utils/navigation.d.ts.map +1 -0
- package/dist/proserviceworld/utils/pageContext.d.ts +12 -0
- package/dist/proserviceworld/utils/pageContext.d.ts.map +1 -0
- package/dist/proserviceworld/utils/pageContext.js +74 -0
- package/dist/proserviceworld/utils/pageContext.js.map +1 -0
- 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 {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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
|
|
11
|
+
var R = ["ORGANIZATION", "INDIVIDUAL"], z = [
|
|
10
12
|
"PROSPECT",
|
|
11
13
|
"ACTIVE",
|
|
12
14
|
"INACTIVE",
|
|
13
15
|
"ARCHIVED"
|
|
14
|
-
],
|
|
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
|
-
},
|
|
24
|
-
let e = i(),
|
|
25
|
-
search:
|
|
26
|
-
status:
|
|
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__ */
|
|
34
|
+
return /* @__PURE__ */ I("div", {
|
|
29
35
|
className: "space-y-6",
|
|
30
36
|
children: [
|
|
31
|
-
/* @__PURE__ */
|
|
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__ */
|
|
35
|
-
actions: /* @__PURE__ */
|
|
36
|
-
onClick: () =>
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
tone:
|
|
42
|
-
onClose: () =>
|
|
43
|
-
children:
|
|
48
|
+
B && /* @__PURE__ */ F(o, {
|
|
49
|
+
tone: B.tone,
|
|
50
|
+
onClose: () => H(null),
|
|
51
|
+
children: B.text
|
|
44
52
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ I("div", {
|
|
46
54
|
className: "flex flex-col gap-2 sm:flex-row sm:items-center",
|
|
47
|
-
children: [/* @__PURE__ */
|
|
55
|
+
children: [/* @__PURE__ */ I("div", {
|
|
48
56
|
className: "relative flex-1",
|
|
49
|
-
children: [/* @__PURE__ */
|
|
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:
|
|
52
|
-
onChange: (e) =>
|
|
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__ */
|
|
56
|
-
value:
|
|
57
|
-
onChange: (e) =>
|
|
69
|
+
}), /* @__PURE__ */ I(f, {
|
|
70
|
+
value: d,
|
|
71
|
+
onChange: (e) => v(e.target.value),
|
|
58
72
|
className: "sm:w-48",
|
|
59
|
-
children: [/* @__PURE__ */
|
|
73
|
+
children: [/* @__PURE__ */ F("option", {
|
|
60
74
|
value: "",
|
|
61
75
|
children: "All statuses"
|
|
62
|
-
}),
|
|
76
|
+
}), x(z)]
|
|
63
77
|
})]
|
|
64
78
|
}),
|
|
65
|
-
|
|
66
|
-
error:
|
|
67
|
-
onRetry: () => void
|
|
68
|
-
}) : !
|
|
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__ */
|
|
72
|
-
action: /* @__PURE__ */
|
|
73
|
-
onClick: () =>
|
|
74
|
-
children: [/* @__PURE__ */ A
|
|
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__ */
|
|
77
|
-
title: `${
|
|
78
|
-
children: /* @__PURE__ */
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
/* @__PURE__ */
|
|
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__ */
|
|
89
|
-
className: "hover:bg-bg-sunken/
|
|
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__ */
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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__ */
|
|
134
|
+
children: /* @__PURE__ */ I("div", {
|
|
107
135
|
className: "flex justify-end gap-1",
|
|
108
|
-
|
|
136
|
+
onClick: (e) => e.stopPropagation(),
|
|
137
|
+
role: "presentation",
|
|
138
|
+
children: [/* @__PURE__ */ F(L, {
|
|
109
139
|
variant: "ghost",
|
|
110
140
|
size: "sm",
|
|
111
|
-
onClick: () =>
|
|
141
|
+
onClick: () => E(t),
|
|
112
142
|
"aria-label": "Edit",
|
|
113
|
-
children: /* @__PURE__ */
|
|
114
|
-
}), t.status !== "ARCHIVED" && /* @__PURE__ */
|
|
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) =>
|
|
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
|
-
|
|
130
|
-
onClose: () =>
|
|
131
|
-
onSaved: (e) =>
|
|
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
|
-
|
|
137
|
-
client:
|
|
138
|
-
onClose: () =>
|
|
139
|
-
onSaved: (e) =>
|
|
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
|
-
},
|
|
147
|
-
let r = e();
|
|
148
|
-
return /* @__PURE__ */
|
|
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) =>
|
|
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__ */
|
|
191
|
+
children: /* @__PURE__ */ F(E, { className: "h-4 w-4" })
|
|
160
192
|
});
|
|
161
|
-
},
|
|
162
|
-
let
|
|
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
|
-
} :
|
|
203
|
+
} : H), [m, h] = T(null), g = (e) => (t) => p((n) => ({
|
|
172
204
|
...n,
|
|
173
205
|
[e]: t.target.value
|
|
174
|
-
})),
|
|
175
|
-
name:
|
|
176
|
-
type:
|
|
177
|
-
status:
|
|
178
|
-
industry:
|
|
179
|
-
contactName:
|
|
180
|
-
contactEmail:
|
|
181
|
-
contactPhone:
|
|
182
|
-
notes:
|
|
183
|
-
}), [
|
|
184
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
220
|
+
footer: /* @__PURE__ */ I(P, { children: [/* @__PURE__ */ F(L, {
|
|
189
221
|
variant: "outline",
|
|
190
222
|
onClick: t,
|
|
191
|
-
disabled:
|
|
223
|
+
disabled: _,
|
|
192
224
|
children: "Cancel"
|
|
193
|
-
}), /* @__PURE__ */
|
|
225
|
+
}), /* @__PURE__ */ F(L, {
|
|
194
226
|
onClick: () => {
|
|
195
|
-
if (
|
|
196
|
-
let n = (e) =>
|
|
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:
|
|
231
|
+
input: b
|
|
200
232
|
}, {
|
|
201
233
|
onSuccess: () => {
|
|
202
|
-
i(
|
|
234
|
+
c("psw.client.updated", { clientId: e.id }), i(b.name), t();
|
|
203
235
|
},
|
|
204
236
|
onError: n
|
|
205
|
-
}) :
|
|
206
|
-
onSuccess: () => {
|
|
207
|
-
i(
|
|
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:
|
|
213
|
-
children:
|
|
244
|
+
disabled: _,
|
|
245
|
+
children: _ ? "Saving…" : e ? "Save changes" : "Create client"
|
|
214
246
|
})] }),
|
|
215
|
-
children: /* @__PURE__ */
|
|
247
|
+
children: /* @__PURE__ */ I("div", {
|
|
216
248
|
className: "space-y-3",
|
|
217
249
|
children: [
|
|
218
|
-
|
|
250
|
+
m && /* @__PURE__ */ F(o, {
|
|
219
251
|
tone: "danger",
|
|
220
|
-
children:
|
|
252
|
+
children: m
|
|
221
253
|
}),
|
|
222
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ F(l, {
|
|
223
255
|
label: "Name",
|
|
224
256
|
required: !0,
|
|
225
|
-
children: /* @__PURE__ */
|
|
226
|
-
value:
|
|
227
|
-
onChange:
|
|
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__ */
|
|
263
|
+
/* @__PURE__ */ I("div", {
|
|
232
264
|
className: "grid grid-cols-2 gap-3",
|
|
233
|
-
children: [/* @__PURE__ */
|
|
265
|
+
children: [/* @__PURE__ */ F(l, {
|
|
234
266
|
label: "Type",
|
|
235
|
-
children: /* @__PURE__ */
|
|
236
|
-
value:
|
|
237
|
-
onChange:
|
|
238
|
-
children:
|
|
267
|
+
children: /* @__PURE__ */ F(f, {
|
|
268
|
+
value: u.type,
|
|
269
|
+
onChange: g("type"),
|
|
270
|
+
children: x(R)
|
|
239
271
|
})
|
|
240
|
-
}), /* @__PURE__ */
|
|
272
|
+
}), /* @__PURE__ */ F(l, {
|
|
241
273
|
label: "Status",
|
|
242
|
-
children: /* @__PURE__ */
|
|
243
|
-
value:
|
|
244
|
-
onChange:
|
|
245
|
-
children:
|
|
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__ */
|
|
281
|
+
/* @__PURE__ */ F(l, {
|
|
250
282
|
label: "Industry",
|
|
251
|
-
children: /* @__PURE__ */
|
|
252
|
-
value:
|
|
253
|
-
onChange:
|
|
283
|
+
children: /* @__PURE__ */ F(y, {
|
|
284
|
+
value: u.industry,
|
|
285
|
+
onChange: g("industry"),
|
|
254
286
|
placeholder: "Financial services"
|
|
255
287
|
})
|
|
256
288
|
}),
|
|
257
|
-
/* @__PURE__ */
|
|
289
|
+
/* @__PURE__ */ I("div", {
|
|
258
290
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
|
|
259
|
-
children: [/* @__PURE__ */
|
|
291
|
+
children: [/* @__PURE__ */ F(l, {
|
|
260
292
|
label: "Contact name",
|
|
261
|
-
children: /* @__PURE__ */
|
|
262
|
-
value:
|
|
263
|
-
onChange:
|
|
293
|
+
children: /* @__PURE__ */ F(y, {
|
|
294
|
+
value: u.contactName,
|
|
295
|
+
onChange: g("contactName")
|
|
264
296
|
})
|
|
265
|
-
}), /* @__PURE__ */
|
|
297
|
+
}), /* @__PURE__ */ F(l, {
|
|
266
298
|
label: "Contact email",
|
|
267
|
-
children: /* @__PURE__ */
|
|
299
|
+
children: /* @__PURE__ */ F(y, {
|
|
268
300
|
type: "email",
|
|
269
|
-
value:
|
|
270
|
-
onChange:
|
|
301
|
+
value: u.contactEmail,
|
|
302
|
+
onChange: g("contactEmail")
|
|
271
303
|
})
|
|
272
304
|
})]
|
|
273
305
|
}),
|
|
274
|
-
/* @__PURE__ */
|
|
306
|
+
/* @__PURE__ */ F(l, {
|
|
275
307
|
label: "Contact phone",
|
|
276
|
-
children: /* @__PURE__ */
|
|
277
|
-
value:
|
|
278
|
-
onChange:
|
|
308
|
+
children: /* @__PURE__ */ F(y, {
|
|
309
|
+
value: u.contactPhone,
|
|
310
|
+
onChange: g("contactPhone")
|
|
279
311
|
})
|
|
280
312
|
}),
|
|
281
|
-
/* @__PURE__ */
|
|
313
|
+
/* @__PURE__ */ F(l, {
|
|
282
314
|
label: "Notes",
|
|
283
|
-
children: /* @__PURE__ */
|
|
284
|
-
value:
|
|
285
|
-
onChange:
|
|
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 {
|
|
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 @@
|
|
|
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"}
|