@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,194 +1,198 @@
1
1
  import { useApproveTimeEntry as e, useEngagements as t, useLogTimeEntry as n, useMatters as r, useRejectTimeEntry as i, useSubmitTimeEntry as a, useTimeEntries as o, useUpdateTimeEntry as s } from "../hooks/useProServiceWorldApi.js";
2
- import { Banner as c, Empty as l, ErrorState as u, Field as d, LoadingBlock as f, MetricCard as p, Modal as m, NativeSelect as h, PageHeader as ee, SectionCard as te, StatusPill as ne, TableWrap as re, Td as g, TextArea as _, TextInput as v, Th as y, enumOptions as ie, fmtDate as ae, fmtMinutesAsHours as b } from "../components/ui.js";
3
- import { useAnalytics as oe } from "../hooks/useAnalytics.js";
4
- import { elapsedMinutes as x, formatTimerDuration as S, useTimeTimer as se } from "../hooks/useTimeTimer.js";
5
- import { useDeferredValue as C, useState as w } from "react";
6
- import { CheckCircle2 as ce, CircleSlash as le, Clock as T, ListChecks as ue, Play as E, Plus as D, Search as de, Send as fe, Square as O, Trash2 as k, Wallet as A } from "lucide-react";
7
- import { Fragment as j, jsx as M, jsxs as N } from "react/jsx-runtime";
8
- import { Button as P } from "@burdenoff/fe-libs/ui";
2
+ import { useEnumLabel as c, useTr as l } from "../hooks/useTr.js";
3
+ import { Banner as u, Empty as d, ErrorState as f, Field as p, LoadingBlock as ee, MetricCard as m, Modal as h, NativeSelect as g, PageHeader as te, SectionCard as ne, StatusPill as re, TableWrap as ie, Td as _, TextArea as v, TextInput as y, Th as b, enumOptions as ae, fmtDate as oe, fmtMinutesAsHours as x } from "../components/ui.js";
4
+ import { useAnalytics as se } from "../hooks/useAnalytics.js";
5
+ import { elapsedMinutes as S, formatTimerDuration as C, useTimeTimer as ce } from "../hooks/useTimeTimer.js";
6
+ import { useDeferredValue as le, useState as w } from "react";
7
+ import { CheckCircle2 as T, CircleSlash as ue, Clock as E, ListChecks as de, Play as D, Plus as O, Search as fe, Send as pe, Square as k, Trash2 as A, Wallet as j } from "lucide-react";
8
+ import { Fragment as M, jsx as N, jsxs as P } from "react/jsx-runtime";
9
+ import { Button as F } from "@burdenoff/fe-libs/ui";
9
10
  //#region src/proserviceworld/pages/TimePage.tsx
10
- var pe = [
11
+ var me = [
11
12
  "DRAFT",
12
13
  "SUBMITTED",
13
14
  "APPROVED",
14
15
  "REJECTED",
15
16
  "BILLED"
16
- ], me = ({ billable: e }) => e ? /* @__PURE__ */ N("span", {
17
- className: "inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-success-text",
18
- children: [/* @__PURE__ */ M("span", { className: "h-1.5 w-1.5 rounded-full bg-current opacity-70" }), "Billable"]
19
- }) : /* @__PURE__ */ N("span", {
20
- className: "inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-tertiary",
21
- children: [/* @__PURE__ */ M("span", { className: "h-1.5 w-1.5 rounded-full bg-current opacity-60" }), "Non-billable"]
22
- }), F = () => {
23
- let [t, n] = w(""), [r, d] = w(""), m = C(r), [_, x] = w(!1), [S, O] = w(!1), [k, F] = w(null), [z, B] = w(null), { data: V, isLoading: _e, error: H, refetch: ve } = o({
24
- status: t || void 0,
25
- search: m.trim() || void 0
26
- }), { emitFact: ye } = oe(), U = a(), W = e(), be = s(), G = i(), [K, q] = w(null), [J, Y] = w(null), X = se(), Z = (V?.items ?? []).reduce((e, t) => e + t.minutes, 0), Q = (V?.items ?? []).filter((e) => e.billable).reduce((e, t) => e + t.minutes, 0), xe = Z > 0 ? Math.round(Q / Z * 100) : 0, $ = (e, t, n) => e.mutate(t, {
17
+ ], he = ({ billable: e }) => {
18
+ let t = l();
19
+ return e ? /* @__PURE__ */ P("span", {
20
+ className: "inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-success-text",
21
+ children: [/* @__PURE__ */ N("span", { className: "h-1.5 w-1.5 rounded-full bg-current opacity-70" }), t("psw.time.billable", "Billable")]
22
+ }) : /* @__PURE__ */ P("span", {
23
+ className: "inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-tertiary",
24
+ children: [/* @__PURE__ */ N("span", { className: "h-1.5 w-1.5 rounded-full bg-current opacity-60" }), t("psw.time.nonBillable", "Non-billable")]
25
+ });
26
+ }, I = () => {
27
+ let t = l(), n = c(), [r, p] = w(""), [h, v] = w(""), S = le(h), [C, k] = w(!1), [A, I] = w(!1), [L, R] = w(null), [z, B] = w(null), { data: V, isLoading: xe, error: H, refetch: Se } = o({
28
+ status: r || void 0,
29
+ search: S.trim() || void 0
30
+ }), { emitFact: Ce } = se(), U = a(), W = e(), we = s(), G = i(), [K, q] = w(null), [J, Y] = w(null), X = ce(), Z = (V?.items ?? []).reduce((e, t) => e + t.minutes, 0), Q = (V?.items ?? []).filter((e) => e.billable).reduce((e, t) => e + t.minutes, 0), Te = Z > 0 ? Math.round(Q / Z * 100) : 0, $ = (e, n, r) => e.mutate(n, {
27
31
  onSuccess: () => B({
28
32
  tone: "success",
29
- text: `Time entry ${n}.`
33
+ text: r
30
34
  }),
31
35
  onError: (e) => B({
32
36
  tone: "danger",
33
- text: e instanceof Error ? e.message : "Failed."
37
+ text: e instanceof Error ? e.message : t("psw.common.failed", "Failed.")
34
38
  })
35
39
  });
36
- return /* @__PURE__ */ N("div", {
40
+ return /* @__PURE__ */ P("div", {
37
41
  className: "space-y-6",
38
42
  children: [
39
- /* @__PURE__ */ M(ee, {
40
- title: "Time",
41
- subtitle: "Capture expert effort against engagements and matters — the raw material of billing and utilization.",
42
- icon: /* @__PURE__ */ M(T, { className: "h-6 w-6" }),
43
- actions: X.timer ? /* @__PURE__ */ M(R, {
43
+ /* @__PURE__ */ N(te, {
44
+ title: t("psw.time.title", "Time"),
45
+ subtitle: t("psw.time.subtitle", "Capture expert effort against engagements and matters — the raw material of billing and utilization."),
46
+ icon: /* @__PURE__ */ N(E, { className: "h-6 w-6" }),
47
+ actions: X.timer ? /* @__PURE__ */ N(ve, {
44
48
  seconds: X.seconds,
45
49
  onStop: () => {
46
50
  let e = X.stop();
47
- e && (F(e), x(!0));
51
+ e && (R(e), k(!0));
48
52
  },
49
53
  onDiscard: X.discard
50
- }) : /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ N(P, {
54
+ }) : /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ P(F, {
51
55
  variant: "outline",
52
- onClick: () => O(!0),
53
- children: [/* @__PURE__ */ M(E, { className: "mr-1.5 h-4 w-4" }), "Start timer"]
54
- }), /* @__PURE__ */ N(P, {
55
- onClick: () => x(!0),
56
- children: [/* @__PURE__ */ M(D, { className: "mr-1.5 h-4 w-4" }), "Log time"]
56
+ onClick: () => I(!0),
57
+ children: [/* @__PURE__ */ N(D, { className: "me-1.5 h-4 w-4" }), t("psw.time.startTimer", "Start timer")]
58
+ }), /* @__PURE__ */ P(F, {
59
+ onClick: () => k(!0),
60
+ children: [/* @__PURE__ */ N(O, { className: "me-1.5 h-4 w-4" }), t("psw.time.logTime", "Log time")]
57
61
  })] })
58
62
  }),
59
- z && /* @__PURE__ */ M(c, {
63
+ z && /* @__PURE__ */ N(u, {
60
64
  tone: z.tone,
61
65
  onClose: () => B(null),
62
66
  children: z.text
63
67
  }),
64
- /* @__PURE__ */ N("div", {
68
+ /* @__PURE__ */ P("div", {
65
69
  className: "grid grid-cols-2 gap-3 sm:grid-cols-4",
66
70
  children: [
67
- /* @__PURE__ */ M(p, {
68
- label: "Entries",
71
+ /* @__PURE__ */ N(m, {
72
+ label: t("psw.time.metricEntries", "Entries"),
69
73
  value: V?.totalCount ?? 0,
70
- icon: /* @__PURE__ */ M(ue, { className: "h-4 w-4" })
74
+ icon: /* @__PURE__ */ N(de, { className: "h-4 w-4" })
71
75
  }),
72
- /* @__PURE__ */ M(p, {
73
- label: "Total hours",
74
- value: b(Z),
75
- icon: /* @__PURE__ */ M(T, { className: "h-4 w-4" })
76
+ /* @__PURE__ */ N(m, {
77
+ label: t("psw.time.metricTotalHours", "Total hours"),
78
+ value: x(Z),
79
+ icon: /* @__PURE__ */ N(E, { className: "h-4 w-4" })
76
80
  }),
77
- /* @__PURE__ */ M(p, {
78
- label: "Billable hours",
79
- value: b(Q),
80
- hint: `${xe}% utilization`,
81
- icon: /* @__PURE__ */ M(A, { className: "h-4 w-4" }),
81
+ /* @__PURE__ */ N(m, {
82
+ label: t("psw.time.metricBillableHours", "Billable hours"),
83
+ value: x(Q),
84
+ hint: t("psw.time.utilizationHint", "{{pct}}% utilization", { pct: Te }),
85
+ icon: /* @__PURE__ */ N(j, { className: "h-4 w-4" }),
82
86
  tone: "accent"
83
87
  }),
84
- /* @__PURE__ */ M(p, {
85
- label: "Non-billable",
86
- value: b(Z - Q),
87
- icon: /* @__PURE__ */ M(le, { className: "h-4 w-4" })
88
+ /* @__PURE__ */ N(m, {
89
+ label: t("psw.time.nonBillable", "Non-billable"),
90
+ value: x(Z - Q),
91
+ icon: /* @__PURE__ */ N(ue, { className: "h-4 w-4" })
88
92
  })
89
93
  ]
90
94
  }),
91
- /* @__PURE__ */ N("div", {
95
+ /* @__PURE__ */ P("div", {
92
96
  className: "flex flex-col gap-2 sm:flex-row sm:items-center",
93
- children: [/* @__PURE__ */ N("div", {
97
+ children: [/* @__PURE__ */ P("div", {
94
98
  className: "relative flex-1",
95
- children: [/* @__PURE__ */ M(de, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ M(v, {
96
- placeholder: "Search time entries…",
97
- value: r,
98
- onChange: (e) => d(e.target.value),
99
+ children: [/* @__PURE__ */ N(fe, { className: "pointer-events-none absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ N(y, {
100
+ placeholder: t("psw.time.searchPlaceholder", "Search time entries…"),
101
+ value: h,
102
+ onChange: (e) => v(e.target.value),
99
103
  onKeyDown: (e) => {
100
- e.key === "Enter" && r.trim() && ye("psw.search.performed", {
104
+ e.key === "Enter" && h.trim() && Ce("psw.search.performed", {
101
105
  entityType: "time-entry",
102
- queryLength: r.trim().length
106
+ queryLength: h.trim().length
103
107
  });
104
108
  },
105
- className: "pl-9"
109
+ className: "ps-9"
106
110
  })]
107
- }), /* @__PURE__ */ N(h, {
108
- value: t,
109
- onChange: (e) => n(e.target.value),
111
+ }), /* @__PURE__ */ P(g, {
112
+ value: r,
113
+ onChange: (e) => p(e.target.value),
110
114
  className: "sm:w-52",
111
- children: [/* @__PURE__ */ M("option", {
115
+ children: [/* @__PURE__ */ N("option", {
112
116
  value: "",
113
- children: "All statuses"
114
- }), ie(pe)]
117
+ children: t("psw.common.allStatuses", "All statuses")
118
+ }), ae(me, n)]
115
119
  })]
116
120
  }),
117
- _e ? /* @__PURE__ */ M(f, {}) : H ? /* @__PURE__ */ M(u, {
121
+ xe ? /* @__PURE__ */ N(ee, {}) : H ? /* @__PURE__ */ N(f, {
118
122
  error: H,
119
- onRetry: () => void ve()
120
- }) : !V || V.items.length === 0 ? /* @__PURE__ */ M(l, {
121
- title: "No time logged",
122
- description: "Log your first time entry against an engagement or matter.",
123
- icon: /* @__PURE__ */ M(T, { className: "h-8 w-8" }),
124
- action: /* @__PURE__ */ N(P, {
125
- onClick: () => x(!0),
126
- children: [/* @__PURE__ */ M(D, { className: "mr-1.5 h-4 w-4" }), "Log time"]
123
+ onRetry: () => void Se()
124
+ }) : !V || V.items.length === 0 ? /* @__PURE__ */ N(d, {
125
+ title: t("psw.time.emptyTitle", "No time logged"),
126
+ description: t("psw.time.emptyDescription", "Log your first time entry against an engagement or matter."),
127
+ icon: /* @__PURE__ */ N(E, { className: "h-8 w-8" }),
128
+ action: /* @__PURE__ */ P(F, {
129
+ onClick: () => k(!0),
130
+ children: [/* @__PURE__ */ N(O, { className: "me-1.5 h-4 w-4" }), t("psw.time.logTime", "Log time")]
127
131
  })
128
- }) : /* @__PURE__ */ M(te, {
129
- title: "Time entries",
130
- children: /* @__PURE__ */ N(re, { children: [/* @__PURE__ */ M("thead", { children: /* @__PURE__ */ N("tr", { children: [
131
- /* @__PURE__ */ M(y, { children: "Date" }),
132
- /* @__PURE__ */ M(y, { children: "Narrative" }),
133
- /* @__PURE__ */ M(y, { children: "Hours" }),
134
- /* @__PURE__ */ M(y, { children: "Billable" }),
135
- /* @__PURE__ */ M(y, { children: "Status" }),
136
- /* @__PURE__ */ M(y, {
137
- className: "text-right",
138
- children: "Actions"
132
+ }) : /* @__PURE__ */ N(ne, {
133
+ title: t("psw.time.entriesTitle", "Time entries"),
134
+ children: /* @__PURE__ */ P(ie, { children: [/* @__PURE__ */ N("thead", { children: /* @__PURE__ */ P("tr", { children: [
135
+ /* @__PURE__ */ N(b, { children: t("psw.common.date", "Date") }),
136
+ /* @__PURE__ */ N(b, { children: t("psw.time.narrative", "Narrative") }),
137
+ /* @__PURE__ */ N(b, { children: t("psw.time.hours", "Hours") }),
138
+ /* @__PURE__ */ N(b, { children: t("psw.time.billable", "Billable") }),
139
+ /* @__PURE__ */ N(b, { children: t("psw.common.status", "Status") }),
140
+ /* @__PURE__ */ N(b, {
141
+ className: "text-end",
142
+ children: t("psw.common.actions", "Actions")
139
143
  })
140
- ] }) }), /* @__PURE__ */ M("tbody", { children: V.items.map((e) => /* @__PURE__ */ N("tr", {
144
+ ] }) }), /* @__PURE__ */ N("tbody", { children: V.items.map((e) => /* @__PURE__ */ P("tr", {
141
145
  className: "transition-colors hover:bg-bg-sunken/60",
142
146
  children: [
143
- /* @__PURE__ */ M(g, {
147
+ /* @__PURE__ */ N(_, {
144
148
  className: "whitespace-nowrap",
145
- children: ae(e.date)
149
+ children: oe(e.date)
146
150
  }),
147
- /* @__PURE__ */ M(g, {
151
+ /* @__PURE__ */ N(_, {
148
152
  className: "max-w-xs truncate text-text-primary",
149
153
  children: e.narrative || "—"
150
154
  }),
151
- /* @__PURE__ */ M(g, {
155
+ /* @__PURE__ */ N(_, {
152
156
  className: "whitespace-nowrap font-medium text-text-primary",
153
- children: b(e.minutes)
157
+ children: x(e.minutes)
154
158
  }),
155
- /* @__PURE__ */ M(g, { children: /* @__PURE__ */ M(me, { billable: e.billable }) }),
156
- /* @__PURE__ */ M(g, { children: /* @__PURE__ */ M(ne, { status: e.status }) }),
157
- /* @__PURE__ */ M(g, {
158
- className: "text-right",
159
- children: /* @__PURE__ */ N("div", {
159
+ /* @__PURE__ */ N(_, { children: /* @__PURE__ */ N(he, { billable: e.billable }) }),
160
+ /* @__PURE__ */ N(_, { children: /* @__PURE__ */ N(re, { status: e.status }) }),
161
+ /* @__PURE__ */ N(_, {
162
+ className: "text-end",
163
+ children: /* @__PURE__ */ P("div", {
160
164
  className: "flex justify-end gap-1",
161
165
  children: [
162
- e.status === "DRAFT" && /* @__PURE__ */ N(P, {
166
+ e.status === "DRAFT" && /* @__PURE__ */ P(F, {
163
167
  variant: "ghost",
164
168
  size: "sm",
165
169
  disabled: U.isPending,
166
- onClick: () => $(U, e.id, "submitted"),
167
- children: [/* @__PURE__ */ M(fe, { className: "mr-1 h-3.5 w-3.5" }), "Submit"]
170
+ onClick: () => $(U, e.id, t("psw.time.submitted", "Time entry submitted.")),
171
+ children: [/* @__PURE__ */ N(pe, { className: "me-1 h-3.5 w-3.5" }), t("psw.time.submit", "Submit")]
168
172
  }),
169
173
  [
170
174
  "DRAFT",
171
175
  "SUBMITTED",
172
176
  "REJECTED"
173
- ].includes(e.status) && /* @__PURE__ */ M(P, {
177
+ ].includes(e.status) && /* @__PURE__ */ N(F, {
174
178
  variant: "ghost",
175
179
  size: "sm",
176
180
  onClick: () => q(e),
177
- children: "Edit"
181
+ children: t("psw.common.edit", "Edit")
178
182
  }),
179
- e.status === "SUBMITTED" && /* @__PURE__ */ N(P, {
183
+ e.status === "SUBMITTED" && /* @__PURE__ */ P(F, {
180
184
  variant: "ghost",
181
185
  size: "sm",
182
186
  disabled: W.isPending,
183
- onClick: () => $(W, e.id, "approved"),
184
- children: [/* @__PURE__ */ M(ce, { className: "mr-1 h-3.5 w-3.5" }), "Approve"]
187
+ onClick: () => $(W, e.id, t("psw.time.approved", "Time entry approved.")),
188
+ children: [/* @__PURE__ */ N(T, { className: "me-1 h-3.5 w-3.5" }), t("psw.time.approve", "Approve")]
185
189
  }),
186
- e.status === "SUBMITTED" && /* @__PURE__ */ M(P, {
190
+ e.status === "SUBMITTED" && /* @__PURE__ */ N(F, {
187
191
  variant: "ghost",
188
192
  size: "sm",
189
193
  disabled: G.isPending,
190
194
  onClick: () => Y(e),
191
- children: "Reject"
195
+ children: t("psw.time.reject", "Reject")
192
196
  })
193
197
  ]
194
198
  })
@@ -196,206 +200,209 @@ var pe = [
196
200
  ]
197
201
  }, e.id)) })] })
198
202
  }),
199
- _ && /* @__PURE__ */ M(ge, {
200
- initialTimer: k,
201
- onClose: () => x(!1),
203
+ C && /* @__PURE__ */ N(be, {
204
+ initialTimer: L,
205
+ onClose: () => k(!1),
202
206
  onDone: () => {
203
- F(null), B({
207
+ R(null), B({
204
208
  tone: "success",
205
- text: "Time logged."
209
+ text: t("psw.time.logged", "Time logged.")
206
210
  });
207
211
  }
208
212
  }),
209
- K && /* @__PURE__ */ M(I, {
213
+ K && /* @__PURE__ */ N(ge, {
210
214
  entry: K,
211
- mutation: be,
215
+ mutation: we,
212
216
  onClose: () => q(null)
213
217
  }),
214
- J && /* @__PURE__ */ M(L, {
218
+ J && /* @__PURE__ */ N(_e, {
215
219
  entry: J,
216
220
  mutation: G,
217
221
  onClose: () => Y(null)
218
222
  }),
219
- S && /* @__PURE__ */ M(he, {
220
- onClose: () => O(!1),
223
+ A && /* @__PURE__ */ N(ye, {
224
+ onClose: () => I(!1),
221
225
  onStart: (e) => {
222
- X.start(e), O(!1), B({
226
+ X.start(e), I(!1), B({
223
227
  tone: "success",
224
- text: "Timer started."
228
+ text: t("psw.time.timerStarted", "Timer started.")
225
229
  });
226
230
  }
227
231
  })
228
232
  ]
229
233
  });
230
- }, I = ({ entry: e, mutation: t, onClose: n }) => {
231
- let [r, i] = w({
234
+ }, ge = ({ entry: e, mutation: t, onClose: n }) => {
235
+ let r = l(), [i, a] = w({
232
236
  date: e.date.slice(0, 10),
233
237
  minutes: String(e.minutes),
234
238
  rate: String(e.rate),
235
239
  narrative: e.narrative ?? "",
236
240
  billable: e.billable
237
- }), [a, o] = w(null);
238
- return /* @__PURE__ */ M(m, {
241
+ }), [o, s] = w(null);
242
+ return /* @__PURE__ */ N(h, {
239
243
  open: !0,
240
244
  onClose: n,
241
- title: "Edit time entry",
242
- footer: /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M(P, {
245
+ title: r("psw.time.editTitle", "Edit time entry"),
246
+ footer: /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(F, {
243
247
  variant: "ghost",
244
248
  onClick: n,
245
- children: "Cancel"
246
- }), /* @__PURE__ */ M(P, {
249
+ children: r("psw.common.cancel", "Cancel")
250
+ }), /* @__PURE__ */ N(F, {
247
251
  onClick: () => {
248
- let i = Number(r.minutes);
249
- if (!Number.isInteger(i) || i <= 0) return o("Enter positive minutes.");
252
+ let a = Number(i.minutes);
253
+ if (!Number.isInteger(a) || a <= 0) return s(r("psw.time.positiveMinutes", "Enter positive minutes."));
250
254
  t.mutate({
251
255
  id: e.id,
252
256
  input: {
253
- date: new Date(r.date).toISOString(),
254
- minutes: i,
255
- rate: Number(r.rate) || 0,
256
- narrative: r.narrative.trim() || null,
257
- billable: r.billable
257
+ date: new Date(i.date).toISOString(),
258
+ minutes: a,
259
+ rate: Number(i.rate) || 0,
260
+ narrative: i.narrative.trim() || null,
261
+ billable: i.billable
258
262
  }
259
263
  }, {
260
264
  onSuccess: n,
261
- onError: (e) => o(e instanceof Error ? e.message : "Failed to save.")
265
+ onError: (e) => s(e instanceof Error ? e.message : r("psw.time.saveFailed", "Failed to save."))
262
266
  });
263
267
  },
264
268
  disabled: t.isPending,
265
- children: "Save"
269
+ children: r("psw.common.save", "Save")
266
270
  })] }),
267
- children: /* @__PURE__ */ N("div", {
271
+ children: /* @__PURE__ */ P("div", {
268
272
  className: "space-y-4",
269
273
  children: [
270
- a && /* @__PURE__ */ M(c, {
274
+ o && /* @__PURE__ */ N(u, {
271
275
  tone: "danger",
272
- children: a
276
+ children: o
273
277
  }),
274
- /* @__PURE__ */ M(d, {
275
- label: "Date",
276
- children: /* @__PURE__ */ M(v, {
278
+ /* @__PURE__ */ N(p, {
279
+ label: r("psw.common.date", "Date"),
280
+ children: /* @__PURE__ */ N(y, {
277
281
  type: "date",
278
- value: r.date,
279
- onChange: (e) => i({
280
- ...r,
282
+ value: i.date,
283
+ onChange: (e) => a({
284
+ ...i,
281
285
  date: e.target.value
282
286
  })
283
287
  })
284
288
  }),
285
- /* @__PURE__ */ M(d, {
286
- label: "Minutes",
287
- children: /* @__PURE__ */ M(v, {
289
+ /* @__PURE__ */ N(p, {
290
+ label: r("psw.time.minutes", "Minutes"),
291
+ children: /* @__PURE__ */ N(y, {
288
292
  type: "number",
289
293
  min: 1,
290
- value: r.minutes,
291
- onChange: (e) => i({
292
- ...r,
294
+ value: i.minutes,
295
+ onChange: (e) => a({
296
+ ...i,
293
297
  minutes: e.target.value
294
298
  })
295
299
  })
296
300
  }),
297
- /* @__PURE__ */ M(d, {
298
- label: "Rate",
299
- children: /* @__PURE__ */ M(v, {
301
+ /* @__PURE__ */ N(p, {
302
+ label: r("psw.time.rate", "Rate"),
303
+ children: /* @__PURE__ */ N(y, {
300
304
  type: "number",
301
305
  min: 0,
302
- value: r.rate,
303
- onChange: (e) => i({
304
- ...r,
306
+ value: i.rate,
307
+ onChange: (e) => a({
308
+ ...i,
305
309
  rate: e.target.value
306
310
  })
307
311
  })
308
312
  }),
309
- /* @__PURE__ */ M(d, {
310
- label: "Narrative",
311
- children: /* @__PURE__ */ M(_, {
312
- value: r.narrative,
313
- onChange: (e) => i({
314
- ...r,
313
+ /* @__PURE__ */ N(p, {
314
+ label: r("psw.time.narrative", "Narrative"),
315
+ children: /* @__PURE__ */ N(v, {
316
+ value: i.narrative,
317
+ onChange: (e) => a({
318
+ ...i,
315
319
  narrative: e.target.value
316
320
  })
317
321
  })
318
322
  }),
319
- /* @__PURE__ */ N("label", {
323
+ /* @__PURE__ */ P("label", {
320
324
  className: "flex items-center gap-2 text-sm",
321
325
  children: [
322
- /* @__PURE__ */ M("input", {
326
+ /* @__PURE__ */ N("input", {
323
327
  type: "checkbox",
324
- checked: r.billable,
325
- onChange: (e) => i({
326
- ...r,
328
+ checked: i.billable,
329
+ onChange: (e) => a({
330
+ ...i,
327
331
  billable: e.target.checked
328
332
  })
329
333
  }),
330
334
  " ",
331
- "Billable"
335
+ r("psw.time.billable", "Billable")
332
336
  ]
333
337
  })
334
338
  ]
335
339
  })
336
340
  });
337
- }, L = ({ entry: e, mutation: t, onClose: n }) => {
338
- let [r, i] = w(""), [a, o] = w(null);
339
- return /* @__PURE__ */ M(m, {
341
+ }, _e = ({ entry: e, mutation: t, onClose: n }) => {
342
+ let r = l(), [i, a] = w(""), [o, s] = w(null);
343
+ return /* @__PURE__ */ N(h, {
340
344
  open: !0,
341
345
  onClose: n,
342
- title: "Reject time entry",
343
- footer: /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M(P, {
346
+ title: r("psw.time.rejectTitle", "Reject time entry"),
347
+ footer: /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(F, {
344
348
  variant: "ghost",
345
349
  onClick: n,
346
- children: "Cancel"
347
- }), /* @__PURE__ */ M(P, {
350
+ children: r("psw.common.cancel", "Cancel")
351
+ }), /* @__PURE__ */ N(F, {
348
352
  onClick: () => {
349
- if (!r.trim()) return o("Enter a rejection reason.");
353
+ if (!i.trim()) return s(r("psw.time.reasonRequired", "Enter a rejection reason."));
350
354
  t.mutate({
351
355
  id: e.id,
352
- reason: r.trim()
356
+ reason: i.trim()
353
357
  }, {
354
358
  onSuccess: n,
355
- onError: (e) => o(e instanceof Error ? e.message : "Failed to reject.")
359
+ onError: (e) => s(e instanceof Error ? e.message : r("psw.time.rejectFailed", "Failed to reject."))
356
360
  });
357
361
  },
358
362
  disabled: t.isPending,
359
- children: "Reject"
363
+ children: r("psw.time.reject", "Reject")
360
364
  })] }),
361
- children: /* @__PURE__ */ N("div", {
365
+ children: /* @__PURE__ */ P("div", {
362
366
  className: "space-y-4",
363
- children: [a && /* @__PURE__ */ M(c, {
367
+ children: [o && /* @__PURE__ */ N(u, {
364
368
  tone: "danger",
365
- children: a
366
- }), /* @__PURE__ */ M(d, {
367
- label: "Reason",
368
- children: /* @__PURE__ */ M(_, {
369
+ children: o
370
+ }), /* @__PURE__ */ N(p, {
371
+ label: r("psw.time.reason", "Reason"),
372
+ children: /* @__PURE__ */ N(v, {
369
373
  autoFocus: !0,
370
- value: r,
371
- onChange: (e) => i(e.target.value),
372
- placeholder: "Explain what needs correction."
374
+ value: i,
375
+ onChange: (e) => a(e.target.value),
376
+ placeholder: r("psw.time.reasonPlaceholder", "Explain what needs correction.")
373
377
  })
374
378
  })]
375
379
  })
376
380
  });
377
- }, R = ({ seconds: e, onStop: t, onDiscard: n }) => /* @__PURE__ */ N("div", {
378
- className: "flex items-center gap-2 rounded-lg border border-border-seam bg-bg-surface px-2 py-1",
379
- children: [
380
- /* @__PURE__ */ M("span", {
381
- className: "font-mono text-sm font-semibold tabular-nums text-text-primary",
382
- "aria-live": "polite",
383
- children: S(e)
384
- }),
385
- /* @__PURE__ */ N(P, {
386
- size: "sm",
387
- onClick: t,
388
- children: [/* @__PURE__ */ M(O, { className: "mr-1 h-3.5 w-3.5 fill-current" }), "Stop"]
389
- }),
390
- /* @__PURE__ */ M(P, {
391
- variant: "ghost",
392
- size: "sm",
393
- onClick: n,
394
- "aria-label": "Discard timer",
395
- children: /* @__PURE__ */ M(k, { className: "h-3.5 w-3.5" })
396
- })
397
- ]
398
- }), z = () => ({
381
+ }, ve = ({ seconds: e, onStop: t, onDiscard: n }) => {
382
+ let r = l();
383
+ return /* @__PURE__ */ P("div", {
384
+ className: "flex items-center gap-2 rounded-lg border border-border-seam bg-bg-surface px-2 py-1",
385
+ children: [
386
+ /* @__PURE__ */ N("span", {
387
+ className: "font-mono text-sm font-semibold tabular-nums text-text-primary",
388
+ "aria-live": "polite",
389
+ children: C(e)
390
+ }),
391
+ /* @__PURE__ */ P(F, {
392
+ size: "sm",
393
+ onClick: t,
394
+ children: [/* @__PURE__ */ N(k, { className: "me-1 h-3.5 w-3.5 fill-current" }), r("psw.time.stop", "Stop")]
395
+ }),
396
+ /* @__PURE__ */ N(F, {
397
+ variant: "ghost",
398
+ size: "sm",
399
+ onClick: n,
400
+ "aria-label": r("psw.time.discardTimer", "Discard timer"),
401
+ children: /* @__PURE__ */ N(A, { className: "h-3.5 w-3.5" })
402
+ })
403
+ ]
404
+ });
405
+ }, L = () => ({
399
406
  against: "engagement",
400
407
  engagementId: "",
401
408
  matterId: "",
@@ -405,257 +412,243 @@ var pe = [
405
412
  rate: "",
406
413
  billable: !0,
407
414
  narrative: ""
408
- }), B = (e, t = Date.now()) => {
409
- let n = x(e, t);
415
+ }), R = (e, t = Date.now()) => {
416
+ let n = S(e, t);
410
417
  return {
411
418
  ...e,
412
419
  hours: String(Math.floor(n / 60)),
413
420
  minutes: String(n % 60)
414
421
  };
415
- }, V = ({ form: e, set: n }) => {
416
- let i = t({ pagination: { limit: 100 } }), a = r({ pagination: { limit: 100 } });
417
- return /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M(d, {
418
- label: "Against",
419
- children: /* @__PURE__ */ N(h, {
422
+ }, z = ({ form: e, set: n }) => {
423
+ let i = l(), a = t({ pagination: { limit: 100 } }), o = r({ pagination: { limit: 100 } });
424
+ return /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(p, {
425
+ label: i("psw.time.against", "Against"),
426
+ children: /* @__PURE__ */ P(g, {
420
427
  value: e.against,
421
428
  onChange: n("against"),
422
- children: [/* @__PURE__ */ M("option", {
429
+ children: [/* @__PURE__ */ N("option", {
423
430
  value: "engagement",
424
- children: "Engagement"
425
- }), /* @__PURE__ */ M("option", {
431
+ children: i("psw.time.engagement", "Engagement")
432
+ }), /* @__PURE__ */ N("option", {
426
433
  value: "matter",
427
- children: "Matter"
434
+ children: i("psw.time.matter", "Matter")
428
435
  })]
429
436
  })
430
- }), e.against === "engagement" ? /* @__PURE__ */ M(d, {
431
- label: "Engagement",
437
+ }), e.against === "engagement" ? /* @__PURE__ */ N(p, {
438
+ label: i("psw.time.engagement", "Engagement"),
432
439
  required: !0,
433
- children: /* @__PURE__ */ N(h, {
440
+ children: /* @__PURE__ */ P(g, {
434
441
  value: e.engagementId,
435
442
  onChange: n("engagementId"),
436
- children: [/* @__PURE__ */ M("option", {
443
+ children: [/* @__PURE__ */ N("option", {
437
444
  value: "",
438
- children: "Select an engagement…"
439
- }), i.data?.items.map((e) => /* @__PURE__ */ M("option", {
445
+ children: i("psw.time.selectEngagementOption", "Select an engagement…")
446
+ }), a.data?.items.map((e) => /* @__PURE__ */ N("option", {
440
447
  value: e.id,
441
448
  children: e.name
442
449
  }, e.id))]
443
450
  })
444
- }) : /* @__PURE__ */ M(d, {
445
- label: "Matter",
451
+ }) : /* @__PURE__ */ N(p, {
452
+ label: i("psw.time.matter", "Matter"),
446
453
  required: !0,
447
- children: /* @__PURE__ */ N(h, {
454
+ children: /* @__PURE__ */ P(g, {
448
455
  value: e.matterId,
449
456
  onChange: n("matterId"),
450
- children: [/* @__PURE__ */ M("option", {
457
+ children: [/* @__PURE__ */ N("option", {
451
458
  value: "",
452
- children: "Select a matter…"
453
- }), a.data?.items.map((e) => /* @__PURE__ */ M("option", {
459
+ children: i("psw.time.selectMatterOption", "Select a matter…")
460
+ }), o.data?.items.map((e) => /* @__PURE__ */ N("option", {
454
461
  value: e.id,
455
462
  children: e.title
456
463
  }, e.id))]
457
464
  })
458
465
  })] });
459
- }, he = ({ onClose: e, onStart: t }) => {
460
- let [n, r] = w(z), [i, a] = w(null), o = (e) => (t) => r((n) => ({
466
+ }, ye = ({ onClose: e, onStart: t }) => {
467
+ let n = l(), [r, i] = w(L), [a, o] = w(null), s = (e) => (t) => i((n) => ({
461
468
  ...n,
462
469
  [e]: t.target.value
463
470
  }));
464
- return /* @__PURE__ */ M(m, {
471
+ return /* @__PURE__ */ N(h, {
465
472
  open: !0,
466
473
  onClose: e,
467
- title: "Start timer",
468
- footer: /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M(P, {
474
+ title: n("psw.time.startTimer", "Start timer"),
475
+ footer: /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(F, {
469
476
  variant: "outline",
470
477
  onClick: e,
471
- children: "Cancel"
472
- }), /* @__PURE__ */ N(P, {
478
+ children: n("psw.common.cancel", "Cancel")
479
+ }), /* @__PURE__ */ P(F, {
473
480
  onClick: () => {
474
- if (n.against === "engagement" && !n.engagementId) return a("Select an engagement.");
475
- if (n.against === "matter" && !n.matterId) return a("Select a matter.");
481
+ if (r.against === "engagement" && !r.engagementId) return o(n("psw.time.selectEngagement", "Select an engagement."));
482
+ if (r.against === "matter" && !r.matterId) return o(n("psw.time.selectMatter", "Select a matter."));
476
483
  t({
477
- against: n.against,
478
- engagementId: n.engagementId,
479
- matterId: n.matterId,
480
- date: n.date,
481
- rate: n.rate,
482
- billable: n.billable,
483
- narrative: n.narrative
484
+ against: r.against,
485
+ engagementId: r.engagementId,
486
+ matterId: r.matterId,
487
+ date: r.date,
488
+ rate: r.rate,
489
+ billable: r.billable,
490
+ narrative: r.narrative
484
491
  });
485
492
  },
486
- children: [/* @__PURE__ */ M(E, { className: "mr-1.5 h-4 w-4" }), "Start timer"]
493
+ children: [/* @__PURE__ */ N(D, { className: "me-1.5 h-4 w-4" }), n("psw.time.startTimer", "Start timer")]
487
494
  })] }),
488
- children: /* @__PURE__ */ N("div", {
495
+ children: /* @__PURE__ */ P("div", {
489
496
  className: "space-y-3",
490
497
  children: [
491
- i && /* @__PURE__ */ M(c, {
498
+ a && /* @__PURE__ */ N(u, {
492
499
  tone: "danger",
493
- children: i
500
+ children: a
494
501
  }),
495
- /* @__PURE__ */ M(V, {
496
- form: n,
497
- set: o
502
+ /* @__PURE__ */ N(z, {
503
+ form: r,
504
+ set: s
498
505
  }),
499
- /* @__PURE__ */ M(d, {
500
- label: "Rate (per hour)",
501
- children: /* @__PURE__ */ M(v, {
506
+ /* @__PURE__ */ N(p, {
507
+ label: n("psw.time.ratePerHour", "Rate (per hour)"),
508
+ children: /* @__PURE__ */ N(y, {
502
509
  type: "number",
503
510
  min: "0",
504
- value: n.rate,
505
- onChange: o("rate"),
511
+ value: r.rate,
512
+ onChange: s("rate"),
506
513
  placeholder: "450"
507
514
  })
508
515
  }),
509
- /* @__PURE__ */ N("label", {
516
+ /* @__PURE__ */ P("label", {
510
517
  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",
511
- children: [/* @__PURE__ */ M("input", {
518
+ children: [/* @__PURE__ */ N("input", {
512
519
  type: "checkbox",
513
- checked: n.billable,
514
- onChange: (e) => r((t) => ({
520
+ checked: r.billable,
521
+ onChange: (e) => i((t) => ({
515
522
  ...t,
516
523
  billable: e.target.checked
517
524
  }))
518
- }), /* @__PURE__ */ M("span", { children: "Billable" })]
525
+ }), /* @__PURE__ */ N("span", { children: n("psw.time.billable", "Billable") })]
519
526
  }),
520
- /* @__PURE__ */ M(d, {
521
- label: "Narrative",
522
- children: /* @__PURE__ */ M(_, {
523
- value: n.narrative,
524
- onChange: o("narrative"),
525
- placeholder: "Describe the work…"
527
+ /* @__PURE__ */ N(p, {
528
+ label: n("psw.time.narrative", "Narrative"),
529
+ children: /* @__PURE__ */ N(v, {
530
+ value: r.narrative,
531
+ onChange: s("narrative"),
532
+ placeholder: n("psw.time.narrativePlaceholderShort", "Describe the work…")
526
533
  })
527
534
  })
528
535
  ]
529
536
  })
530
537
  });
531
- }, ge = ({ initialTimer: e, onClose: t, onDone: r }) => {
532
- let i = n(), [a, o] = w(() => e ? B(e) : z()), [s, l] = w(null), u = (e) => (t) => o((n) => ({
538
+ }, be = ({ initialTimer: e, onClose: t, onDone: r }) => {
539
+ let i = l(), a = n(), [o, s] = w(() => e ? R(e) : L()), [c, d] = w(null), f = (e) => (t) => s((n) => ({
533
540
  ...n,
534
541
  [e]: t.target.value
535
542
  }));
536
- return /* @__PURE__ */ M(m, {
543
+ return /* @__PURE__ */ N(h, {
537
544
  open: !0,
538
545
  onClose: t,
539
- title: "Log time",
540
- footer: /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M(P, {
546
+ title: i("psw.time.logTime", "Log time"),
547
+ footer: /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(F, {
541
548
  variant: "outline",
542
549
  onClick: t,
543
- disabled: i.isPending,
544
- children: "Cancel"
545
- }), /* @__PURE__ */ M(P, {
550
+ disabled: a.isPending,
551
+ children: i("psw.common.cancel", "Cancel")
552
+ }), /* @__PURE__ */ N(F, {
546
553
  onClick: () => {
547
- l(null);
548
- let e = (Number(a.hours) || 0) * 60 + (Number(a.minutes) || 0);
549
- if (e <= 0) return l("Enter the time spent.");
550
- let n = a.against === "engagement" ? { engagementId: a.engagementId } : { matterId: a.matterId };
551
- if (a.against === "engagement" && !a.engagementId) return l("Select an engagement.");
552
- if (a.against === "matter" && !a.matterId) return l("Select a matter.");
553
- i.mutate({
554
+ d(null);
555
+ let e = (Number(o.hours) || 0) * 60 + (Number(o.minutes) || 0);
556
+ if (e <= 0) return d(i("psw.time.timeRequired", "Enter the time spent."));
557
+ let n = o.against === "engagement" ? { engagementId: o.engagementId } : { matterId: o.matterId };
558
+ if (o.against === "engagement" && !o.engagementId) return d(i("psw.time.selectEngagement", "Select an engagement."));
559
+ if (o.against === "matter" && !o.matterId) return d(i("psw.time.selectMatter", "Select a matter."));
560
+ a.mutate({
554
561
  ...n,
555
- date: new Date(a.date).toISOString(),
562
+ date: new Date(o.date).toISOString(),
556
563
  minutes: e,
557
- rate: a.rate ? Number(a.rate) : 0,
558
- billable: a.billable,
559
- narrative: a.narrative.trim() || null
564
+ rate: o.rate ? Number(o.rate) : 0,
565
+ billable: o.billable,
566
+ narrative: o.narrative.trim() || null
560
567
  }, {
561
568
  onSuccess: () => {
562
569
  r(), t();
563
570
  },
564
- onError: (e) => l(e instanceof Error ? e.message : "Failed.")
571
+ onError: (e) => d(e instanceof Error ? e.message : i("psw.common.failed", "Failed."))
565
572
  });
566
573
  },
567
- disabled: i.isPending,
568
- children: i.isPending ? "Logging…" : "Log time"
574
+ disabled: a.isPending,
575
+ children: a.isPending ? i("psw.time.logging", "Logging…") : i("psw.time.logTime", "Log time")
569
576
  })] }),
570
- children: /* @__PURE__ */ N("div", {
577
+ children: /* @__PURE__ */ P("div", {
571
578
  className: "space-y-3",
572
579
  children: [
573
- s && /* @__PURE__ */ M(c, {
580
+ c && /* @__PURE__ */ N(u, {
574
581
  tone: "danger",
575
- children: s
576
- }),
577
- /* @__PURE__ */ M(d, {
578
- label: "Against",
579
- children: /* @__PURE__ */ N(h, {
580
- value: a.against,
581
- onChange: u("against"),
582
- children: [/* @__PURE__ */ M("option", {
583
- value: "engagement",
584
- children: "Engagement"
585
- }), /* @__PURE__ */ M("option", {
586
- value: "matter",
587
- children: "Matter"
588
- })]
589
- })
582
+ children: c
590
583
  }),
591
- /* @__PURE__ */ M(V, {
592
- form: a,
593
- set: u
584
+ /* @__PURE__ */ N(z, {
585
+ form: o,
586
+ set: f
594
587
  }),
595
- /* @__PURE__ */ N("div", {
588
+ /* @__PURE__ */ P("div", {
596
589
  className: "grid grid-cols-3 gap-3",
597
590
  children: [
598
- /* @__PURE__ */ M(d, {
599
- label: "Date",
600
- children: /* @__PURE__ */ M(v, {
591
+ /* @__PURE__ */ N(p, {
592
+ label: i("psw.common.date", "Date"),
593
+ children: /* @__PURE__ */ N(y, {
601
594
  type: "date",
602
- value: a.date,
603
- onChange: u("date")
595
+ value: o.date,
596
+ onChange: f("date")
604
597
  })
605
598
  }),
606
- /* @__PURE__ */ M(d, {
607
- label: "Hours",
608
- children: /* @__PURE__ */ M(v, {
599
+ /* @__PURE__ */ N(p, {
600
+ label: i("psw.time.hours", "Hours"),
601
+ children: /* @__PURE__ */ N(y, {
609
602
  type: "number",
610
603
  min: "0",
611
- value: a.hours,
612
- onChange: u("hours"),
604
+ value: o.hours,
605
+ onChange: f("hours"),
613
606
  placeholder: "2"
614
607
  })
615
608
  }),
616
- /* @__PURE__ */ M(d, {
617
- label: "Minutes",
618
- children: /* @__PURE__ */ M(v, {
609
+ /* @__PURE__ */ N(p, {
610
+ label: i("psw.time.minutes", "Minutes"),
611
+ children: /* @__PURE__ */ N(y, {
619
612
  type: "number",
620
613
  min: "0",
621
614
  max: "59",
622
- value: a.minutes,
623
- onChange: u("minutes"),
615
+ value: o.minutes,
616
+ onChange: f("minutes"),
624
617
  placeholder: "30"
625
618
  })
626
619
  })
627
620
  ]
628
621
  }),
629
- /* @__PURE__ */ M(d, {
630
- label: "Rate (per hour)",
631
- children: /* @__PURE__ */ M(v, {
622
+ /* @__PURE__ */ N(p, {
623
+ label: i("psw.time.ratePerHour", "Rate (per hour)"),
624
+ children: /* @__PURE__ */ N(y, {
632
625
  type: "number",
633
626
  min: "0",
634
- value: a.rate,
635
- onChange: u("rate"),
627
+ value: o.rate,
628
+ onChange: f("rate"),
636
629
  placeholder: "450"
637
630
  })
638
631
  }),
639
- /* @__PURE__ */ N("label", {
632
+ /* @__PURE__ */ P("label", {
640
633
  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",
641
- children: [/* @__PURE__ */ M("input", {
634
+ children: [/* @__PURE__ */ N("input", {
642
635
  type: "checkbox",
643
- checked: a.billable,
644
- onChange: (e) => o((t) => ({
636
+ checked: o.billable,
637
+ onChange: (e) => s((t) => ({
645
638
  ...t,
646
639
  billable: e.target.checked
647
640
  }))
648
- }), /* @__PURE__ */ N("span", {
641
+ }), /* @__PURE__ */ P("span", {
649
642
  className: "flex items-center gap-1.5",
650
- children: [/* @__PURE__ */ M(A, { className: "h-3.5 w-3.5 text-status-success-text" }), "Billable"]
643
+ children: [/* @__PURE__ */ N(j, { className: "h-3.5 w-3.5 text-status-success-text" }), i("psw.time.billable", "Billable")]
651
644
  })]
652
645
  }),
653
- /* @__PURE__ */ M(d, {
654
- label: "Narrative",
655
- children: /* @__PURE__ */ M(_, {
656
- value: a.narrative,
657
- onChange: u("narrative"),
658
- placeholder: "Reviewed working papers and drafted findings memo…"
646
+ /* @__PURE__ */ N(p, {
647
+ label: i("psw.time.narrative", "Narrative"),
648
+ children: /* @__PURE__ */ N(v, {
649
+ value: o.narrative,
650
+ onChange: f("narrative"),
651
+ placeholder: i("psw.time.narrativePlaceholder", "Reviewed working papers and drafted findings memo…")
659
652
  })
660
653
  })
661
654
  ]
@@ -663,6 +656,6 @@ var pe = [
663
656
  });
664
657
  };
665
658
  //#endregion
666
- export { F as TimePage, B as timerToLogForm };
659
+ export { I as TimePage, R as timerToLogForm };
667
660
 
668
661
  //# sourceMappingURL=TimePage.js.map