@burdenoff/microfe-proserviceworld 2026.706.3 → 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/ui.d.ts +82 -0
- package/dist/proserviceworld/components/ui.d.ts.map +1 -0
- 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/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/ClientDetailPage.d.ts +4 -0
- package/dist/proserviceworld/pages/ClientDetailPage.d.ts.map +1 -0
- 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 +157 -146
- 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/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/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 +162 -156
- 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 +141 -128
- 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/MattersPage.d.ts +4 -0
- package/dist/proserviceworld/pages/MattersPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/MattersPage.js +165 -150
- 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/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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnalyticsPage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/AnalyticsPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAehC,eAAO,MAAM,aAAa,EAAE,EA6G3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientDetailPage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/ClientDetailPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAsDhC,eAAO,MAAM,gBAAgB,EAAE,EA2P9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientsPage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/ClientsPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA8ChC,qDAAqD;AACrD,eAAO,MAAM,MAAM,EAAE,EAAE,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAU3D,CAAC;AAuBF,eAAO,MAAM,WAAW,EAAE,EAoLzB,CAAC"}
|
|
@@ -2,21 +2,22 @@ import { useArchiveClient as e, useClients as t, useCreateClient as n, useUpdate
|
|
|
2
2
|
import { useNav as i } from "../utils/nav.js";
|
|
3
3
|
import { cn as a } from "../utils/cn.js";
|
|
4
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 {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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";
|
|
9
10
|
//#region src/proserviceworld/pages/ClientsPage.tsx
|
|
10
|
-
var
|
|
11
|
+
var R = ["ORGANIZATION", "INDIVIDUAL"], z = [
|
|
11
12
|
"PROSPECT",
|
|
12
13
|
"ACTIVE",
|
|
13
14
|
"INACTIVE",
|
|
14
15
|
"ARCHIVED"
|
|
15
|
-
],
|
|
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", {
|
|
16
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),
|
|
17
18
|
"aria-hidden": !0,
|
|
18
|
-
children:
|
|
19
|
-
}),
|
|
19
|
+
children: B(e)
|
|
20
|
+
}), H = {
|
|
20
21
|
name: "",
|
|
21
22
|
type: "ORGANIZATION",
|
|
22
23
|
status: "PROSPECT",
|
|
@@ -25,116 +26,124 @@ var L = ["ORGANIZATION", "INDIVIDUAL"], R = [
|
|
|
25
26
|
contactEmail: "",
|
|
26
27
|
contactPhone: "",
|
|
27
28
|
notes: ""
|
|
28
|
-
},
|
|
29
|
-
let e = i(),
|
|
30
|
-
search:
|
|
31
|
-
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
|
|
32
33
|
});
|
|
33
|
-
return /* @__PURE__ */
|
|
34
|
+
return /* @__PURE__ */ I("div", {
|
|
34
35
|
className: "space-y-6",
|
|
35
36
|
children: [
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ F(p, {
|
|
37
38
|
title: "Clients",
|
|
38
39
|
subtitle: "Every person or organization your firm serves — the record engagements, matters, documents and invoices hang off.",
|
|
39
|
-
icon: /* @__PURE__ */
|
|
40
|
-
actions: /* @__PURE__ */
|
|
41
|
-
onClick: () =>
|
|
42
|
-
|
|
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"]
|
|
43
46
|
})
|
|
44
47
|
}),
|
|
45
|
-
|
|
46
|
-
tone:
|
|
47
|
-
onClose: () =>
|
|
48
|
-
children:
|
|
48
|
+
B && /* @__PURE__ */ F(o, {
|
|
49
|
+
tone: B.tone,
|
|
50
|
+
onClose: () => H(null),
|
|
51
|
+
children: B.text
|
|
49
52
|
}),
|
|
50
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ I("div", {
|
|
51
54
|
className: "flex flex-col gap-2 sm:flex-row sm:items-center",
|
|
52
|
-
children: [/* @__PURE__ */
|
|
55
|
+
children: [/* @__PURE__ */ I("div", {
|
|
53
56
|
className: "relative flex-1",
|
|
54
|
-
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, {
|
|
55
58
|
placeholder: "Search clients…",
|
|
56
|
-
value:
|
|
57
|
-
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
|
+
},
|
|
58
67
|
className: "pl-9"
|
|
59
68
|
})]
|
|
60
|
-
}), /* @__PURE__ */
|
|
61
|
-
value:
|
|
62
|
-
onChange: (e) =>
|
|
69
|
+
}), /* @__PURE__ */ I(f, {
|
|
70
|
+
value: d,
|
|
71
|
+
onChange: (e) => v(e.target.value),
|
|
63
72
|
className: "sm:w-48",
|
|
64
|
-
children: [/* @__PURE__ */
|
|
73
|
+
children: [/* @__PURE__ */ F("option", {
|
|
65
74
|
value: "",
|
|
66
75
|
children: "All statuses"
|
|
67
|
-
}), x(
|
|
76
|
+
}), x(z)]
|
|
68
77
|
})]
|
|
69
78
|
}),
|
|
70
|
-
|
|
71
|
-
error:
|
|
72
|
-
onRetry: () => void
|
|
73
|
-
}) : !
|
|
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, {
|
|
74
83
|
title: "No clients yet",
|
|
75
84
|
description: "Add your first client to start scoping engagements and matters.",
|
|
76
|
-
icon: /* @__PURE__ */
|
|
77
|
-
action: /* @__PURE__ */
|
|
78
|
-
onClick: () =>
|
|
79
|
-
children: [/* @__PURE__ */
|
|
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"]
|
|
80
89
|
})
|
|
81
|
-
}) : /* @__PURE__ */
|
|
82
|
-
title: `${
|
|
83
|
-
children: /* @__PURE__ */
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
/* @__PURE__ */
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
/* @__PURE__ */
|
|
88
|
-
/* @__PURE__ */
|
|
89
|
-
/* @__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, {
|
|
90
99
|
className: "text-right",
|
|
91
100
|
children: "Actions"
|
|
92
101
|
})
|
|
93
|
-
] }) }), /* @__PURE__ */
|
|
102
|
+
] }) }), /* @__PURE__ */ F("tbody", { children: U.items.map((t) => /* @__PURE__ */ I("tr", {
|
|
94
103
|
className: "group cursor-pointer transition-colors hover:bg-bg-sunken/60",
|
|
95
104
|
onClick: () => e(`clients/${t.id}`),
|
|
96
105
|
children: [
|
|
97
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ F(_, { children: /* @__PURE__ */ I("div", {
|
|
98
107
|
className: "flex items-center gap-3",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
108
|
+
children: [/* @__PURE__ */ F(V, { name: t.name }), /* @__PURE__ */ I("div", {
|
|
100
109
|
className: "min-w-0",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
110
|
+
children: [/* @__PURE__ */ I("div", {
|
|
102
111
|
className: "flex items-center gap-1 font-medium text-text-primary transition-colors group-hover:text-accent",
|
|
103
|
-
children: [/* @__PURE__ */
|
|
112
|
+
children: [/* @__PURE__ */ F("span", {
|
|
104
113
|
className: "truncate",
|
|
105
114
|
children: t.name
|
|
106
|
-
}), /* @__PURE__ */
|
|
107
|
-
}), t.contactName ? /* @__PURE__ */
|
|
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", {
|
|
108
117
|
className: "truncate text-xs text-text-tertiary",
|
|
109
118
|
children: t.contactName
|
|
110
119
|
}) : null]
|
|
111
120
|
})]
|
|
112
121
|
}) }),
|
|
113
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ F(_, { children: /* @__PURE__ */ I("span", {
|
|
114
123
|
className: "inline-flex items-center gap-1.5 text-text-secondary",
|
|
115
|
-
children: [t.type === "ORGANIZATION" ? /* @__PURE__ */
|
|
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"]
|
|
116
125
|
}) }),
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
-
/* @__PURE__ */
|
|
119
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ F(_, { children: t.industry || "—" }),
|
|
127
|
+
/* @__PURE__ */ F(_, { children: /* @__PURE__ */ F(h, { status: t.status }) }),
|
|
128
|
+
/* @__PURE__ */ F(_, {
|
|
120
129
|
className: "whitespace-nowrap",
|
|
121
130
|
children: S(t.createdAt)
|
|
122
131
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
132
|
+
/* @__PURE__ */ F(_, {
|
|
124
133
|
className: "text-right",
|
|
125
|
-
children: /* @__PURE__ */
|
|
134
|
+
children: /* @__PURE__ */ I("div", {
|
|
126
135
|
className: "flex justify-end gap-1",
|
|
127
136
|
onClick: (e) => e.stopPropagation(),
|
|
128
137
|
role: "presentation",
|
|
129
|
-
children: [/* @__PURE__ */
|
|
138
|
+
children: [/* @__PURE__ */ F(L, {
|
|
130
139
|
variant: "ghost",
|
|
131
140
|
size: "sm",
|
|
132
|
-
onClick: () =>
|
|
141
|
+
onClick: () => E(t),
|
|
133
142
|
"aria-label": "Edit",
|
|
134
|
-
children: /* @__PURE__ */
|
|
135
|
-
}), t.status !== "ARCHIVED" && /* @__PURE__ */
|
|
143
|
+
children: /* @__PURE__ */ F(k, { className: "h-4 w-4" })
|
|
144
|
+
}), t.status !== "ARCHIVED" && /* @__PURE__ */ F(W, {
|
|
136
145
|
id: t.id,
|
|
137
|
-
onDone: (e) =>
|
|
146
|
+
onDone: (e) => H(e ? {
|
|
138
147
|
tone: "success",
|
|
139
148
|
text: `${t.name} archived.`
|
|
140
149
|
} : {
|
|
@@ -147,40 +156,42 @@ var L = ["ORGANIZATION", "INDIVIDUAL"], R = [
|
|
|
147
156
|
]
|
|
148
157
|
}, t.id)) })] })
|
|
149
158
|
}),
|
|
150
|
-
|
|
151
|
-
onClose: () =>
|
|
152
|
-
onSaved: (e) =>
|
|
159
|
+
P && /* @__PURE__ */ F(G, {
|
|
160
|
+
onClose: () => R(!1),
|
|
161
|
+
onSaved: (e) => H({
|
|
153
162
|
tone: "success",
|
|
154
163
|
text: `${e} created.`
|
|
155
164
|
})
|
|
156
165
|
}),
|
|
157
|
-
|
|
158
|
-
client:
|
|
159
|
-
onClose: () =>
|
|
160
|
-
onSaved: (e) =>
|
|
166
|
+
w && /* @__PURE__ */ F(G, {
|
|
167
|
+
client: w,
|
|
168
|
+
onClose: () => E(null),
|
|
169
|
+
onSaved: (e) => H({
|
|
161
170
|
tone: "success",
|
|
162
171
|
text: `${e} updated.`
|
|
163
172
|
})
|
|
164
173
|
})
|
|
165
174
|
]
|
|
166
175
|
});
|
|
167
|
-
},
|
|
168
|
-
let r = e();
|
|
169
|
-
return /* @__PURE__ */
|
|
176
|
+
}, W = ({ id: t, onDone: n }) => {
|
|
177
|
+
let r = e(), { emitFact: i } = C();
|
|
178
|
+
return /* @__PURE__ */ F(L, {
|
|
170
179
|
variant: "ghost",
|
|
171
180
|
size: "sm",
|
|
172
181
|
"aria-label": "Archive",
|
|
173
182
|
disabled: r.isPending,
|
|
174
183
|
onClick: () => {
|
|
175
184
|
window.confirm("Archive this client? Their engagements and matters remain.") && r.mutate(t, {
|
|
176
|
-
onSuccess: (e) =>
|
|
185
|
+
onSuccess: (e) => {
|
|
186
|
+
i("psw.client.archived", { clientId: t }), n(!!e);
|
|
187
|
+
},
|
|
177
188
|
onError: () => n(!1)
|
|
178
189
|
});
|
|
179
190
|
},
|
|
180
|
-
children: /* @__PURE__ */
|
|
191
|
+
children: /* @__PURE__ */ F(E, { className: "h-4 w-4" })
|
|
181
192
|
});
|
|
182
|
-
},
|
|
183
|
-
let a = n(), s = r(),
|
|
193
|
+
}, G = ({ client: e, onClose: t, onSaved: i }) => {
|
|
194
|
+
let a = n(), s = r(), { emitFact: c } = C(), [u, p] = T(e ? {
|
|
184
195
|
name: e.name,
|
|
185
196
|
type: e.type,
|
|
186
197
|
status: e.status,
|
|
@@ -189,121 +200,121 @@ var L = ["ORGANIZATION", "INDIVIDUAL"], R = [
|
|
|
189
200
|
contactEmail: e.contactEmail ?? "",
|
|
190
201
|
contactPhone: e.contactPhone ?? "",
|
|
191
202
|
notes: e.notes ?? ""
|
|
192
|
-
} :
|
|
203
|
+
} : H), [m, h] = T(null), g = (e) => (t) => p((n) => ({
|
|
193
204
|
...n,
|
|
194
205
|
[e]: t.target.value
|
|
195
|
-
})),
|
|
196
|
-
name:
|
|
197
|
-
type:
|
|
198
|
-
status:
|
|
199
|
-
industry:
|
|
200
|
-
contactName:
|
|
201
|
-
contactEmail:
|
|
202
|
-
contactPhone:
|
|
203
|
-
notes:
|
|
204
|
-
}), [
|
|
205
|
-
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, {
|
|
206
217
|
open: !0,
|
|
207
218
|
onClose: t,
|
|
208
219
|
title: e ? "Edit client" : "New client",
|
|
209
|
-
footer: /* @__PURE__ */
|
|
220
|
+
footer: /* @__PURE__ */ I(P, { children: [/* @__PURE__ */ F(L, {
|
|
210
221
|
variant: "outline",
|
|
211
222
|
onClick: t,
|
|
212
|
-
disabled:
|
|
223
|
+
disabled: _,
|
|
213
224
|
children: "Cancel"
|
|
214
|
-
}), /* @__PURE__ */
|
|
225
|
+
}), /* @__PURE__ */ F(L, {
|
|
215
226
|
onClick: () => {
|
|
216
|
-
if (
|
|
217
|
-
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.");
|
|
218
229
|
e ? s.mutate({
|
|
219
230
|
id: e.id,
|
|
220
|
-
input:
|
|
231
|
+
input: b
|
|
221
232
|
}, {
|
|
222
233
|
onSuccess: () => {
|
|
223
|
-
i(
|
|
234
|
+
c("psw.client.updated", { clientId: e.id }), i(b.name), t();
|
|
224
235
|
},
|
|
225
236
|
onError: n
|
|
226
|
-
}) : a.mutate(
|
|
227
|
-
onSuccess: () => {
|
|
228
|
-
i(
|
|
237
|
+
}) : a.mutate(b, {
|
|
238
|
+
onSuccess: (e) => {
|
|
239
|
+
c("psw.client.created", { clientId: e.pswCreateClient.id }), i(b.name), t();
|
|
229
240
|
},
|
|
230
241
|
onError: n
|
|
231
242
|
});
|
|
232
243
|
},
|
|
233
|
-
disabled:
|
|
234
|
-
children:
|
|
244
|
+
disabled: _,
|
|
245
|
+
children: _ ? "Saving…" : e ? "Save changes" : "Create client"
|
|
235
246
|
})] }),
|
|
236
|
-
children: /* @__PURE__ */
|
|
247
|
+
children: /* @__PURE__ */ I("div", {
|
|
237
248
|
className: "space-y-3",
|
|
238
249
|
children: [
|
|
239
|
-
|
|
250
|
+
m && /* @__PURE__ */ F(o, {
|
|
240
251
|
tone: "danger",
|
|
241
|
-
children:
|
|
252
|
+
children: m
|
|
242
253
|
}),
|
|
243
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ F(l, {
|
|
244
255
|
label: "Name",
|
|
245
256
|
required: !0,
|
|
246
|
-
children: /* @__PURE__ */
|
|
247
|
-
value:
|
|
248
|
-
onChange:
|
|
257
|
+
children: /* @__PURE__ */ F(y, {
|
|
258
|
+
value: u.name,
|
|
259
|
+
onChange: g("name"),
|
|
249
260
|
placeholder: "Acme Holdings Ltd."
|
|
250
261
|
})
|
|
251
262
|
}),
|
|
252
|
-
/* @__PURE__ */
|
|
263
|
+
/* @__PURE__ */ I("div", {
|
|
253
264
|
className: "grid grid-cols-2 gap-3",
|
|
254
|
-
children: [/* @__PURE__ */
|
|
265
|
+
children: [/* @__PURE__ */ F(l, {
|
|
255
266
|
label: "Type",
|
|
256
|
-
children: /* @__PURE__ */
|
|
257
|
-
value:
|
|
258
|
-
onChange:
|
|
259
|
-
children: x(
|
|
267
|
+
children: /* @__PURE__ */ F(f, {
|
|
268
|
+
value: u.type,
|
|
269
|
+
onChange: g("type"),
|
|
270
|
+
children: x(R)
|
|
260
271
|
})
|
|
261
|
-
}), /* @__PURE__ */
|
|
272
|
+
}), /* @__PURE__ */ F(l, {
|
|
262
273
|
label: "Status",
|
|
263
|
-
children: /* @__PURE__ */
|
|
264
|
-
value:
|
|
265
|
-
onChange:
|
|
266
|
-
children: x(
|
|
274
|
+
children: /* @__PURE__ */ F(f, {
|
|
275
|
+
value: u.status,
|
|
276
|
+
onChange: g("status"),
|
|
277
|
+
children: x(z)
|
|
267
278
|
})
|
|
268
279
|
})]
|
|
269
280
|
}),
|
|
270
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ F(l, {
|
|
271
282
|
label: "Industry",
|
|
272
|
-
children: /* @__PURE__ */
|
|
273
|
-
value:
|
|
274
|
-
onChange:
|
|
283
|
+
children: /* @__PURE__ */ F(y, {
|
|
284
|
+
value: u.industry,
|
|
285
|
+
onChange: g("industry"),
|
|
275
286
|
placeholder: "Financial services"
|
|
276
287
|
})
|
|
277
288
|
}),
|
|
278
|
-
/* @__PURE__ */
|
|
289
|
+
/* @__PURE__ */ I("div", {
|
|
279
290
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
|
|
280
|
-
children: [/* @__PURE__ */
|
|
291
|
+
children: [/* @__PURE__ */ F(l, {
|
|
281
292
|
label: "Contact name",
|
|
282
|
-
children: /* @__PURE__ */
|
|
283
|
-
value:
|
|
284
|
-
onChange:
|
|
293
|
+
children: /* @__PURE__ */ F(y, {
|
|
294
|
+
value: u.contactName,
|
|
295
|
+
onChange: g("contactName")
|
|
285
296
|
})
|
|
286
|
-
}), /* @__PURE__ */
|
|
297
|
+
}), /* @__PURE__ */ F(l, {
|
|
287
298
|
label: "Contact email",
|
|
288
|
-
children: /* @__PURE__ */
|
|
299
|
+
children: /* @__PURE__ */ F(y, {
|
|
289
300
|
type: "email",
|
|
290
|
-
value:
|
|
291
|
-
onChange:
|
|
301
|
+
value: u.contactEmail,
|
|
302
|
+
onChange: g("contactEmail")
|
|
292
303
|
})
|
|
293
304
|
})]
|
|
294
305
|
}),
|
|
295
|
-
/* @__PURE__ */
|
|
306
|
+
/* @__PURE__ */ F(l, {
|
|
296
307
|
label: "Contact phone",
|
|
297
|
-
children: /* @__PURE__ */
|
|
298
|
-
value:
|
|
299
|
-
onChange:
|
|
308
|
+
children: /* @__PURE__ */ F(y, {
|
|
309
|
+
value: u.contactPhone,
|
|
310
|
+
onChange: g("contactPhone")
|
|
300
311
|
})
|
|
301
312
|
}),
|
|
302
|
-
/* @__PURE__ */
|
|
313
|
+
/* @__PURE__ */ F(l, {
|
|
303
314
|
label: "Notes",
|
|
304
|
-
children: /* @__PURE__ */
|
|
305
|
-
value:
|
|
306
|
-
onChange:
|
|
315
|
+
children: /* @__PURE__ */ F(v, {
|
|
316
|
+
value: u.notes,
|
|
317
|
+
onChange: g("notes")
|
|
307
318
|
})
|
|
308
319
|
})
|
|
309
320
|
]
|
|
@@ -311,6 +322,6 @@ var L = ["ORGANIZATION", "INDIVIDUAL"], R = [
|
|
|
311
322
|
});
|
|
312
323
|
};
|
|
313
324
|
//#endregion
|
|
314
|
-
export {
|
|
325
|
+
export { U as ClientsPage };
|
|
315
326
|
|
|
316
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, 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 {\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 [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\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 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":";;;;;;;;;;AAmCA,IAAM,IAAe,CAAC,gBAAgB,aAAa,EAC7C,IAAqC;CAAC;CAAY;CAAU;CAAY;CAAW,EAEnF,KAAY,MAChB,EACG,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,MAAM,GAAG,EAAE,CACX,KAAK,MAAM,EAAE,IAAI,aAAa,IAAI,GAAG,CACrC,KAAK,GAAG,IAAI,KAGJ,KAAoD,EAAE,SAAM,mBACvE,kBAAC,QAAD;CACE,WAAW,EACT,kJACA,EACD;CACD,eAAA;WAEC,EAAS,EAAK;CACV,CAAA,EAaH,IAAuB;CAC3B,MAAM;CACN,MAAM;CACN,QAAQ;CACR,UAAU;CACV,aAAa;CACb,cAAc;CACd,cAAc;CACd,OAAO;CACR,EAEY,UAAwB;CACnC,IAAM,IAAM,GAAQ,EACd,EAAE,eAAY,gBAAa,GAAc,EACzC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAc,KAAmB,EAA+B,GAAG,EACpE,CAAC,GAAS,KAAc,EAA2B,KAAK,EACxD,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAQ,KAAa,EAA8D,KAAK,EAEzF,EAAE,SAAM,cAAW,UAAO,eAAY,EAAW;EACrD,QAAQ,EAAO,MAAM,IAAI,KAAA;EACzB,QAAQ,KAAgB,KAAA;EACzB,CAAC;AAEF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,OAAM;IACN,UAAS;IACT,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;IACnC,SACE,kBAAC,GAAD;KACE,eAAe;AAEb,MADA,EAAW,4BAA4B,EACvC,EAAY,GAAK;;eAHrB,CAME,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,cAC5B;;IAEX,CAAA;GAED,KACC,kBAAC,GAAD;IAAQ,MAAM,EAAO;IAAM,eAAe,EAAU,KAAK;cACtD,EAAO;IACD,CAAA;GAGX,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,2FAA4F,CAAA,EAC9G,kBAAC,GAAD;MACE,aAAY;MACZ,OAAO;MACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;MAC1C,YAAY,MAAM;AAChB,OAAI,EAAE,QAAQ,WAAW,EAAO,MAAM,IACpC,EAAS,wBAAwB;QAC/B,YAAY;QACZ,aAAa,EAAO,MAAM,CAAC;QAC5B,CAAC;;MAGN,WAAU;MACV,CAAA,CACE;QACN,kBAAC,GAAD;KACE,OAAO;KACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAA8B;KACxE,WAAU;eAHZ,CAKE,kBAAC,UAAD;MAAQ,OAAM;gBAAG;MAAqB,CAAA,EACrC,EAAY,EAAgB,CAChB;OACX;;GAEL,IACC,kBAAC,GAAD,EAAgB,CAAA,GACd,IACF,kBAAC,GAAD;IAAmB;IAAO,eAAe,KAAK,GAAS;IAAI,CAAA,GACzD,CAAC,KAAQ,EAAK,MAAM,WAAW,IACjC,kBAAC,GAAD;IACE,OAAM;IACN,aAAY;IACZ,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;IACnC,QACE,kBAAC,GAAD;KAAQ,eAAe,EAAY,GAAK;eAAxC,CACE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,cAC5B;;IAEX,CAAA,GAEF,kBAAC,GAAD;IAAa,OAAO,GAAG,EAAK,WAAW,SAAS,EAAK,eAAe,IAAI,KAAK;cAC3E,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD,EAAA,UAAA;KACE,kBAAC,GAAD,EAAA,UAAI,QAAS,CAAA;KACb,kBAAC,GAAD,EAAA,UAAI,QAAS,CAAA;KACb,kBAAC,GAAD,EAAA,UAAI,YAAa,CAAA;KACjB,kBAAC,GAAD,EAAA,UAAI,UAAW,CAAA;KACf,kBAAC,GAAD,EAAA,UAAI,SAAU,CAAA;KACd,kBAAC,GAAD;MAAI,WAAU;gBAAa;MAAY,CAAA;KACpC,EAAA,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAK,MAAM,KAAK,MACf,kBAAC,MAAD;KAEE,WAAU;KACV,eAAe,EAAI,WAAW,EAAE,KAAK;eAHvC;MAKE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAQ,MAAM,EAAE,MAAQ,CAAA,EACxB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;oBAAY,EAAE;UAAY,CAAA,EAC1C,kBAAC,GAAD,EAAc,WAAU,gGAAiG,CAAA,CACrH;YACL,EAAE,cACD,kBAAC,OAAD;SAAK,WAAU;mBAAuC,EAAE;SAAkB,CAAA,GACxE,KACA;UACF;UACH,CAAA;MACL,kBAAC,GAAD,EAAA,UACE,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CACG,EAAE,SAAS,iBACV,kBAAC,GAAD,EAAW,WAAU,kCAAmC,CAAA,GAExD,kBAAC,GAAD,EAAM,WAAU,kCAAmC,CAAA,EAEpD,EAAE,SAAS,iBAAiB,iBAAiB,aACzC;UACJ,CAAA;MACL,kBAAC,GAAD,EAAA,UAAK,EAAE,YAAY,KAAS,CAAA;MAC5B,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAY,QAAQ,EAAE,QAAU,CAAA,EAC7B,CAAA;MACL,kBAAC,GAAD;OAAI,WAAU;iBAAqB,EAAQ,EAAE,UAAU;OAAM,CAAA;MAC7D,kBAAC,GAAD;OAAI,WAAU;iBACZ,kBAAC,OAAD;QACE,WAAU;QACV,UAAU,MAAO,EAAG,iBAAiB;QACrC,MAAK;kBAHP,CAKE,kBAAC,GAAD;SACE,SAAQ;SACR,MAAK;SACL,eAAe,EAAW,EAAE;SAC5B,cAAW;mBAEX,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;SACvB,CAAA,EACR,EAAE,WAAW,cACZ,kBAAC,GAAD;SACE,IAAI,EAAE;SACN,SAAS,MACP,EACE,IACI;UAAE,MAAM;UAAW,MAAM,GAAG,EAAE,KAAK;UAAa,GAChD;UAAE,MAAM;UAAU,MAAM;UAA6B,CAC1D;SAEH,CAAA,CAEA;;OACH,CAAA;MACF;OA7DE,EAAE,GA6DJ,CACL,EACI,CAAA,CACE,EAAA,CAAA;IACA,CAAA;GAGf,KACC,kBAAC,GAAD;IACE,eAAe,EAAY,GAAM;IACjC,UAAU,MAAS,EAAU;KAAE,MAAM;KAAW,MAAM,GAAG,EAAK;KAAY,CAAC;IAC3E,CAAA;GAEH,KACC,kBAAC,GAAD;IACE,QAAQ;IACR,eAAe,EAAW,KAAK;IAC/B,UAAU,MAAS,EAAU;KAAE,MAAM;KAAW,MAAM,GAAG,EAAK;KAAY,CAAC;IAC3E,CAAA;GAEA;;GAIJ,KAAoE,EAAE,OAAI,gBAAa;CAC3F,IAAM,IAAU,GAAkB,EAC5B,EAAE,gBAAa,GAAc;AACnC,QACE,kBAAC,GAAD;EACE,SAAQ;EACR,MAAK;EACL,cAAW;EACX,UAAU,EAAQ;EAClB,eAAe;AACR,UAAO,QAAQ,6DAA6D,IACjF,EAAQ,OAAO,GAAI;IACjB,YAAY,MAAM;AAEhB,KADA,EAAS,uBAAuB,EAAE,UAAU,GAAI,CAAC,EACjD,EAAO,EAAQ,EAAG;;IAEpB,eAAe,EAAO,GAAM;IAC7B,CAAC;;YAGJ,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;EACxB,CAAA;GAIP,KAIA,EAAE,WAAQ,YAAS,iBAAc;CACrC,IAAM,IAAS,GAAiB,EAC1B,IAAS,GAAiB,EAC1B,EAAE,gBAAa,GAAc,EAC7B,CAAC,GAAM,KAAW,EACtB,IACI;EACE,MAAM,EAAO;EACb,MAAM,EAAO;EACb,QAAQ,EAAO;EACf,UAAU,EAAO,YAAY;EAC7B,aAAa,EAAO,eAAe;EACnC,cAAc,EAAO,gBAAgB;EACrC,cAAc,EAAO,gBAAgB;EACrC,OAAO,EAAO,SAAS;EACxB,GACD,EACL,EACK,CAAC,GAAK,KAAU,EAAwB,KAAK,EAC7C,KAAO,OAAwB,MACnC,GAAS,OAAO;EAAE,GAAG;GAAI,IAAI,EAAE,OAAO;EAAO,EAAE,EAC3C,IAAU,EAAO,aAAa,EAAO,WAErC,IAAU,SACP;EACL,MAAM,EAAK,KAAK,MAAM;EACtB,MAAM,EAAK;EACX,QAAQ,EAAK;EACb,UAAU,EAAK,SAAS,MAAM,IAAI;EAClC,aAAa,EAAK,YAAY,MAAM,IAAI;EACxC,cAAc,EAAK,aAAa,MAAM,IAAI;EAC1C,cAAc,EAAK,aAAa,MAAM,IAAI;EAC1C,OAAO,EAAK,MAAM,MAAM,IAAI;EAC7B,GACD,CAAC,EAAK,CACP;AA8BD,QACE,kBAAC,GAAD;EACE,MAAA;EACS;EACT,OAAO,IAAS,gBAAgB;EAChC,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAQ,SAAQ;GAAU,SAAS;GAAS,UAAU;aAAS;GAEtD,CAAA,EACT,kBAAC,GAAD;GAAQ,eAtCK;AAEnB,QADA,EAAO,KAAK,EACR,CAAC,EAAQ,KAAM,QAAO,EAAO,2BAA2B;IAC5D,IAAM,KAAW,MAAe,EAAO,aAAa,QAAQ,EAAE,UAAU,eAAe;AACvF,IAAI,IACF,EAAO,OACL;KAAE,IAAI,EAAO;KAAI,OAAO;KAAS,EACjC;KACE,iBAAiB;AAGf,MAFA,EAAS,sBAAsB,EAAE,UAAU,EAAO,IAAI,CAAC,EACvD,EAAQ,EAAQ,KAAK,EACrB,GAAS;;KAEX;KACD,CACF,GAED,EAAO,OAAO,GAAS;KACrB,YAAY,MAAY;AAGtB,MAFA,EAAS,sBAAsB,EAAE,UAAU,EAAQ,gBAAgB,IAAI,CAAC,EACxE,EAAQ,EAAQ,KAAK,EACrB,GAAS;;KAEX;KACD,CAAC;;GAc2B,UAAU;aAChC,IAAU,YAAY,IAAS,iBAAiB;GAC1C,CAAA,CACR,EAAA,CAAA;YAGL,kBAAC,OAAD;GAAK,WAAU;aAAf;IACG,KAAO,kBAAC,GAAD;KAAQ,MAAK;eAAU;KAAa,CAAA;IAC5C,kBAAC,GAAD;KAAO,OAAM;KAAO,UAAA;eAClB,kBAAC,GAAD;MAAW,OAAO,EAAK;MAAM,UAAU,EAAI,OAAO;MAAE,aAAY;MAAuB,CAAA;KACjF,CAAA;IACR,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAO,OAAM;gBACX,kBAAC,GAAD;OAAc,OAAO,EAAK;OAAM,UAAU,EAAI,OAAO;iBAClD,EAAY,EAAa;OACb,CAAA;MACT,CAAA,EACR,kBAAC,GAAD;MAAO,OAAM;gBACX,kBAAC,GAAD;OAAc,OAAO,EAAK;OAAQ,UAAU,EAAI,SAAS;iBACtD,EAAY,EAAgB;OAChB,CAAA;MACT,CAAA,CACJ;;IACN,kBAAC,GAAD;KAAO,OAAM;eACX,kBAAC,GAAD;MACE,OAAO,EAAK;MACZ,UAAU,EAAI,WAAW;MACzB,aAAY;MACZ,CAAA;KACI,CAAA;IACR,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAO,OAAM;gBACX,kBAAC,GAAD;OAAW,OAAO,EAAK;OAAa,UAAU,EAAI,cAAc;OAAI,CAAA;MAC9D,CAAA,EACR,kBAAC,GAAD;MAAO,OAAM;gBACX,kBAAC,GAAD;OAAW,MAAK;OAAQ,OAAO,EAAK;OAAc,UAAU,EAAI,eAAe;OAAI,CAAA;MAC7E,CAAA,CACJ;;IACN,kBAAC,GAAD;KAAO,OAAM;eACX,kBAAC,GAAD;MAAW,OAAO,EAAK;MAAc,UAAU,EAAI,eAAe;MAAI,CAAA;KAChE,CAAA;IACR,kBAAC,GAAD;KAAO,OAAM;eACX,kBAAC,GAAD;MAAU,OAAO,EAAK;MAAO,UAAU,EAAI,QAAQ;MAAI,CAAA;KACjD,CAAA;IACJ;;EACA,CAAA"}
|
|
@@ -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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConflictsPage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/ConflictsPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAsChC,eAAO,MAAM,aAAa,EAAE,EA+G3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardPage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/DashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AA0C3C,eAAO,MAAM,aAAa,EAAE,EA0G3B,CAAC"}
|