@burdenoff/microfe-proserviceworld 2026.706.3 → 2026.709.2
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 +3 -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/ProServiceWorldRoutes.js +95 -42
- package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
- package/dist/proserviceworld/components/DiscussionThread.d.ts +12 -0
- package/dist/proserviceworld/components/DiscussionThread.d.ts.map +1 -0
- package/dist/proserviceworld/components/FeatureFlaggedPage.d.ts +8 -0
- package/dist/proserviceworld/components/FeatureFlaggedPage.d.ts.map +1 -0
- package/dist/proserviceworld/components/FeatureFlaggedPage.js +17 -0
- package/dist/proserviceworld/components/FeatureFlaggedPage.js.map +1 -0
- package/dist/proserviceworld/components/LoadMore.d.ts +12 -0
- package/dist/proserviceworld/components/LoadMore.d.ts.map +1 -0
- package/dist/proserviceworld/components/LoadMore.js +30 -0
- package/dist/proserviceworld/components/LoadMore.js.map +1 -0
- package/dist/proserviceworld/components/TagPicker.d.ts +11 -0
- package/dist/proserviceworld/components/TagPicker.d.ts.map +1 -0
- package/dist/proserviceworld/components/TagPicker.js +31 -0
- package/dist/proserviceworld/components/TagPicker.js.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/usePageViewAnalytics.d.ts +10 -0
- package/dist/proserviceworld/hooks/usePageViewAnalytics.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/usePageViewAnalytics.js +24 -0
- package/dist/proserviceworld/hooks/usePageViewAnalytics.js.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/hooks/useProServiceWorldApi.js +47 -27
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -1
- package/dist/proserviceworld/i18n/index.d.ts +13 -0
- package/dist/proserviceworld/i18n/index.d.ts.map +1 -0
- package/dist/proserviceworld/i18n/index.js +171 -0
- package/dist/proserviceworld/i18n/index.js.map +1 -0
- package/dist/proserviceworld/index.d.ts +6 -0
- package/dist/proserviceworld/index.d.ts.map +1 -0
- package/dist/proserviceworld/index.js +2 -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 +218 -155
- 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 +201 -140
- 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 +212 -158
- 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/native.d.ts +23 -0
- package/dist/proserviceworld/utils/native.d.ts.map +1 -0
- package/dist/proserviceworld/utils/native.js +14 -0
- package/dist/proserviceworld/utils/native.js.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,173 +1,223 @@
|
|
|
1
|
-
import { useClients as e, useCloseMatter as t, useCreateMatter as n, useMatters as r, usePracticeAreas as i } from "../hooks/useProServiceWorldApi.js";
|
|
2
|
-
import { Banner as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { useClients as e, useCloseMatter as t, useCreateMatter as n, useMatters as r, usePracticeAreas as i, useUpdateMatter as a } from "../hooks/useProServiceWorldApi.js";
|
|
2
|
+
import { Banner as o, Empty as s, ErrorState as c, Field as l, LoadingBlock as u, MetricCard as d, Modal as f, NativeSelect as p, PageHeader as m, SectionCard as h, StatusPill as g, TableWrap as _, Td as v, TextArea as y, TextInput as b, Th as x, enumOptions as S, fmtDate as C } from "../components/ui.js";
|
|
3
|
+
import { useAnalytics as w } from "../hooks/useAnalytics.js";
|
|
4
|
+
import { impactFeedback as T } from "../utils/native.js";
|
|
5
|
+
import { TagPicker as E } from "../components/TagPicker.js";
|
|
6
|
+
import { LoadMore as ee } from "../components/LoadMore.js";
|
|
7
|
+
import { useMemo as te, useState as D } from "react";
|
|
8
|
+
import { AlertTriangle as O, CheckCircle2 as k, CircleDot as A, FolderKanban as j, Lock as M, Plus as N, Search as P } from "lucide-react";
|
|
9
|
+
import { Fragment as F, jsx as I, jsxs as L } from "react/jsx-runtime";
|
|
10
|
+
import { Button as R } from "@burdenoff/fe-libs/ui";
|
|
7
11
|
//#region src/proserviceworld/pages/MattersPage.tsx
|
|
8
|
-
var
|
|
12
|
+
var z = [
|
|
9
13
|
"OPEN",
|
|
10
14
|
"ON_HOLD",
|
|
11
15
|
"CLOSED",
|
|
12
16
|
"ARCHIVED"
|
|
13
|
-
],
|
|
17
|
+
], B = [
|
|
14
18
|
"LOW",
|
|
15
19
|
"MEDIUM",
|
|
16
20
|
"HIGH",
|
|
17
21
|
"CRITICAL"
|
|
18
|
-
],
|
|
22
|
+
], ne = () => /* @__PURE__ */ I("span", {
|
|
19
23
|
className: "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md bg-status-warning-bg-subtle text-status-warning-text",
|
|
20
24
|
title: "Privileged / confidential",
|
|
21
25
|
"aria-label": "Privileged",
|
|
22
|
-
children: /* @__PURE__ */ M
|
|
23
|
-
}),
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}),
|
|
28
|
-
|
|
26
|
+
children: /* @__PURE__ */ I(M, { className: "h-3 w-3" })
|
|
27
|
+
}), V = 25, H = () => {
|
|
28
|
+
let { emitIntent: e, emitFact: n } = w(), [i, l] = D(""), [f, y] = D(""), [B, H] = D(!1), [U, W] = D(null), [G, K] = D({
|
|
29
|
+
limit: V,
|
|
30
|
+
offset: 0
|
|
31
|
+
}), { data: q, isLoading: J, error: Y, refetch: X } = r({
|
|
32
|
+
search: i.trim() || void 0,
|
|
33
|
+
status: f || void 0,
|
|
34
|
+
pagination: G
|
|
35
|
+
}), Z = t(), ie = a(), Q = te(() => q?.items ?? [], [q]), ae = Q.filter((e) => e.status === "OPEN").length, oe = Q.filter((e) => e.isPrivileged).length, $ = Q.filter((e) => e.priority === "HIGH" || e.priority === "CRITICAL").length;
|
|
36
|
+
return /* @__PURE__ */ L("div", {
|
|
29
37
|
className: "space-y-6",
|
|
30
38
|
children: [
|
|
31
|
-
/* @__PURE__ */
|
|
39
|
+
/* @__PURE__ */ I(m, {
|
|
32
40
|
title: "Matters",
|
|
33
41
|
subtitle: "The regulated threads of work — legal matters, audits, filings — with their own deadlines and sensitive-document handling.",
|
|
34
|
-
icon: /* @__PURE__ */
|
|
35
|
-
actions: /* @__PURE__ */
|
|
36
|
-
onClick: () =>
|
|
37
|
-
|
|
42
|
+
icon: /* @__PURE__ */ I(j, { className: "h-6 w-6" }),
|
|
43
|
+
actions: /* @__PURE__ */ L(R, {
|
|
44
|
+
onClick: () => {
|
|
45
|
+
T("light"), e("psw.matter.create_clicked"), H(!0);
|
|
46
|
+
},
|
|
47
|
+
children: [/* @__PURE__ */ I(N, { className: "mr-1.5 h-4 w-4" }), "New matter"]
|
|
38
48
|
})
|
|
39
49
|
}),
|
|
40
|
-
|
|
41
|
-
tone:
|
|
42
|
-
onClose: () =>
|
|
43
|
-
children:
|
|
50
|
+
U && /* @__PURE__ */ I(o, {
|
|
51
|
+
tone: U.tone,
|
|
52
|
+
onClose: () => W(null),
|
|
53
|
+
children: U.text
|
|
44
54
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ L("div", {
|
|
46
56
|
className: "flex flex-col gap-2 sm:flex-row sm:items-center",
|
|
47
|
-
children: [/* @__PURE__ */
|
|
57
|
+
children: [/* @__PURE__ */ L("div", {
|
|
48
58
|
className: "relative flex-1",
|
|
49
|
-
children: [/* @__PURE__ */
|
|
59
|
+
children: [/* @__PURE__ */ I(P, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ I(b, {
|
|
50
60
|
placeholder: "Search matters…",
|
|
51
|
-
value:
|
|
52
|
-
onChange: (e) =>
|
|
61
|
+
value: i,
|
|
62
|
+
onChange: (e) => {
|
|
63
|
+
l(e.target.value), K({
|
|
64
|
+
limit: V,
|
|
65
|
+
offset: 0
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
onKeyDown: (e) => {
|
|
69
|
+
e.key === "Enter" && i.trim() && n("psw.search.performed", {
|
|
70
|
+
entityType: "matter",
|
|
71
|
+
queryLength: i.trim().length
|
|
72
|
+
});
|
|
73
|
+
},
|
|
53
74
|
className: "pl-9"
|
|
54
75
|
})]
|
|
55
|
-
}), /* @__PURE__ */
|
|
56
|
-
value:
|
|
57
|
-
onChange: (e) =>
|
|
76
|
+
}), /* @__PURE__ */ L(p, {
|
|
77
|
+
value: f,
|
|
78
|
+
onChange: (e) => {
|
|
79
|
+
y(e.target.value), K({
|
|
80
|
+
limit: V,
|
|
81
|
+
offset: 0
|
|
82
|
+
});
|
|
83
|
+
},
|
|
58
84
|
className: "sm:w-48",
|
|
59
|
-
children: [/* @__PURE__ */
|
|
85
|
+
children: [/* @__PURE__ */ I("option", {
|
|
60
86
|
value: "",
|
|
61
87
|
children: "All statuses"
|
|
62
|
-
}),
|
|
88
|
+
}), S(z)]
|
|
63
89
|
})]
|
|
64
90
|
}),
|
|
65
|
-
|
|
66
|
-
error:
|
|
67
|
-
onRetry: () => void
|
|
68
|
-
}) : !
|
|
91
|
+
J ? /* @__PURE__ */ I(u, {}) : Y ? /* @__PURE__ */ I(c, {
|
|
92
|
+
error: Y,
|
|
93
|
+
onRetry: () => void X()
|
|
94
|
+
}) : !q || q.items.length === 0 ? /* @__PURE__ */ I(s, {
|
|
69
95
|
title: "No matters yet",
|
|
70
96
|
description: "Open a matter to track a regulated thread of work for a client.",
|
|
71
|
-
icon: /* @__PURE__ */
|
|
72
|
-
action: /* @__PURE__ */
|
|
73
|
-
onClick: () =>
|
|
74
|
-
children: [/* @__PURE__ */
|
|
97
|
+
icon: /* @__PURE__ */ I(j, { className: "h-8 w-8" }),
|
|
98
|
+
action: /* @__PURE__ */ L(R, {
|
|
99
|
+
onClick: () => H(!0),
|
|
100
|
+
children: [/* @__PURE__ */ I(N, { className: "mr-1.5 h-4 w-4" }), "New matter"]
|
|
75
101
|
})
|
|
76
|
-
}) : /* @__PURE__ */
|
|
102
|
+
}) : /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ L("div", {
|
|
77
103
|
className: "grid grid-cols-2 gap-3 lg:grid-cols-4",
|
|
78
104
|
children: [
|
|
79
|
-
/* @__PURE__ */
|
|
105
|
+
/* @__PURE__ */ I(d, {
|
|
80
106
|
label: "Matters",
|
|
81
|
-
value:
|
|
82
|
-
icon: /* @__PURE__ */
|
|
107
|
+
value: q.totalCount,
|
|
108
|
+
icon: /* @__PURE__ */ I(j, { className: "h-4 w-4" })
|
|
83
109
|
}),
|
|
84
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ I(d, {
|
|
85
111
|
label: "Open",
|
|
86
|
-
value:
|
|
87
|
-
icon: /* @__PURE__ */
|
|
112
|
+
value: ae,
|
|
113
|
+
icon: /* @__PURE__ */ I(A, { className: "h-4 w-4" }),
|
|
88
114
|
tone: "accent"
|
|
89
115
|
}),
|
|
90
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ I(d, {
|
|
91
117
|
label: "Privileged",
|
|
92
|
-
value:
|
|
93
|
-
icon: /* @__PURE__ */ M
|
|
118
|
+
value: oe,
|
|
119
|
+
icon: /* @__PURE__ */ I(M, { className: "h-4 w-4" }),
|
|
94
120
|
tone: "warning"
|
|
95
121
|
}),
|
|
96
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ I(d, {
|
|
97
123
|
label: "High priority",
|
|
98
|
-
value:
|
|
99
|
-
icon: /* @__PURE__ */
|
|
100
|
-
tone:
|
|
124
|
+
value: $,
|
|
125
|
+
icon: /* @__PURE__ */ I(O, { className: "h-4 w-4" }),
|
|
126
|
+
tone: $ ? "danger" : "neutral"
|
|
101
127
|
})
|
|
102
128
|
]
|
|
103
|
-
}), /* @__PURE__ */
|
|
104
|
-
title: `${
|
|
105
|
-
children: /* @__PURE__ */
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
/* @__PURE__ */
|
|
108
|
-
/* @__PURE__ */
|
|
109
|
-
/* @__PURE__ */
|
|
110
|
-
/* @__PURE__ */
|
|
111
|
-
/* @__PURE__ */
|
|
129
|
+
}), /* @__PURE__ */ L(h, {
|
|
130
|
+
title: `${q.totalCount} matter${q.totalCount === 1 ? "" : "s"}`,
|
|
131
|
+
children: [/* @__PURE__ */ L(_, { children: [/* @__PURE__ */ I("thead", { children: /* @__PURE__ */ L("tr", { children: [
|
|
132
|
+
/* @__PURE__ */ I(x, { children: "Matter" }),
|
|
133
|
+
/* @__PURE__ */ I(x, { children: "Client" }),
|
|
134
|
+
/* @__PURE__ */ I(x, { children: "Priority" }),
|
|
135
|
+
/* @__PURE__ */ I(x, { children: "Status" }),
|
|
136
|
+
/* @__PURE__ */ I(x, { children: "Due" }),
|
|
137
|
+
/* @__PURE__ */ I(x, { children: "Tags" }),
|
|
138
|
+
/* @__PURE__ */ I(x, {
|
|
112
139
|
className: "text-right",
|
|
113
140
|
children: "Actions"
|
|
114
141
|
})
|
|
115
|
-
] }) }), /* @__PURE__ */
|
|
142
|
+
] }) }), /* @__PURE__ */ I("tbody", { children: q.items.map((e) => /* @__PURE__ */ L("tr", {
|
|
116
143
|
className: "transition-colors hover:bg-bg-sunken/60",
|
|
117
144
|
children: [
|
|
118
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ L(v, { children: [/* @__PURE__ */ L("span", {
|
|
119
146
|
className: "flex items-center gap-2 font-medium text-text-primary",
|
|
120
|
-
children: [e.isPrivileged && /* @__PURE__ */
|
|
147
|
+
children: [e.isPrivileged && /* @__PURE__ */ I(ne, {}), /* @__PURE__ */ I("span", {
|
|
121
148
|
className: "truncate",
|
|
122
149
|
children: e.title
|
|
123
150
|
})]
|
|
124
|
-
}), e.reference ? /* @__PURE__ */
|
|
151
|
+
}), e.reference ? /* @__PURE__ */ L("div", {
|
|
125
152
|
className: "mt-0.5 pl-0 text-xs text-text-tertiary",
|
|
126
153
|
children: ["Ref: ", e.reference]
|
|
127
154
|
}) : null] }),
|
|
128
|
-
/* @__PURE__ */
|
|
155
|
+
/* @__PURE__ */ I(v, {
|
|
129
156
|
className: "text-text-primary",
|
|
130
157
|
children: e.client?.name ?? "—"
|
|
131
158
|
}),
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
-
/* @__PURE__ */
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
-
/* @__PURE__ */
|
|
159
|
+
/* @__PURE__ */ I(v, { children: /* @__PURE__ */ I(g, { status: e.priority }) }),
|
|
160
|
+
/* @__PURE__ */ I(v, { children: /* @__PURE__ */ I(g, { status: e.status }) }),
|
|
161
|
+
/* @__PURE__ */ I(v, { children: C(e.dueDate) }),
|
|
162
|
+
/* @__PURE__ */ I(v, { children: /* @__PURE__ */ I(E, {
|
|
163
|
+
entityType: "PswMatter",
|
|
164
|
+
entityId: e.id,
|
|
165
|
+
tags: e.tags ?? [],
|
|
166
|
+
onChange: async (t) => {
|
|
167
|
+
await ie.mutateAsync({
|
|
168
|
+
id: e.id,
|
|
169
|
+
input: { tags: t }
|
|
170
|
+
}), X();
|
|
171
|
+
},
|
|
172
|
+
maxTags: 5
|
|
173
|
+
}) }),
|
|
174
|
+
/* @__PURE__ */ I(v, {
|
|
136
175
|
className: "text-right",
|
|
137
|
-
children: e.status !== "CLOSED" && e.status !== "ARCHIVED" ? /* @__PURE__ */
|
|
176
|
+
children: e.status !== "CLOSED" && e.status !== "ARCHIVED" ? /* @__PURE__ */ L(R, {
|
|
138
177
|
variant: "ghost",
|
|
139
178
|
size: "sm",
|
|
140
|
-
disabled:
|
|
141
|
-
onClick: () =>
|
|
142
|
-
onSuccess: () =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
179
|
+
disabled: Z.isPending,
|
|
180
|
+
onClick: () => Z.mutate(e.id, {
|
|
181
|
+
onSuccess: () => {
|
|
182
|
+
n("psw.matter.closed", { matterId: e.id }), W({
|
|
183
|
+
tone: "success",
|
|
184
|
+
text: `${e.title} closed.`
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
onError: (e) => W({
|
|
147
188
|
tone: "danger",
|
|
148
189
|
text: e instanceof Error ? e.message : "Failed."
|
|
149
190
|
})
|
|
150
191
|
}),
|
|
151
|
-
children: [/* @__PURE__ */
|
|
152
|
-
}) : /* @__PURE__ */
|
|
192
|
+
children: [/* @__PURE__ */ I(k, { className: "mr-1 h-4 w-4" }), " Close"]
|
|
193
|
+
}) : /* @__PURE__ */ I("span", {
|
|
153
194
|
className: "text-xs text-text-tertiary",
|
|
154
|
-
children: e.closedAt ? `Closed ${
|
|
195
|
+
children: e.closedAt ? `Closed ${C(e.closedAt)}` : "—"
|
|
155
196
|
})
|
|
156
197
|
})
|
|
157
198
|
]
|
|
158
|
-
}, e.id)) })] })
|
|
199
|
+
}, e.id)) })] }), /* @__PURE__ */ I(ee, {
|
|
200
|
+
hasMore: q?.pageInfo?.hasMore ?? !1,
|
|
201
|
+
loading: J,
|
|
202
|
+
loadedCount: Q.length,
|
|
203
|
+
totalCount: q?.totalCount ?? Q.length,
|
|
204
|
+
onLoadMore: () => K((e) => ({
|
|
205
|
+
limit: V,
|
|
206
|
+
offset: e.offset + V
|
|
207
|
+
}))
|
|
208
|
+
})]
|
|
159
209
|
})] }),
|
|
160
|
-
|
|
161
|
-
onClose: () =>
|
|
162
|
-
onSaved: (e) =>
|
|
210
|
+
B && /* @__PURE__ */ I(re, {
|
|
211
|
+
onClose: () => H(!1),
|
|
212
|
+
onSaved: (e) => W({
|
|
163
213
|
tone: "success",
|
|
164
214
|
text: `${e} opened.`
|
|
165
215
|
})
|
|
166
216
|
})
|
|
167
217
|
]
|
|
168
218
|
});
|
|
169
|
-
},
|
|
170
|
-
let
|
|
219
|
+
}, re = ({ onClose: t, onSaved: r }) => {
|
|
220
|
+
let a = n(), { emitFact: s } = w(), c = e({ pagination: { limit: 100 } }), u = i(), [d, m] = D({
|
|
171
221
|
clientId: "",
|
|
172
222
|
practiceAreaId: "",
|
|
173
223
|
title: "",
|
|
@@ -176,134 +226,138 @@ var F = [
|
|
|
176
226
|
priority: "MEDIUM",
|
|
177
227
|
dueDate: "",
|
|
178
228
|
isPrivileged: !1
|
|
179
|
-
}), [
|
|
229
|
+
}), [h, g] = D(null), _ = (e) => (t) => m((n) => ({
|
|
180
230
|
...n,
|
|
181
231
|
[e]: t.target.value
|
|
182
232
|
}));
|
|
183
|
-
return /* @__PURE__ */
|
|
233
|
+
return /* @__PURE__ */ I(f, {
|
|
184
234
|
open: !0,
|
|
185
235
|
onClose: t,
|
|
186
236
|
title: "New matter",
|
|
187
|
-
footer: /* @__PURE__ */
|
|
237
|
+
footer: /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ I(R, {
|
|
188
238
|
variant: "outline",
|
|
189
239
|
onClick: t,
|
|
190
|
-
disabled:
|
|
240
|
+
disabled: a.isPending,
|
|
191
241
|
children: "Cancel"
|
|
192
|
-
}), /* @__PURE__ */
|
|
242
|
+
}), /* @__PURE__ */ I(R, {
|
|
193
243
|
onClick: () => {
|
|
194
|
-
if (
|
|
195
|
-
if (!
|
|
196
|
-
|
|
197
|
-
clientId:
|
|
198
|
-
practiceAreaId:
|
|
199
|
-
title:
|
|
200
|
-
reference:
|
|
201
|
-
description:
|
|
202
|
-
priority:
|
|
203
|
-
isPrivileged:
|
|
204
|
-
dueDate:
|
|
244
|
+
if (g(null), !d.clientId) return g("Select a client.");
|
|
245
|
+
if (!d.title.trim()) return g("Matter title is required.");
|
|
246
|
+
a.mutate({
|
|
247
|
+
clientId: d.clientId,
|
|
248
|
+
practiceAreaId: d.practiceAreaId || null,
|
|
249
|
+
title: d.title.trim(),
|
|
250
|
+
reference: d.reference.trim() || null,
|
|
251
|
+
description: d.description.trim() || null,
|
|
252
|
+
priority: d.priority,
|
|
253
|
+
isPrivileged: d.isPrivileged,
|
|
254
|
+
dueDate: d.dueDate ? new Date(d.dueDate).toISOString() : null
|
|
205
255
|
}, {
|
|
206
|
-
onSuccess: () => {
|
|
207
|
-
|
|
256
|
+
onSuccess: (e) => {
|
|
257
|
+
let n = e.pswCreateMatter;
|
|
258
|
+
s("psw.matter.created", {
|
|
259
|
+
matterId: n.id,
|
|
260
|
+
clientId: d.clientId
|
|
261
|
+
}), r(d.title.trim()), t();
|
|
208
262
|
},
|
|
209
|
-
onError: (e) =>
|
|
263
|
+
onError: (e) => g(e instanceof Error ? e.message : "Failed.")
|
|
210
264
|
});
|
|
211
265
|
},
|
|
212
|
-
disabled:
|
|
213
|
-
children:
|
|
266
|
+
disabled: a.isPending,
|
|
267
|
+
children: a.isPending ? "Opening…" : "Open matter"
|
|
214
268
|
})] }),
|
|
215
|
-
children: /* @__PURE__ */
|
|
269
|
+
children: /* @__PURE__ */ L("div", {
|
|
216
270
|
className: "space-y-3",
|
|
217
271
|
children: [
|
|
218
|
-
|
|
272
|
+
h && /* @__PURE__ */ I(o, {
|
|
219
273
|
tone: "danger",
|
|
220
|
-
children:
|
|
274
|
+
children: h
|
|
221
275
|
}),
|
|
222
|
-
/* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ I(l, {
|
|
223
277
|
label: "Client",
|
|
224
278
|
required: !0,
|
|
225
|
-
children: /* @__PURE__ */
|
|
226
|
-
value:
|
|
227
|
-
onChange:
|
|
228
|
-
children: [/* @__PURE__ */
|
|
279
|
+
children: /* @__PURE__ */ L(p, {
|
|
280
|
+
value: d.clientId,
|
|
281
|
+
onChange: _("clientId"),
|
|
282
|
+
children: [/* @__PURE__ */ I("option", {
|
|
229
283
|
value: "",
|
|
230
284
|
children: "Select a client…"
|
|
231
|
-
}),
|
|
285
|
+
}), c.data?.items.map((e) => /* @__PURE__ */ I("option", {
|
|
232
286
|
value: e.id,
|
|
233
287
|
children: e.name
|
|
234
288
|
}, e.id))]
|
|
235
289
|
})
|
|
236
290
|
}),
|
|
237
|
-
/* @__PURE__ */
|
|
291
|
+
/* @__PURE__ */ I(l, {
|
|
238
292
|
label: "Title",
|
|
239
293
|
required: !0,
|
|
240
|
-
children: /* @__PURE__ */
|
|
241
|
-
value:
|
|
242
|
-
onChange:
|
|
294
|
+
children: /* @__PURE__ */ I(b, {
|
|
295
|
+
value: d.title,
|
|
296
|
+
onChange: _("title"),
|
|
243
297
|
placeholder: "Regulatory investigation — SEC inquiry"
|
|
244
298
|
})
|
|
245
299
|
}),
|
|
246
|
-
/* @__PURE__ */
|
|
300
|
+
/* @__PURE__ */ L("div", {
|
|
247
301
|
className: "grid grid-cols-2 gap-3",
|
|
248
|
-
children: [/* @__PURE__ */
|
|
302
|
+
children: [/* @__PURE__ */ I(l, {
|
|
249
303
|
label: "Reference",
|
|
250
|
-
children: /* @__PURE__ */
|
|
251
|
-
value:
|
|
252
|
-
onChange:
|
|
304
|
+
children: /* @__PURE__ */ I(b, {
|
|
305
|
+
value: d.reference,
|
|
306
|
+
onChange: _("reference"),
|
|
253
307
|
placeholder: "MAT-2026-014"
|
|
254
308
|
})
|
|
255
|
-
}), /* @__PURE__ */
|
|
309
|
+
}), /* @__PURE__ */ I(l, {
|
|
256
310
|
label: "Priority",
|
|
257
|
-
children: /* @__PURE__ */
|
|
258
|
-
value:
|
|
259
|
-
onChange:
|
|
260
|
-
children:
|
|
311
|
+
children: /* @__PURE__ */ I(p, {
|
|
312
|
+
value: d.priority,
|
|
313
|
+
onChange: _("priority"),
|
|
314
|
+
children: S(B)
|
|
261
315
|
})
|
|
262
316
|
})]
|
|
263
317
|
}),
|
|
264
|
-
/* @__PURE__ */
|
|
318
|
+
/* @__PURE__ */ L("div", {
|
|
265
319
|
className: "grid grid-cols-2 gap-3",
|
|
266
|
-
children: [/* @__PURE__ */
|
|
320
|
+
children: [/* @__PURE__ */ I(l, {
|
|
267
321
|
label: "Practice area",
|
|
268
|
-
children: /* @__PURE__ */
|
|
269
|
-
value:
|
|
270
|
-
onChange:
|
|
271
|
-
children: [/* @__PURE__ */
|
|
322
|
+
children: /* @__PURE__ */ L(p, {
|
|
323
|
+
value: d.practiceAreaId,
|
|
324
|
+
onChange: _("practiceAreaId"),
|
|
325
|
+
children: [/* @__PURE__ */ I("option", {
|
|
272
326
|
value: "",
|
|
273
327
|
children: "Unassigned"
|
|
274
|
-
}),
|
|
328
|
+
}), u.data?.map((e) => /* @__PURE__ */ I("option", {
|
|
275
329
|
value: e.id,
|
|
276
330
|
children: e.name
|
|
277
331
|
}, e.id))]
|
|
278
332
|
})
|
|
279
|
-
}), /* @__PURE__ */
|
|
333
|
+
}), /* @__PURE__ */ I(l, {
|
|
280
334
|
label: "Due date",
|
|
281
|
-
children: /* @__PURE__ */
|
|
335
|
+
children: /* @__PURE__ */ I(b, {
|
|
282
336
|
type: "date",
|
|
283
|
-
value:
|
|
284
|
-
onChange:
|
|
337
|
+
value: d.dueDate,
|
|
338
|
+
onChange: _("dueDate")
|
|
285
339
|
})
|
|
286
340
|
})]
|
|
287
341
|
}),
|
|
288
|
-
/* @__PURE__ */
|
|
342
|
+
/* @__PURE__ */ I(l, {
|
|
289
343
|
label: "Description",
|
|
290
|
-
children: /* @__PURE__ */
|
|
291
|
-
value:
|
|
292
|
-
onChange:
|
|
344
|
+
children: /* @__PURE__ */ I(y, {
|
|
345
|
+
value: d.description,
|
|
346
|
+
onChange: _("description")
|
|
293
347
|
})
|
|
294
348
|
}),
|
|
295
|
-
/* @__PURE__ */
|
|
349
|
+
/* @__PURE__ */ L("label", {
|
|
296
350
|
className: "flex items-center gap-2.5 rounded-lg border border-border-seam bg-bg-canvas px-3 py-2.5 text-sm text-text-secondary",
|
|
297
|
-
children: [/* @__PURE__ */
|
|
351
|
+
children: [/* @__PURE__ */ I("input", {
|
|
298
352
|
type: "checkbox",
|
|
299
|
-
checked:
|
|
300
|
-
onChange: (e) =>
|
|
353
|
+
checked: d.isPrivileged,
|
|
354
|
+
onChange: (e) => m((t) => ({
|
|
301
355
|
...t,
|
|
302
356
|
isPrivileged: e.target.checked
|
|
303
357
|
}))
|
|
304
|
-
}), /* @__PURE__ */
|
|
358
|
+
}), /* @__PURE__ */ L("span", {
|
|
305
359
|
className: "flex items-center gap-1.5",
|
|
306
|
-
children: [/* @__PURE__ */ M
|
|
360
|
+
children: [/* @__PURE__ */ I(M, { className: "h-3.5 w-3.5 text-status-warning-text" }), "Privileged / confidential matter"]
|
|
307
361
|
})]
|
|
308
362
|
})
|
|
309
363
|
]
|
|
@@ -311,6 +365,6 @@ var F = [
|
|
|
311
365
|
});
|
|
312
366
|
};
|
|
313
367
|
//#endregion
|
|
314
|
-
export {
|
|
368
|
+
export { H as MattersPage };
|
|
315
369
|
|
|
316
370
|
//# sourceMappingURL=MattersPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MattersPage.js","names":[],"sources":["../../../src/proserviceworld/pages/MattersPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n Search,\n FolderKanban,\n Lock,\n CheckCircle2,\n CircleDot,\n AlertTriangle,\n} from 'lucide-react';\nimport {\n useMatters,\n useCreateMatter,\n useCloseMatter,\n useClients,\n usePracticeAreas,\n type PswMatterStatus,\n} from '../hooks/useProServiceWorldApi';\nimport {\n PageHeader,\n SectionCard,\n MetricCard,\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 STATUSES: PswMatterStatus[] = ['OPEN', 'ON_HOLD', 'CLOSED', 'ARCHIVED'];\nconst PRIORITIES = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] as const;\n\n/** Amber padlock chip that flags privileged / confidential matters. */\nconst PrivilegeLock: FC = () => (\n <span\n className=\"inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md bg-status-warning-bg-subtle text-status-warning-text\"\n title=\"Privileged / confidential\"\n aria-label=\"Privileged\"\n >\n <Lock className=\"h-3 w-3\" />\n </span>\n);\n\nexport const MattersPage: FC = () => {\n const [search, setSearch] = useState('');\n const [statusFilter, setStatusFilter] = useState<PswMatterStatus | ''>('');\n const [creating, setCreating] = useState(false);\n const [banner, setBanner] = useState<{ tone: 'success' | 'danger'; text: string } | null>(null);\n const { data, isLoading, error, refetch } = useMatters({\n search: search.trim() || undefined,\n status: statusFilter || undefined,\n });\n const close = useCloseMatter();\n\n const items = data?.items ?? [];\n const openCount = items.filter((m) => m.status === 'OPEN').length;\n const privilegedCount = items.filter((m) => m.isPrivileged).length;\n const highCount = items.filter((m) => m.priority === 'HIGH' || m.priority === 'CRITICAL').length;\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Matters\"\n subtitle=\"The regulated threads of work — legal matters, audits, filings — with their own deadlines and sensitive-document handling.\"\n icon={<FolderKanban className=\"h-6 w-6\" />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New matter\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 matters…\"\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 PswMatterStatus | '')}\n className=\"sm:w-48\"\n >\n <option value=\"\">All statuses</option>\n {enumOptions(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 matters yet\"\n description=\"Open a matter to track a regulated thread of work for a client.\"\n icon={<FolderKanban className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New matter\n </Button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-3 lg:grid-cols-4\">\n <MetricCard\n label=\"Matters\"\n value={data.totalCount}\n icon={<FolderKanban className=\"h-4 w-4\" />}\n />\n <MetricCard\n label=\"Open\"\n value={openCount}\n icon={<CircleDot className=\"h-4 w-4\" />}\n tone=\"accent\"\n />\n <MetricCard\n label=\"Privileged\"\n value={privilegedCount}\n icon={<Lock className=\"h-4 w-4\" />}\n tone=\"warning\"\n />\n <MetricCard\n label=\"High priority\"\n value={highCount}\n icon={<AlertTriangle className=\"h-4 w-4\" />}\n tone={highCount ? 'danger' : 'neutral'}\n />\n </div>\n\n <SectionCard title={`${data.totalCount} matter${data.totalCount === 1 ? '' : 's'}`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Matter</Th>\n <Th>Client</Th>\n <Th>Priority</Th>\n <Th>Status</Th>\n <Th>Due</Th>\n <Th className=\"text-right\">Actions</Th>\n </tr>\n </thead>\n <tbody>\n {data.items.map((m) => (\n <tr key={m.id} className=\"transition-colors hover:bg-bg-sunken/60\">\n <Td>\n <span className=\"flex items-center gap-2 font-medium text-text-primary\">\n {m.isPrivileged && <PrivilegeLock />}\n <span className=\"truncate\">{m.title}</span>\n </span>\n {m.reference ? (\n <div className=\"mt-0.5 pl-0 text-xs text-text-tertiary\">\n Ref: {m.reference}\n </div>\n ) : null}\n </Td>\n <Td className=\"text-text-primary\">{m.client?.name ?? '—'}</Td>\n <Td>\n <StatusPill status={m.priority} />\n </Td>\n <Td>\n <StatusPill status={m.status} />\n </Td>\n <Td>{fmtDate(m.dueDate)}</Td>\n <Td className=\"text-right\">\n {m.status !== 'CLOSED' && m.status !== 'ARCHIVED' ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={close.isPending}\n onClick={() =>\n close.mutate(m.id, {\n onSuccess: () =>\n setBanner({ tone: 'success', text: `${m.title} closed.` }),\n onError: (e) =>\n setBanner({\n tone: 'danger',\n text: e instanceof Error ? e.message : 'Failed.',\n }),\n })\n }\n >\n <CheckCircle2 className=\"mr-1 h-4 w-4\" /> Close\n </Button>\n ) : (\n <span className=\"text-xs text-text-tertiary\">\n {m.closedAt ? `Closed ${fmtDate(m.closedAt)}` : '—'}\n </span>\n )}\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n </SectionCard>\n </>\n )}\n\n {creating && (\n <MatterModal\n onClose={() => setCreating(false)}\n onSaved={(t) => setBanner({ tone: 'success', text: `${t} opened.` })}\n />\n )}\n </div>\n );\n};\n\nconst MatterModal: FC<{ onClose: () => void; onSaved: (title: string) => void }> = ({\n onClose,\n onSaved,\n}) => {\n const create = useCreateMatter();\n const clients = useClients({ pagination: { limit: 100 } });\n const practiceAreas = usePracticeAreas();\n const [form, setForm] = useState({\n clientId: '',\n practiceAreaId: '',\n title: '',\n reference: '',\n description: '',\n priority: 'MEDIUM',\n dueDate: '',\n isPrivileged: false,\n });\n const [err, setErr] = useState<string | null>(null);\n const set = (k: keyof typeof form) => (e: { target: { value: string } }) =>\n setForm((f) => ({ ...f, [k]: e.target.value }));\n\n const submit = () => {\n setErr(null);\n if (!form.clientId) return setErr('Select a client.');\n if (!form.title.trim()) return setErr('Matter title is required.');\n create.mutate(\n {\n clientId: form.clientId,\n practiceAreaId: form.practiceAreaId || null,\n title: form.title.trim(),\n reference: form.reference.trim() || null,\n description: form.description.trim() || null,\n priority: form.priority,\n isPrivileged: form.isPrivileged,\n dueDate: form.dueDate ? new Date(form.dueDate).toISOString() : null,\n },\n {\n onSuccess: () => {\n onSaved(form.title.trim());\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title=\"New matter\"\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={create.isPending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={create.isPending}>\n {create.isPending ? 'Opening…' : 'Open matter'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Client\" required>\n <NativeSelect value={form.clientId} onChange={set('clientId')}>\n <option value=\"\">Select a client…</option>\n {clients.data?.items.map((c) => (\n <option key={c.id} value={c.id}>\n {c.name}\n </option>\n ))}\n </NativeSelect>\n </Field>\n <Field label=\"Title\" required>\n <TextInput\n value={form.title}\n onChange={set('title')}\n placeholder=\"Regulatory investigation — SEC inquiry\"\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Reference\">\n <TextInput\n value={form.reference}\n onChange={set('reference')}\n placeholder=\"MAT-2026-014\"\n />\n </Field>\n <Field label=\"Priority\">\n <NativeSelect value={form.priority} onChange={set('priority')}>\n {enumOptions(PRIORITIES)}\n </NativeSelect>\n </Field>\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Practice area\">\n <NativeSelect value={form.practiceAreaId} onChange={set('practiceAreaId')}>\n <option value=\"\">Unassigned</option>\n {practiceAreas.data?.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </NativeSelect>\n </Field>\n <Field label=\"Due date\">\n <TextInput type=\"date\" value={form.dueDate} onChange={set('dueDate')} />\n </Field>\n </div>\n <Field label=\"Description\">\n <TextArea value={form.description} onChange={set('description')} />\n </Field>\n <label className=\"flex items-center gap-2.5 rounded-lg border border-border-seam bg-bg-canvas px-3 py-2.5 text-sm text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={form.isPrivileged}\n onChange={(e) => setForm((f) => ({ ...f, isPrivileged: e.target.checked }))}\n />\n <span className=\"flex items-center gap-1.5\">\n <Lock className=\"h-3.5 w-3.5 text-status-warning-text\" />\n Privileged / confidential matter\n </span>\n </label>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MattersPage.js","names":[],"sources":["../../../src/proserviceworld/pages/MattersPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n Search,\n FolderKanban,\n Lock,\n CheckCircle2,\n CircleDot,\n AlertTriangle,\n} from 'lucide-react';\nimport {\n useMatters,\n useCreateMatter,\n useUpdateMatter,\n useCloseMatter,\n useClients,\n usePracticeAreas,\n type PswMatterStatus,\n type PswMatter,\n} from '../hooks/useProServiceWorldApi';\nimport { useAnalytics } from '../hooks/useAnalytics';\nimport { impactFeedback } from '../utils/native';\nimport {\n PageHeader,\n SectionCard,\n MetricCard,\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';\nimport { TagPicker } from '../components/TagPicker';\nimport { LoadMore } from '../components/LoadMore';\n\nconst STATUSES: PswMatterStatus[] = ['OPEN', 'ON_HOLD', 'CLOSED', 'ARCHIVED'];\nconst PRIORITIES = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] as const;\n\n/** Amber padlock chip that flags privileged / confidential matters. */\nconst PrivilegeLock: FC = () => (\n <span\n className=\"inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md bg-status-warning-bg-subtle text-status-warning-text\"\n title=\"Privileged / confidential\"\n aria-label=\"Privileged\"\n >\n <Lock className=\"h-3 w-3\" />\n </span>\n);\n\nconst PAGE_SIZE = 25;\n\nexport const MattersPage: FC = () => {\n const { emitIntent, emitFact } = useAnalytics();\n const [search, setSearch] = useState('');\n const [statusFilter, setStatusFilter] = useState<PswMatterStatus | ''>('');\n const [creating, setCreating] = useState(false);\n const [banner, setBanner] = useState<{ tone: 'success' | 'danger'; text: string } | null>(null);\n const [pagination, setPagination] = useState({ limit: PAGE_SIZE, offset: 0 });\n const { data, isLoading, error, refetch } = useMatters({\n search: search.trim() || undefined,\n status: statusFilter || undefined,\n pagination,\n });\n const close = useCloseMatter();\n const update = useUpdateMatter();\n\n const items = useMemo(() => data?.items ?? [], [data]);\n const openCount = items.filter((m) => m.status === 'OPEN').length;\n const privilegedCount = items.filter((m) => m.isPrivileged).length;\n const highCount = items.filter((m) => m.priority === 'HIGH' || m.priority === 'CRITICAL').length;\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Matters\"\n subtitle=\"The regulated threads of work — legal matters, audits, filings — with their own deadlines and sensitive-document handling.\"\n icon={<FolderKanban className=\"h-6 w-6\" />}\n actions={\n <Button\n onClick={() => {\n void impactFeedback('light');\n emitIntent('psw.matter.create_clicked');\n setCreating(true);\n }}\n >\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New matter\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 matters…\"\n value={search}\n onChange={(e) => {\n setSearch(e.target.value);\n setPagination({ limit: PAGE_SIZE, offset: 0 });\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && search.trim()) {\n emitFact('psw.search.performed', {\n entityType: 'matter',\n queryLength: search.trim().length,\n });\n }\n }}\n className=\"pl-9\"\n />\n </div>\n <NativeSelect\n value={statusFilter}\n onChange={(e) => {\n setStatusFilter(e.target.value as PswMatterStatus | '');\n setPagination({ limit: PAGE_SIZE, offset: 0 });\n }}\n className=\"sm:w-48\"\n >\n <option value=\"\">All statuses</option>\n {enumOptions(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 matters yet\"\n description=\"Open a matter to track a regulated thread of work for a client.\"\n icon={<FolderKanban className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n New matter\n </Button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-3 lg:grid-cols-4\">\n <MetricCard\n label=\"Matters\"\n value={data.totalCount}\n icon={<FolderKanban className=\"h-4 w-4\" />}\n />\n <MetricCard\n label=\"Open\"\n value={openCount}\n icon={<CircleDot className=\"h-4 w-4\" />}\n tone=\"accent\"\n />\n <MetricCard\n label=\"Privileged\"\n value={privilegedCount}\n icon={<Lock className=\"h-4 w-4\" />}\n tone=\"warning\"\n />\n <MetricCard\n label=\"High priority\"\n value={highCount}\n icon={<AlertTriangle className=\"h-4 w-4\" />}\n tone={highCount ? 'danger' : 'neutral'}\n />\n </div>\n\n <SectionCard title={`${data.totalCount} matter${data.totalCount === 1 ? '' : 's'}`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Matter</Th>\n <Th>Client</Th>\n <Th>Priority</Th>\n <Th>Status</Th>\n <Th>Due</Th>\n <Th>Tags</Th>\n <Th className=\"text-right\">Actions</Th>\n </tr>\n </thead>\n <tbody>\n {data.items.map((m) => (\n <tr key={m.id} className=\"transition-colors hover:bg-bg-sunken/60\">\n <Td>\n <span className=\"flex items-center gap-2 font-medium text-text-primary\">\n {m.isPrivileged && <PrivilegeLock />}\n <span className=\"truncate\">{m.title}</span>\n </span>\n {m.reference ? (\n <div className=\"mt-0.5 pl-0 text-xs text-text-tertiary\">\n Ref: {m.reference}\n </div>\n ) : null}\n </Td>\n <Td className=\"text-text-primary\">{m.client?.name ?? '—'}</Td>\n <Td>\n <StatusPill status={m.priority} />\n </Td>\n <Td>\n <StatusPill status={m.status} />\n </Td>\n <Td>{fmtDate(m.dueDate)}</Td>\n <Td>\n <TagPicker\n entityType=\"PswMatter\"\n entityId={m.id}\n tags={m.tags ?? []}\n onChange={async (tags) => {\n await update.mutateAsync({ id: m.id, input: { tags } });\n void refetch();\n }}\n maxTags={5}\n />\n </Td>\n <Td className=\"text-right\">\n {m.status !== 'CLOSED' && m.status !== 'ARCHIVED' ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={close.isPending}\n onClick={() =>\n close.mutate(m.id, {\n onSuccess: () => {\n emitFact('psw.matter.closed', { matterId: m.id });\n setBanner({ tone: 'success', text: `${m.title} closed.` });\n },\n onError: (e) =>\n setBanner({\n tone: 'danger',\n text: e instanceof Error ? e.message : 'Failed.',\n }),\n })\n }\n >\n <CheckCircle2 className=\"mr-1 h-4 w-4\" /> Close\n </Button>\n ) : (\n <span className=\"text-xs text-text-tertiary\">\n {m.closedAt ? `Closed ${fmtDate(m.closedAt)}` : '—'}\n </span>\n )}\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n <LoadMore\n hasMore={data?.pageInfo?.hasMore ?? false}\n loading={isLoading}\n loadedCount={items.length}\n totalCount={data?.totalCount ?? items.length}\n onLoadMore={() =>\n setPagination((p) => ({ limit: PAGE_SIZE, offset: p.offset + PAGE_SIZE }))\n }\n />\n </SectionCard>\n </>\n )}\n\n {creating && (\n <MatterModal\n onClose={() => setCreating(false)}\n onSaved={(t) => setBanner({ tone: 'success', text: `${t} opened.` })}\n />\n )}\n </div>\n );\n};\n\nconst MatterModal: FC<{ onClose: () => void; onSaved: (title: string) => void }> = ({\n onClose,\n onSaved,\n}) => {\n const create = useCreateMatter();\n const { emitFact } = useAnalytics();\n const clients = useClients({ pagination: { limit: 100 } });\n const practiceAreas = usePracticeAreas();\n const [form, setForm] = useState({\n clientId: '',\n practiceAreaId: '',\n title: '',\n reference: '',\n description: '',\n priority: 'MEDIUM',\n dueDate: '',\n isPrivileged: false,\n });\n const [err, setErr] = useState<string | null>(null);\n const set = (k: keyof typeof form) => (e: { target: { value: string } }) =>\n setForm((f) => ({ ...f, [k]: e.target.value }));\n\n const submit = () => {\n setErr(null);\n if (!form.clientId) return setErr('Select a client.');\n if (!form.title.trim()) return setErr('Matter title is required.');\n create.mutate(\n {\n clientId: form.clientId,\n practiceAreaId: form.practiceAreaId || null,\n title: form.title.trim(),\n reference: form.reference.trim() || null,\n description: form.description.trim() || null,\n priority: form.priority,\n isPrivileged: form.isPrivileged,\n dueDate: form.dueDate ? new Date(form.dueDate).toISOString() : null,\n },\n {\n onSuccess: (created) => {\n const matter = (created as { pswCreateMatter: PswMatter }).pswCreateMatter;\n emitFact('psw.matter.created', {\n matterId: matter.id,\n clientId: form.clientId,\n });\n onSaved(form.title.trim());\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title=\"New matter\"\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={create.isPending}>\n Cancel\n </Button>\n <Button onClick={submit} disabled={create.isPending}>\n {create.isPending ? 'Opening…' : 'Open matter'}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label=\"Client\" required>\n <NativeSelect value={form.clientId} onChange={set('clientId')}>\n <option value=\"\">Select a client…</option>\n {clients.data?.items.map((c) => (\n <option key={c.id} value={c.id}>\n {c.name}\n </option>\n ))}\n </NativeSelect>\n </Field>\n <Field label=\"Title\" required>\n <TextInput\n value={form.title}\n onChange={set('title')}\n placeholder=\"Regulatory investigation — SEC inquiry\"\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Reference\">\n <TextInput\n value={form.reference}\n onChange={set('reference')}\n placeholder=\"MAT-2026-014\"\n />\n </Field>\n <Field label=\"Priority\">\n <NativeSelect value={form.priority} onChange={set('priority')}>\n {enumOptions(PRIORITIES)}\n </NativeSelect>\n </Field>\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Practice area\">\n <NativeSelect value={form.practiceAreaId} onChange={set('practiceAreaId')}>\n <option value=\"\">Unassigned</option>\n {practiceAreas.data?.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </NativeSelect>\n </Field>\n <Field label=\"Due date\">\n <TextInput type=\"date\" value={form.dueDate} onChange={set('dueDate')} />\n </Field>\n </div>\n <Field label=\"Description\">\n <TextArea value={form.description} onChange={set('description')} />\n </Field>\n <label className=\"flex items-center gap-2.5 rounded-lg border border-border-seam bg-bg-canvas px-3 py-2.5 text-sm text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={form.isPrivileged}\n onChange={(e) => setForm((f) => ({ ...f, isPrivileged: e.target.checked }))}\n />\n <span className=\"flex items-center gap-1.5\">\n <Lock className=\"h-3.5 w-3.5 text-status-warning-text\" />\n Privileged / confidential matter\n </span>\n </label>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|