@argusoft/medplat-product-management 1.0.9 → 1.0.11

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 (128) hide show
  1. package/dist/BrandsPage-DBFBor6L.js +384 -0
  2. package/dist/{BrandsPage-DMw2vT0u.js.map → BrandsPage-DBFBor6L.js.map} +1 -1
  3. package/dist/CategoriesPage-DbR56Dxb.js +396 -0
  4. package/dist/{CategoriesPage-D3ihx9Gi.js.map → CategoriesPage-DbR56Dxb.js.map} +1 -1
  5. package/dist/DashboardPage-Dw_xutHp.js +435 -0
  6. package/dist/DashboardPage-Dw_xutHp.js.map +1 -0
  7. package/dist/FacilityPicker-DoN5Uorg.js +132 -0
  8. package/dist/FacilityPicker-DoN5Uorg.js.map +1 -0
  9. package/dist/InventoryPage-BETRRdVj.js +1004 -0
  10. package/dist/InventoryPage-BETRRdVj.js.map +1 -0
  11. package/dist/LocationPicker-DNg0iSZm.js +321 -0
  12. package/dist/LocationPicker-DNg0iSZm.js.map +1 -0
  13. package/dist/PaymentCreatePage--WFg0fgT.js +513 -0
  14. package/dist/PaymentCreatePage--WFg0fgT.js.map +1 -0
  15. package/dist/PaymentsPage-CYSXziah.js +168 -0
  16. package/dist/PaymentsPage-CYSXziah.js.map +1 -0
  17. package/dist/PickupBatchLinesEditor-CR_5BIOa.js +114 -0
  18. package/dist/{PickupBatchLinesEditor-CE2RuyJT.js.map → PickupBatchLinesEditor-CR_5BIOa.js.map} +1 -1
  19. package/dist/{PickupCreatePage-B4O_-vE5.js → PickupCreatePage-BNK2p8Wj.js} +207 -189
  20. package/dist/PickupCreatePage-BNK2p8Wj.js.map +1 -0
  21. package/dist/PickupsPage-cIBMy6kz.js +810 -0
  22. package/dist/PickupsPage-cIBMy6kz.js.map +1 -0
  23. package/dist/PmDocumentDownload-B1zLnOPX.js +46 -0
  24. package/dist/PmDocumentDownload-B1zLnOPX.js.map +1 -0
  25. package/dist/PmGuard-DzOloo0T.js +624 -0
  26. package/dist/PmGuard-DzOloo0T.js.map +1 -0
  27. package/dist/PmTable-nWK5C3ew.js +542 -0
  28. package/dist/{PmTable-CwKORZGg.js.map → PmTable-nWK5C3ew.js.map} +1 -1
  29. package/dist/ProductEditPage-mCCCmDyz.js +1512 -0
  30. package/dist/ProductEditPage-mCCCmDyz.js.map +1 -0
  31. package/dist/ProductsPage-Cr-Ay4tP.js +303 -0
  32. package/dist/ProductsPage-Cr-Ay4tP.js.map +1 -0
  33. package/dist/PurchaseCreatePage-djceX_Mi.js +723 -0
  34. package/dist/PurchaseCreatePage-djceX_Mi.js.map +1 -0
  35. package/dist/PurchaseRequestDetailPage-Cc3vdQ33.js +1551 -0
  36. package/dist/PurchaseRequestDetailPage-Cc3vdQ33.js.map +1 -0
  37. package/dist/PurchaseRequestsPage-dQDeAWYz.js +278 -0
  38. package/dist/{PurchaseRequestsPage-DS9i4o0-.js.map → PurchaseRequestsPage-dQDeAWYz.js.map} +1 -1
  39. package/dist/PurchasesPage-DpMPd8JH.js +305 -0
  40. package/dist/PurchasesPage-DpMPd8JH.js.map +1 -0
  41. package/dist/SaleCreatePage-DDedCbwe.js +575 -0
  42. package/dist/SaleCreatePage-DDedCbwe.js.map +1 -0
  43. package/dist/SalesPage-CelCu5Tw.js +325 -0
  44. package/dist/SalesPage-CelCu5Tw.js.map +1 -0
  45. package/dist/SettingsPage-BEyiYNFC.js +1163 -0
  46. package/dist/SettingsPage-BEyiYNFC.js.map +1 -0
  47. package/dist/StorageUnitsPage-CqlGFV83.js +987 -0
  48. package/dist/StorageUnitsPage-CqlGFV83.js.map +1 -0
  49. package/dist/TransactionsPage-CdidHnRk.js +763 -0
  50. package/dist/TransactionsPage-CdidHnRk.js.map +1 -0
  51. package/dist/TransferCreatePage-C84ze-RN.js +638 -0
  52. package/dist/TransferCreatePage-C84ze-RN.js.map +1 -0
  53. package/dist/TransfersPage-Pvjid97y.js +591 -0
  54. package/dist/TransfersPage-Pvjid97y.js.map +1 -0
  55. package/dist/VialsPage-VjNQ4SGI.js +452 -0
  56. package/dist/VialsPage-VjNQ4SGI.js.map +1 -0
  57. package/dist/constants-Dvu1Zd5X.js +498 -0
  58. package/dist/constants-Dvu1Zd5X.js.map +1 -0
  59. package/dist/format-qqBoZCqP.js +50 -0
  60. package/dist/{format-UOyOu75i.js.map → format-qqBoZCqP.js.map} +1 -1
  61. package/dist/index.js +363 -369
  62. package/dist/index.js.map +1 -1
  63. package/dist/listValueStore-BW6BS4BN.js +41 -0
  64. package/dist/listValueStore-BW6BS4BN.js.map +1 -0
  65. package/dist/settingsStore-C1aUfwS9.js +558 -0
  66. package/dist/settingsStore-C1aUfwS9.js.map +1 -0
  67. package/dist/useFieldErrors-Dh04ptYj.js +27 -0
  68. package/dist/{useFieldErrors-hDG8ox_x.js.map → useFieldErrors-Dh04ptYj.js.map} +1 -1
  69. package/dist/validation-CKx4Zzpx.js +108 -0
  70. package/dist/{validation-BzlHnL-r.js.map → validation-CKx4Zzpx.js.map} +1 -1
  71. package/package.json +11 -5
  72. package/dist/BrandsPage-DMw2vT0u.js +0 -386
  73. package/dist/CategoriesPage-D3ihx9Gi.js +0 -398
  74. package/dist/DashboardPage-asr2XDRu.js +0 -436
  75. package/dist/DashboardPage-asr2XDRu.js.map +0 -1
  76. package/dist/FacilityPicker-DYl_PDyt.js +0 -79
  77. package/dist/FacilityPicker-DYl_PDyt.js.map +0 -1
  78. package/dist/InventoryPage-DOotGZrj.js +0 -655
  79. package/dist/InventoryPage-DOotGZrj.js.map +0 -1
  80. package/dist/MemberProfileCard-D5CgkTdJ.js +0 -273
  81. package/dist/MemberProfileCard-D5CgkTdJ.js.map +0 -1
  82. package/dist/PaymentCreatePage-DfvSZ-kB.js +0 -481
  83. package/dist/PaymentCreatePage-DfvSZ-kB.js.map +0 -1
  84. package/dist/PaymentsPage-DMNjYWAJ.js +0 -157
  85. package/dist/PaymentsPage-DMNjYWAJ.js.map +0 -1
  86. package/dist/PickupBatchLinesEditor-CE2RuyJT.js +0 -116
  87. package/dist/PickupCreatePage-B4O_-vE5.js.map +0 -1
  88. package/dist/PickupsPage-D7zyioJB.js +0 -812
  89. package/dist/PickupsPage-D7zyioJB.js.map +0 -1
  90. package/dist/PmGuard-BZE-y4In.js +0 -592
  91. package/dist/PmGuard-BZE-y4In.js.map +0 -1
  92. package/dist/PmTable-CwKORZGg.js +0 -544
  93. package/dist/ProductEditPage-BVlVUCtD.js +0 -1296
  94. package/dist/ProductEditPage-BVlVUCtD.js.map +0 -1
  95. package/dist/ProductsPage-DvNHIeZt.js +0 -253
  96. package/dist/ProductsPage-DvNHIeZt.js.map +0 -1
  97. package/dist/PurchaseCreatePage-Cq_i9snz.js +0 -675
  98. package/dist/PurchaseCreatePage-Cq_i9snz.js.map +0 -1
  99. package/dist/PurchaseRequestDetailPage-CA9KFOfE.js +0 -1543
  100. package/dist/PurchaseRequestDetailPage-CA9KFOfE.js.map +0 -1
  101. package/dist/PurchaseRequestsPage-DS9i4o0-.js +0 -280
  102. package/dist/PurchasesPage-DgL5T6BY.js +0 -294
  103. package/dist/PurchasesPage-DgL5T6BY.js.map +0 -1
  104. package/dist/SaleCreatePage-CZnIOydv.js +0 -543
  105. package/dist/SaleCreatePage-CZnIOydv.js.map +0 -1
  106. package/dist/SalesPage-DPIRrC_O.js +0 -314
  107. package/dist/SalesPage-DPIRrC_O.js.map +0 -1
  108. package/dist/SettingsPage-BC_R6Z-Q.js +0 -674
  109. package/dist/SettingsPage-BC_R6Z-Q.js.map +0 -1
  110. package/dist/StorageUnitsPage-BDRkdCjW.js +0 -722
  111. package/dist/StorageUnitsPage-BDRkdCjW.js.map +0 -1
  112. package/dist/TransactionsPage-CqWTMNU8.js +0 -744
  113. package/dist/TransactionsPage-CqWTMNU8.js.map +0 -1
  114. package/dist/TransferCreatePage-DF7FZaTJ.js +0 -315
  115. package/dist/TransferCreatePage-DF7FZaTJ.js.map +0 -1
  116. package/dist/TransfersPage-CGrRFaBF.js +0 -470
  117. package/dist/TransfersPage-CGrRFaBF.js.map +0 -1
  118. package/dist/VialsPage-rvvXjgZG.js +0 -320
  119. package/dist/VialsPage-rvvXjgZG.js.map +0 -1
  120. package/dist/constants-DpXnLsAB.js +0 -412
  121. package/dist/constants-DpXnLsAB.js.map +0 -1
  122. package/dist/format-UOyOu75i.js +0 -52
  123. package/dist/listValueStore-BFQtDYIR.js +0 -36
  124. package/dist/listValueStore-BFQtDYIR.js.map +0 -1
  125. package/dist/settingsStore-BHHOmcCP.js +0 -448
  126. package/dist/settingsStore-BHHOmcCP.js.map +0 -1
  127. package/dist/useFieldErrors-hDG8ox_x.js +0 -29
  128. package/dist/validation-BzlHnL-r.js +0 -110
@@ -0,0 +1,384 @@
1
+ import { r as usePmSettings, x as getBrands, xt as upsertBrand } from "./settingsStore-C1aUfwS9.js";
2
+ import { c as PmTableCard, l as showToast, n as PmFieldHelp, s as PmTable, t as PmEmptyRow } from "./PmTable-nWK5C3ew.js";
3
+ import { i as validateEmail, m as validateRequired, t as isClean } from "./validation-CKx4Zzpx.js";
4
+ import { t as useFieldErrors } from "./useFieldErrors-Dh04ptYj.js";
5
+ import { a as PmPageShell, i as usePmPermissions, n as PmNav, r as usePermissionedEffect, t as PmGuard } from "./PmGuard-DzOloo0T.js";
6
+ import { useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { Alert, Box, Button, Checkbox, Chip, Dialog, DialogActions, DialogContent, DialogTitle, FormControlLabel, InputAdornment, Skeleton, Stack, TableBody, TableCell, TableHead, TableRow, TextField, Typography } from "@mui/material";
9
+ import { findCountry, validatePhoneForCountry } from "@/common/constants/countries";
10
+ import { v4 } from "uuid";
11
+ import AddRoundedIcon from "@mui/icons-material/AddRounded";
12
+ import RefreshRoundedIcon from "@mui/icons-material/RefreshRounded";
13
+ import SellRoundedIcon from "@mui/icons-material/SellRounded";
14
+ import CustomSwitch from "@/views/custom-components/CustomSwitch";
15
+ function parseContactInfo(e) {
16
+ if (!e) return {
17
+ phone: "",
18
+ email: ""
19
+ };
20
+ try {
21
+ let w = JSON.parse(e);
22
+ return {
23
+ phone: typeof w?.phone == "string" ? w.phone : "",
24
+ email: typeof w?.email == "string" ? w.email : ""
25
+ };
26
+ } catch {
27
+ return {
28
+ phone: "",
29
+ email: ""
30
+ };
31
+ }
32
+ }
33
+ function serializeContactInfo({ phone: e, email: w }) {
34
+ let T = {};
35
+ return e?.trim() && (T.phone = e.trim()), w?.trim() && (T.email = w.trim()), Object.keys(T).length ? JSON.stringify(T) : null;
36
+ }
37
+ function BrandsPage() {
38
+ let E = usePmPermissions().has("update.manage.productManagement.brand"), D = findCountry(usePmSettings()?.countryCode), [O, k] = useState([]), [A, j] = useState(!1), [M, N] = useState(""), [P, F] = useState(!1), [I, L] = useState(null), [R, z] = useState(!1), [B, V] = useState(U()), H = useFieldErrors();
39
+ function U() {
40
+ return {
41
+ id: "",
42
+ name: "",
43
+ manufacturerCode: "",
44
+ contactPhone: "",
45
+ contactEmail: "",
46
+ isActive: !0
47
+ };
48
+ }
49
+ async function W() {
50
+ j(!0), N("");
51
+ try {
52
+ k(await getBrands(void 0, !0));
53
+ } catch (e) {
54
+ let w = e?.response?.data?.message ?? e?.message ?? "Failed to load brands";
55
+ N(w), showToast({
56
+ message: w,
57
+ type: "error"
58
+ });
59
+ } finally {
60
+ j(!1);
61
+ }
62
+ }
63
+ usePermissionedEffect("view.manage.productManagement.brand", () => {
64
+ W();
65
+ }, []);
66
+ function G() {
67
+ L(null), V({
68
+ ...U(),
69
+ id: v4()
70
+ }), H.reset(), N(""), F(!0);
71
+ }
72
+ function K(e) {
73
+ let { phone: w, email: T } = parseContactInfo(e.contactInfo);
74
+ L(e), H.reset(), N(""), V({
75
+ id: e.id,
76
+ name: e.name ?? "",
77
+ manufacturerCode: e.manufacturerCode ?? "",
78
+ contactPhone: w,
79
+ contactEmail: T,
80
+ isActive: e.isActive !== !1
81
+ }), F(!0);
82
+ }
83
+ let q = validateRequired(B.manufacturerCode, "Manufacturer code"), J = B.manufacturerCode.trim().toUpperCase(), Y = !q && J && O.some((e) => e.id !== B.id && (e.manufacturerCode || "").toUpperCase() === J), X = {
84
+ name: validateRequired(B.name, "Name"),
85
+ manufacturerCode: q || (Y ? "Code is already in use — edit it manually to make it unique." : ""),
86
+ contactPhone: validatePhoneForCountry(B.contactPhone, D),
87
+ contactEmail: validateEmail(B.contactEmail)
88
+ }, Z = isClean(X);
89
+ async function Q() {
90
+ if (!Z) {
91
+ H.markAllTouched(), N("Please fix the highlighted fields.");
92
+ return;
93
+ }
94
+ try {
95
+ await upsertBrand({
96
+ id: B.id,
97
+ name: B.name.trim(),
98
+ manufacturerCode: B.manufacturerCode.trim().toUpperCase(),
99
+ contactInfo: serializeContactInfo({
100
+ phone: B.contactPhone,
101
+ email: B.contactEmail
102
+ }),
103
+ isActive: B.isActive
104
+ }), showToast({
105
+ message: "Brand saved.",
106
+ type: "success"
107
+ }), F(!1), await W();
108
+ } catch (e) {
109
+ let w = e?.response?.data?.message ?? e?.message ?? "Failed to save brand";
110
+ N(w), showToast({
111
+ message: w,
112
+ type: "error"
113
+ });
114
+ }
115
+ }
116
+ let $ = R ? O : O.filter((e) => e.isActive !== !1);
117
+ return /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(PmNav, {}), /* @__PURE__ */ jsxs(PmGuard, {
118
+ perm: "view.manage.productManagement.brand",
119
+ children: [/* @__PURE__ */ jsxs(PmPageShell, {
120
+ title: "Brands",
121
+ subtitle: "The manufacturer or supplier of each product.",
122
+ chips: ["Catalog"],
123
+ actions: /* @__PURE__ */ jsxs(Stack, {
124
+ direction: "row",
125
+ spacing: 1,
126
+ children: [/* @__PURE__ */ jsx(Button, {
127
+ variant: "outlined",
128
+ startIcon: /* @__PURE__ */ jsx(RefreshRoundedIcon, {}),
129
+ onClick: () => void W(),
130
+ children: "Refresh"
131
+ }), E ? /* @__PURE__ */ jsx(Button, {
132
+ variant: "contained",
133
+ startIcon: /* @__PURE__ */ jsx(AddRoundedIcon, {}),
134
+ onClick: G,
135
+ children: "New Brand"
136
+ }) : null]
137
+ }),
138
+ children: [M ? /* @__PURE__ */ jsx(Alert, {
139
+ severity: "error",
140
+ sx: { mb: 2 },
141
+ children: M
142
+ }) : null, /* @__PURE__ */ jsx(PmTableCard, {
143
+ eyebrow: "Master data",
144
+ title: "Brands",
145
+ subtitle: A ? "Loading…" : `${$.length} ${$.length === 1 ? "brand" : "brands"}`,
146
+ actions: /* @__PURE__ */ jsx(FormControlLabel, {
147
+ control: /* @__PURE__ */ jsx(CustomSwitch, {
148
+ checked: R,
149
+ onChange: (e) => z(e.target.checked)
150
+ }),
151
+ label: /* @__PURE__ */ jsx(Typography, {
152
+ variant: "body2",
153
+ sx: { fontWeight: 600 },
154
+ children: "Show inactive"
155
+ }),
156
+ labelPlacement: "start",
157
+ sx: {
158
+ mr: .5,
159
+ ml: 0
160
+ }
161
+ }),
162
+ children: /* @__PURE__ */ jsxs(PmTable, { children: [/* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
163
+ /* @__PURE__ */ jsx(TableCell, { children: "Name" }),
164
+ /* @__PURE__ */ jsx(TableCell, { children: "Manufacturer Code" }),
165
+ /* @__PURE__ */ jsx(TableCell, { children: "Contact" }),
166
+ /* @__PURE__ */ jsx(TableCell, { children: "Status" }),
167
+ /* @__PURE__ */ jsx(TableCell, {
168
+ align: "right",
169
+ children: "Action"
170
+ })
171
+ ] }) }), /* @__PURE__ */ jsx(TableBody, { children: A ? Array.from({ length: 4 }).map((e, w) => /* @__PURE__ */ jsx(TableRow, { children: Array.from({ length: 5 }).map((e, w) => /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Skeleton, { height: 22 }) }, w)) }, w)) : $.length === 0 ? /* @__PURE__ */ jsx(PmEmptyRow, {
172
+ colSpan: 5,
173
+ icon: SellRoundedIcon,
174
+ title: O.length === 0 ? "No brands yet" : "No active brands",
175
+ hint: O.length === 0 ? "Add manufacturers so you can link them to your products." : "Turn on “Show inactive” to see deactivated brands.",
176
+ action: O.length === 0 && E ? /* @__PURE__ */ jsx(Button, {
177
+ variant: "contained",
178
+ size: "small",
179
+ startIcon: /* @__PURE__ */ jsx(AddRoundedIcon, {}),
180
+ onClick: G,
181
+ children: "Create first brand"
182
+ }) : null
183
+ }) : $.map((e) => {
184
+ let { phone: w, email: T } = parseContactInfo(e.contactInfo);
185
+ return /* @__PURE__ */ jsxs(TableRow, {
186
+ hover: !0,
187
+ children: [
188
+ /* @__PURE__ */ jsx(TableCell, {
189
+ sx: { maxWidth: 240 },
190
+ children: /* @__PURE__ */ jsx(Typography, {
191
+ variant: "body2",
192
+ sx: {
193
+ fontWeight: 700,
194
+ wordBreak: "break-word"
195
+ },
196
+ children: e.name
197
+ })
198
+ }),
199
+ /* @__PURE__ */ jsx(TableCell, {
200
+ sx: { maxWidth: 160 },
201
+ children: /* @__PURE__ */ jsx(Box, {
202
+ component: "span",
203
+ sx: {
204
+ display: "inline-block",
205
+ px: .85,
206
+ py: .25,
207
+ borderRadius: 1,
208
+ bgcolor: "grey.100",
209
+ fontFamily: "monospace",
210
+ fontSize: "0.72rem",
211
+ fontWeight: 800,
212
+ maxWidth: "100%",
213
+ wordBreak: "break-all"
214
+ },
215
+ children: e.manufacturerCode
216
+ })
217
+ }),
218
+ /* @__PURE__ */ jsx(TableCell, { children: w || T ? /* @__PURE__ */ jsxs(Stack, {
219
+ spacing: .25,
220
+ children: [w ? /* @__PURE__ */ jsx(Typography, {
221
+ variant: "caption",
222
+ sx: { fontWeight: 600 },
223
+ children: w
224
+ }) : null, T ? /* @__PURE__ */ jsx(Typography, {
225
+ variant: "caption",
226
+ color: "text.secondary",
227
+ children: T
228
+ }) : null]
229
+ }) : /* @__PURE__ */ jsx(Typography, {
230
+ variant: "caption",
231
+ color: "text.disabled",
232
+ children: "—"
233
+ }) }),
234
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Chip, {
235
+ size: "small",
236
+ label: e.isActive ? "Active" : "Inactive",
237
+ color: e.isActive ? "success" : "default",
238
+ variant: e.isActive ? "filled" : "outlined",
239
+ sx: {
240
+ fontWeight: 700,
241
+ borderRadius: 1.5,
242
+ height: 22
243
+ }
244
+ }) }),
245
+ /* @__PURE__ */ jsx(TableCell, {
246
+ align: "right",
247
+ children: E ? /* @__PURE__ */ jsx(Button, {
248
+ size: "small",
249
+ variant: "outlined",
250
+ onClick: () => K(e),
251
+ children: "Edit"
252
+ }) : null
253
+ })
254
+ ]
255
+ }, e.id);
256
+ }) })] })
257
+ })]
258
+ }), /* @__PURE__ */ jsxs(Dialog, {
259
+ open: P,
260
+ onClose: () => F(!1),
261
+ fullWidth: !0,
262
+ maxWidth: "sm",
263
+ children: [
264
+ /* @__PURE__ */ jsx(DialogTitle, { children: I ? "Edit Brand" : "New Brand" }),
265
+ /* @__PURE__ */ jsx(DialogContent, {
266
+ dividers: !0,
267
+ children: /* @__PURE__ */ jsxs(Stack, {
268
+ spacing: 2,
269
+ sx: { pt: 1 },
270
+ children: [
271
+ /* @__PURE__ */ jsx(TextField, {
272
+ required: !0,
273
+ label: "Name",
274
+ size: "small",
275
+ fullWidth: !0,
276
+ value: B.name,
277
+ inputProps: { maxLength: 255 },
278
+ onChange: (e) => {
279
+ let w = e.target.value, T = w.split(/\s+/).filter(Boolean).map((e) => e[0]).join("").toUpperCase();
280
+ V((e) => ({
281
+ ...e,
282
+ name: w,
283
+ manufacturerCode: I ? e.manufacturerCode : T
284
+ }));
285
+ },
286
+ onBlur: H.onBlur("name"),
287
+ error: H.show("name") && !!X.name,
288
+ FormHelperTextProps: { component: "div" },
289
+ helperText: /* @__PURE__ */ jsx(PmFieldHelp, {
290
+ message: H.show("name") ? X.name : "",
291
+ value: B.name,
292
+ max: 255
293
+ })
294
+ }),
295
+ /* @__PURE__ */ jsx(TextField, {
296
+ required: !0,
297
+ label: "Manufacturer code",
298
+ size: "small",
299
+ fullWidth: !0,
300
+ value: B.manufacturerCode,
301
+ inputProps: { maxLength: 100 },
302
+ onChange: (e) => V({
303
+ ...B,
304
+ manufacturerCode: e.target.value.toUpperCase()
305
+ }),
306
+ onBlur: H.onBlur("manufacturerCode"),
307
+ error: H.show("manufacturerCode") && !!X.manufacturerCode,
308
+ FormHelperTextProps: { component: "div" },
309
+ helperText: /* @__PURE__ */ jsx(PmFieldHelp, {
310
+ message: H.show("manufacturerCode") && X.manufacturerCode ? X.manufacturerCode : "Auto-generated from the name as initials. Edit if needed to make it unique.",
311
+ value: B.manufacturerCode,
312
+ max: 100
313
+ })
314
+ }),
315
+ /* @__PURE__ */ jsx(TextField, {
316
+ label: "Contact Number",
317
+ size: "small",
318
+ fullWidth: !0,
319
+ type: "tel",
320
+ placeholder: D ? D.phoneMin === D.phoneMax ? `${D.phoneMin}-digit local number` : `${D.phoneMin}–${D.phoneMax} digit local number` : "Local number",
321
+ value: B.contactPhone,
322
+ onChange: (e) => V({
323
+ ...B,
324
+ contactPhone: e.target.value.replace(/[^\d\s]/g, "")
325
+ }),
326
+ onBlur: H.onBlur("contactPhone"),
327
+ error: H.show("contactPhone") && !!X.contactPhone,
328
+ helperText: H.show("contactPhone") && X.contactPhone ? X.contactPhone : D ? `Format for ${D.name}: ${D.phoneCode} followed by ${D.phoneMin}${D.phoneMin === D.phoneMax ? "" : `–${D.phoneMax}`} digits.` : "Local number, digits only.",
329
+ InputProps: D ? { startAdornment: /* @__PURE__ */ jsx(InputAdornment, {
330
+ position: "start",
331
+ children: /* @__PURE__ */ jsx(Box, {
332
+ component: "span",
333
+ sx: {
334
+ fontWeight: 700,
335
+ color: "text.secondary"
336
+ },
337
+ children: D.phoneCode
338
+ })
339
+ }) } : void 0
340
+ }),
341
+ /* @__PURE__ */ jsx(TextField, {
342
+ label: "Email",
343
+ size: "small",
344
+ fullWidth: !0,
345
+ type: "email",
346
+ placeholder: "e.g. contact@manufacturer.example",
347
+ value: B.contactEmail,
348
+ onChange: (e) => V({
349
+ ...B,
350
+ contactEmail: e.target.value
351
+ }),
352
+ onBlur: H.onBlur("contactEmail"),
353
+ error: H.show("contactEmail") && !!X.contactEmail,
354
+ helperText: H.show("contactEmail") ? X.contactEmail : ""
355
+ }),
356
+ /* @__PURE__ */ jsx(FormControlLabel, {
357
+ control: /* @__PURE__ */ jsx(Checkbox, {
358
+ checked: B.isActive,
359
+ onChange: (e) => V({
360
+ ...B,
361
+ isActive: e.target.checked
362
+ })
363
+ }),
364
+ label: "Active"
365
+ })
366
+ ]
367
+ })
368
+ }),
369
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
370
+ onClick: () => F(!1),
371
+ children: "Cancel"
372
+ }), /* @__PURE__ */ jsx(Button, {
373
+ variant: "contained",
374
+ disabled: !Z,
375
+ onClick: () => void Q(),
376
+ children: "Save"
377
+ })] })
378
+ ]
379
+ })]
380
+ })] });
381
+ }
382
+ export { BrandsPage as default };
383
+
384
+ //# sourceMappingURL=BrandsPage-DBFBor6L.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BrandsPage-DMw2vT0u.js","names":[],"sources":["../src/views/BrandsPage.jsx"],"sourcesContent":["import { useState } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Box,\n Button,\n Checkbox,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n InputAdornment,\n Skeleton,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material';\nimport AddRoundedIcon from '@mui/icons-material/AddRounded';\nimport RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';\nimport SellRoundedIcon from '@mui/icons-material/SellRounded';\nimport { showToast } from '@pm/utils/pmToast';\nimport CustomSwitch from '@/views/custom-components/CustomSwitch';\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 { PmEmptyRow, PmFieldHelp, PmTable, PmTableCard } from '@pm/components/PmTable';\nimport { getBrands, upsertBrand } from '@pm/services/pmApi';\nimport { isClean, validateEmail, validateRequired } from '@pm/utils/validation';\nimport { findCountry, validatePhoneForCountry } from '@/common/constants/countries';\nimport { usePmSettings } from '@pm/utils/settingsStore';\nimport { useFieldErrors } from '@pm/utils/useFieldErrors';\n\n// Backend stores contact_info as a JSON-encoded string. We keep the discrete\n// fields here so the UI is form-friendly, and only ever round-trip the JSON.\nfunction parseContactInfo(raw) {\n if (!raw) return { phone: '', email: '' };\n try {\n const obj = JSON.parse(raw);\n return {\n phone: typeof obj?.phone === 'string' ? obj.phone : '',\n email: typeof obj?.email === 'string' ? obj.email : '',\n };\n } catch {\n return { phone: '', email: '' };\n }\n}\n\nfunction serializeContactInfo({ phone, email }) {\n const out = {};\n if (phone?.trim()) out.phone = phone.trim();\n if (email?.trim()) out.email = email.trim();\n return Object.keys(out).length ? JSON.stringify(out) : null;\n}\n\nexport default function BrandsPage() {\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.brand');\n const settings = usePmSettings();\n const country = findCountry(settings?.countryCode);\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [openDialog, setOpenDialog] = useState(false);\n const [editing, setEditing] = useState(null);\n // Default to active-only; the toggle above the table reveals inactive rows.\n const [showInactive, setShowInactive] = useState(false);\n const [form, setForm] = useState(emptyForm());\n const fieldErrors = useFieldErrors();\n\n function emptyForm() {\n return {\n id: '',\n name: '',\n manufacturerCode: '',\n contactPhone: '',\n contactEmail: '',\n isActive: true,\n };\n }\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n const data = await getBrands(undefined, true);\n setItems(data);\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load brands';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.brand', () => {\n void load();\n }, []);\n\n function openCreate() {\n setEditing(null);\n setForm({ ...emptyForm(), id: uuidv4() });\n fieldErrors.reset();\n setError('');\n setOpenDialog(true);\n }\n\n function openEdit(item) {\n const { phone, email } = parseContactInfo(item.contactInfo);\n setEditing(item);\n fieldErrors.reset();\n setError('');\n setForm({\n id: item.id,\n name: item.name ?? '',\n manufacturerCode: item.manufacturerCode ?? '',\n contactPhone: phone,\n contactEmail: email,\n isActive: item.isActive !== false,\n });\n setOpenDialog(true);\n }\n\n const mfrCodeBase = validateRequired(form.manufacturerCode, 'Manufacturer code');\n const mfrNorm = form.manufacturerCode.trim().toUpperCase();\n const mfrClash = !mfrCodeBase\n && mfrNorm\n && items.some((b) => b.id !== form.id && (b.manufacturerCode || '').toUpperCase() === mfrNorm);\n const formErrors = {\n name: validateRequired(form.name, 'Name'),\n manufacturerCode: mfrCodeBase || (mfrClash ? 'Code is already in use — edit it manually to make it unique.' : ''),\n contactPhone: validatePhoneForCountry(form.contactPhone, country),\n contactEmail: validateEmail(form.contactEmail),\n };\n const formIsValid = isClean(formErrors);\n\n async function save() {\n if (!formIsValid) {\n fieldErrors.markAllTouched();\n setError('Please fix the highlighted fields.');\n return;\n }\n try {\n await upsertBrand({\n id: form.id,\n name: form.name.trim(),\n manufacturerCode: form.manufacturerCode.trim().toUpperCase(),\n contactInfo: serializeContactInfo({\n phone: form.contactPhone,\n email: form.contactEmail,\n }),\n isActive: form.isActive,\n });\n showToast({ message: 'Brand saved.', type: 'success' });\n setOpenDialog(false);\n await load();\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to save brand';\n setError(message);\n showToast({ message, type: 'error' });\n }\n }\n\n const visible = showInactive ? items : items.filter((b) => b.isActive !== false);\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.brand'}>\n <PmPageShell\n title=\"Brands\"\n subtitle=\"The manufacturer or supplier of each product.\"\n chips={['Catalog']}\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\" startIcon={<RefreshRoundedIcon />} onClick={() => void load()}>Refresh</Button>\n {canWrite ? (\n <Button variant=\"contained\" startIcon={<AddRoundedIcon />} onClick={openCreate}>New Brand</Button>\n ) : null}\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n <PmTableCard\n eyebrow=\"Master data\"\n title=\"Brands\"\n subtitle={loading ? 'Loading…' : `${visible.length} ${visible.length === 1 ? 'brand' : 'brands'}`}\n actions={\n <FormControlLabel\n control={<CustomSwitch checked={showInactive}\n onChange={(e) => setShowInactive(e.target.checked)} />}\n label={<Typography variant=\"body2\" sx={{ fontWeight: 600 }}>Show inactive</Typography>}\n labelPlacement=\"start\"\n sx={{ mr: 0.5, ml: 0 }}\n />\n }\n >\n <PmTable>\n <TableHead>\n <TableRow>\n <TableCell>Name</TableCell>\n <TableCell>Manufacturer Code</TableCell>\n <TableCell>Contact</TableCell>\n <TableCell>Status</TableCell>\n <TableCell align=\"right\">Action</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: 4 }).map((_, i) => (\n <TableRow key={i}>\n {Array.from({ length: 5 }).map((__, j) => (\n <TableCell key={j}><Skeleton height={22} /></TableCell>\n ))}\n </TableRow>\n ))\n ) : visible.length === 0 ? (\n <PmEmptyRow\n colSpan={5}\n icon={SellRoundedIcon}\n title={items.length === 0 ? 'No brands yet' : 'No active brands'}\n hint={items.length === 0\n ? 'Add manufacturers so you can link them to your products.'\n : 'Turn on “Show inactive” to see deactivated brands.'}\n action={items.length === 0 && canWrite ? (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={openCreate}>\n Create first brand\n </Button>\n ) : null}\n />\n ) : visible.map((b) => {\n const { phone, email } = parseContactInfo(b.contactInfo);\n return (\n <TableRow key={b.id} hover>\n <TableCell sx={{ maxWidth: 240 }}>\n <Typography variant=\"body2\" sx={{ fontWeight: 700, wordBreak: 'break-word' }}>{b.name}</Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 160 }}>\n <Box component=\"span\" sx={{\n display: 'inline-block', px: 0.85, py: 0.25, borderRadius: 1,\n bgcolor: 'grey.100', fontFamily: 'monospace', fontSize: '0.72rem', fontWeight: 800,\n maxWidth: '100%', wordBreak: 'break-all',\n }}>\n {b.manufacturerCode}\n </Box>\n </TableCell>\n <TableCell>\n {phone || email ? (\n <Stack spacing={0.25}>\n {phone ? <Typography variant=\"caption\" sx={{ fontWeight: 600 }}>{phone}</Typography> : null}\n {email ? <Typography variant=\"caption\" color=\"text.secondary\">{email}</Typography> : null}\n </Stack>\n ) : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={b.isActive ? 'Active' : 'Inactive'}\n color={b.isActive ? 'success' : 'default'}\n variant={b.isActive ? 'filled' : 'outlined'}\n sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }}\n />\n </TableCell>\n <TableCell align=\"right\">\n {canWrite ? (\n <Button size=\"small\" variant=\"outlined\" onClick={() => openEdit(b)}>Edit</Button>\n ) : null}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n\n <Dialog open={openDialog} onClose={() => setOpenDialog(false)} fullWidth maxWidth=\"sm\">\n <DialogTitle>{editing ? 'Edit Brand' : 'New Brand'}</DialogTitle>\n <DialogContent dividers>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <TextField\n required\n label=\"Name\" size=\"small\" fullWidth\n value={form.name}\n inputProps={{ maxLength: 255 }}\n onChange={(e) => {\n const nextName = e.target.value;\n // Auto-derive manufacturer code from initials of every word — but\n // only on create (when editing an existing brand we never overwrite\n // a code the user has already curated).\n const initialsFromName = nextName\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => w[0])\n .join('')\n .toUpperCase();\n setForm((f) => ({\n ...f,\n name: nextName,\n manufacturerCode: editing ? f.manufacturerCode : initialsFromName,\n }));\n }}\n onBlur={fieldErrors.onBlur('name')}\n error={fieldErrors.show('name') && !!formErrors.name}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message={fieldErrors.show('name') ? formErrors.name : ''} value={form.name} max={255} />}\n />\n <TextField\n required\n label=\"Manufacturer code\" size=\"small\" fullWidth\n value={form.manufacturerCode}\n inputProps={{ maxLength: 100 }}\n onChange={(e) => setForm({ ...form, manufacturerCode: e.target.value.toUpperCase() })}\n onBlur={fieldErrors.onBlur('manufacturerCode')}\n error={fieldErrors.show('manufacturerCode') && !!formErrors.manufacturerCode}\n FormHelperTextProps={{ component: 'div' }}\n helperText={\n <PmFieldHelp\n message={fieldErrors.show('manufacturerCode') && formErrors.manufacturerCode\n ? formErrors.manufacturerCode\n : 'Auto-generated from the name as initials. Edit if needed to make it unique.'}\n value={form.manufacturerCode}\n max={100}\n />\n }\n />\n <TextField\n label=\"Contact Number\"\n size=\"small\"\n fullWidth\n type=\"tel\"\n placeholder={country\n ? (country.phoneMin === country.phoneMax\n ? `${country.phoneMin}-digit local number`\n : `${country.phoneMin}–${country.phoneMax} digit local number`)\n : 'Local number'}\n value={form.contactPhone}\n // Keep only digits and spaces — the dial code lives in the\n // adornment, not in the value.\n onChange={(e) => setForm({ ...form, contactPhone: e.target.value.replace(/[^\\d\\s]/g, '') })}\n onBlur={fieldErrors.onBlur('contactPhone')}\n error={fieldErrors.show('contactPhone') && !!formErrors.contactPhone}\n helperText={\n fieldErrors.show('contactPhone') && formErrors.contactPhone\n ? formErrors.contactPhone\n : country\n ? `Format for ${country.name}: ${country.phoneCode} followed by ${country.phoneMin}${country.phoneMin === country.phoneMax ? '' : `–${country.phoneMax}`} digits.`\n : 'Local number, digits only.'\n }\n InputProps={country ? {\n startAdornment: (\n <InputAdornment position=\"start\">\n <Box component=\"span\" sx={{ fontWeight: 700, color: 'text.secondary' }}>{country.phoneCode}</Box>\n </InputAdornment>\n ),\n } : undefined}\n />\n <TextField\n label=\"Email\"\n size=\"small\"\n fullWidth\n type=\"email\"\n placeholder=\"e.g. contact@manufacturer.example\"\n value={form.contactEmail}\n onChange={(e) => setForm({ ...form, contactEmail: e.target.value })}\n onBlur={fieldErrors.onBlur('contactEmail')}\n error={fieldErrors.show('contactEmail') && !!formErrors.contactEmail}\n helperText={fieldErrors.show('contactEmail') ? formErrors.contactEmail : ''}\n />\n <FormControlLabel\n control={<Checkbox checked={form.isActive}\n onChange={(e) => setForm({ ...form, isActive: e.target.checked })} />}\n label=\"Active\" />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setOpenDialog(false)}>Cancel</Button>\n <Button variant=\"contained\" disabled={!formIsValid} onClick={() => void save()}>Save</Button>\n </DialogActions>\n </Dialog>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BrandsPage-DBFBor6L.js","names":[],"sources":["../src/views/BrandsPage.jsx"],"sourcesContent":["import { useState } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Box,\n Button,\n Checkbox,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n InputAdornment,\n Skeleton,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material';\nimport AddRoundedIcon from '@mui/icons-material/AddRounded';\nimport RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';\nimport SellRoundedIcon from '@mui/icons-material/SellRounded';\nimport { showToast } from '@pm/utils/pmToast';\nimport CustomSwitch from '@/views/custom-components/CustomSwitch';\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 { PmEmptyRow, PmFieldHelp, PmTable, PmTableCard } from '@pm/components/PmTable';\nimport { getBrands, upsertBrand } from '@pm/services/pmApi';\nimport { isClean, validateEmail, validateRequired } from '@pm/utils/validation';\nimport { findCountry, validatePhoneForCountry } from '@/common/constants/countries';\nimport { usePmSettings } from '@pm/utils/settingsStore';\nimport { useFieldErrors } from '@pm/utils/useFieldErrors';\n\n// Backend stores contact_info as a JSON-encoded string. We keep the discrete\n// fields here so the UI is form-friendly, and only ever round-trip the JSON.\nfunction parseContactInfo(raw) {\n if (!raw) return { phone: '', email: '' };\n try {\n const obj = JSON.parse(raw);\n return {\n phone: typeof obj?.phone === 'string' ? obj.phone : '',\n email: typeof obj?.email === 'string' ? obj.email : '',\n };\n } catch {\n return { phone: '', email: '' };\n }\n}\n\nfunction serializeContactInfo({ phone, email }) {\n const out = {};\n if (phone?.trim()) out.phone = phone.trim();\n if (email?.trim()) out.email = email.trim();\n return Object.keys(out).length ? JSON.stringify(out) : null;\n}\n\nexport default function BrandsPage() {\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.brand');\n const settings = usePmSettings();\n const country = findCountry(settings?.countryCode);\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [openDialog, setOpenDialog] = useState(false);\n const [editing, setEditing] = useState(null);\n // Default to active-only; the toggle above the table reveals inactive rows.\n const [showInactive, setShowInactive] = useState(false);\n const [form, setForm] = useState(emptyForm());\n const fieldErrors = useFieldErrors();\n\n function emptyForm() {\n return {\n id: '',\n name: '',\n manufacturerCode: '',\n contactPhone: '',\n contactEmail: '',\n isActive: true,\n };\n }\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n const data = await getBrands(undefined, true);\n setItems(data);\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load brands';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.brand', () => {\n void load();\n }, []);\n\n function openCreate() {\n setEditing(null);\n setForm({ ...emptyForm(), id: uuidv4() });\n fieldErrors.reset();\n setError('');\n setOpenDialog(true);\n }\n\n function openEdit(item) {\n const { phone, email } = parseContactInfo(item.contactInfo);\n setEditing(item);\n fieldErrors.reset();\n setError('');\n setForm({\n id: item.id,\n name: item.name ?? '',\n manufacturerCode: item.manufacturerCode ?? '',\n contactPhone: phone,\n contactEmail: email,\n isActive: item.isActive !== false,\n });\n setOpenDialog(true);\n }\n\n const mfrCodeBase = validateRequired(form.manufacturerCode, 'Manufacturer code');\n const mfrNorm = form.manufacturerCode.trim().toUpperCase();\n const mfrClash = !mfrCodeBase\n && mfrNorm\n && items.some((b) => b.id !== form.id && (b.manufacturerCode || '').toUpperCase() === mfrNorm);\n const formErrors = {\n name: validateRequired(form.name, 'Name'),\n manufacturerCode: mfrCodeBase || (mfrClash ? 'Code is already in use — edit it manually to make it unique.' : ''),\n contactPhone: validatePhoneForCountry(form.contactPhone, country),\n contactEmail: validateEmail(form.contactEmail),\n };\n const formIsValid = isClean(formErrors);\n\n async function save() {\n if (!formIsValid) {\n fieldErrors.markAllTouched();\n setError('Please fix the highlighted fields.');\n return;\n }\n try {\n await upsertBrand({\n id: form.id,\n name: form.name.trim(),\n manufacturerCode: form.manufacturerCode.trim().toUpperCase(),\n contactInfo: serializeContactInfo({\n phone: form.contactPhone,\n email: form.contactEmail,\n }),\n isActive: form.isActive,\n });\n showToast({ message: 'Brand saved.', type: 'success' });\n setOpenDialog(false);\n await load();\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to save brand';\n setError(message);\n showToast({ message, type: 'error' });\n }\n }\n\n const visible = showInactive ? items : items.filter((b) => b.isActive !== false);\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.brand'}>\n <PmPageShell\n title=\"Brands\"\n subtitle=\"The manufacturer or supplier of each product.\"\n chips={['Catalog']}\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\" startIcon={<RefreshRoundedIcon />} onClick={() => void load()}>Refresh</Button>\n {canWrite ? (\n <Button variant=\"contained\" startIcon={<AddRoundedIcon />} onClick={openCreate}>New Brand</Button>\n ) : null}\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n <PmTableCard\n eyebrow=\"Master data\"\n title=\"Brands\"\n subtitle={loading ? 'Loading…' : `${visible.length} ${visible.length === 1 ? 'brand' : 'brands'}`}\n actions={\n <FormControlLabel\n control={<CustomSwitch checked={showInactive}\n onChange={(e) => setShowInactive(e.target.checked)} />}\n label={<Typography variant=\"body2\" sx={{ fontWeight: 600 }}>Show inactive</Typography>}\n labelPlacement=\"start\"\n sx={{ mr: 0.5, ml: 0 }}\n />\n }\n >\n <PmTable>\n <TableHead>\n <TableRow>\n <TableCell>Name</TableCell>\n <TableCell>Manufacturer Code</TableCell>\n <TableCell>Contact</TableCell>\n <TableCell>Status</TableCell>\n <TableCell align=\"right\">Action</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: 4 }).map((_, i) => (\n <TableRow key={i}>\n {Array.from({ length: 5 }).map((__, j) => (\n <TableCell key={j}><Skeleton height={22} /></TableCell>\n ))}\n </TableRow>\n ))\n ) : visible.length === 0 ? (\n <PmEmptyRow\n colSpan={5}\n icon={SellRoundedIcon}\n title={items.length === 0 ? 'No brands yet' : 'No active brands'}\n hint={items.length === 0\n ? 'Add manufacturers so you can link them to your products.'\n : 'Turn on “Show inactive” to see deactivated brands.'}\n action={items.length === 0 && canWrite ? (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={openCreate}>\n Create first brand\n </Button>\n ) : null}\n />\n ) : visible.map((b) => {\n const { phone, email } = parseContactInfo(b.contactInfo);\n return (\n <TableRow key={b.id} hover>\n <TableCell sx={{ maxWidth: 240 }}>\n <Typography variant=\"body2\" sx={{ fontWeight: 700, wordBreak: 'break-word' }}>{b.name}</Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 160 }}>\n <Box component=\"span\" sx={{\n display: 'inline-block', px: 0.85, py: 0.25, borderRadius: 1,\n bgcolor: 'grey.100', fontFamily: 'monospace', fontSize: '0.72rem', fontWeight: 800,\n maxWidth: '100%', wordBreak: 'break-all',\n }}>\n {b.manufacturerCode}\n </Box>\n </TableCell>\n <TableCell>\n {phone || email ? (\n <Stack spacing={0.25}>\n {phone ? <Typography variant=\"caption\" sx={{ fontWeight: 600 }}>{phone}</Typography> : null}\n {email ? <Typography variant=\"caption\" color=\"text.secondary\">{email}</Typography> : null}\n </Stack>\n ) : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={b.isActive ? 'Active' : 'Inactive'}\n color={b.isActive ? 'success' : 'default'}\n variant={b.isActive ? 'filled' : 'outlined'}\n sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }}\n />\n </TableCell>\n <TableCell align=\"right\">\n {canWrite ? (\n <Button size=\"small\" variant=\"outlined\" onClick={() => openEdit(b)}>Edit</Button>\n ) : null}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n\n <Dialog open={openDialog} onClose={() => setOpenDialog(false)} fullWidth maxWidth=\"sm\">\n <DialogTitle>{editing ? 'Edit Brand' : 'New Brand'}</DialogTitle>\n <DialogContent dividers>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <TextField\n required\n label=\"Name\" size=\"small\" fullWidth\n value={form.name}\n inputProps={{ maxLength: 255 }}\n onChange={(e) => {\n const nextName = e.target.value;\n // Auto-derive manufacturer code from initials of every word — but\n // only on create (when editing an existing brand we never overwrite\n // a code the user has already curated).\n const initialsFromName = nextName\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => w[0])\n .join('')\n .toUpperCase();\n setForm((f) => ({\n ...f,\n name: nextName,\n manufacturerCode: editing ? f.manufacturerCode : initialsFromName,\n }));\n }}\n onBlur={fieldErrors.onBlur('name')}\n error={fieldErrors.show('name') && !!formErrors.name}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message={fieldErrors.show('name') ? formErrors.name : ''} value={form.name} max={255} />}\n />\n <TextField\n required\n label=\"Manufacturer code\" size=\"small\" fullWidth\n value={form.manufacturerCode}\n inputProps={{ maxLength: 100 }}\n onChange={(e) => setForm({ ...form, manufacturerCode: e.target.value.toUpperCase() })}\n onBlur={fieldErrors.onBlur('manufacturerCode')}\n error={fieldErrors.show('manufacturerCode') && !!formErrors.manufacturerCode}\n FormHelperTextProps={{ component: 'div' }}\n helperText={\n <PmFieldHelp\n message={fieldErrors.show('manufacturerCode') && formErrors.manufacturerCode\n ? formErrors.manufacturerCode\n : 'Auto-generated from the name as initials. Edit if needed to make it unique.'}\n value={form.manufacturerCode}\n max={100}\n />\n }\n />\n <TextField\n label=\"Contact Number\"\n size=\"small\"\n fullWidth\n type=\"tel\"\n placeholder={country\n ? (country.phoneMin === country.phoneMax\n ? `${country.phoneMin}-digit local number`\n : `${country.phoneMin}–${country.phoneMax} digit local number`)\n : 'Local number'}\n value={form.contactPhone}\n // Keep only digits and spaces — the dial code lives in the\n // adornment, not in the value.\n onChange={(e) => setForm({ ...form, contactPhone: e.target.value.replace(/[^\\d\\s]/g, '') })}\n onBlur={fieldErrors.onBlur('contactPhone')}\n error={fieldErrors.show('contactPhone') && !!formErrors.contactPhone}\n helperText={\n fieldErrors.show('contactPhone') && formErrors.contactPhone\n ? formErrors.contactPhone\n : country\n ? `Format for ${country.name}: ${country.phoneCode} followed by ${country.phoneMin}${country.phoneMin === country.phoneMax ? '' : `–${country.phoneMax}`} digits.`\n : 'Local number, digits only.'\n }\n InputProps={country ? {\n startAdornment: (\n <InputAdornment position=\"start\">\n <Box component=\"span\" sx={{ fontWeight: 700, color: 'text.secondary' }}>{country.phoneCode}</Box>\n </InputAdornment>\n ),\n } : undefined}\n />\n <TextField\n label=\"Email\"\n size=\"small\"\n fullWidth\n type=\"email\"\n placeholder=\"e.g. contact@manufacturer.example\"\n value={form.contactEmail}\n onChange={(e) => setForm({ ...form, contactEmail: e.target.value })}\n onBlur={fieldErrors.onBlur('contactEmail')}\n error={fieldErrors.show('contactEmail') && !!formErrors.contactEmail}\n helperText={fieldErrors.show('contactEmail') ? formErrors.contactEmail : ''}\n />\n <FormControlLabel\n control={<Checkbox checked={form.isActive}\n onChange={(e) => setForm({ ...form, isActive: e.target.checked })} />}\n label=\"Active\" />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setOpenDialog(false)}>Cancel</Button>\n <Button variant=\"contained\" disabled={!formIsValid} onClick={() => void save()}>Save</Button>\n </DialogActions>\n </Dialog>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}