@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.
Files changed (65) hide show
  1. package/dist/BrandsPage-DCMCVvDY.js +334 -0
  2. package/dist/BrandsPage-DCMCVvDY.js.map +1 -0
  3. package/dist/CategoriesPage-BpRhwfrc.js +284 -0
  4. package/dist/CategoriesPage-BpRhwfrc.js.map +1 -0
  5. package/dist/DashboardPage-BNKUQj46.js +436 -0
  6. package/dist/DashboardPage-BNKUQj46.js.map +1 -0
  7. package/dist/FacilityPicker-Coi8I3yE.js +79 -0
  8. package/dist/FacilityPicker-Coi8I3yE.js.map +1 -0
  9. package/dist/InventoryPage-BR6jOzg2.js +517 -0
  10. package/dist/InventoryPage-BR6jOzg2.js.map +1 -0
  11. package/dist/MemberProfileCard-DbHZCS5n.js +272 -0
  12. package/dist/MemberProfileCard-DbHZCS5n.js.map +1 -0
  13. package/dist/PaymentCreatePage-Ci3ERnby.js +487 -0
  14. package/dist/PaymentCreatePage-Ci3ERnby.js.map +1 -0
  15. package/dist/PaymentsPage-sdg902zX.js +157 -0
  16. package/dist/PaymentsPage-sdg902zX.js.map +1 -0
  17. package/dist/PickupCreatePage-CieMsgWV.js +310 -0
  18. package/dist/PickupCreatePage-CieMsgWV.js.map +1 -0
  19. package/dist/PickupsPage-Ci2Ll0Kn.js +566 -0
  20. package/dist/PickupsPage-Ci2Ll0Kn.js.map +1 -0
  21. package/dist/PmGuard-CjJBisaN.js +1195 -0
  22. package/dist/PmGuard-CjJBisaN.js.map +1 -0
  23. package/dist/PmTable-BuXZQZCU.js +302 -0
  24. package/dist/PmTable-BuXZQZCU.js.map +1 -0
  25. package/dist/ProductEditPage-DL8gy85Y.js +666 -0
  26. package/dist/ProductEditPage-DL8gy85Y.js.map +1 -0
  27. package/dist/ProductsPage-BANTKxLb.js +221 -0
  28. package/dist/ProductsPage-BANTKxLb.js.map +1 -0
  29. package/dist/PurchaseCreatePage-C3KMfBxJ.js +626 -0
  30. package/dist/PurchaseCreatePage-C3KMfBxJ.js.map +1 -0
  31. package/dist/PurchaseRequestDetailPage-C0GYFJDl.js +586 -0
  32. package/dist/PurchaseRequestDetailPage-C0GYFJDl.js.map +1 -0
  33. package/dist/PurchaseRequestsPage-DvFH_tWe.js +265 -0
  34. package/dist/PurchaseRequestsPage-DvFH_tWe.js.map +1 -0
  35. package/dist/PurchasesPage-BCvLvSp4.js +295 -0
  36. package/dist/PurchasesPage-BCvLvSp4.js.map +1 -0
  37. package/dist/SaleCreatePage-DpkQMoTq.js +548 -0
  38. package/dist/SaleCreatePage-DpkQMoTq.js.map +1 -0
  39. package/dist/SalesPage-DUwgkEO-.js +315 -0
  40. package/dist/SalesPage-DUwgkEO-.js.map +1 -0
  41. package/dist/SettingsPage-CusC0jqJ.js +710 -0
  42. package/dist/SettingsPage-CusC0jqJ.js.map +1 -0
  43. package/dist/StorageUnitsPage-BlC2AgrJ.js +469 -0
  44. package/dist/StorageUnitsPage-BlC2AgrJ.js.map +1 -0
  45. package/dist/TransactionsPage-DDaK4VyY.js +714 -0
  46. package/dist/TransactionsPage-DDaK4VyY.js.map +1 -0
  47. package/dist/TransferCreatePage-BxudLfhS.js +363 -0
  48. package/dist/TransferCreatePage-BxudLfhS.js.map +1 -0
  49. package/dist/TransfersPage-zgmt7teZ.js +480 -0
  50. package/dist/TransfersPage-zgmt7teZ.js.map +1 -0
  51. package/dist/VialsPage-CjqPfgpV.js +855 -0
  52. package/dist/VialsPage-CjqPfgpV.js.map +1 -0
  53. package/dist/constants-BrA_hfAI.js +254 -0
  54. package/dist/constants-BrA_hfAI.js.map +1 -0
  55. package/dist/currency-BDDCDgeE.js +169 -0
  56. package/dist/currency-BDDCDgeE.js.map +1 -0
  57. package/dist/format-UOyOu75i.js +52 -0
  58. package/dist/format-UOyOu75i.js.map +1 -0
  59. package/dist/index.js +45 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/useFieldErrors-hDG8ox_x.js +29 -0
  62. package/dist/useFieldErrors-hDG8ox_x.js.map +1 -0
  63. package/dist/validation-Ba7puFIO.js +109 -0
  64. package/dist/validation-Ba7puFIO.js.map +1 -0
  65. 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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"}