@burdenoff/microfe-proserviceworld 2026.1026.2 → 2026.1031.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/proserviceworld/components/CredentialDirectory.js +44 -43
  2. package/dist/proserviceworld/components/CredentialDirectory.js.map +1 -1
  3. package/dist/proserviceworld/components/CredentialReminderPanel.js +5 -4
  4. package/dist/proserviceworld/components/CredentialReminderPanel.js.map +1 -1
  5. package/dist/proserviceworld/components/ui.d.ts +7 -3
  6. package/dist/proserviceworld/components/ui.d.ts.map +1 -1
  7. package/dist/proserviceworld/components/ui.js +135 -121
  8. package/dist/proserviceworld/components/ui.js.map +1 -1
  9. package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts +28 -0
  10. package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts.map +1 -1
  11. package/dist/proserviceworld/hooks/useProServiceWorldApi.js +95 -73
  12. package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -1
  13. package/dist/proserviceworld/hooks/useTr.d.ts +49 -8
  14. package/dist/proserviceworld/hooks/useTr.d.ts.map +1 -1
  15. package/dist/proserviceworld/hooks/useTr.js +45 -21
  16. package/dist/proserviceworld/hooks/useTr.js.map +1 -1
  17. package/dist/proserviceworld/i18n/catalog/analytics.d.ts +5 -0
  18. package/dist/proserviceworld/i18n/catalog/analytics.d.ts.map +1 -0
  19. package/dist/proserviceworld/i18n/catalog/analytics.js +271 -0
  20. package/dist/proserviceworld/i18n/catalog/analytics.js.map +1 -0
  21. package/dist/proserviceworld/i18n/catalog/common.d.ts +9 -0
  22. package/dist/proserviceworld/i18n/catalog/common.d.ts.map +1 -0
  23. package/dist/proserviceworld/i18n/catalog/common.js +163 -0
  24. package/dist/proserviceworld/i18n/catalog/common.js.map +1 -0
  25. package/dist/proserviceworld/i18n/catalog/compliance.d.ts +5 -0
  26. package/dist/proserviceworld/i18n/catalog/compliance.d.ts.map +1 -0
  27. package/dist/proserviceworld/i18n/catalog/compliance.js +157 -0
  28. package/dist/proserviceworld/i18n/catalog/compliance.js.map +1 -0
  29. package/dist/proserviceworld/i18n/catalog/conflicts.d.ts +5 -0
  30. package/dist/proserviceworld/i18n/catalog/conflicts.d.ts.map +1 -0
  31. package/dist/proserviceworld/i18n/catalog/conflicts.js +145 -0
  32. package/dist/proserviceworld/i18n/catalog/conflicts.js.map +1 -0
  33. package/dist/proserviceworld/i18n/catalog/documents.d.ts +5 -0
  34. package/dist/proserviceworld/i18n/catalog/documents.d.ts.map +1 -0
  35. package/dist/proserviceworld/i18n/catalog/documents.js +157 -0
  36. package/dist/proserviceworld/i18n/catalog/documents.js.map +1 -0
  37. package/dist/proserviceworld/i18n/catalog/enums.d.ts +10 -0
  38. package/dist/proserviceworld/i18n/catalog/enums.d.ts.map +1 -0
  39. package/dist/proserviceworld/i18n/catalog/enums.js +481 -0
  40. package/dist/proserviceworld/i18n/catalog/enums.js.map +1 -0
  41. package/dist/proserviceworld/i18n/catalog/index.d.ts +9 -0
  42. package/dist/proserviceworld/i18n/catalog/index.d.ts.map +1 -0
  43. package/dist/proserviceworld/i18n/catalog/index.js +25 -0
  44. package/dist/proserviceworld/i18n/catalog/index.js.map +1 -0
  45. package/dist/proserviceworld/i18n/catalog/invoices.d.ts +5 -0
  46. package/dist/proserviceworld/i18n/catalog/invoices.d.ts.map +1 -0
  47. package/dist/proserviceworld/i18n/catalog/invoices.js +247 -0
  48. package/dist/proserviceworld/i18n/catalog/invoices.js.map +1 -0
  49. package/dist/proserviceworld/i18n/catalog/practiceAreas.d.ts +5 -0
  50. package/dist/proserviceworld/i18n/catalog/practiceAreas.d.ts.map +1 -0
  51. package/dist/proserviceworld/i18n/catalog/practiceAreas.js +97 -0
  52. package/dist/proserviceworld/i18n/catalog/practiceAreas.js.map +1 -0
  53. package/dist/proserviceworld/i18n/catalog/time.d.ts +5 -0
  54. package/dist/proserviceworld/i18n/catalog/time.d.ts.map +1 -0
  55. package/dist/proserviceworld/i18n/catalog/time.js +301 -0
  56. package/dist/proserviceworld/i18n/catalog/time.js.map +1 -0
  57. package/dist/proserviceworld/i18n/index.d.ts +10 -9
  58. package/dist/proserviceworld/i18n/index.d.ts.map +1 -1
  59. package/dist/proserviceworld/i18n/index.js +16 -12
  60. package/dist/proserviceworld/i18n/index.js.map +1 -1
  61. package/dist/proserviceworld/i18n/types.d.ts +13 -0
  62. package/dist/proserviceworld/i18n/types.d.ts.map +1 -0
  63. package/dist/proserviceworld/i18n/types.js +18 -0
  64. package/dist/proserviceworld/i18n/types.js.map +1 -0
  65. package/dist/proserviceworld/pages/AnalyticsPage.d.ts.map +1 -1
  66. package/dist/proserviceworld/pages/AnalyticsPage.js +236 -152
  67. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  68. package/dist/proserviceworld/pages/ClientDetailPage.js +99 -98
  69. package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -1
  70. package/dist/proserviceworld/pages/ClientsPage.d.ts.map +1 -1
  71. package/dist/proserviceworld/pages/ClientsPage.js +181 -181
  72. package/dist/proserviceworld/pages/ClientsPage.js.map +1 -1
  73. package/dist/proserviceworld/pages/CompliancePage.d.ts.map +1 -1
  74. package/dist/proserviceworld/pages/CompliancePage.js +210 -209
  75. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -1
  76. package/dist/proserviceworld/pages/ConflictsPage.d.ts.map +1 -1
  77. package/dist/proserviceworld/pages/ConflictsPage.js +139 -138
  78. package/dist/proserviceworld/pages/ConflictsPage.js.map +1 -1
  79. package/dist/proserviceworld/pages/DocumentsPage.d.ts.map +1 -1
  80. package/dist/proserviceworld/pages/DocumentsPage.js +150 -149
  81. package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
  82. package/dist/proserviceworld/pages/EngagementDetailPage.js +105 -104
  83. package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -1
  84. package/dist/proserviceworld/pages/EngagementsPage.d.ts.map +1 -1
  85. package/dist/proserviceworld/pages/EngagementsPage.js +137 -137
  86. package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -1
  87. package/dist/proserviceworld/pages/InvoicesPage.d.ts.map +1 -1
  88. package/dist/proserviceworld/pages/InvoicesPage.js +275 -258
  89. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
  90. package/dist/proserviceworld/pages/MattersPage.d.ts.map +1 -1
  91. package/dist/proserviceworld/pages/MattersPage.js +166 -166
  92. package/dist/proserviceworld/pages/MattersPage.js.map +1 -1
  93. package/dist/proserviceworld/pages/PracticeAreasPage.d.ts.map +1 -1
  94. package/dist/proserviceworld/pages/PracticeAreasPage.js +100 -99
  95. package/dist/proserviceworld/pages/PracticeAreasPage.js.map +1 -1
  96. package/dist/proserviceworld/pages/PractitionerCredentialsPage.js +30 -29
  97. package/dist/proserviceworld/pages/PractitionerCredentialsPage.js.map +1 -1
  98. package/dist/proserviceworld/pages/TimePage.d.ts.map +1 -1
  99. package/dist/proserviceworld/pages/TimePage.js +343 -350
  100. package/dist/proserviceworld/pages/TimePage.js.map +1 -1
  101. package/dist/proserviceworld/utils/humanize.d.ts +3 -0
  102. package/dist/proserviceworld/utils/humanize.d.ts.map +1 -0
  103. package/dist/proserviceworld/utils/humanize.js +6 -0
  104. package/dist/proserviceworld/utils/humanize.js.map +1 -0
  105. package/package.json +1 -1
@@ -1,277 +1,278 @@
1
1
  import { useArchiveDocument as e, useCreateDocument as t, useDocuments as n } from "../hooks/useProServiceWorldApi.js";
2
- import { Banner as r, Empty as i, ErrorState as a, Field as o, LoadingBlock as s, Modal as c, NativeSelect as l, PageHeader as u, SectionCard as d, StatusPill as f, TableWrap as p, Td as m, TextArea as h, TextInput as g, Th as _, enumOptions as v, fmtDate as y, humanize as b } from "../components/ui.js";
3
- import { useAnalytics as x } from "../hooks/useAnalytics.js";
4
- import { getDocumentDownloadUrl as S, uploadDocumentFile as C } from "../hooks/useFiles.js";
5
- import { useDeferredValue as w, useState as T } from "react";
6
- import { Archive as E, Download as D, FileText as O, Lock as k, Plus as A, Search as j, Upload as M } from "lucide-react";
7
- import { Fragment as N, jsx as P, jsxs as F } from "react/jsx-runtime";
8
- import { Button as I } from "@burdenoff/fe-libs/ui";
2
+ import { plural as r, useEnumLabel as i, useTr as a } from "../hooks/useTr.js";
3
+ 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";
4
+ import { useAnalytics as C } from "../hooks/useAnalytics.js";
5
+ import { getDocumentDownloadUrl as w, uploadDocumentFile as T } from "../hooks/useFiles.js";
6
+ import { useDeferredValue as E, useState as D } from "react";
7
+ import { Archive as O, Download as k, FileText as A, Lock as j, Plus as M, Search as N, Upload as P } from "lucide-react";
8
+ import { Fragment as F, jsx as I, jsxs as L } from "react/jsx-runtime";
9
+ import { Button as R } from "@burdenoff/fe-libs/ui";
9
10
  //#region src/proserviceworld/pages/DocumentsPage.tsx
10
- var L = [
11
+ var z = [
11
12
  "PUBLIC",
12
13
  "INTERNAL",
13
14
  "CONFIDENTIAL",
14
15
  "PRIVILEGED"
15
- ], R = () => {
16
- let [t, o] = T(""), [c, h] = T(""), C = w(c), [M, N] = T(!1), [R, B] = T(null), { data: V, isLoading: H, error: U, refetch: W } = n({
17
- classification: t || void 0,
18
- search: C.trim() || void 0
19
- }), { emitFact: G } = x(), K = e(), q = async (e) => {
16
+ ], B = () => {
17
+ let t = a(), l = i(), [d, v] = D(""), [T, P] = D(""), F = E(T), [B, H] = D(!1), [U, W] = D(null), { data: G, isLoading: K, error: q, refetch: J } = n({
18
+ classification: d || void 0,
19
+ search: F.trim() || void 0
20
+ }), { emitFact: Y } = C(), X = e(), Z = async (e) => {
20
21
  try {
21
- let t = await S(e);
22
+ let t = await w(e);
22
23
  window.open(t, "_blank", "noopener");
23
24
  } catch (e) {
24
- B({
25
+ W({
25
26
  tone: "danger",
26
- text: e instanceof Error ? e.message : "Could not open document."
27
+ text: e instanceof Error ? e.message : t("psw.documents.openFailed", "Could not open document.")
27
28
  });
28
29
  }
29
30
  };
30
- return /* @__PURE__ */ F("div", {
31
+ return /* @__PURE__ */ L("div", {
31
32
  className: "space-y-6",
32
33
  children: [
33
- /* @__PURE__ */ P(u, {
34
- title: "Documents",
35
- subtitle: "Engagement letters, opinions, filings and evidence — metadata, classification and legal hold here; the file itself lives in the shared Files service.",
36
- icon: /* @__PURE__ */ P(O, { className: "h-6 w-6" }),
37
- actions: /* @__PURE__ */ F(I, {
38
- onClick: () => N(!0),
39
- children: [/* @__PURE__ */ P(A, { className: "mr-1.5 h-4 w-4" }), "Add document"]
34
+ /* @__PURE__ */ I(p, {
35
+ title: t("psw.documents.title", "Documents"),
36
+ subtitle: t("psw.documents.subtitle", "Engagement letters, opinions, filings and evidence — metadata, classification and legal hold here; the file itself lives in the shared Files service."),
37
+ icon: /* @__PURE__ */ I(A, { className: "h-6 w-6" }),
38
+ actions: /* @__PURE__ */ L(R, {
39
+ onClick: () => H(!0),
40
+ children: [/* @__PURE__ */ I(M, { className: "me-1.5 h-4 w-4" }), t("psw.documents.add", "Add document")]
40
41
  })
41
42
  }),
42
- R && /* @__PURE__ */ P(r, {
43
- tone: R.tone,
44
- onClose: () => B(null),
45
- children: R.text
43
+ U && /* @__PURE__ */ I(o, {
44
+ tone: U.tone,
45
+ onClose: () => W(null),
46
+ children: U.text
46
47
  }),
47
- /* @__PURE__ */ F("div", {
48
+ /* @__PURE__ */ L("div", {
48
49
  className: "flex flex-col gap-2 sm:flex-row sm:items-center",
49
- children: [/* @__PURE__ */ F("div", {
50
+ children: [/* @__PURE__ */ L("div", {
50
51
  className: "relative flex-1",
51
- children: [/* @__PURE__ */ P(j, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ P(g, {
52
- placeholder: "Search documents…",
53
- value: c,
54
- onChange: (e) => h(e.target.value),
52
+ children: [/* @__PURE__ */ I(N, { className: "pointer-events-none absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ I(y, {
53
+ placeholder: t("psw.documents.searchPlaceholder", "Search documents…"),
54
+ value: T,
55
+ onChange: (e) => P(e.target.value),
55
56
  onKeyDown: (e) => {
56
- e.key === "Enter" && c.trim() && G("psw.search.performed", {
57
+ e.key === "Enter" && T.trim() && Y("psw.search.performed", {
57
58
  entityType: "document",
58
- queryLength: c.trim().length
59
+ queryLength: T.trim().length
59
60
  });
60
61
  },
61
- className: "pl-9"
62
+ className: "ps-9"
62
63
  })]
63
- }), /* @__PURE__ */ F(l, {
64
- value: t,
65
- onChange: (e) => o(e.target.value),
64
+ }), /* @__PURE__ */ L(f, {
65
+ value: d,
66
+ onChange: (e) => v(e.target.value),
66
67
  className: "sm:w-52",
67
- children: [/* @__PURE__ */ P("option", {
68
+ children: [/* @__PURE__ */ I("option", {
68
69
  value: "",
69
- children: "All classifications"
70
- }), v(L)]
70
+ children: t("psw.documents.allClassifications", "All classifications")
71
+ }), x(z, l)]
71
72
  })]
72
73
  }),
73
- H ? /* @__PURE__ */ P(s, {}) : U ? /* @__PURE__ */ P(a, {
74
- error: U,
75
- onRetry: () => void W()
76
- }) : !V || V.items.length === 0 ? /* @__PURE__ */ P(i, {
77
- title: "No documents",
78
- description: "Add a document — upload the file to the shared Files service and record it here.",
79
- icon: /* @__PURE__ */ P(O, { className: "h-8 w-8" }),
80
- action: /* @__PURE__ */ F(I, {
81
- onClick: () => N(!0),
82
- children: [/* @__PURE__ */ P(A, { className: "mr-1.5 h-4 w-4" }), "Add document"]
74
+ K ? /* @__PURE__ */ I(u, {}) : q ? /* @__PURE__ */ I(c, {
75
+ error: q,
76
+ onRetry: () => void J()
77
+ }) : !G || G.items.length === 0 ? /* @__PURE__ */ I(s, {
78
+ title: t("psw.documents.emptyTitle", "No documents"),
79
+ description: t("psw.documents.emptyDescription", "Add a document — upload the file to the shared Files service and record it here."),
80
+ icon: /* @__PURE__ */ I(A, { className: "h-8 w-8" }),
81
+ action: /* @__PURE__ */ L(R, {
82
+ onClick: () => H(!0),
83
+ children: [/* @__PURE__ */ I(M, { className: "me-1.5 h-4 w-4" }), t("psw.documents.add", "Add document")]
83
84
  })
84
- }) : /* @__PURE__ */ P(d, {
85
- title: `${V.totalCount} document${V.totalCount === 1 ? "" : "s"}`,
86
- children: /* @__PURE__ */ F(p, { children: [/* @__PURE__ */ P("thead", { children: /* @__PURE__ */ F("tr", { children: [
87
- /* @__PURE__ */ P(_, { children: "Name" }),
88
- /* @__PURE__ */ P(_, { children: "Classification" }),
89
- /* @__PURE__ */ P(_, { children: "Status" }),
90
- /* @__PURE__ */ P(_, { children: "Added" }),
91
- /* @__PURE__ */ P(_, {
92
- className: "text-right",
93
- children: "Actions"
85
+ }) : /* @__PURE__ */ I(m, {
86
+ title: r(t, "psw.documents.count", G.totalCount, "{{count}} document", "{{count}} documents"),
87
+ children: /* @__PURE__ */ L(g, { children: [/* @__PURE__ */ I("thead", { children: /* @__PURE__ */ L("tr", { children: [
88
+ /* @__PURE__ */ I(b, { children: t("psw.common.name", "Name") }),
89
+ /* @__PURE__ */ I(b, { children: t("psw.documents.classification", "Classification") }),
90
+ /* @__PURE__ */ I(b, { children: t("psw.common.status", "Status") }),
91
+ /* @__PURE__ */ I(b, { children: t("psw.common.added", "Added") }),
92
+ /* @__PURE__ */ I(b, {
93
+ className: "text-end",
94
+ children: t("psw.common.actions", "Actions")
94
95
  })
95
- ] }) }), /* @__PURE__ */ P("tbody", { children: V.items.map((e) => /* @__PURE__ */ F("tr", {
96
+ ] }) }), /* @__PURE__ */ I("tbody", { children: G.items.map((e) => /* @__PURE__ */ L("tr", {
96
97
  className: "hover:bg-bg-sunken/50",
97
98
  children: [
98
- /* @__PURE__ */ P(m, { children: /* @__PURE__ */ F("span", {
99
+ /* @__PURE__ */ I(_, { children: /* @__PURE__ */ L("span", {
99
100
  className: "flex items-center gap-1.5 font-medium text-text-primary",
100
101
  children: [
101
- e.legalHold && /* @__PURE__ */ P(k, {
102
+ e.legalHold && /* @__PURE__ */ I(j, {
102
103
  className: "h-3.5 w-3.5 text-status-warning-text",
103
- "aria-label": "Legal hold"
104
+ "aria-label": t("psw.documents.legalHold", "Legal hold")
104
105
  }),
105
106
  e.name,
106
107
  " ",
107
- /* @__PURE__ */ F("span", {
108
+ /* @__PURE__ */ L("span", {
108
109
  className: "text-xs text-text-tertiary",
109
110
  children: ["v", e.version]
110
111
  })
111
112
  ]
112
113
  }) }),
113
- /* @__PURE__ */ P(m, { children: b(e.classification) }),
114
- /* @__PURE__ */ P(m, { children: /* @__PURE__ */ P(f, { status: e.status }) }),
115
- /* @__PURE__ */ P(m, { children: y(e.createdAt) }),
116
- /* @__PURE__ */ P(m, {
117
- className: "text-right",
118
- children: /* @__PURE__ */ F("div", {
114
+ /* @__PURE__ */ I(_, { children: l(e.classification) }),
115
+ /* @__PURE__ */ I(_, { children: /* @__PURE__ */ I(h, { status: e.status }) }),
116
+ /* @__PURE__ */ I(_, { children: S(e.createdAt) }),
117
+ /* @__PURE__ */ I(_, {
118
+ className: "text-end",
119
+ children: /* @__PURE__ */ L("div", {
119
120
  className: "flex justify-end gap-1",
120
- children: [e.file?.id && /* @__PURE__ */ P(I, {
121
+ children: [e.file?.id && /* @__PURE__ */ I(R, {
121
122
  variant: "ghost",
122
123
  size: "sm",
123
- onClick: () => void q(e.file.id),
124
- "aria-label": "Download",
125
- children: /* @__PURE__ */ P(D, { className: "h-4 w-4" })
126
- }), e.status !== "ARCHIVED" && /* @__PURE__ */ P(I, {
124
+ onClick: () => void Z(e.file.id),
125
+ "aria-label": t("psw.documents.download", "Download"),
126
+ children: /* @__PURE__ */ I(k, { className: "h-4 w-4" })
127
+ }), e.status !== "ARCHIVED" && /* @__PURE__ */ I(R, {
127
128
  variant: "ghost",
128
129
  size: "sm",
129
- "aria-label": "Archive",
130
- disabled: K.isPending,
131
- onClick: () => K.mutate(e.id, {
132
- onSuccess: () => B({
130
+ "aria-label": t("psw.common.archive", "Archive"),
131
+ disabled: X.isPending,
132
+ onClick: () => X.mutate(e.id, {
133
+ onSuccess: () => W({
133
134
  tone: "success",
134
- text: `${e.name} archived.`
135
+ text: t("psw.documents.archived", "{{name}} archived.", { name: e.name })
135
136
  }),
136
- onError: (e) => B({
137
+ onError: (e) => W({
137
138
  tone: "danger",
138
- text: e instanceof Error ? e.message : "Failed."
139
+ text: e instanceof Error ? e.message : t("psw.common.failed", "Failed.")
139
140
  })
140
141
  }),
141
- children: /* @__PURE__ */ P(E, { className: "h-4 w-4" })
142
+ children: /* @__PURE__ */ I(O, { className: "h-4 w-4" })
142
143
  })]
143
144
  })
144
145
  })
145
146
  ]
146
147
  }, e.id)) })] })
147
148
  }),
148
- M && /* @__PURE__ */ P(z, {
149
- onClose: () => N(!1),
149
+ B && /* @__PURE__ */ I(V, {
150
+ onClose: () => H(!1),
150
151
  onDone: () => {
151
- W(), B({
152
+ J(), W({
152
153
  tone: "success",
153
- text: "Document added."
154
+ text: t("psw.documents.added", "Document added.")
154
155
  });
155
156
  }
156
157
  })
157
158
  ]
158
159
  });
159
- }, z = ({ onClose: e, onDone: n }) => {
160
- let i = t(), [a, s] = T({
160
+ }, V = ({ onClose: e, onDone: n }) => {
161
+ let r = a(), s = i(), c = t(), [u, p] = D({
161
162
  name: "",
162
163
  classification: "INTERNAL",
163
164
  description: "",
164
165
  legalHold: !1
165
- }), [u, d] = T(null), [f, p] = T(!1), [m, _] = T(null), y = async () => {
166
- if (_(null), !a.name.trim()) return _("Document name is required.");
166
+ }), [m, h] = D(null), [g, _] = D(!1), [b, S] = D(null), C = async () => {
167
+ if (S(null), !u.name.trim()) return S(r("psw.documents.nameRequired", "Document name is required."));
167
168
  let t = null;
168
- if (u) {
169
+ if (m) {
169
170
  try {
170
- p(!0), t = (await C(u)).fileId;
171
+ _(!0), t = (await T(m)).fileId;
171
172
  } catch (e) {
172
- return p(!1), _(e instanceof Error ? e.message : "Upload failed.");
173
+ return _(!1), S(e instanceof Error ? e.message : r("psw.documents.uploadFailed", "Upload failed."));
173
174
  }
174
- p(!1);
175
+ _(!1);
175
176
  }
176
- i.mutate({
177
- name: a.name.trim(),
178
- classification: a.classification,
179
- description: a.description.trim() || null,
180
- legalHold: a.legalHold,
177
+ c.mutate({
178
+ name: u.name.trim(),
179
+ classification: u.classification,
180
+ description: u.description.trim() || null,
181
+ legalHold: u.legalHold,
181
182
  fileId: t
182
183
  }, {
183
184
  onSuccess: () => {
184
185
  n(), e();
185
186
  },
186
- onError: (e) => _(e instanceof Error ? e.message : "Failed.")
187
+ onError: (e) => S(e instanceof Error ? e.message : r("psw.common.failed", "Failed."))
187
188
  });
188
- }, b = f || i.isPending;
189
- return /* @__PURE__ */ P(c, {
189
+ }, w = g || c.isPending;
190
+ return /* @__PURE__ */ I(d, {
190
191
  open: !0,
191
192
  onClose: e,
192
- title: "Add document",
193
- footer: /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P(I, {
193
+ title: r("psw.documents.add", "Add document"),
194
+ footer: /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ I(R, {
194
195
  variant: "outline",
195
196
  onClick: e,
196
- disabled: b,
197
- children: "Cancel"
198
- }), /* @__PURE__ */ P(I, {
199
- onClick: () => void y(),
200
- disabled: b,
201
- children: f ? "Uploading…" : i.isPending ? "Saving…" : "Add document"
197
+ disabled: w,
198
+ children: r("psw.common.cancel", "Cancel")
199
+ }), /* @__PURE__ */ I(R, {
200
+ onClick: () => void C(),
201
+ disabled: w,
202
+ children: g ? r("psw.documents.uploading", "Uploading…") : c.isPending ? r("psw.common.saving", "Saving…") : r("psw.documents.add", "Add document")
202
203
  })] }),
203
- children: /* @__PURE__ */ F("div", {
204
+ children: /* @__PURE__ */ L("div", {
204
205
  className: "space-y-3",
205
206
  children: [
206
- m && /* @__PURE__ */ P(r, {
207
+ b && /* @__PURE__ */ I(o, {
207
208
  tone: "danger",
208
- children: m
209
+ children: b
209
210
  }),
210
- /* @__PURE__ */ P(o, {
211
- label: "Name",
211
+ /* @__PURE__ */ I(l, {
212
+ label: r("psw.common.name", "Name"),
212
213
  required: !0,
213
- children: /* @__PURE__ */ P(g, {
214
- value: a.name,
215
- onChange: (e) => s((t) => ({
214
+ children: /* @__PURE__ */ I(y, {
215
+ value: u.name,
216
+ onChange: (e) => p((t) => ({
216
217
  ...t,
217
218
  name: e.target.value
218
219
  })),
219
- placeholder: "Engagement letter — Acme FY26"
220
+ placeholder: r("psw.documents.namePlaceholder", "Engagement letter — Acme FY26")
220
221
  })
221
222
  }),
222
- /* @__PURE__ */ P(o, {
223
- label: "Classification",
224
- children: /* @__PURE__ */ P(l, {
225
- value: a.classification,
226
- onChange: (e) => s((t) => ({
223
+ /* @__PURE__ */ I(l, {
224
+ label: r("psw.documents.classification", "Classification"),
225
+ children: /* @__PURE__ */ I(f, {
226
+ value: u.classification,
227
+ onChange: (e) => p((t) => ({
227
228
  ...t,
228
229
  classification: e.target.value
229
230
  })),
230
- children: v(L)
231
+ children: x(z, s)
231
232
  })
232
233
  }),
233
- /* @__PURE__ */ P(o, {
234
- label: "File",
235
- hint: "Optional — stored in the shared Files service.",
236
- children: /* @__PURE__ */ F("label", {
234
+ /* @__PURE__ */ I(l, {
235
+ label: r("psw.documents.file", "File"),
236
+ hint: r("psw.documents.fileHint", "Optional — stored in the shared Files service."),
237
+ children: /* @__PURE__ */ L("label", {
237
238
  className: "flex cursor-pointer items-center gap-2 rounded-lg border border-dashed border-border-seam bg-bg-canvas px-3 py-3 text-sm text-text-secondary hover:border-accent",
238
239
  children: [
239
- /* @__PURE__ */ P(M, { className: "h-4 w-4 text-text-tertiary" }),
240
- u ? u.name : "Choose a file…",
241
- /* @__PURE__ */ P("input", {
240
+ /* @__PURE__ */ I(P, { className: "h-4 w-4 text-text-tertiary" }),
241
+ m ? m.name : r("psw.documents.chooseFile", "Choose a file…"),
242
+ /* @__PURE__ */ I("input", {
242
243
  type: "file",
243
244
  className: "hidden",
244
- onChange: (e) => d(e.target.files?.[0] ?? null)
245
+ onChange: (e) => h(e.target.files?.[0] ?? null)
245
246
  })
246
247
  ]
247
248
  })
248
249
  }),
249
- /* @__PURE__ */ P(o, {
250
- label: "Description",
251
- children: /* @__PURE__ */ P(h, {
252
- value: a.description,
253
- onChange: (e) => s((t) => ({
250
+ /* @__PURE__ */ I(l, {
251
+ label: r("psw.common.description", "Description"),
252
+ children: /* @__PURE__ */ I(v, {
253
+ value: u.description,
254
+ onChange: (e) => p((t) => ({
254
255
  ...t,
255
256
  description: e.target.value
256
257
  }))
257
258
  })
258
259
  }),
259
- /* @__PURE__ */ F("label", {
260
+ /* @__PURE__ */ L("label", {
260
261
  className: "flex items-center gap-2 text-sm text-text-secondary",
261
- children: [/* @__PURE__ */ P("input", {
262
+ children: [/* @__PURE__ */ I("input", {
262
263
  type: "checkbox",
263
- checked: a.legalHold,
264
- onChange: (e) => s((t) => ({
264
+ checked: u.legalHold,
265
+ onChange: (e) => p((t) => ({
265
266
  ...t,
266
267
  legalHold: e.target.checked
267
268
  }))
268
- }), "Place under legal hold (cannot be disposed)"]
269
+ }), r("psw.documents.legalHoldLabel", "Place under legal hold (cannot be disposed)")]
269
270
  })
270
271
  ]
271
272
  })
272
273
  });
273
274
  };
274
275
  //#endregion
275
- export { R as DocumentsPage };
276
+ export { B as DocumentsPage };
276
277
 
277
278
  //# sourceMappingURL=DocumentsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/DocumentsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useDeferredValue, useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Plus, FileText, Download, Archive, Lock, Upload, Search } from 'lucide-react';\nimport {\n useDocuments,\n useCreateDocument,\n useArchiveDocument,\n type PswDocumentClassification,\n} from '../hooks/useProServiceWorldApi';\nimport { uploadDocumentFile, getDocumentDownloadUrl } from '../hooks/useFiles';\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 humanize,\n} from '../components/ui';\nimport { useAnalytics } from '../hooks/useAnalytics';\n\nconst CLASSIFICATIONS = ['PUBLIC', 'INTERNAL', 'CONFIDENTIAL', 'PRIVILEGED'] as const;\n\nexport const DocumentsPage: FC = () => {\n const [classFilter, setClassFilter] = useState<PswDocumentClassification | ''>('');\n const [search, setSearch] = useState('');\n const deferredSearch = useDeferredValue(search);\n const [creating, setCreating] = useState(false);\n const [banner, setBanner] = useState<{ tone: 'success' | 'danger'; text: string } | null>(null);\n const { data, isLoading, error, refetch } = useDocuments({\n classification: classFilter || undefined,\n search: deferredSearch.trim() || undefined,\n });\n const { emitFact } = useAnalytics();\n const archive = useArchiveDocument();\n\n const download = async (fileId: string) => {\n try {\n const url = await getDocumentDownloadUrl(fileId);\n window.open(url, '_blank', 'noopener');\n } catch (e) {\n setBanner({\n tone: 'danger',\n text: e instanceof Error ? e.message : 'Could not open document.',\n });\n }\n };\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Documents\"\n subtitle=\"Engagement letters, opinions, filings and evidence — metadata, classification and legal hold here; the file itself lives in the shared Files service.\"\n icon={<FileText className=\"h-6 w-6\" />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Add document\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 documents…\"\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: 'document',\n queryLength: search.trim().length,\n });\n }\n }}\n className=\"pl-9\"\n />\n </div>\n <NativeSelect\n value={classFilter}\n onChange={(e) => setClassFilter(e.target.value as PswDocumentClassification | '')}\n className=\"sm:w-52\"\n >\n <option value=\"\">All classifications</option>\n {enumOptions(CLASSIFICATIONS)}\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 documents\"\n description=\"Add a document — upload the file to the shared Files service and record it here.\"\n icon={<FileText className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" />\n Add document\n </Button>\n }\n />\n ) : (\n <SectionCard title={`${data.totalCount} document${data.totalCount === 1 ? '' : 's'}`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Name</Th>\n <Th>Classification</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((d) => (\n <tr key={d.id} className=\"hover:bg-bg-sunken/50\">\n <Td>\n <span className=\"flex items-center gap-1.5 font-medium text-text-primary\">\n {d.legalHold && (\n <Lock\n className=\"h-3.5 w-3.5 text-status-warning-text\"\n aria-label=\"Legal hold\"\n />\n )}\n {d.name} <span className=\"text-xs text-text-tertiary\">v{d.version}</span>\n </span>\n </Td>\n <Td>{humanize(d.classification)}</Td>\n <Td>\n <StatusPill status={d.status} />\n </Td>\n <Td>{fmtDate(d.createdAt)}</Td>\n <Td className=\"text-right\">\n <div className=\"flex justify-end gap-1\">\n {d.file?.id && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => void download(d.file!.id)}\n aria-label=\"Download\"\n >\n <Download className=\"h-4 w-4\" />\n </Button>\n )}\n {d.status !== 'ARCHIVED' && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Archive\"\n disabled={archive.isPending}\n onClick={() =>\n archive.mutate(d.id, {\n onSuccess: () =>\n setBanner({ tone: 'success', text: `${d.name} archived.` }),\n onError: (e) =>\n setBanner({\n tone: 'danger',\n text: e instanceof Error ? e.message : 'Failed.',\n }),\n })\n }\n >\n <Archive className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n </SectionCard>\n )}\n\n {creating && (\n <DocumentModal\n onClose={() => setCreating(false)}\n onDone={() => {\n void refetch();\n setBanner({ tone: 'success', text: 'Document added.' });\n }}\n />\n )}\n </div>\n );\n};\n\nconst DocumentModal: FC<{ onClose: () => void; onDone: () => void }> = ({ onClose, onDone }) => {\n const create = useCreateDocument();\n const [form, setForm] = useState({\n name: '',\n classification: 'INTERNAL',\n description: '',\n legalHold: false,\n });\n const [file, setFile] = useState<File | null>(null);\n const [uploading, setUploading] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n\n const submit = async () => {\n setErr(null);\n if (!form.name.trim()) return setErr('Document name is required.');\n let fileId: string | null = null;\n if (file) {\n try {\n setUploading(true);\n const uploaded = await uploadDocumentFile(file);\n fileId = uploaded.fileId;\n } catch (e) {\n setUploading(false);\n return setErr(e instanceof Error ? e.message : 'Upload failed.');\n }\n setUploading(false);\n }\n create.mutate(\n {\n name: form.name.trim(),\n classification: form.classification,\n description: form.description.trim() || null,\n legalHold: form.legalHold,\n fileId,\n },\n {\n onSuccess: () => {\n onDone();\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : 'Failed.'),\n }\n );\n };\n\n const busy = uploading || create.isPending;\n return (\n <Modal\n open\n onClose={onClose}\n title=\"Add document\"\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={busy}>\n Cancel\n </Button>\n <Button onClick={() => void submit()} disabled={busy}>\n {uploading ? 'Uploading…' : create.isPending ? 'Saving…' : 'Add document'}\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\n value={form.name}\n onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}\n placeholder=\"Engagement letter — Acme FY26\"\n />\n </Field>\n <Field label=\"Classification\">\n <NativeSelect\n value={form.classification}\n onChange={(e) => setForm((f) => ({ ...f, classification: e.target.value }))}\n >\n {enumOptions(CLASSIFICATIONS)}\n </NativeSelect>\n </Field>\n <Field label=\"File\" hint=\"Optional — stored in the shared Files service.\">\n <label className=\"flex cursor-pointer items-center gap-2 rounded-lg border border-dashed border-border-seam bg-bg-canvas px-3 py-3 text-sm text-text-secondary hover:border-accent\">\n <Upload className=\"h-4 w-4 text-text-tertiary\" />\n {file ? file.name : 'Choose a file…'}\n <input\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => setFile(e.target.files?.[0] ?? null)}\n />\n </label>\n </Field>\n <Field label=\"Description\">\n <TextArea\n value={form.description}\n onChange={(e) => setForm((f) => ({ ...f, description: e.target.value }))}\n />\n </Field>\n <label className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={form.legalHold}\n onChange={(e) => setForm((f) => ({ ...f, legalHold: e.target.checked }))}\n />\n Place under legal hold (cannot be disposed)\n </label>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"DocumentsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/DocumentsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useDeferredValue, useState } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Plus, FileText, Download, Archive, Lock, Upload, Search } from 'lucide-react';\nimport {\n useDocuments,\n useCreateDocument,\n useArchiveDocument,\n type PswDocumentClassification,\n} from '../hooks/useProServiceWorldApi';\nimport { uploadDocumentFile, getDocumentDownloadUrl } from '../hooks/useFiles';\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';\nimport { useAnalytics } from '../hooks/useAnalytics';\nimport { plural, useEnumLabel, useTr } from '../hooks/useTr';\n\nconst CLASSIFICATIONS = ['PUBLIC', 'INTERNAL', 'CONFIDENTIAL', 'PRIVILEGED'] as const;\n\nexport const DocumentsPage: FC = () => {\n const tr = useTr();\n const enumLabel = useEnumLabel();\n const [classFilter, setClassFilter] = useState<PswDocumentClassification | ''>('');\n const [search, setSearch] = useState('');\n const deferredSearch = useDeferredValue(search);\n const [creating, setCreating] = useState(false);\n const [banner, setBanner] = useState<{ tone: 'success' | 'danger'; text: string } | null>(null);\n const { data, isLoading, error, refetch } = useDocuments({\n classification: classFilter || undefined,\n search: deferredSearch.trim() || undefined,\n });\n const { emitFact } = useAnalytics();\n const archive = useArchiveDocument();\n\n const download = async (fileId: string) => {\n try {\n const url = await getDocumentDownloadUrl(fileId);\n window.open(url, '_blank', 'noopener');\n } catch (e) {\n setBanner({\n tone: 'danger',\n text:\n e instanceof Error\n ? e.message\n : tr('psw.documents.openFailed', 'Could not open document.'),\n });\n }\n };\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title={tr('psw.documents.title', 'Documents')}\n subtitle={tr(\n 'psw.documents.subtitle',\n 'Engagement letters, opinions, filings and evidence — metadata, classification and legal hold here; the file itself lives in the shared Files service.'\n )}\n icon={<FileText className=\"h-6 w-6\" />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"me-1.5 h-4 w-4\" />\n {tr('psw.documents.add', 'Add document')}\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 start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary\" />\n <TextInput\n placeholder={tr('psw.documents.searchPlaceholder', 'Search documents…')}\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: 'document',\n queryLength: search.trim().length,\n });\n }\n }}\n className=\"ps-9\"\n />\n </div>\n <NativeSelect\n value={classFilter}\n onChange={(e) => setClassFilter(e.target.value as PswDocumentClassification | '')}\n className=\"sm:w-52\"\n >\n <option value=\"\">{tr('psw.documents.allClassifications', 'All classifications')}</option>\n {enumOptions(CLASSIFICATIONS, enumLabel)}\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={tr('psw.documents.emptyTitle', 'No documents')}\n description={tr(\n 'psw.documents.emptyDescription',\n 'Add a document — upload the file to the shared Files service and record it here.'\n )}\n icon={<FileText className=\"h-8 w-8\" />}\n action={\n <Button onClick={() => setCreating(true)}>\n <Plus className=\"me-1.5 h-4 w-4\" />\n {tr('psw.documents.add', 'Add document')}\n </Button>\n }\n />\n ) : (\n <SectionCard\n title={plural(\n tr,\n 'psw.documents.count',\n data.totalCount,\n '{{count}} document',\n '{{count}} documents'\n )}\n >\n <TableWrap>\n <thead>\n <tr>\n <Th>{tr('psw.common.name', 'Name')}</Th>\n <Th>{tr('psw.documents.classification', 'Classification')}</Th>\n <Th>{tr('psw.common.status', 'Status')}</Th>\n <Th>{tr('psw.common.added', 'Added')}</Th>\n <Th className=\"text-end\">{tr('psw.common.actions', 'Actions')}</Th>\n </tr>\n </thead>\n <tbody>\n {data.items.map((d) => (\n <tr key={d.id} className=\"hover:bg-bg-sunken/50\">\n <Td>\n <span className=\"flex items-center gap-1.5 font-medium text-text-primary\">\n {d.legalHold && (\n <Lock\n className=\"h-3.5 w-3.5 text-status-warning-text\"\n aria-label={tr('psw.documents.legalHold', 'Legal hold')}\n />\n )}\n {d.name} <span className=\"text-xs text-text-tertiary\">v{d.version}</span>\n </span>\n </Td>\n <Td>{enumLabel(d.classification)}</Td>\n <Td>\n <StatusPill status={d.status} />\n </Td>\n <Td>{fmtDate(d.createdAt)}</Td>\n <Td className=\"text-end\">\n <div className=\"flex justify-end gap-1\">\n {d.file?.id && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => void download(d.file!.id)}\n aria-label={tr('psw.documents.download', 'Download')}\n >\n <Download className=\"h-4 w-4\" />\n </Button>\n )}\n {d.status !== 'ARCHIVED' && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={tr('psw.common.archive', 'Archive')}\n disabled={archive.isPending}\n onClick={() =>\n archive.mutate(d.id, {\n onSuccess: () =>\n setBanner({\n tone: 'success',\n text: tr('psw.documents.archived', '{{name}} archived.', {\n name: d.name,\n }),\n }),\n onError: (e) =>\n setBanner({\n tone: 'danger',\n text:\n e instanceof Error\n ? e.message\n : tr('psw.common.failed', 'Failed.'),\n }),\n })\n }\n >\n <Archive className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n </SectionCard>\n )}\n\n {creating && (\n <DocumentModal\n onClose={() => setCreating(false)}\n onDone={() => {\n void refetch();\n setBanner({ tone: 'success', text: tr('psw.documents.added', 'Document added.') });\n }}\n />\n )}\n </div>\n );\n};\n\nconst DocumentModal: FC<{ onClose: () => void; onDone: () => void }> = ({ onClose, onDone }) => {\n const tr = useTr();\n const enumLabel = useEnumLabel();\n const create = useCreateDocument();\n const [form, setForm] = useState({\n name: '',\n classification: 'INTERNAL',\n description: '',\n legalHold: false,\n });\n const [file, setFile] = useState<File | null>(null);\n const [uploading, setUploading] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n\n const submit = async () => {\n setErr(null);\n if (!form.name.trim())\n return setErr(tr('psw.documents.nameRequired', 'Document name is required.'));\n let fileId: string | null = null;\n if (file) {\n try {\n setUploading(true);\n const uploaded = await uploadDocumentFile(file);\n fileId = uploaded.fileId;\n } catch (e) {\n setUploading(false);\n return setErr(\n e instanceof Error ? e.message : tr('psw.documents.uploadFailed', 'Upload failed.')\n );\n }\n setUploading(false);\n }\n create.mutate(\n {\n name: form.name.trim(),\n classification: form.classification,\n description: form.description.trim() || null,\n legalHold: form.legalHold,\n fileId,\n },\n {\n onSuccess: () => {\n onDone();\n onClose();\n },\n onError: (e) => setErr(e instanceof Error ? e.message : tr('psw.common.failed', 'Failed.')),\n }\n );\n };\n\n const busy = uploading || create.isPending;\n return (\n <Modal\n open\n onClose={onClose}\n title={tr('psw.documents.add', 'Add document')}\n footer={\n <>\n <Button variant=\"outline\" onClick={onClose} disabled={busy}>\n {tr('psw.common.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void submit()} disabled={busy}>\n {uploading\n ? tr('psw.documents.uploading', 'Uploading…')\n : create.isPending\n ? tr('psw.common.saving', 'Saving…')\n : tr('psw.documents.add', 'Add document')}\n </Button>\n </>\n }\n >\n <div className=\"space-y-3\">\n {err && <Banner tone=\"danger\">{err}</Banner>}\n <Field label={tr('psw.common.name', 'Name')} required>\n <TextInput\n value={form.name}\n onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}\n placeholder={tr('psw.documents.namePlaceholder', 'Engagement letter — Acme FY26')}\n />\n </Field>\n <Field label={tr('psw.documents.classification', 'Classification')}>\n <NativeSelect\n value={form.classification}\n onChange={(e) => setForm((f) => ({ ...f, classification: e.target.value }))}\n >\n {enumOptions(CLASSIFICATIONS, enumLabel)}\n </NativeSelect>\n </Field>\n <Field\n label={tr('psw.documents.file', 'File')}\n hint={tr('psw.documents.fileHint', 'Optional — stored in the shared Files service.')}\n >\n <label className=\"flex cursor-pointer items-center gap-2 rounded-lg border border-dashed border-border-seam bg-bg-canvas px-3 py-3 text-sm text-text-secondary hover:border-accent\">\n <Upload className=\"h-4 w-4 text-text-tertiary\" />\n {file ? file.name : tr('psw.documents.chooseFile', 'Choose a file…')}\n <input\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => setFile(e.target.files?.[0] ?? null)}\n />\n </label>\n </Field>\n <Field label={tr('psw.common.description', 'Description')}>\n <TextArea\n value={form.description}\n onChange={(e) => setForm((f) => ({ ...f, description: e.target.value }))}\n />\n </Field>\n <label className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <input\n type=\"checkbox\"\n checked={form.legalHold}\n onChange={(e) => setForm((f) => ({ ...f, legalHold: e.target.checked }))}\n />\n {tr('psw.documents.legalHoldLabel', 'Place under legal hold (cannot be disposed)')}\n </label>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}