@argusoft/medplat-product-management 1.0.0
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/BrandsPage-DCMCVvDY.js +334 -0
- package/dist/BrandsPage-DCMCVvDY.js.map +1 -0
- package/dist/CategoriesPage-BpRhwfrc.js +284 -0
- package/dist/CategoriesPage-BpRhwfrc.js.map +1 -0
- package/dist/DashboardPage-BNKUQj46.js +436 -0
- package/dist/DashboardPage-BNKUQj46.js.map +1 -0
- package/dist/FacilityPicker-Coi8I3yE.js +79 -0
- package/dist/FacilityPicker-Coi8I3yE.js.map +1 -0
- package/dist/InventoryPage-BR6jOzg2.js +517 -0
- package/dist/InventoryPage-BR6jOzg2.js.map +1 -0
- package/dist/MemberProfileCard-DbHZCS5n.js +272 -0
- package/dist/MemberProfileCard-DbHZCS5n.js.map +1 -0
- package/dist/PaymentCreatePage-Ci3ERnby.js +487 -0
- package/dist/PaymentCreatePage-Ci3ERnby.js.map +1 -0
- package/dist/PaymentsPage-sdg902zX.js +157 -0
- package/dist/PaymentsPage-sdg902zX.js.map +1 -0
- package/dist/PickupCreatePage-CieMsgWV.js +310 -0
- package/dist/PickupCreatePage-CieMsgWV.js.map +1 -0
- package/dist/PickupsPage-Ci2Ll0Kn.js +566 -0
- package/dist/PickupsPage-Ci2Ll0Kn.js.map +1 -0
- package/dist/PmGuard-CjJBisaN.js +1195 -0
- package/dist/PmGuard-CjJBisaN.js.map +1 -0
- package/dist/PmTable-BuXZQZCU.js +302 -0
- package/dist/PmTable-BuXZQZCU.js.map +1 -0
- package/dist/ProductEditPage-DL8gy85Y.js +666 -0
- package/dist/ProductEditPage-DL8gy85Y.js.map +1 -0
- package/dist/ProductsPage-BANTKxLb.js +221 -0
- package/dist/ProductsPage-BANTKxLb.js.map +1 -0
- package/dist/PurchaseCreatePage-C3KMfBxJ.js +626 -0
- package/dist/PurchaseCreatePage-C3KMfBxJ.js.map +1 -0
- package/dist/PurchaseRequestDetailPage-C0GYFJDl.js +586 -0
- package/dist/PurchaseRequestDetailPage-C0GYFJDl.js.map +1 -0
- package/dist/PurchaseRequestsPage-DvFH_tWe.js +265 -0
- package/dist/PurchaseRequestsPage-DvFH_tWe.js.map +1 -0
- package/dist/PurchasesPage-BCvLvSp4.js +295 -0
- package/dist/PurchasesPage-BCvLvSp4.js.map +1 -0
- package/dist/SaleCreatePage-DpkQMoTq.js +548 -0
- package/dist/SaleCreatePage-DpkQMoTq.js.map +1 -0
- package/dist/SalesPage-DUwgkEO-.js +315 -0
- package/dist/SalesPage-DUwgkEO-.js.map +1 -0
- package/dist/SettingsPage-CusC0jqJ.js +710 -0
- package/dist/SettingsPage-CusC0jqJ.js.map +1 -0
- package/dist/StorageUnitsPage-BlC2AgrJ.js +469 -0
- package/dist/StorageUnitsPage-BlC2AgrJ.js.map +1 -0
- package/dist/TransactionsPage-DDaK4VyY.js +714 -0
- package/dist/TransactionsPage-DDaK4VyY.js.map +1 -0
- package/dist/TransferCreatePage-BxudLfhS.js +363 -0
- package/dist/TransferCreatePage-BxudLfhS.js.map +1 -0
- package/dist/TransfersPage-zgmt7teZ.js +480 -0
- package/dist/TransfersPage-zgmt7teZ.js.map +1 -0
- package/dist/VialsPage-CjqPfgpV.js +855 -0
- package/dist/VialsPage-CjqPfgpV.js.map +1 -0
- package/dist/constants-BrA_hfAI.js +254 -0
- package/dist/constants-BrA_hfAI.js.map +1 -0
- package/dist/currency-BDDCDgeE.js +169 -0
- package/dist/currency-BDDCDgeE.js.map +1 -0
- package/dist/format-UOyOu75i.js +52 -0
- package/dist/format-UOyOu75i.js.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/useFieldErrors-hDG8ox_x.js +29 -0
- package/dist/useFieldErrors-hDG8ox_x.js.map +1 -0
- package/dist/validation-Ba7puFIO.js +109 -0
- package/dist/validation-Ba7puFIO.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { W as e, a as t, c as n, i as r, n as i, r as a, t as ee } from "./PmGuard-CjJBisaN.js";
|
|
2
|
+
import { t as te } from "./currency-BDDCDgeE.js";
|
|
3
|
+
import { a as o, i as s, o as c, r as l, t as u } from "./PmTable-BuXZQZCU.js";
|
|
4
|
+
import { t as d } from "./format-UOyOu75i.js";
|
|
5
|
+
import { useMemo as f, useState as p } from "react";
|
|
6
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
7
|
+
import { Alert as ne, Box as g, Button as _, Chip as v, InputAdornment as y, Skeleton as b, Stack as x, TableBody as S, TableCell as C, TableHead as w, TableRow as T, TextField as E, Typography as D } from "@mui/material";
|
|
8
|
+
import O from "@mui/icons-material/AddRounded";
|
|
9
|
+
import re from "@mui/icons-material/RefreshRounded";
|
|
10
|
+
import { showToast as ie } from "@/common/toaster/toaster";
|
|
11
|
+
import { useNavigate as ae } from "react-router-dom";
|
|
12
|
+
import { alpha as k, useTheme as A } from "@mui/material/styles";
|
|
13
|
+
import oe from "@mui/icons-material/ShoppingCartRounded";
|
|
14
|
+
import se from "@mui/icons-material/SearchRounded";
|
|
15
|
+
//#region src/views/PurchasesPage.jsx
|
|
16
|
+
var ce = 3;
|
|
17
|
+
function j() {
|
|
18
|
+
let j = r().has("update.manage.productManagement.purchase"), M = n(), N = te(M?.currencyCode), P = M?.managePurchaseAmounts !== !1, F = ae(), I = A(), [L, R] = p([]), [z, B] = p(!0), [V, H] = p(""), [U, W] = p(""), [G, K] = p(""), [q, J] = p("");
|
|
19
|
+
async function Y() {
|
|
20
|
+
B(!0), H("");
|
|
21
|
+
try {
|
|
22
|
+
R(await e(0, 50));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
let t = e?.response?.data?.message ?? e?.message ?? "Failed to load purchases";
|
|
25
|
+
H(t), ie({
|
|
26
|
+
message: t,
|
|
27
|
+
type: "error"
|
|
28
|
+
});
|
|
29
|
+
} finally {
|
|
30
|
+
B(!1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
a("view.manage.productManagement.purchase", () => {
|
|
34
|
+
Y();
|
|
35
|
+
}, []);
|
|
36
|
+
let X = f(() => {
|
|
37
|
+
let e = U.trim().toLowerCase(), t = G ? new Date(G) : null, n = q ? new Date(q) : null;
|
|
38
|
+
return L.filter((r) => {
|
|
39
|
+
if (e) {
|
|
40
|
+
let t = (r.batches ?? []).map((e) => `${e.productName ?? ""} ${e.lotNumber ?? ""}`).join(" ");
|
|
41
|
+
if (!`${r.notes ?? ""} ${t}`.toLowerCase().includes(e)) return !1;
|
|
42
|
+
}
|
|
43
|
+
if (t || n) {
|
|
44
|
+
if (!r.purchaseDate) return !1;
|
|
45
|
+
let e = new Date(r.purchaseDate);
|
|
46
|
+
if (t && e < t) return !1;
|
|
47
|
+
if (n) {
|
|
48
|
+
let t = new Date(n);
|
|
49
|
+
if (t.setHours(23, 59, 59, 999), e > t) return !1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return !0;
|
|
53
|
+
});
|
|
54
|
+
}, [
|
|
55
|
+
L,
|
|
56
|
+
U,
|
|
57
|
+
G,
|
|
58
|
+
q
|
|
59
|
+
]), le = f(() => X.reduce((e, t) => e + Number(t.totalAmount || 0), 0), [X]), Z = U.trim() !== "" || G !== "" || q !== "";
|
|
60
|
+
function Q() {
|
|
61
|
+
W(""), K(""), J("");
|
|
62
|
+
}
|
|
63
|
+
let $ = P ? 7 : 5;
|
|
64
|
+
return /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ m(i, {}), /* @__PURE__ */ m(ee, {
|
|
65
|
+
perm: "view.manage.productManagement.purchase",
|
|
66
|
+
children: /* @__PURE__ */ h(t, {
|
|
67
|
+
title: "Completed Purchases",
|
|
68
|
+
subtitle: "Completed purchases and approved requests. Each shows the items and cost.",
|
|
69
|
+
actions: /* @__PURE__ */ h(x, {
|
|
70
|
+
direction: "row",
|
|
71
|
+
spacing: 1,
|
|
72
|
+
children: [/* @__PURE__ */ m(_, {
|
|
73
|
+
variant: "outlined",
|
|
74
|
+
startIcon: /* @__PURE__ */ m(re, {}),
|
|
75
|
+
onClick: () => void Y(),
|
|
76
|
+
children: "Refresh"
|
|
77
|
+
}), j ? /* @__PURE__ */ m(_, {
|
|
78
|
+
variant: "contained",
|
|
79
|
+
startIcon: /* @__PURE__ */ m(O, {}),
|
|
80
|
+
onClick: () => F("/ui/medplat/manage/pm/purchases/new"),
|
|
81
|
+
children: "New Purchase"
|
|
82
|
+
}) : null]
|
|
83
|
+
}),
|
|
84
|
+
children: [V ? /* @__PURE__ */ m(ne, {
|
|
85
|
+
severity: "error",
|
|
86
|
+
sx: { mb: 2 },
|
|
87
|
+
children: V
|
|
88
|
+
}) : null, /* @__PURE__ */ h(c, {
|
|
89
|
+
eyebrow: "Procurement",
|
|
90
|
+
title: "Recent purchases",
|
|
91
|
+
subtitle: z ? "Loading…" : P ? `${X.length} ${X.length === 1 ? "purchase" : "purchases"} · total spend ${N}${le.toFixed(2)}` : `${X.length} ${X.length === 1 ? "purchase" : "purchases"}`,
|
|
92
|
+
children: [/* @__PURE__ */ h(x, {
|
|
93
|
+
direction: {
|
|
94
|
+
xs: "column",
|
|
95
|
+
md: "row"
|
|
96
|
+
},
|
|
97
|
+
spacing: 1.5,
|
|
98
|
+
sx: { mb: 2 },
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ m(E, {
|
|
101
|
+
size: "small",
|
|
102
|
+
fullWidth: !0,
|
|
103
|
+
placeholder: "Search notes or items…",
|
|
104
|
+
value: U,
|
|
105
|
+
onChange: (e) => W(e.target.value),
|
|
106
|
+
InputProps: { startAdornment: /* @__PURE__ */ m(y, {
|
|
107
|
+
position: "start",
|
|
108
|
+
children: /* @__PURE__ */ m(se, { fontSize: "small" })
|
|
109
|
+
}) }
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ m(E, {
|
|
112
|
+
size: "small",
|
|
113
|
+
type: "date",
|
|
114
|
+
label: "From",
|
|
115
|
+
InputLabelProps: { shrink: !0 },
|
|
116
|
+
value: G,
|
|
117
|
+
onChange: (e) => K(e.target.value),
|
|
118
|
+
sx: { minWidth: 160 }
|
|
119
|
+
}),
|
|
120
|
+
/* @__PURE__ */ m(E, {
|
|
121
|
+
size: "small",
|
|
122
|
+
type: "date",
|
|
123
|
+
label: "To",
|
|
124
|
+
InputLabelProps: { shrink: !0 },
|
|
125
|
+
value: q,
|
|
126
|
+
onChange: (e) => J(e.target.value),
|
|
127
|
+
sx: { minWidth: 160 }
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ m(_, {
|
|
130
|
+
variant: "text",
|
|
131
|
+
onClick: Q,
|
|
132
|
+
disabled: !Z,
|
|
133
|
+
sx: { alignSelf: { md: "center" } },
|
|
134
|
+
children: "Clear"
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
}), /* @__PURE__ */ h(o, {
|
|
138
|
+
dense: !0,
|
|
139
|
+
children: [/* @__PURE__ */ m(w, { children: /* @__PURE__ */ h(T, { children: [
|
|
140
|
+
/* @__PURE__ */ m(C, { children: "Ref" }),
|
|
141
|
+
/* @__PURE__ */ m(C, { children: "Date" }),
|
|
142
|
+
/* @__PURE__ */ m(C, { children: "Owner" }),
|
|
143
|
+
/* @__PURE__ */ m(C, { children: "Items" }),
|
|
144
|
+
P ? /* @__PURE__ */ m(C, { children: "Payment" }) : null,
|
|
145
|
+
P ? /* @__PURE__ */ m(C, {
|
|
146
|
+
align: "right",
|
|
147
|
+
children: "Total"
|
|
148
|
+
}) : null,
|
|
149
|
+
/* @__PURE__ */ m(C, { children: "Notes" })
|
|
150
|
+
] }) }), /* @__PURE__ */ m(S, { children: z ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ m(T, { children: Array.from({ length: $ }).map((e, t) => /* @__PURE__ */ m(C, { children: /* @__PURE__ */ m(b, { height: 22 }) }, t)) }, t)) : X.length === 0 ? /* @__PURE__ */ m(u, {
|
|
151
|
+
colSpan: $,
|
|
152
|
+
icon: oe,
|
|
153
|
+
title: Z ? "No purchases match your filters" : "No purchases yet",
|
|
154
|
+
hint: Z ? "Adjust your search or filters." : "Record a purchase to add items to your stock.",
|
|
155
|
+
action: Z ? /* @__PURE__ */ m(_, {
|
|
156
|
+
variant: "text",
|
|
157
|
+
size: "small",
|
|
158
|
+
onClick: Q,
|
|
159
|
+
children: "Clear filters"
|
|
160
|
+
}) : j ? /* @__PURE__ */ m(_, {
|
|
161
|
+
variant: "contained",
|
|
162
|
+
size: "small",
|
|
163
|
+
startIcon: /* @__PURE__ */ m(O, {}),
|
|
164
|
+
onClick: () => F("/ui/medplat/manage/pm/purchases/new"),
|
|
165
|
+
children: "Record first purchase"
|
|
166
|
+
}) : null
|
|
167
|
+
}) : X.map((e) => {
|
|
168
|
+
let t = e.batches ?? [], n = t.slice(0, ce), r = t.length - n.length;
|
|
169
|
+
return /* @__PURE__ */ h(T, {
|
|
170
|
+
hover: !0,
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ m(C, { children: /* @__PURE__ */ m(s, { id: e.serialId }) }),
|
|
173
|
+
/* @__PURE__ */ m(C, { children: /* @__PURE__ */ m(D, {
|
|
174
|
+
variant: "body2",
|
|
175
|
+
sx: { fontWeight: 700 },
|
|
176
|
+
children: d(e.purchaseDate)
|
|
177
|
+
}) }),
|
|
178
|
+
/* @__PURE__ */ h(C, { children: [/* @__PURE__ */ m(D, {
|
|
179
|
+
variant: "body2",
|
|
180
|
+
sx: { fontWeight: 700 },
|
|
181
|
+
children: e.ownerName || (e.ownerType === "USER" ? "Personal" : "Facility")
|
|
182
|
+
}), /* @__PURE__ */ m(D, {
|
|
183
|
+
variant: "caption",
|
|
184
|
+
color: "text.secondary",
|
|
185
|
+
children: e.ownerType
|
|
186
|
+
})] }),
|
|
187
|
+
/* @__PURE__ */ m(C, {
|
|
188
|
+
sx: { maxWidth: 360 },
|
|
189
|
+
children: t.length === 0 ? /* @__PURE__ */ m(D, {
|
|
190
|
+
variant: "caption",
|
|
191
|
+
color: "text.disabled",
|
|
192
|
+
children: "—"
|
|
193
|
+
}) : /* @__PURE__ */ h(x, {
|
|
194
|
+
direction: "row",
|
|
195
|
+
spacing: .5,
|
|
196
|
+
flexWrap: "wrap",
|
|
197
|
+
useFlexGap: !0,
|
|
198
|
+
children: [n.map((e) => /* @__PURE__ */ m(v, {
|
|
199
|
+
size: "small",
|
|
200
|
+
label: /* @__PURE__ */ h(g, {
|
|
201
|
+
component: "span",
|
|
202
|
+
sx: {
|
|
203
|
+
display: "inline-flex",
|
|
204
|
+
alignItems: "baseline",
|
|
205
|
+
gap: .5
|
|
206
|
+
},
|
|
207
|
+
children: [/* @__PURE__ */ m(g, {
|
|
208
|
+
component: "span",
|
|
209
|
+
sx: { fontWeight: 700 },
|
|
210
|
+
children: e.productName ?? "—"
|
|
211
|
+
}), /* @__PURE__ */ h(g, {
|
|
212
|
+
component: "span",
|
|
213
|
+
sx: {
|
|
214
|
+
fontWeight: 700,
|
|
215
|
+
fontVariantNumeric: "tabular-nums",
|
|
216
|
+
color: "text.secondary"
|
|
217
|
+
},
|
|
218
|
+
children: ["×", e.qtyPurchased ?? 0]
|
|
219
|
+
})]
|
|
220
|
+
}),
|
|
221
|
+
sx: {
|
|
222
|
+
height: 22,
|
|
223
|
+
borderRadius: 1.5,
|
|
224
|
+
bgcolor: k(I.palette.primary.main, .06),
|
|
225
|
+
color: "text.primary",
|
|
226
|
+
border: `1px solid ${k(I.palette.primary.main, .16)}`,
|
|
227
|
+
"& .MuiChip-label": { px: .85 }
|
|
228
|
+
}
|
|
229
|
+
}, e.id)), r > 0 ? /* @__PURE__ */ m(v, {
|
|
230
|
+
size: "small",
|
|
231
|
+
label: `+${r} more`,
|
|
232
|
+
sx: {
|
|
233
|
+
height: 22,
|
|
234
|
+
borderRadius: 1.5,
|
|
235
|
+
bgcolor: "transparent",
|
|
236
|
+
color: "text.secondary",
|
|
237
|
+
border: `1px dashed ${I.palette.divider}`,
|
|
238
|
+
"& .MuiChip-label": {
|
|
239
|
+
px: .85,
|
|
240
|
+
fontWeight: 700
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}) : null]
|
|
244
|
+
})
|
|
245
|
+
}),
|
|
246
|
+
P ? /* @__PURE__ */ m(C, { children: e.paymentMode ? /* @__PURE__ */ m(v, {
|
|
247
|
+
size: "small",
|
|
248
|
+
label: e.paymentMode,
|
|
249
|
+
sx: {
|
|
250
|
+
fontWeight: 700,
|
|
251
|
+
borderRadius: 1.5,
|
|
252
|
+
height: 22,
|
|
253
|
+
bgcolor: k(I.palette.primary.main, .08),
|
|
254
|
+
color: "primary.dark",
|
|
255
|
+
border: `1px solid ${k(I.palette.primary.main, .18)}`
|
|
256
|
+
}
|
|
257
|
+
}) : /* @__PURE__ */ m(D, {
|
|
258
|
+
variant: "caption",
|
|
259
|
+
color: "text.disabled",
|
|
260
|
+
children: "—"
|
|
261
|
+
}) }) : null,
|
|
262
|
+
P ? /* @__PURE__ */ m(C, {
|
|
263
|
+
align: "right",
|
|
264
|
+
children: /* @__PURE__ */ m(l, { value: e.totalAmount })
|
|
265
|
+
}) : null,
|
|
266
|
+
/* @__PURE__ */ m(C, {
|
|
267
|
+
sx: { maxWidth: 320 },
|
|
268
|
+
children: e.notes ? /* @__PURE__ */ m(D, {
|
|
269
|
+
variant: "caption",
|
|
270
|
+
color: "text.secondary",
|
|
271
|
+
sx: {
|
|
272
|
+
display: "block",
|
|
273
|
+
overflow: "hidden",
|
|
274
|
+
textOverflow: "ellipsis",
|
|
275
|
+
whiteSpace: "nowrap"
|
|
276
|
+
},
|
|
277
|
+
children: e.notes
|
|
278
|
+
}) : /* @__PURE__ */ m(D, {
|
|
279
|
+
variant: "caption",
|
|
280
|
+
color: "text.disabled",
|
|
281
|
+
children: "—"
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
]
|
|
285
|
+
}, e.id);
|
|
286
|
+
}) })]
|
|
287
|
+
})]
|
|
288
|
+
})]
|
|
289
|
+
})
|
|
290
|
+
})] });
|
|
291
|
+
}
|
|
292
|
+
//#endregion
|
|
293
|
+
export { j as default };
|
|
294
|
+
|
|
295
|
+
//# sourceMappingURL=PurchasesPage-BCvLvSp4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PurchasesPage-BCvLvSp4.js","names":[],"sources":["../src/views/PurchasesPage.jsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n Alert,\n Box,\n Button,\n Chip,\n InputAdornment,\n Skeleton,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material';\nimport { alpha, useTheme } from '@mui/material/styles';\nimport AddRoundedIcon from '@mui/icons-material/AddRounded';\nimport RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';\nimport SearchRoundedIcon from '@mui/icons-material/SearchRounded';\nimport ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded';\nimport { showToast } from '@/common/toaster/toaster';\nimport PmPageShell from '@pm/components/PmPageShell';\nimport PmNav from '@pm/components/PmNav';\nimport PmGuard from '@pm/components/PmGuard';\nimport { usePermissionedEffect, usePmPermissions } from '@pm/utils/permissions';\nimport {\n PmEmptyRow,\n PmMoney,\n PmRef,\n PmTable,\n PmTableCard,\n} from '@pm/components/PmTable';\nimport { listPurchases } from '@pm/services/pmApi';\nimport { formatDate } from '@pm/utils/format';\nimport { currencySymbol } from '@pm/utils/currency';\nimport { usePmSettings } from '@pm/utils/settingsStore';\n\n// Compact one-liner of items+qty for the table. We render up to MAX_ITEMS_INLINE\n// pills inline; anything beyond gets a \"+N more\" pill so the row height stays\n// stable regardless of how many lines a purchase has.\nconst MAX_ITEMS_INLINE = 3;\n\nexport default function PurchasesPage() {\n const perms = usePmPermissions();\n const canCreate = perms.has('update.manage.productManagement.purchase');\n const settings = usePmSettings();\n const cur = currencySymbol(settings?.currencyCode);\n const manageAmounts = settings?.managePurchaseAmounts !== false;\n const navigate = useNavigate();\n const theme = useTheme();\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n const [search, setSearch] = useState('');\n const [fromDate, setFromDate] = useState('');\n const [toDate, setToDate] = useState('');\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n setItems(await listPurchases(0, 50));\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load purchases';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.purchase', () => {\n void load();\n }, []);\n\n // Search hits notes + every batch's productName + lotNumber. Date filters\n // bracket purchaseDate inclusively on either side; either bound is optional.\n const filteredItems = useMemo(() => {\n const q = search.trim().toLowerCase();\n const from = fromDate ? new Date(fromDate) : null;\n const to = toDate ? new Date(toDate) : null;\n return items.filter((p) => {\n if (q) {\n const hayItems = (p.batches ?? [])\n .map((b) => `${b.productName ?? ''} ${b.lotNumber ?? ''}`)\n .join(' ');\n const hay = `${p.notes ?? ''} ${hayItems}`.toLowerCase();\n if (!hay.includes(q)) return false;\n }\n if (from || to) {\n if (!p.purchaseDate) return false;\n const d = new Date(p.purchaseDate);\n if (from && d < from) return false;\n if (to) {\n // Date inputs give midnight; include the entire `to` day.\n const toEnd = new Date(to);\n toEnd.setHours(23, 59, 59, 999);\n if (d > toEnd) return false;\n }\n }\n return true;\n });\n }, [items, search, fromDate, toDate]);\n\n const totalSpend = useMemo(\n () => filteredItems.reduce((s, x) => s + Number(x.totalAmount || 0), 0),\n [filteredItems],\n );\n\n const hasFilter = search.trim() !== '' || fromDate !== '' || toDate !== '';\n\n function clearFilters() {\n setSearch('');\n setFromDate('');\n setToDate('');\n }\n\n // Match the table column count when manageAmounts swaps Payment + Total in\n // and out. Owner + Items columns are always present.\n const columnCount = manageAmounts ? 7 : 5;\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.purchase'}>\n <PmPageShell\n title=\"Completed Purchases\"\n subtitle=\"Completed purchases and approved requests. Each shows the items and cost.\"\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\" startIcon={<RefreshRoundedIcon />} onClick={() => void load()}>Refresh</Button>\n {canCreate ? (\n <Button variant=\"contained\" startIcon={<AddRoundedIcon />} onClick={() => navigate('/ui/medplat/manage/pm/purchases/new')}>\n New Purchase\n </Button>\n ) : null}\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n <PmTableCard\n eyebrow=\"Procurement\"\n title=\"Recent purchases\"\n subtitle={loading\n ? 'Loading…'\n : manageAmounts\n ? `${filteredItems.length} ${filteredItems.length === 1 ? 'purchase' : 'purchases'} · total spend ${cur}${totalSpend.toFixed(2)}`\n : `${filteredItems.length} ${filteredItems.length === 1 ? 'purchase' : 'purchases'}`}\n >\n <Stack direction={{ xs: 'column', md: 'row' }} spacing={1.5} sx={{ mb: 2 }}>\n <TextField\n size=\"small\"\n fullWidth\n placeholder=\"Search notes or items…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchRoundedIcon fontSize=\"small\" />\n </InputAdornment>\n ),\n }}\n />\n <TextField\n size=\"small\"\n type=\"date\"\n label=\"From\"\n InputLabelProps={{ shrink: true }}\n value={fromDate}\n onChange={(e) => setFromDate(e.target.value)}\n sx={{ minWidth: 160 }}\n />\n <TextField\n size=\"small\"\n type=\"date\"\n label=\"To\"\n InputLabelProps={{ shrink: true }}\n value={toDate}\n onChange={(e) => setToDate(e.target.value)}\n sx={{ minWidth: 160 }}\n />\n <Button\n variant=\"text\"\n onClick={clearFilters}\n disabled={!hasFilter}\n sx={{ alignSelf: { md: 'center' } }}\n >\n Clear\n </Button>\n </Stack>\n\n <PmTable dense>\n <TableHead>\n <TableRow>\n <TableCell>Ref</TableCell>\n <TableCell>Date</TableCell>\n <TableCell>Owner</TableCell>\n <TableCell>Items</TableCell>\n {manageAmounts ? <TableCell>Payment</TableCell> : null}\n {manageAmounts ? <TableCell align=\"right\">Total</TableCell> : null}\n <TableCell>Notes</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: 5 }).map((_, i) => (\n <TableRow key={i}>\n {Array.from({ length: columnCount }).map((__, j) => (\n <TableCell key={j}><Skeleton height={22} /></TableCell>\n ))}\n </TableRow>\n ))\n ) : filteredItems.length === 0 ? (\n <PmEmptyRow\n colSpan={columnCount}\n icon={ShoppingCartRoundedIcon}\n title={hasFilter ? 'No purchases match your filters' : 'No purchases yet'}\n hint={hasFilter\n ? 'Adjust your search or filters.'\n : 'Record a purchase to add items to your stock.'}\n action={hasFilter\n ? <Button variant=\"text\" size=\"small\" onClick={clearFilters}>Clear filters</Button>\n : !canCreate ? null : (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={() => navigate('/ui/medplat/manage/pm/purchases/new')}>\n Record first purchase\n </Button>\n )}\n />\n ) : filteredItems.map((p) => {\n const batches = p.batches ?? [];\n const visibleBatches = batches.slice(0, MAX_ITEMS_INLINE);\n const overflow = batches.length - visibleBatches.length;\n return (\n <TableRow key={p.id} hover>\n <TableCell><PmRef id={p.serialId} /></TableCell>\n <TableCell>\n <Typography variant=\"body2\" sx={{ fontWeight: 700 }}>{formatDate(p.purchaseDate)}</Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" sx={{ fontWeight: 700 }}>\n {p.ownerName || (p.ownerType === 'USER' ? 'Personal' : 'Facility')}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {p.ownerType}\n </Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {batches.length === 0 ? (\n <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>\n ) : (\n <Stack direction=\"row\" spacing={0.5} flexWrap=\"wrap\" useFlexGap>\n {visibleBatches.map((b) => (\n <Chip\n key={b.id}\n size=\"small\"\n label={\n <Box component=\"span\" sx={{ display: 'inline-flex', alignItems: 'baseline', gap: 0.5 }}>\n <Box component=\"span\" sx={{ fontWeight: 700 }}>{b.productName ?? '—'}</Box>\n <Box component=\"span\" sx={{ fontWeight: 700, fontVariantNumeric: 'tabular-nums', color: 'text.secondary' }}>\n ×{b.qtyPurchased ?? 0}\n </Box>\n </Box>\n }\n sx={{\n height: 22,\n borderRadius: 1.5,\n bgcolor: alpha(theme.palette.primary.main, 0.06),\n color: 'text.primary',\n border: `1px solid ${alpha(theme.palette.primary.main, 0.16)}`,\n '& .MuiChip-label': { px: 0.85 },\n }}\n />\n ))}\n {overflow > 0 ? (\n <Chip\n size=\"small\"\n label={`+${overflow} more`}\n sx={{\n height: 22,\n borderRadius: 1.5,\n bgcolor: 'transparent',\n color: 'text.secondary',\n border: `1px dashed ${theme.palette.divider}`,\n '& .MuiChip-label': { px: 0.85, fontWeight: 700 },\n }}\n />\n ) : null}\n </Stack>\n )}\n </TableCell>\n {manageAmounts ? (\n <TableCell>\n {p.paymentMode ? (\n <Chip\n size=\"small\"\n label={p.paymentMode}\n sx={{\n fontWeight: 700, borderRadius: 1.5, height: 22,\n bgcolor: alpha(theme.palette.primary.main, 0.08),\n color: 'primary.dark',\n border: `1px solid ${alpha(theme.palette.primary.main, 0.18)}`,\n }}\n />\n ) : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n ) : null}\n {manageAmounts ? (\n <TableCell align=\"right\"><PmMoney value={p.totalAmount} /></TableCell>\n ) : null}\n <TableCell sx={{ maxWidth: 320 }}>\n {p.notes ? (\n <Typography variant=\"caption\" color=\"text.secondary\"\n sx={{ display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {p.notes}\n </Typography>\n ) : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
|