@burdenoff/microfe-proserviceworld 2026.1015.1 → 2026.1026.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/proserviceworld/hooks/useProServiceWorldApi.d.ts +18 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts.map +1 -1
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js +67 -35
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -1
- package/dist/proserviceworld/hooks/useTimeTimer.d.ts +24 -0
- package/dist/proserviceworld/hooks/useTimeTimer.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/useTimeTimer.js +58 -0
- package/dist/proserviceworld/hooks/useTimeTimer.js.map +1 -0
- package/dist/proserviceworld/pages/InvoicesPage.d.ts.map +1 -1
- package/dist/proserviceworld/pages/InvoicesPage.js +308 -154
- package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
- package/dist/proserviceworld/pages/TimePage.d.ts +7 -0
- package/dist/proserviceworld/pages/TimePage.d.ts.map +1 -1
- package/dist/proserviceworld/pages/TimePage.js +514 -194
- package/dist/proserviceworld/pages/TimePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,166 +1,320 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { cn as
|
|
3
|
-
import { Banner as
|
|
4
|
-
import { useAnalytics as
|
|
5
|
-
import { useDeferredValue as
|
|
6
|
-
import { AlertCircle as
|
|
7
|
-
import { Fragment as
|
|
8
|
-
import { Button as
|
|
1
|
+
import { useCancelInvoice as e, useClients as t, useCreateInvoice as n, useEngagements as r, useInvoice as i, useInvoices as a, useMarkInvoicePaid as o } from "../hooks/useProServiceWorldApi.js";
|
|
2
|
+
import { cn as s } from "../utils/cn.js";
|
|
3
|
+
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 g, SectionCard as _, StatusPill as v, TableWrap as y, Td as b, TextArea as x, TextInput as S, Th as C, enumOptions as w, fmtDate as T, fmtMoney as E } from "../components/ui.js";
|
|
4
|
+
import { useAnalytics as D } from "../hooks/useAnalytics.js";
|
|
5
|
+
import { useDeferredValue as O, useMemo as k, useState as A } from "react";
|
|
6
|
+
import { AlertCircle as ee, CheckCircle2 as te, Eye as ne, Plus as j, Receipt as M, Search as N, Wallet as P, XCircle as F } from "lucide-react";
|
|
7
|
+
import { Fragment as I, jsx as L, jsxs as R } from "react/jsx-runtime";
|
|
8
|
+
import { Button as z } from "@burdenoff/fe-libs/ui";
|
|
9
9
|
//#region src/proserviceworld/pages/InvoicesPage.tsx
|
|
10
|
-
var
|
|
10
|
+
var B = [
|
|
11
11
|
"DRAFT",
|
|
12
12
|
"SENT",
|
|
13
13
|
"PAID",
|
|
14
14
|
"OVERDUE",
|
|
15
15
|
"CANCELLED"
|
|
16
|
-
],
|
|
17
|
-
let [
|
|
18
|
-
status:
|
|
19
|
-
search:
|
|
20
|
-
}), { emitFact:
|
|
21
|
-
return /* @__PURE__ */
|
|
16
|
+
], V = () => {
|
|
17
|
+
let [n, r] = A(""), [i, d] = A(""), m = O(i), [x, I] = A(!1), [V, U] = A(null), [W, G] = A(null), { data: K, isLoading: ie, error: q, refetch: ae } = a({
|
|
18
|
+
status: n || void 0,
|
|
19
|
+
search: m.trim() || void 0
|
|
20
|
+
}), { emitFact: oe } = D(), J = o(), Y = e(), X = t({ pagination: { limit: 100 } }), Z = k(() => new Map((X.data?.items ?? []).map((e) => [e.id, e.name])), [X.data]), Q = (K?.items ?? []).filter((e) => e.status === "SENT" || e.status === "OVERDUE"), $ = (K?.items ?? []).filter((e) => e.status === "PAID"), se = Q.reduce((e, t) => e + t.total, 0), ce = $.reduce((e, t) => e + t.total, 0);
|
|
21
|
+
return /* @__PURE__ */ R("div", {
|
|
22
22
|
className: "space-y-6",
|
|
23
23
|
children: [
|
|
24
|
-
/* @__PURE__ */
|
|
24
|
+
/* @__PURE__ */ L(g, {
|
|
25
25
|
title: "Invoices",
|
|
26
26
|
subtitle: "Assemble invoices from time, milestones and fixed-fee schedules — and track what's outstanding.",
|
|
27
|
-
icon: /* @__PURE__ */
|
|
28
|
-
actions: /* @__PURE__ */
|
|
29
|
-
onClick: () =>
|
|
30
|
-
children: [/* @__PURE__ */
|
|
27
|
+
icon: /* @__PURE__ */ L(M, { className: "h-6 w-6" }),
|
|
28
|
+
actions: /* @__PURE__ */ R(z, {
|
|
29
|
+
onClick: () => I(!0),
|
|
30
|
+
children: [/* @__PURE__ */ L(j, { className: "mr-1.5 h-4 w-4" }), "New invoice"]
|
|
31
31
|
})
|
|
32
32
|
}),
|
|
33
|
-
|
|
34
|
-
tone:
|
|
35
|
-
onClose: () =>
|
|
36
|
-
children:
|
|
33
|
+
W && /* @__PURE__ */ L(c, {
|
|
34
|
+
tone: W.tone,
|
|
35
|
+
onClose: () => G(null),
|
|
36
|
+
children: W.text
|
|
37
37
|
}),
|
|
38
|
-
/* @__PURE__ */
|
|
38
|
+
/* @__PURE__ */ R("div", {
|
|
39
39
|
className: "grid grid-cols-1 gap-3 sm:grid-cols-3",
|
|
40
40
|
children: [
|
|
41
|
-
/* @__PURE__ */
|
|
41
|
+
/* @__PURE__ */ L(p, {
|
|
42
42
|
label: "Invoices",
|
|
43
|
-
value:
|
|
44
|
-
icon: /* @__PURE__ */
|
|
43
|
+
value: K?.totalCount ?? 0,
|
|
44
|
+
icon: /* @__PURE__ */ L(M, { className: "h-4 w-4" })
|
|
45
45
|
}),
|
|
46
|
-
/* @__PURE__ */
|
|
46
|
+
/* @__PURE__ */ L(p, {
|
|
47
47
|
label: "Outstanding",
|
|
48
|
-
value:
|
|
48
|
+
value: E(se),
|
|
49
49
|
hint: `${Q.length} sent + overdue`,
|
|
50
|
-
icon: /* @__PURE__ */
|
|
50
|
+
icon: /* @__PURE__ */ L(ee, { className: "h-4 w-4" }),
|
|
51
51
|
tone: "warning"
|
|
52
52
|
}),
|
|
53
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ L(p, {
|
|
54
54
|
label: "Collected",
|
|
55
|
-
value:
|
|
55
|
+
value: E(ce),
|
|
56
56
|
hint: `${$.length} paid`,
|
|
57
|
-
icon: /* @__PURE__ */
|
|
57
|
+
icon: /* @__PURE__ */ L(P, { className: "h-4 w-4" }),
|
|
58
58
|
tone: "success"
|
|
59
59
|
})
|
|
60
60
|
]
|
|
61
61
|
}),
|
|
62
|
-
/* @__PURE__ */
|
|
62
|
+
/* @__PURE__ */ R("div", {
|
|
63
63
|
className: "flex flex-col gap-2 sm:flex-row sm:items-center",
|
|
64
|
-
children: [/* @__PURE__ */
|
|
64
|
+
children: [/* @__PURE__ */ R("div", {
|
|
65
65
|
className: "relative flex-1",
|
|
66
|
-
children: [/* @__PURE__ */
|
|
66
|
+
children: [/* @__PURE__ */ L(N, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary" }), /* @__PURE__ */ L(S, {
|
|
67
67
|
placeholder: "Search invoices…",
|
|
68
|
-
value:
|
|
69
|
-
onChange: (e) =>
|
|
68
|
+
value: i,
|
|
69
|
+
onChange: (e) => d(e.target.value),
|
|
70
70
|
onKeyDown: (e) => {
|
|
71
|
-
e.key === "Enter" &&
|
|
71
|
+
e.key === "Enter" && i.trim() && oe("psw.search.performed", {
|
|
72
72
|
entityType: "invoice",
|
|
73
|
-
queryLength:
|
|
73
|
+
queryLength: i.trim().length
|
|
74
74
|
});
|
|
75
75
|
},
|
|
76
76
|
className: "pl-9"
|
|
77
77
|
})]
|
|
78
|
-
}), /* @__PURE__ */
|
|
79
|
-
value:
|
|
80
|
-
onChange: (e) =>
|
|
78
|
+
}), /* @__PURE__ */ R(h, {
|
|
79
|
+
value: n,
|
|
80
|
+
onChange: (e) => r(e.target.value),
|
|
81
81
|
className: "sm:w-48",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
82
|
+
children: [/* @__PURE__ */ L("option", {
|
|
83
83
|
value: "",
|
|
84
84
|
children: "All statuses"
|
|
85
|
-
}),
|
|
85
|
+
}), w(B)]
|
|
86
86
|
})]
|
|
87
87
|
}),
|
|
88
|
-
|
|
89
|
-
error:
|
|
90
|
-
onRetry: () => void
|
|
91
|
-
}) : !
|
|
88
|
+
ie ? /* @__PURE__ */ L(f, {}) : q ? /* @__PURE__ */ L(u, {
|
|
89
|
+
error: q,
|
|
90
|
+
onRetry: () => void ae()
|
|
91
|
+
}) : !K || K.items.length === 0 ? /* @__PURE__ */ L(l, {
|
|
92
92
|
title: "No invoices yet",
|
|
93
93
|
description: "Raise an invoice for a client to start tracking receivables.",
|
|
94
|
-
icon: /* @__PURE__ */
|
|
95
|
-
action: /* @__PURE__ */
|
|
96
|
-
onClick: () =>
|
|
97
|
-
children: [/* @__PURE__ */
|
|
94
|
+
icon: /* @__PURE__ */ L(M, { className: "h-8 w-8" }),
|
|
95
|
+
action: /* @__PURE__ */ R(z, {
|
|
96
|
+
onClick: () => I(!0),
|
|
97
|
+
children: [/* @__PURE__ */ L(j, { className: "mr-1.5 h-4 w-4" }), "New invoice"]
|
|
98
98
|
})
|
|
99
|
-
}) : /* @__PURE__ */
|
|
99
|
+
}) : /* @__PURE__ */ L(_, {
|
|
100
100
|
title: "Invoices",
|
|
101
|
-
children: /* @__PURE__ */
|
|
102
|
-
/* @__PURE__ */
|
|
103
|
-
/* @__PURE__ */
|
|
104
|
-
/* @__PURE__ */
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
/* @__PURE__ */
|
|
101
|
+
children: /* @__PURE__ */ R(y, { children: [/* @__PURE__ */ L("thead", { children: /* @__PURE__ */ R("tr", { children: [
|
|
102
|
+
/* @__PURE__ */ L(C, { children: "Number" }),
|
|
103
|
+
/* @__PURE__ */ L(C, { children: "Client" }),
|
|
104
|
+
/* @__PURE__ */ L(C, { children: "Total" }),
|
|
105
|
+
/* @__PURE__ */ L(C, { children: "Status" }),
|
|
106
|
+
/* @__PURE__ */ L(C, { children: "Due" }),
|
|
107
|
+
/* @__PURE__ */ L(C, {
|
|
108
108
|
className: "text-right",
|
|
109
109
|
children: "Actions"
|
|
110
110
|
})
|
|
111
|
-
] }) }), /* @__PURE__ */
|
|
111
|
+
] }) }), /* @__PURE__ */ L("tbody", { children: K.items.map((e) => /* @__PURE__ */ R("tr", {
|
|
112
112
|
className: "transition-colors hover:bg-bg-sunken/60",
|
|
113
113
|
children: [
|
|
114
|
-
/* @__PURE__ */
|
|
114
|
+
/* @__PURE__ */ L(b, { children: /* @__PURE__ */ L("span", {
|
|
115
115
|
className: "font-medium text-text-primary",
|
|
116
116
|
children: e.number
|
|
117
117
|
}) }),
|
|
118
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ L(b, {
|
|
119
119
|
className: "text-text-primary",
|
|
120
120
|
children: Z.get(e.clientId) ?? "—"
|
|
121
121
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ L(b, {
|
|
123
123
|
className: "whitespace-nowrap font-semibold text-text-primary",
|
|
124
|
-
children:
|
|
124
|
+
children: E(e.total, e.currency)
|
|
125
125
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
127
|
-
/* @__PURE__ */
|
|
128
|
-
className:
|
|
129
|
-
children:
|
|
126
|
+
/* @__PURE__ */ L(b, { children: /* @__PURE__ */ L(v, { status: e.status }) }),
|
|
127
|
+
/* @__PURE__ */ L(b, {
|
|
128
|
+
className: s("whitespace-nowrap", e.status === "OVERDUE" && "font-medium text-status-error-text"),
|
|
129
|
+
children: T(e.dueDate)
|
|
130
130
|
}),
|
|
131
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ L(b, {
|
|
132
132
|
className: "text-right",
|
|
133
|
-
children:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
children: /* @__PURE__ */ R("div", {
|
|
134
|
+
className: "flex items-center justify-end gap-1",
|
|
135
|
+
children: [
|
|
136
|
+
/* @__PURE__ */ R(z, {
|
|
137
|
+
variant: "ghost",
|
|
138
|
+
size: "sm",
|
|
139
|
+
onClick: () => U(e.id),
|
|
140
|
+
children: [/* @__PURE__ */ L(ne, { className: "mr-1 h-4 w-4" }), "View"]
|
|
141
|
+
}),
|
|
142
|
+
e.status !== "PAID" && e.status !== "CANCELLED" && /* @__PURE__ */ R(z, {
|
|
143
|
+
variant: "ghost",
|
|
144
|
+
size: "sm",
|
|
145
|
+
disabled: J.isPending,
|
|
146
|
+
onClick: () => J.mutate(e.id, {
|
|
147
|
+
onSuccess: () => G({
|
|
148
|
+
tone: "success",
|
|
149
|
+
text: `${e.number} marked paid.`
|
|
150
|
+
}),
|
|
151
|
+
onError: (e) => G({
|
|
152
|
+
tone: "danger",
|
|
153
|
+
text: e instanceof Error ? e.message : "Failed."
|
|
154
|
+
})
|
|
155
|
+
}),
|
|
156
|
+
children: [/* @__PURE__ */ L(te, { className: "mr-1 h-4 w-4" }), "Mark paid"]
|
|
141
157
|
}),
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
(e.status === "DRAFT" || e.status === "SENT") && /* @__PURE__ */ R(z, {
|
|
159
|
+
variant: "ghost",
|
|
160
|
+
size: "sm",
|
|
161
|
+
disabled: Y.isPending,
|
|
162
|
+
onClick: () => Y.mutate(e.id, {
|
|
163
|
+
onSuccess: () => G({
|
|
164
|
+
tone: "success",
|
|
165
|
+
text: `${e.number} cancelled.`
|
|
166
|
+
}),
|
|
167
|
+
onError: (e) => G({
|
|
168
|
+
tone: "danger",
|
|
169
|
+
text: e instanceof Error ? e.message : "Failed."
|
|
170
|
+
})
|
|
171
|
+
}),
|
|
172
|
+
children: [/* @__PURE__ */ L(F, { className: "mr-1 h-4 w-4" }), "Cancel"]
|
|
145
173
|
})
|
|
146
|
-
|
|
147
|
-
children: [/* @__PURE__ */ I(A, { className: "mr-1 h-4 w-4" }), "Mark paid"]
|
|
174
|
+
]
|
|
148
175
|
})
|
|
149
176
|
})
|
|
150
177
|
]
|
|
151
178
|
}, e.id)) })] })
|
|
152
179
|
}),
|
|
153
|
-
|
|
154
|
-
onClose: () =>
|
|
155
|
-
onSaved: (e) =>
|
|
180
|
+
x && /* @__PURE__ */ L(re, {
|
|
181
|
+
onClose: () => I(!1),
|
|
182
|
+
onSaved: (e) => G({
|
|
156
183
|
tone: "success",
|
|
157
184
|
text: `${e} created.`
|
|
158
185
|
})
|
|
186
|
+
}),
|
|
187
|
+
V && /* @__PURE__ */ L(H, {
|
|
188
|
+
id: V,
|
|
189
|
+
clientName: Z,
|
|
190
|
+
onClose: () => U(null),
|
|
191
|
+
onCancelled: (e) => {
|
|
192
|
+
U(null), G({
|
|
193
|
+
tone: "success",
|
|
194
|
+
text: `${e} cancelled.`
|
|
195
|
+
});
|
|
196
|
+
}
|
|
159
197
|
})
|
|
160
198
|
]
|
|
161
199
|
});
|
|
162
|
-
},
|
|
163
|
-
let
|
|
200
|
+
}, H = ({ id: t, clientName: n, onClose: r, onCancelled: a }) => {
|
|
201
|
+
let { data: o, isLoading: s, error: d } = i(t), p = e(), [h, g] = A(null);
|
|
202
|
+
return /* @__PURE__ */ L(m, {
|
|
203
|
+
open: !0,
|
|
204
|
+
onClose: r,
|
|
205
|
+
title: o ? `Invoice ${o.number}` : "Invoice",
|
|
206
|
+
footer: /* @__PURE__ */ R(I, { children: [/* @__PURE__ */ L(z, {
|
|
207
|
+
variant: "outline",
|
|
208
|
+
onClick: r,
|
|
209
|
+
children: "Close"
|
|
210
|
+
}), o && (o.status === "DRAFT" || o.status === "SENT") && /* @__PURE__ */ R(z, {
|
|
211
|
+
variant: "destructive",
|
|
212
|
+
disabled: p.isPending,
|
|
213
|
+
onClick: () => {
|
|
214
|
+
g(null), p.mutate(o.id, {
|
|
215
|
+
onSuccess: () => a(o.number),
|
|
216
|
+
onError: (e) => g(e instanceof Error ? e.message : "Failed.")
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
children: [/* @__PURE__ */ L(F, { className: "mr-1.5 h-4 w-4" }), p.isPending ? "Cancelling…" : "Cancel invoice"]
|
|
220
|
+
})] }),
|
|
221
|
+
children: /* @__PURE__ */ R("div", {
|
|
222
|
+
className: "space-y-3",
|
|
223
|
+
children: [h && /* @__PURE__ */ L(c, {
|
|
224
|
+
tone: "danger",
|
|
225
|
+
children: h
|
|
226
|
+
}), s ? /* @__PURE__ */ L(f, {}) : d ? /* @__PURE__ */ L(u, { error: d }) : o ? /* @__PURE__ */ R(I, { children: [
|
|
227
|
+
/* @__PURE__ */ R("div", {
|
|
228
|
+
className: "grid grid-cols-2 gap-3 text-sm",
|
|
229
|
+
children: [
|
|
230
|
+
/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
231
|
+
className: "text-text-tertiary",
|
|
232
|
+
children: "Client"
|
|
233
|
+
}), /* @__PURE__ */ L("div", {
|
|
234
|
+
className: "font-medium text-text-primary",
|
|
235
|
+
children: n.get(o.clientId) ?? "—"
|
|
236
|
+
})] }),
|
|
237
|
+
/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
238
|
+
className: "text-text-tertiary",
|
|
239
|
+
children: "Status"
|
|
240
|
+
}), /* @__PURE__ */ L(v, { status: o.status })] }),
|
|
241
|
+
/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
242
|
+
className: "text-text-tertiary",
|
|
243
|
+
children: "Issue date"
|
|
244
|
+
}), /* @__PURE__ */ L("div", {
|
|
245
|
+
className: "text-text-primary",
|
|
246
|
+
children: T(o.issueDate)
|
|
247
|
+
})] }),
|
|
248
|
+
/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
249
|
+
className: "text-text-tertiary",
|
|
250
|
+
children: "Due date"
|
|
251
|
+
}), /* @__PURE__ */ L("div", {
|
|
252
|
+
className: "text-text-primary",
|
|
253
|
+
children: T(o.dueDate)
|
|
254
|
+
})] }),
|
|
255
|
+
/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
256
|
+
className: "text-text-tertiary",
|
|
257
|
+
children: "Sent"
|
|
258
|
+
}), /* @__PURE__ */ L("div", {
|
|
259
|
+
className: "text-text-primary",
|
|
260
|
+
children: T(o.sentAt)
|
|
261
|
+
})] }),
|
|
262
|
+
/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
263
|
+
className: "text-text-tertiary",
|
|
264
|
+
children: "Paid"
|
|
265
|
+
}), /* @__PURE__ */ L("div", {
|
|
266
|
+
className: "text-text-primary",
|
|
267
|
+
children: T(o.paidAt)
|
|
268
|
+
})] })
|
|
269
|
+
]
|
|
270
|
+
}),
|
|
271
|
+
o.lineItems && o.lineItems.length > 0 && /* @__PURE__ */ R(y, { children: [/* @__PURE__ */ L("thead", { children: /* @__PURE__ */ R("tr", { children: [
|
|
272
|
+
/* @__PURE__ */ L(C, { children: "Source" }),
|
|
273
|
+
/* @__PURE__ */ L(C, { children: "Description" }),
|
|
274
|
+
/* @__PURE__ */ L(C, {
|
|
275
|
+
className: "text-right",
|
|
276
|
+
children: "Amount"
|
|
277
|
+
})
|
|
278
|
+
] }) }), /* @__PURE__ */ L("tbody", { children: o.lineItems.map((e, t) => /* @__PURE__ */ R("tr", { children: [
|
|
279
|
+
/* @__PURE__ */ L(b, { children: e.sourceType }),
|
|
280
|
+
/* @__PURE__ */ L(b, { children: e.description ?? e.sourceId }),
|
|
281
|
+
/* @__PURE__ */ L(b, {
|
|
282
|
+
className: "text-right",
|
|
283
|
+
children: E(e.amount, o.currency)
|
|
284
|
+
})
|
|
285
|
+
] }, `${e.sourceType}-${e.sourceId}-${t}`)) })] }),
|
|
286
|
+
/* @__PURE__ */ R("div", {
|
|
287
|
+
className: "rounded-lg bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
288
|
+
children: [
|
|
289
|
+
/* @__PURE__ */ R("div", {
|
|
290
|
+
className: "flex justify-between",
|
|
291
|
+
children: [/* @__PURE__ */ L("span", { children: "Subtotal" }), /* @__PURE__ */ L("span", { children: E(o.subtotal, o.currency) })]
|
|
292
|
+
}),
|
|
293
|
+
/* @__PURE__ */ R("div", {
|
|
294
|
+
className: "flex justify-between",
|
|
295
|
+
children: [/* @__PURE__ */ L("span", { children: "Tax" }), /* @__PURE__ */ L("span", { children: E(o.taxAmount, o.currency) })]
|
|
296
|
+
}),
|
|
297
|
+
/* @__PURE__ */ R("div", {
|
|
298
|
+
className: "flex justify-between font-semibold text-text-primary",
|
|
299
|
+
children: [/* @__PURE__ */ L("span", { children: "Total" }), /* @__PURE__ */ L("span", { children: E(o.total, o.currency) })]
|
|
300
|
+
})
|
|
301
|
+
]
|
|
302
|
+
}),
|
|
303
|
+
o.notes && /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
|
|
304
|
+
className: "text-sm text-text-tertiary",
|
|
305
|
+
children: "Notes"
|
|
306
|
+
}), /* @__PURE__ */ L("div", {
|
|
307
|
+
className: "text-sm text-text-primary",
|
|
308
|
+
children: o.notes
|
|
309
|
+
})] })
|
|
310
|
+
] }) : /* @__PURE__ */ L(l, {
|
|
311
|
+
title: "Invoice not found",
|
|
312
|
+
icon: /* @__PURE__ */ L(M, { className: "h-8 w-8" })
|
|
313
|
+
})]
|
|
314
|
+
})
|
|
315
|
+
});
|
|
316
|
+
}, re = ({ onClose: e, onSaved: i }) => {
|
|
317
|
+
let a = n(), o = t({ pagination: { limit: 100 } }), [s, l] = A({
|
|
164
318
|
clientId: "",
|
|
165
319
|
engagementId: "",
|
|
166
320
|
number: "",
|
|
@@ -170,159 +324,159 @@ var z = [
|
|
|
170
324
|
issueDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
171
325
|
dueDate: "",
|
|
172
326
|
notes: ""
|
|
173
|
-
}), [
|
|
174
|
-
clientId:
|
|
327
|
+
}), [u, f] = A(null), p = r({
|
|
328
|
+
clientId: s.clientId || void 0,
|
|
175
329
|
pagination: { limit: 100 }
|
|
176
|
-
}), g = (e) => (t) =>
|
|
330
|
+
}), g = (e) => (t) => l((n) => ({
|
|
177
331
|
...n,
|
|
178
332
|
[e]: t.target.value
|
|
179
|
-
})), _ = (Number(
|
|
180
|
-
return /* @__PURE__ */
|
|
333
|
+
})), _ = (Number(s.subtotal) || 0) + (Number(s.taxAmount) || 0);
|
|
334
|
+
return /* @__PURE__ */ L(m, {
|
|
181
335
|
open: !0,
|
|
182
|
-
onClose:
|
|
336
|
+
onClose: e,
|
|
183
337
|
title: "New invoice",
|
|
184
|
-
footer: /* @__PURE__ */
|
|
338
|
+
footer: /* @__PURE__ */ R(I, { children: [/* @__PURE__ */ L(z, {
|
|
185
339
|
variant: "outline",
|
|
186
|
-
onClick:
|
|
340
|
+
onClick: e,
|
|
187
341
|
disabled: a.isPending,
|
|
188
342
|
children: "Cancel"
|
|
189
|
-
}), /* @__PURE__ */
|
|
343
|
+
}), /* @__PURE__ */ L(z, {
|
|
190
344
|
onClick: () => {
|
|
191
|
-
if (
|
|
192
|
-
if (!
|
|
345
|
+
if (f(null), !s.clientId) return f("Select a client.");
|
|
346
|
+
if (!s.number.trim()) return f("Invoice number is required.");
|
|
193
347
|
a.mutate({
|
|
194
|
-
clientId:
|
|
195
|
-
engagementId:
|
|
196
|
-
number:
|
|
197
|
-
currency:
|
|
198
|
-
subtotal: Number(
|
|
199
|
-
taxAmount: Number(
|
|
348
|
+
clientId: s.clientId,
|
|
349
|
+
engagementId: s.engagementId || null,
|
|
350
|
+
number: s.number.trim(),
|
|
351
|
+
currency: s.currency || "USD",
|
|
352
|
+
subtotal: Number(s.subtotal) || 0,
|
|
353
|
+
taxAmount: Number(s.taxAmount) || 0,
|
|
200
354
|
total: _,
|
|
201
|
-
issueDate:
|
|
202
|
-
dueDate:
|
|
203
|
-
notes:
|
|
355
|
+
issueDate: s.issueDate ? new Date(s.issueDate).toISOString() : null,
|
|
356
|
+
dueDate: s.dueDate ? new Date(s.dueDate).toISOString() : null,
|
|
357
|
+
notes: s.notes.trim() || null
|
|
204
358
|
}, {
|
|
205
359
|
onSuccess: () => {
|
|
206
|
-
i(
|
|
360
|
+
i(s.number.trim()), e();
|
|
207
361
|
},
|
|
208
|
-
onError: (e) =>
|
|
362
|
+
onError: (e) => f(e instanceof Error ? e.message : "Failed.")
|
|
209
363
|
});
|
|
210
364
|
},
|
|
211
365
|
disabled: a.isPending,
|
|
212
366
|
children: a.isPending ? "Creating…" : "Create invoice"
|
|
213
367
|
})] }),
|
|
214
|
-
children: /* @__PURE__ */
|
|
368
|
+
children: /* @__PURE__ */ R("div", {
|
|
215
369
|
className: "space-y-3",
|
|
216
370
|
children: [
|
|
217
|
-
|
|
371
|
+
u && /* @__PURE__ */ L(c, {
|
|
218
372
|
tone: "danger",
|
|
219
|
-
children:
|
|
373
|
+
children: u
|
|
220
374
|
}),
|
|
221
|
-
/* @__PURE__ */
|
|
375
|
+
/* @__PURE__ */ R("div", {
|
|
222
376
|
className: "grid grid-cols-2 gap-3",
|
|
223
|
-
children: [/* @__PURE__ */
|
|
377
|
+
children: [/* @__PURE__ */ L(d, {
|
|
224
378
|
label: "Client",
|
|
225
379
|
required: !0,
|
|
226
|
-
children: /* @__PURE__ */
|
|
227
|
-
value:
|
|
380
|
+
children: /* @__PURE__ */ R(h, {
|
|
381
|
+
value: s.clientId,
|
|
228
382
|
onChange: g("clientId"),
|
|
229
|
-
children: [/* @__PURE__ */
|
|
383
|
+
children: [/* @__PURE__ */ L("option", {
|
|
230
384
|
value: "",
|
|
231
385
|
children: "Select…"
|
|
232
|
-
}),
|
|
386
|
+
}), o.data?.items.map((e) => /* @__PURE__ */ L("option", {
|
|
233
387
|
value: e.id,
|
|
234
388
|
children: e.name
|
|
235
389
|
}, e.id))]
|
|
236
390
|
})
|
|
237
|
-
}), /* @__PURE__ */
|
|
391
|
+
}), /* @__PURE__ */ L(d, {
|
|
238
392
|
label: "Number",
|
|
239
393
|
required: !0,
|
|
240
|
-
children: /* @__PURE__ */
|
|
241
|
-
value:
|
|
394
|
+
children: /* @__PURE__ */ L(S, {
|
|
395
|
+
value: s.number,
|
|
242
396
|
onChange: g("number"),
|
|
243
397
|
placeholder: "INV-2026-014"
|
|
244
398
|
})
|
|
245
399
|
})]
|
|
246
400
|
}),
|
|
247
|
-
/* @__PURE__ */
|
|
401
|
+
/* @__PURE__ */ L(d, {
|
|
248
402
|
label: "Engagement (optional)",
|
|
249
|
-
children: /* @__PURE__ */
|
|
250
|
-
value:
|
|
403
|
+
children: /* @__PURE__ */ R(h, {
|
|
404
|
+
value: s.engagementId,
|
|
251
405
|
onChange: g("engagementId"),
|
|
252
|
-
disabled: !
|
|
253
|
-
children: [/* @__PURE__ */
|
|
406
|
+
disabled: !s.clientId,
|
|
407
|
+
children: [/* @__PURE__ */ L("option", {
|
|
254
408
|
value: "",
|
|
255
409
|
children: "None"
|
|
256
|
-
}),
|
|
410
|
+
}), p.data?.items.map((e) => /* @__PURE__ */ L("option", {
|
|
257
411
|
value: e.id,
|
|
258
412
|
children: e.name
|
|
259
413
|
}, e.id))]
|
|
260
414
|
})
|
|
261
415
|
}),
|
|
262
|
-
/* @__PURE__ */
|
|
416
|
+
/* @__PURE__ */ R("div", {
|
|
263
417
|
className: "grid grid-cols-3 gap-3",
|
|
264
418
|
children: [
|
|
265
|
-
/* @__PURE__ */
|
|
419
|
+
/* @__PURE__ */ L(d, {
|
|
266
420
|
label: "Subtotal",
|
|
267
|
-
children: /* @__PURE__ */
|
|
421
|
+
children: /* @__PURE__ */ L(S, {
|
|
268
422
|
type: "number",
|
|
269
423
|
min: "0",
|
|
270
|
-
value:
|
|
424
|
+
value: s.subtotal,
|
|
271
425
|
onChange: g("subtotal")
|
|
272
426
|
})
|
|
273
427
|
}),
|
|
274
|
-
/* @__PURE__ */
|
|
428
|
+
/* @__PURE__ */ L(d, {
|
|
275
429
|
label: "Tax",
|
|
276
|
-
children: /* @__PURE__ */
|
|
430
|
+
children: /* @__PURE__ */ L(S, {
|
|
277
431
|
type: "number",
|
|
278
432
|
min: "0",
|
|
279
|
-
value:
|
|
433
|
+
value: s.taxAmount,
|
|
280
434
|
onChange: g("taxAmount")
|
|
281
435
|
})
|
|
282
436
|
}),
|
|
283
|
-
/* @__PURE__ */
|
|
437
|
+
/* @__PURE__ */ L(d, {
|
|
284
438
|
label: "Currency",
|
|
285
|
-
children: /* @__PURE__ */
|
|
286
|
-
value:
|
|
439
|
+
children: /* @__PURE__ */ L(S, {
|
|
440
|
+
value: s.currency,
|
|
287
441
|
onChange: g("currency"),
|
|
288
442
|
maxLength: 3
|
|
289
443
|
})
|
|
290
444
|
})
|
|
291
445
|
]
|
|
292
446
|
}),
|
|
293
|
-
/* @__PURE__ */
|
|
447
|
+
/* @__PURE__ */ R("div", {
|
|
294
448
|
className: "rounded-lg bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
295
449
|
children: [
|
|
296
450
|
"Total:",
|
|
297
451
|
" ",
|
|
298
|
-
/* @__PURE__ */
|
|
452
|
+
/* @__PURE__ */ L("span", {
|
|
299
453
|
className: "font-semibold text-text-primary",
|
|
300
|
-
children:
|
|
454
|
+
children: E(_, s.currency)
|
|
301
455
|
})
|
|
302
456
|
]
|
|
303
457
|
}),
|
|
304
|
-
/* @__PURE__ */
|
|
458
|
+
/* @__PURE__ */ R("div", {
|
|
305
459
|
className: "grid grid-cols-2 gap-3",
|
|
306
|
-
children: [/* @__PURE__ */
|
|
460
|
+
children: [/* @__PURE__ */ L(d, {
|
|
307
461
|
label: "Issue date",
|
|
308
|
-
children: /* @__PURE__ */
|
|
462
|
+
children: /* @__PURE__ */ L(S, {
|
|
309
463
|
type: "date",
|
|
310
|
-
value:
|
|
464
|
+
value: s.issueDate,
|
|
311
465
|
onChange: g("issueDate")
|
|
312
466
|
})
|
|
313
|
-
}), /* @__PURE__ */
|
|
467
|
+
}), /* @__PURE__ */ L(d, {
|
|
314
468
|
label: "Due date",
|
|
315
|
-
children: /* @__PURE__ */
|
|
469
|
+
children: /* @__PURE__ */ L(S, {
|
|
316
470
|
type: "date",
|
|
317
|
-
value:
|
|
471
|
+
value: s.dueDate,
|
|
318
472
|
onChange: g("dueDate")
|
|
319
473
|
})
|
|
320
474
|
})]
|
|
321
475
|
}),
|
|
322
|
-
/* @__PURE__ */
|
|
476
|
+
/* @__PURE__ */ L(d, {
|
|
323
477
|
label: "Notes",
|
|
324
|
-
children: /* @__PURE__ */
|
|
325
|
-
value:
|
|
478
|
+
children: /* @__PURE__ */ L(x, {
|
|
479
|
+
value: s.notes,
|
|
326
480
|
onChange: g("notes")
|
|
327
481
|
})
|
|
328
482
|
})
|
|
@@ -331,6 +485,6 @@ var z = [
|
|
|
331
485
|
});
|
|
332
486
|
};
|
|
333
487
|
//#endregion
|
|
334
|
-
export {
|
|
488
|
+
export { V as InvoicesPage };
|
|
335
489
|
|
|
336
490
|
//# sourceMappingURL=InvoicesPage.js.map
|