@argusoft/medplat-product-management 1.0.7 → 1.0.8
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-CdqGFmGf.js → BrandsPage-DmRW5bhm.js} +77 -78
- package/dist/{BrandsPage-CdqGFmGf.js.map → BrandsPage-DmRW5bhm.js.map} +1 -1
- package/dist/{CategoriesPage-DJM0Nalw.js → CategoriesPage-BsS5IQh3.js} +6 -7
- package/dist/{CategoriesPage-DJM0Nalw.js.map → CategoriesPage-BsS5IQh3.js.map} +1 -1
- package/dist/{DashboardPage-BASkXr00.js → DashboardPage-C3bKc5na.js} +3 -3
- package/dist/{DashboardPage-BASkXr00.js.map → DashboardPage-C3bKc5na.js.map} +1 -1
- package/dist/{FacilityPicker-jV-qXp1k.js → FacilityPicker-BiZeupmP.js} +6 -8
- package/dist/{FacilityPicker-jV-qXp1k.js.map → FacilityPicker-BiZeupmP.js.map} +1 -1
- package/dist/{InventoryPage-CTdq6txa.js → InventoryPage-C_AxSy7A.js} +9 -12
- package/dist/{InventoryPage-CTdq6txa.js.map → InventoryPage-C_AxSy7A.js.map} +1 -1
- package/dist/{MemberProfileCard-DwWda-tS.js → MemberProfileCard-BdUNgHRB.js} +3 -3
- package/dist/{MemberProfileCard-DwWda-tS.js.map → MemberProfileCard-BdUNgHRB.js.map} +1 -1
- package/dist/{PaymentCreatePage-B3bP-K01.js → PaymentCreatePage-CIVe0P0p.js} +114 -114
- package/dist/{PaymentCreatePage-B3bP-K01.js.map → PaymentCreatePage-CIVe0P0p.js.map} +1 -1
- package/dist/{PaymentsPage-Dh8bqXVE.js → PaymentsPage-BvPe5Q9F.js} +4 -4
- package/dist/{PaymentsPage-Dh8bqXVE.js.map → PaymentsPage-BvPe5Q9F.js.map} +1 -1
- package/dist/{PickupBatchLinesEditor-B2fLx1lU.js → PickupBatchLinesEditor-DHmcAG23.js} +2 -2
- package/dist/{PickupBatchLinesEditor-B2fLx1lU.js.map → PickupBatchLinesEditor-DHmcAG23.js.map} +1 -1
- package/dist/{PickupCreatePage-BeYhR45k.js → PickupCreatePage-CB0Sl0Hb.js} +58 -58
- package/dist/PickupCreatePage-CB0Sl0Hb.js.map +1 -0
- package/dist/{PickupsPage-C6lBtAoQ.js → PickupsPage-Ctpghavs.js} +7 -9
- package/dist/{PickupsPage-C6lBtAoQ.js.map → PickupsPage-Ctpghavs.js.map} +1 -1
- package/dist/{PmGuard-DrIl1sHL.js → PmGuard-b10TGXEi.js} +3 -3
- package/dist/{PmGuard-DrIl1sHL.js.map → PmGuard-b10TGXEi.js.map} +1 -1
- package/dist/{PmTable-BSV_bMJZ.js → PmTable-_GbScaa4.js} +3 -4
- package/dist/{PmTable-BSV_bMJZ.js.map → PmTable-_GbScaa4.js.map} +1 -1
- package/dist/{ProductEditPage-DZTUH95T.js → ProductEditPage-C1thoKHu.js} +8 -9
- package/dist/{ProductEditPage-DZTUH95T.js.map → ProductEditPage-C1thoKHu.js.map} +1 -1
- package/dist/{ProductsPage-CqOsah4_.js → ProductsPage-CupVmOD4.js} +4 -4
- package/dist/{ProductsPage-CqOsah4_.js.map → ProductsPage-CupVmOD4.js.map} +1 -1
- package/dist/{PurchaseCreatePage-D6os7srp.js → PurchaseCreatePage-YD3NmhPQ.js} +6 -6
- package/dist/{PurchaseCreatePage-D6os7srp.js.map → PurchaseCreatePage-YD3NmhPQ.js.map} +1 -1
- package/dist/{PurchaseRequestDetailPage-DErqGKiq.js → PurchaseRequestDetailPage-Dg_MRY_N.js} +6 -7
- package/dist/{PurchaseRequestDetailPage-DErqGKiq.js.map → PurchaseRequestDetailPage-Dg_MRY_N.js.map} +1 -1
- package/dist/{PurchaseRequestsPage-CHBoRzzH.js → PurchaseRequestsPage-DPAPzpmm.js} +4 -4
- package/dist/{PurchaseRequestsPage-CHBoRzzH.js.map → PurchaseRequestsPage-DPAPzpmm.js.map} +1 -1
- package/dist/{PurchasesPage-C-2K7wH6.js → PurchasesPage-It1GHiXl.js} +4 -4
- package/dist/{PurchasesPage-C-2K7wH6.js.map → PurchasesPage-It1GHiXl.js.map} +1 -1
- package/dist/{SaleCreatePage-DB3_UEgy.js → SaleCreatePage-C9kFmTvm.js} +20 -20
- package/dist/{SaleCreatePage-DB3_UEgy.js.map → SaleCreatePage-C9kFmTvm.js.map} +1 -1
- package/dist/{SalesPage-BhBGG426.js → SalesPage-D18DCseD.js} +74 -74
- package/dist/{SalesPage-BhBGG426.js.map → SalesPage-D18DCseD.js.map} +1 -1
- package/dist/{SettingsPage-CBUu9DZK.js → SettingsPage-VsxI-ano.js} +4 -4
- package/dist/{SettingsPage-CBUu9DZK.js.map → SettingsPage-VsxI-ano.js.map} +1 -1
- package/dist/{StorageUnitsPage-oe0lXLd1.js → StorageUnitsPage-7EqwuMOI.js} +7 -8
- package/dist/{StorageUnitsPage-oe0lXLd1.js.map → StorageUnitsPage-7EqwuMOI.js.map} +1 -1
- package/dist/{TransactionsPage-7dRZpZOD.js → TransactionsPage-DrH53pVS.js} +4 -4
- package/dist/{TransactionsPage-7dRZpZOD.js.map → TransactionsPage-DrH53pVS.js.map} +1 -1
- package/dist/{TransferCreatePage-DtkAlP9l.js → TransferCreatePage-CuvoMrYH.js} +4 -4
- package/dist/{TransferCreatePage-DtkAlP9l.js.map → TransferCreatePage-CuvoMrYH.js.map} +1 -1
- package/dist/{TransfersPage-BaEjbvnj.js → TransfersPage-Cf701t8s.js} +4 -4
- package/dist/{TransfersPage-BaEjbvnj.js.map → TransfersPage-Cf701t8s.js.map} +1 -1
- package/dist/{VialsPage-vo9Of9oC.js → VialsPage-8oAc1yFv.js} +5 -5
- package/dist/{VialsPage-vo9Of9oC.js.map → VialsPage-8oAc1yFv.js.map} +1 -1
- package/dist/constants-ClZJY2x1.js.map +1 -1
- package/dist/format-UOyOu75i.js.map +1 -1
- package/dist/index.js +253 -240
- package/dist/index.js.map +1 -1
- package/dist/{settingsStore-BlA2GIhl.js → settingsStore-BifOsjlB.js} +2 -2
- package/dist/{settingsStore-BlA2GIhl.js.map → settingsStore-BifOsjlB.js.map} +1 -1
- package/dist/{validation-B6Kl5Xf9.js → validation-BzlHnL-r.js} +16 -15
- package/dist/{validation-B6Kl5Xf9.js.map → validation-BzlHnL-r.js.map} +1 -1
- package/package.json +1 -1
- package/dist/PickupCreatePage-BeYhR45k.js.map +0 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { g as e, ot as t, r as n } from "./settingsStore-
|
|
2
|
-
import { c as ee, l as r, n as i, s as te, t as
|
|
3
|
-
import { i as
|
|
4
|
-
import { t as
|
|
5
|
-
import { a as
|
|
1
|
+
import { g as e, ot as t, r as n } from "./settingsStore-BifOsjlB.js";
|
|
2
|
+
import { c as ee, l as r, n as i, s as te, t as ne } from "./PmTable-_GbScaa4.js";
|
|
3
|
+
import { i as re, m as a, t as o } from "./validation-BzlHnL-r.js";
|
|
4
|
+
import { t as ie } from "./useFieldErrors-hDG8ox_x.js";
|
|
5
|
+
import { a as ae, i as oe, n as s, r as c, t as l } from "./PmGuard-b10TGXEi.js";
|
|
6
6
|
import { useState as u } from "react";
|
|
7
7
|
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
8
|
-
import { Alert as se, Box as p, Button as m, Checkbox as
|
|
9
|
-
import { findCountry as
|
|
10
|
-
import { v4 as
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
8
|
+
import { Alert as se, Box as p, Button as m, Checkbox as ce, Chip as le, Dialog as ue, DialogActions as h, DialogContent as de, DialogTitle as g, FormControlLabel as _, InputAdornment as fe, Skeleton as v, Stack as y, TableBody as b, TableCell as x, TableHead as pe, TableRow as S, TextField as C, Typography as w } from "@mui/material";
|
|
9
|
+
import { findCountry as me, validatePhoneForCountry as he } from "@/common/constants/countries";
|
|
10
|
+
import { v4 as ge } from "uuid";
|
|
11
|
+
import T from "@mui/icons-material/AddRounded";
|
|
12
|
+
import E from "@mui/icons-material/RefreshRounded";
|
|
13
|
+
import D from "@mui/icons-material/SellRounded";
|
|
14
|
+
import O from "@/views/custom-components/CustomSwitch";
|
|
15
15
|
//#region src/views/BrandsPage.jsx
|
|
16
|
-
function
|
|
16
|
+
function k(e) {
|
|
17
17
|
if (!e) return {
|
|
18
18
|
phone: "",
|
|
19
19
|
email: ""
|
|
@@ -31,12 +31,12 @@ function O(e) {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function A({ phone: e, email: t }) {
|
|
35
35
|
let n = {};
|
|
36
36
|
return e?.trim() && (n.phone = e.trim()), t?.trim() && (n.email = t.trim()), Object.keys(n).length ? JSON.stringify(n) : null;
|
|
37
37
|
}
|
|
38
|
-
function
|
|
39
|
-
let
|
|
38
|
+
function j() {
|
|
39
|
+
let j = oe().has("update.manage.productManagement.brand"), M = me(n()?.countryCode), [N, P] = u([]), [F, I] = u(!1), [L, R] = u(""), [_e, z] = u(!1), [B, V] = u(null), [H, ve] = u(!1), [U, W] = u(K()), G = ie();
|
|
40
40
|
function K() {
|
|
41
41
|
return {
|
|
42
42
|
id: "",
|
|
@@ -50,8 +50,7 @@ function A() {
|
|
|
50
50
|
async function q() {
|
|
51
51
|
I(!0), R("");
|
|
52
52
|
try {
|
|
53
|
-
|
|
54
|
-
P(t);
|
|
53
|
+
P(await e(void 0, !0));
|
|
55
54
|
} catch (e) {
|
|
56
55
|
let t = e?.response?.data?.message ?? e?.message ?? "Failed to load brands";
|
|
57
56
|
R(t), r({
|
|
@@ -62,17 +61,17 @@ function A() {
|
|
|
62
61
|
I(!1);
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
|
-
|
|
64
|
+
c("view.manage.productManagement.brand", () => {
|
|
66
65
|
q();
|
|
67
66
|
}, []);
|
|
68
67
|
function J() {
|
|
69
68
|
V(null), W({
|
|
70
69
|
...K(),
|
|
71
|
-
id:
|
|
70
|
+
id: ge()
|
|
72
71
|
}), G.reset(), R(""), z(!0);
|
|
73
72
|
}
|
|
74
|
-
function
|
|
75
|
-
let { phone: t, email: n } =
|
|
73
|
+
function ye(e) {
|
|
74
|
+
let { phone: t, email: n } = k(e.contactInfo);
|
|
76
75
|
V(e), G.reset(), R(""), W({
|
|
77
76
|
id: e.id,
|
|
78
77
|
name: e.name ?? "",
|
|
@@ -82,13 +81,13 @@ function A() {
|
|
|
82
81
|
isActive: e.isActive !== !1
|
|
83
82
|
}), z(!0);
|
|
84
83
|
}
|
|
85
|
-
let Y =
|
|
86
|
-
name:
|
|
87
|
-
manufacturerCode: Y || (
|
|
88
|
-
contactPhone:
|
|
89
|
-
contactEmail:
|
|
90
|
-
}, Q =
|
|
91
|
-
async function
|
|
84
|
+
let Y = a(U.manufacturerCode, "Manufacturer code"), X = U.manufacturerCode.trim().toUpperCase(), be = !Y && X && N.some((e) => e.id !== U.id && (e.manufacturerCode || "").toUpperCase() === X), Z = {
|
|
85
|
+
name: a(U.name, "Name"),
|
|
86
|
+
manufacturerCode: Y || (be ? "Code is already in use — edit it manually to make it unique." : ""),
|
|
87
|
+
contactPhone: he(U.contactPhone, M),
|
|
88
|
+
contactEmail: re(U.contactEmail)
|
|
89
|
+
}, Q = o(Z);
|
|
90
|
+
async function xe() {
|
|
92
91
|
if (!Q) {
|
|
93
92
|
G.markAllTouched(), R("Please fix the highlighted fields.");
|
|
94
93
|
return;
|
|
@@ -98,7 +97,7 @@ function A() {
|
|
|
98
97
|
id: U.id,
|
|
99
98
|
name: U.name.trim(),
|
|
100
99
|
manufacturerCode: U.manufacturerCode.trim().toUpperCase(),
|
|
101
|
-
contactInfo:
|
|
100
|
+
contactInfo: A({
|
|
102
101
|
phone: U.contactPhone,
|
|
103
102
|
email: U.contactEmail
|
|
104
103
|
}),
|
|
@@ -116,23 +115,23 @@ function A() {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
let $ = H ? N : N.filter((e) => e.isActive !== !1);
|
|
119
|
-
return /* @__PURE__ */ f(p, { children: [/* @__PURE__ */ d(
|
|
118
|
+
return /* @__PURE__ */ f(p, { children: [/* @__PURE__ */ d(s, {}), /* @__PURE__ */ f(l, {
|
|
120
119
|
perm: "view.manage.productManagement.brand",
|
|
121
|
-
children: [/* @__PURE__ */ f(
|
|
120
|
+
children: [/* @__PURE__ */ f(ae, {
|
|
122
121
|
title: "Brands",
|
|
123
122
|
subtitle: "The manufacturer or supplier of each product.",
|
|
124
123
|
chips: ["Catalog"],
|
|
125
|
-
actions: /* @__PURE__ */ f(
|
|
124
|
+
actions: /* @__PURE__ */ f(y, {
|
|
126
125
|
direction: "row",
|
|
127
126
|
spacing: 1,
|
|
128
127
|
children: [/* @__PURE__ */ d(m, {
|
|
129
128
|
variant: "outlined",
|
|
130
|
-
startIcon: /* @__PURE__ */ d(
|
|
129
|
+
startIcon: /* @__PURE__ */ d(E, {}),
|
|
131
130
|
onClick: () => void q(),
|
|
132
131
|
children: "Refresh"
|
|
133
|
-
}),
|
|
132
|
+
}), j ? /* @__PURE__ */ d(m, {
|
|
134
133
|
variant: "contained",
|
|
135
|
-
startIcon: /* @__PURE__ */ d(
|
|
134
|
+
startIcon: /* @__PURE__ */ d(T, {}),
|
|
136
135
|
onClick: J,
|
|
137
136
|
children: "New Brand"
|
|
138
137
|
}) : null]
|
|
@@ -145,12 +144,12 @@ function A() {
|
|
|
145
144
|
eyebrow: "Master data",
|
|
146
145
|
title: "Brands",
|
|
147
146
|
subtitle: F ? "Loading…" : `${$.length} ${$.length === 1 ? "brand" : "brands"}`,
|
|
148
|
-
actions: /* @__PURE__ */ d(
|
|
149
|
-
control: /* @__PURE__ */ d(
|
|
147
|
+
actions: /* @__PURE__ */ d(_, {
|
|
148
|
+
control: /* @__PURE__ */ d(O, {
|
|
150
149
|
checked: H,
|
|
151
|
-
onChange: (e) =>
|
|
150
|
+
onChange: (e) => ve(e.target.checked)
|
|
152
151
|
}),
|
|
153
|
-
label: /* @__PURE__ */ d(
|
|
152
|
+
label: /* @__PURE__ */ d(w, {
|
|
154
153
|
variant: "body2",
|
|
155
154
|
sx: { fontWeight: 600 },
|
|
156
155
|
children: "Show inactive"
|
|
@@ -161,35 +160,35 @@ function A() {
|
|
|
161
160
|
ml: 0
|
|
162
161
|
}
|
|
163
162
|
}),
|
|
164
|
-
children: /* @__PURE__ */ f(te, { children: [/* @__PURE__ */ d(
|
|
165
|
-
/* @__PURE__ */ d(
|
|
166
|
-
/* @__PURE__ */ d(
|
|
167
|
-
/* @__PURE__ */ d(
|
|
168
|
-
/* @__PURE__ */ d(
|
|
169
|
-
/* @__PURE__ */ d(
|
|
163
|
+
children: /* @__PURE__ */ f(te, { children: [/* @__PURE__ */ d(pe, { children: /* @__PURE__ */ f(S, { children: [
|
|
164
|
+
/* @__PURE__ */ d(x, { children: "Name" }),
|
|
165
|
+
/* @__PURE__ */ d(x, { children: "Manufacturer Code" }),
|
|
166
|
+
/* @__PURE__ */ d(x, { children: "Contact" }),
|
|
167
|
+
/* @__PURE__ */ d(x, { children: "Status" }),
|
|
168
|
+
/* @__PURE__ */ d(x, {
|
|
170
169
|
align: "right",
|
|
171
170
|
children: "Action"
|
|
172
171
|
})
|
|
173
|
-
] }) }), /* @__PURE__ */ d(
|
|
172
|
+
] }) }), /* @__PURE__ */ d(b, { children: F ? Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */ d(S, { children: Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ d(x, { children: /* @__PURE__ */ d(v, { height: 22 }) }, t)) }, t)) : $.length === 0 ? /* @__PURE__ */ d(ne, {
|
|
174
173
|
colSpan: 5,
|
|
175
|
-
icon:
|
|
174
|
+
icon: D,
|
|
176
175
|
title: N.length === 0 ? "No brands yet" : "No active brands",
|
|
177
176
|
hint: N.length === 0 ? "Add manufacturers so you can link them to your products." : "Turn on “Show inactive” to see deactivated brands.",
|
|
178
|
-
action: N.length === 0 &&
|
|
177
|
+
action: N.length === 0 && j ? /* @__PURE__ */ d(m, {
|
|
179
178
|
variant: "contained",
|
|
180
179
|
size: "small",
|
|
181
|
-
startIcon: /* @__PURE__ */ d(
|
|
180
|
+
startIcon: /* @__PURE__ */ d(T, {}),
|
|
182
181
|
onClick: J,
|
|
183
182
|
children: "Create first brand"
|
|
184
183
|
}) : null
|
|
185
184
|
}) : $.map((e) => {
|
|
186
|
-
let { phone: t, email: n } =
|
|
187
|
-
return /* @__PURE__ */ f(
|
|
185
|
+
let { phone: t, email: n } = k(e.contactInfo);
|
|
186
|
+
return /* @__PURE__ */ f(S, {
|
|
188
187
|
hover: !0,
|
|
189
188
|
children: [
|
|
190
|
-
/* @__PURE__ */ d(
|
|
189
|
+
/* @__PURE__ */ d(x, {
|
|
191
190
|
sx: { maxWidth: 240 },
|
|
192
|
-
children: /* @__PURE__ */ d(
|
|
191
|
+
children: /* @__PURE__ */ d(w, {
|
|
193
192
|
variant: "body2",
|
|
194
193
|
sx: {
|
|
195
194
|
fontWeight: 700,
|
|
@@ -198,7 +197,7 @@ function A() {
|
|
|
198
197
|
children: e.name
|
|
199
198
|
})
|
|
200
199
|
}),
|
|
201
|
-
/* @__PURE__ */ d(
|
|
200
|
+
/* @__PURE__ */ d(x, {
|
|
202
201
|
sx: { maxWidth: 160 },
|
|
203
202
|
children: /* @__PURE__ */ d(p, {
|
|
204
203
|
component: "span",
|
|
@@ -217,23 +216,23 @@ function A() {
|
|
|
217
216
|
children: e.manufacturerCode
|
|
218
217
|
})
|
|
219
218
|
}),
|
|
220
|
-
/* @__PURE__ */ d(
|
|
219
|
+
/* @__PURE__ */ d(x, { children: t || n ? /* @__PURE__ */ f(y, {
|
|
221
220
|
spacing: .25,
|
|
222
|
-
children: [t ? /* @__PURE__ */ d(
|
|
221
|
+
children: [t ? /* @__PURE__ */ d(w, {
|
|
223
222
|
variant: "caption",
|
|
224
223
|
sx: { fontWeight: 600 },
|
|
225
224
|
children: t
|
|
226
|
-
}) : null, n ? /* @__PURE__ */ d(
|
|
225
|
+
}) : null, n ? /* @__PURE__ */ d(w, {
|
|
227
226
|
variant: "caption",
|
|
228
227
|
color: "text.secondary",
|
|
229
228
|
children: n
|
|
230
229
|
}) : null]
|
|
231
|
-
}) : /* @__PURE__ */ d(
|
|
230
|
+
}) : /* @__PURE__ */ d(w, {
|
|
232
231
|
variant: "caption",
|
|
233
232
|
color: "text.disabled",
|
|
234
233
|
children: "—"
|
|
235
234
|
}) }),
|
|
236
|
-
/* @__PURE__ */ d(
|
|
235
|
+
/* @__PURE__ */ d(x, { children: /* @__PURE__ */ d(le, {
|
|
237
236
|
size: "small",
|
|
238
237
|
label: e.isActive ? "Active" : "Inactive",
|
|
239
238
|
color: e.isActive ? "success" : "default",
|
|
@@ -244,12 +243,12 @@ function A() {
|
|
|
244
243
|
height: 22
|
|
245
244
|
}
|
|
246
245
|
}) }),
|
|
247
|
-
/* @__PURE__ */ d(
|
|
246
|
+
/* @__PURE__ */ d(x, {
|
|
248
247
|
align: "right",
|
|
249
|
-
children:
|
|
248
|
+
children: j ? /* @__PURE__ */ d(m, {
|
|
250
249
|
size: "small",
|
|
251
250
|
variant: "outlined",
|
|
252
|
-
onClick: () =>
|
|
251
|
+
onClick: () => ye(e),
|
|
253
252
|
children: "Edit"
|
|
254
253
|
}) : null
|
|
255
254
|
})
|
|
@@ -257,20 +256,20 @@ function A() {
|
|
|
257
256
|
}, e.id);
|
|
258
257
|
}) })] })
|
|
259
258
|
})]
|
|
260
|
-
}), /* @__PURE__ */ f(
|
|
261
|
-
open:
|
|
259
|
+
}), /* @__PURE__ */ f(ue, {
|
|
260
|
+
open: _e,
|
|
262
261
|
onClose: () => z(!1),
|
|
263
262
|
fullWidth: !0,
|
|
264
263
|
maxWidth: "sm",
|
|
265
264
|
children: [
|
|
266
|
-
/* @__PURE__ */ d(
|
|
265
|
+
/* @__PURE__ */ d(g, { children: B ? "Edit Brand" : "New Brand" }),
|
|
267
266
|
/* @__PURE__ */ d(de, {
|
|
268
267
|
dividers: !0,
|
|
269
|
-
children: /* @__PURE__ */ f(
|
|
268
|
+
children: /* @__PURE__ */ f(y, {
|
|
270
269
|
spacing: 2,
|
|
271
270
|
sx: { pt: 1 },
|
|
272
271
|
children: [
|
|
273
|
-
/* @__PURE__ */ d(
|
|
272
|
+
/* @__PURE__ */ d(C, {
|
|
274
273
|
required: !0,
|
|
275
274
|
label: "Name",
|
|
276
275
|
size: "small",
|
|
@@ -294,7 +293,7 @@ function A() {
|
|
|
294
293
|
max: 255
|
|
295
294
|
})
|
|
296
295
|
}),
|
|
297
|
-
/* @__PURE__ */ d(
|
|
296
|
+
/* @__PURE__ */ d(C, {
|
|
298
297
|
required: !0,
|
|
299
298
|
label: "Manufacturer code",
|
|
300
299
|
size: "small",
|
|
@@ -314,7 +313,7 @@ function A() {
|
|
|
314
313
|
max: 100
|
|
315
314
|
})
|
|
316
315
|
}),
|
|
317
|
-
/* @__PURE__ */ d(
|
|
316
|
+
/* @__PURE__ */ d(C, {
|
|
318
317
|
label: "Contact Number",
|
|
319
318
|
size: "small",
|
|
320
319
|
fullWidth: !0,
|
|
@@ -328,7 +327,7 @@ function A() {
|
|
|
328
327
|
onBlur: G.onBlur("contactPhone"),
|
|
329
328
|
error: G.show("contactPhone") && !!Z.contactPhone,
|
|
330
329
|
helperText: G.show("contactPhone") && Z.contactPhone ? Z.contactPhone : M ? `Format for ${M.name}: ${M.phoneCode} followed by ${M.phoneMin}${M.phoneMin === M.phoneMax ? "" : `–${M.phoneMax}`} digits.` : "Local number, digits only.",
|
|
331
|
-
InputProps: M ? { startAdornment: /* @__PURE__ */ d(
|
|
330
|
+
InputProps: M ? { startAdornment: /* @__PURE__ */ d(fe, {
|
|
332
331
|
position: "start",
|
|
333
332
|
children: /* @__PURE__ */ d(p, {
|
|
334
333
|
component: "span",
|
|
@@ -340,7 +339,7 @@ function A() {
|
|
|
340
339
|
})
|
|
341
340
|
}) } : void 0
|
|
342
341
|
}),
|
|
343
|
-
/* @__PURE__ */ d(
|
|
342
|
+
/* @__PURE__ */ d(C, {
|
|
344
343
|
label: "Email",
|
|
345
344
|
size: "small",
|
|
346
345
|
fullWidth: !0,
|
|
@@ -355,8 +354,8 @@ function A() {
|
|
|
355
354
|
error: G.show("contactEmail") && !!Z.contactEmail,
|
|
356
355
|
helperText: G.show("contactEmail") ? Z.contactEmail : ""
|
|
357
356
|
}),
|
|
358
|
-
/* @__PURE__ */ d(
|
|
359
|
-
control: /* @__PURE__ */ d(
|
|
357
|
+
/* @__PURE__ */ d(_, {
|
|
358
|
+
control: /* @__PURE__ */ d(ce, {
|
|
360
359
|
checked: U.isActive,
|
|
361
360
|
onChange: (e) => W({
|
|
362
361
|
...U,
|
|
@@ -368,13 +367,13 @@ function A() {
|
|
|
368
367
|
]
|
|
369
368
|
})
|
|
370
369
|
}),
|
|
371
|
-
/* @__PURE__ */ f(
|
|
370
|
+
/* @__PURE__ */ f(h, { children: [/* @__PURE__ */ d(m, {
|
|
372
371
|
onClick: () => z(!1),
|
|
373
372
|
children: "Cancel"
|
|
374
373
|
}), /* @__PURE__ */ d(m, {
|
|
375
374
|
variant: "contained",
|
|
376
375
|
disabled: !Q,
|
|
377
|
-
onClick: () => void
|
|
376
|
+
onClick: () => void xe(),
|
|
378
377
|
children: "Save"
|
|
379
378
|
})] })
|
|
380
379
|
]
|
|
@@ -382,6 +381,6 @@ function A() {
|
|
|
382
381
|
})] });
|
|
383
382
|
}
|
|
384
383
|
//#endregion
|
|
385
|
-
export {
|
|
384
|
+
export { j as default };
|
|
386
385
|
|
|
387
|
-
//# sourceMappingURL=BrandsPage-
|
|
386
|
+
//# sourceMappingURL=BrandsPage-DmRW5bhm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrandsPage-CdqGFmGf.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-DmRW5bhm.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,9 +1,9 @@
|
|
|
1
|
-
import { _ as e, st as t } from "./settingsStore-
|
|
2
|
-
import { c as ee, l as n, n as r, s as i, t as te } from "./PmTable-
|
|
1
|
+
import { _ as e, st as t } from "./settingsStore-BifOsjlB.js";
|
|
2
|
+
import { c as ee, l as n, n as r, s as i, t as te } from "./PmTable-_GbScaa4.js";
|
|
3
3
|
import { r as ne, x as a } from "./constants-ClZJY2x1.js";
|
|
4
|
-
import { m as re, r as o, t as s } from "./validation-
|
|
4
|
+
import { m as re, r as o, t as s } from "./validation-BzlHnL-r.js";
|
|
5
5
|
import { t as c } from "./useFieldErrors-hDG8ox_x.js";
|
|
6
|
-
import { a as l, i as ie, n as ae, r as oe, t as se } from "./PmGuard-
|
|
6
|
+
import { a as l, i as ie, n as ae, r as oe, t as se } from "./PmGuard-b10TGXEi.js";
|
|
7
7
|
import { useState as u } from "react";
|
|
8
8
|
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
9
9
|
import { Alert as ce, Autocomplete as le, Box as p, Button as m, Checkbox as ue, Chip as h, Dialog as g, DialogActions as _, DialogContent as v, DialogTitle as y, FormControlLabel as b, InputAdornment as de, Skeleton as fe, Stack as x, TableBody as pe, TableCell as S, TableHead as me, TableRow as C, TextField as w, Typography as T } from "@mui/material";
|
|
@@ -29,8 +29,7 @@ function M() {
|
|
|
29
29
|
async function q() {
|
|
30
30
|
I(!0), R("");
|
|
31
31
|
try {
|
|
32
|
-
|
|
33
|
-
P(t);
|
|
32
|
+
P(await e(void 0, !0));
|
|
34
33
|
} catch (e) {
|
|
35
34
|
let t = e?.response?.data?.message ?? e?.message ?? "Failed to load categories";
|
|
36
35
|
R(t), n({
|
|
@@ -389,4 +388,4 @@ function M() {
|
|
|
389
388
|
//#endregion
|
|
390
389
|
export { M as default };
|
|
391
390
|
|
|
392
|
-
//# sourceMappingURL=CategoriesPage-
|
|
391
|
+
//# sourceMappingURL=CategoriesPage-BsS5IQh3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CategoriesPage-DJM0Nalw.js","names":[],"sources":["../src/views/CategoriesPage.jsx"],"sourcesContent":["import { useState } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Autocomplete,\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 CategoryRoundedIcon from '@mui/icons-material/CategoryRounded';\nimport { showToast } from '@pm/utils/pmToast';\nimport CustomSwitch from '@/views/custom-components/CustomSwitch';\nimport FontAwesomeIcons from '@/common/fontAwesomeIcons/FontAwesomeIcons';\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 { getCategories, upsertCategory } from '@pm/services/pmApi';\nimport { CATEGORY_ICONS, iconLabel } from '@pm/utils/constants';\nimport { isClean, validateCode, validateRequired } from '@pm/utils/validation';\nimport { useFieldErrors } from '@pm/utils/useFieldErrors';\n\nexport default function CategoriesPage() {\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.category');\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 const [form, setForm] = useState(emptyForm());\n // Default to active-only; the toggle above the table reveals inactive rows.\n const [showInactive, setShowInactive] = useState(false);\n const fieldErrors = useFieldErrors();\n\n function emptyForm() {\n return { id: '', name: '', code: '', description: '', icon: '', isActive: true };\n }\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n const data = await getCategories(undefined, true);\n setItems(data);\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load categories';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.category', () => {\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 setEditing(item);\n fieldErrors.reset();\n setError('');\n setForm({\n id: item.id,\n name: item.name ?? '',\n code: item.code ?? '',\n description: item.description ?? '',\n icon: item.icon ?? '',\n isActive: item.isActive !== false,\n });\n setOpenDialog(true);\n }\n\n const codeBase = validateCode(form.code, { required: true });\n const codeNorm = form.code.trim().toUpperCase();\n const codeClash = !codeBase\n && codeNorm\n && items.some((c) => c.id !== form.id && (c.code || '').toUpperCase() === codeNorm);\n const formErrors = {\n name: validateRequired(form.name, 'Name'),\n code: codeBase || (codeClash ? 'Code is already in use — pick a different one.' : ''),\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 upsertCategory({\n id: form.id,\n name: form.name.trim(),\n code: form.code.trim().toUpperCase(),\n description: form.description || null,\n icon: form.icon || null,\n isActive: form.isActive,\n });\n showToast({ message: 'Category saved.', type: 'success' });\n setOpenDialog(false);\n await load();\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to save category';\n setError(message);\n showToast({ message, type: 'error' });\n }\n }\n\n const visible = showInactive ? items : items.filter((c) => c.isActive !== false);\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.category'}>\n <PmPageShell\n title=\"Product Categories\"\n subtitle=\"Groups of products with similar handling requirements.\"\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 Category</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=\"Product categories\"\n subtitle={loading ? 'Loading…' : `${visible.length} ${visible.length === 1 ? 'category' : 'categories'}`}\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>Code</TableCell>\n <TableCell>Name</TableCell>\n <TableCell>Description</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={CategoryRoundedIcon}\n title={items.length === 0 ? 'No categories yet' : 'No active categories'}\n hint={items.length === 0\n ? 'Categories control how products are managed. For example, vaccines need special configuration.'\n : 'Turn on “Show inactive” to see deactivated categories.'}\n action={items.length === 0 && canWrite ? (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={openCreate}>\n Create first category\n </Button>\n ) : null}\n />\n ) : visible.map((c) => (\n <TableRow key={c.id} hover>\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, letterSpacing: 0.4,\n maxWidth: '100%', wordBreak: 'break-all',\n }}>\n {c.code}\n </Box>\n </TableCell>\n <TableCell sx={{ maxWidth: 220 }}>\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n {c.icon ? (\n <Box sx={{ color: 'primary.main', width: 18, textAlign: 'center', flexShrink: 0 }}>\n <FontAwesomeIcons iconName={c.icon} />\n </Box>\n ) : null}\n <Typography variant=\"body2\" sx={{ fontWeight: 700, wordBreak: 'break-word' }}>{c.name}</Typography>\n </Stack>\n </TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {c.description\n ? <Typography variant=\"caption\" color=\"text.secondary\"\n sx={{ display: 'block', wordBreak: 'break-word' }}>\n {c.description}\n </Typography>\n : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={c.isActive ? 'Active' : 'Inactive'}\n color={c.isActive ? 'success' : 'default'}\n variant={c.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(c)}>Edit</Button>\n ) : null}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n\n <Dialog open={openDialog} onClose={() => setOpenDialog(false)} fullWidth maxWidth=\"sm\">\n <DialogTitle>{editing ? 'Edit Category' : 'New Category'}</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) => setForm({ ...form, name: e.target.value })}\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=\"Code (uppercase, A-Z, 0-9, _)\"\n size=\"small\" fullWidth\n value={form.code}\n inputProps={{ maxLength: 100 }}\n onChange={(e) => setForm({ ...form, code: e.target.value.toUpperCase() })}\n onBlur={fieldErrors.onBlur('code')}\n error={fieldErrors.show('code') && !!formErrors.code}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message={fieldErrors.show('code') ? formErrors.code : 'Must be unique.'} value={form.code} max={100} />}\n />\n <TextField label=\"Description (optional)\" size=\"small\" multiline minRows={2} fullWidth value={form.description}\n inputProps={{ maxLength: 500 }}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message=\"\" value={form.description} max={500} />} />\n <Autocomplete\n size=\"small\"\n options={CATEGORY_ICONS}\n value={form.icon || null}\n onChange={(_, next) => setForm({ ...form, icon: next ?? '' })}\n getOptionLabel={(opt) => iconLabel(opt)}\n renderOption={(props, opt) => (\n <Box component=\"li\" {...props} sx={{ display: 'flex', alignItems: 'center', gap: 1.25 }}>\n <Box sx={{ width: 20, textAlign: 'center', color: 'primary.main' }}>\n <FontAwesomeIcons iconName={opt} />\n </Box>\n <span>{iconLabel(opt)}</span>\n </Box>\n )}\n renderInput={(params) => (\n <TextField\n {...params}\n label=\"Icon (optional)\"\n placeholder=\"Search icons…\"\n helperText=\"Shown next to the category across the app.\"\n InputProps={{\n ...params.InputProps,\n startAdornment: form.icon ? (\n <InputAdornment position=\"start\">\n <Box sx={{ color: 'primary.main', display: 'flex' }}>\n <FontAwesomeIcons iconName={form.icon} />\n </Box>\n </InputAdornment>\n ) : null,\n }}\n />\n )}\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":"CategoriesPage-BsS5IQh3.js","names":[],"sources":["../src/views/CategoriesPage.jsx"],"sourcesContent":["import { useState } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Autocomplete,\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 CategoryRoundedIcon from '@mui/icons-material/CategoryRounded';\nimport { showToast } from '@pm/utils/pmToast';\nimport CustomSwitch from '@/views/custom-components/CustomSwitch';\nimport FontAwesomeIcons from '@/common/fontAwesomeIcons/FontAwesomeIcons';\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 { getCategories, upsertCategory } from '@pm/services/pmApi';\nimport { CATEGORY_ICONS, iconLabel } from '@pm/utils/constants';\nimport { isClean, validateCode, validateRequired } from '@pm/utils/validation';\nimport { useFieldErrors } from '@pm/utils/useFieldErrors';\n\nexport default function CategoriesPage() {\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.category');\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 const [form, setForm] = useState(emptyForm());\n // Default to active-only; the toggle above the table reveals inactive rows.\n const [showInactive, setShowInactive] = useState(false);\n const fieldErrors = useFieldErrors();\n\n function emptyForm() {\n return { id: '', name: '', code: '', description: '', icon: '', isActive: true };\n }\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n const data = await getCategories(undefined, true);\n setItems(data);\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load categories';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.category', () => {\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 setEditing(item);\n fieldErrors.reset();\n setError('');\n setForm({\n id: item.id,\n name: item.name ?? '',\n code: item.code ?? '',\n description: item.description ?? '',\n icon: item.icon ?? '',\n isActive: item.isActive !== false,\n });\n setOpenDialog(true);\n }\n\n const codeBase = validateCode(form.code, { required: true });\n const codeNorm = form.code.trim().toUpperCase();\n const codeClash = !codeBase\n && codeNorm\n && items.some((c) => c.id !== form.id && (c.code || '').toUpperCase() === codeNorm);\n const formErrors = {\n name: validateRequired(form.name, 'Name'),\n code: codeBase || (codeClash ? 'Code is already in use — pick a different one.' : ''),\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 upsertCategory({\n id: form.id,\n name: form.name.trim(),\n code: form.code.trim().toUpperCase(),\n description: form.description || null,\n icon: form.icon || null,\n isActive: form.isActive,\n });\n showToast({ message: 'Category saved.', type: 'success' });\n setOpenDialog(false);\n await load();\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to save category';\n setError(message);\n showToast({ message, type: 'error' });\n }\n }\n\n const visible = showInactive ? items : items.filter((c) => c.isActive !== false);\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.category'}>\n <PmPageShell\n title=\"Product Categories\"\n subtitle=\"Groups of products with similar handling requirements.\"\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 Category</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=\"Product categories\"\n subtitle={loading ? 'Loading…' : `${visible.length} ${visible.length === 1 ? 'category' : 'categories'}`}\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>Code</TableCell>\n <TableCell>Name</TableCell>\n <TableCell>Description</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={CategoryRoundedIcon}\n title={items.length === 0 ? 'No categories yet' : 'No active categories'}\n hint={items.length === 0\n ? 'Categories control how products are managed. For example, vaccines need special configuration.'\n : 'Turn on “Show inactive” to see deactivated categories.'}\n action={items.length === 0 && canWrite ? (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={openCreate}>\n Create first category\n </Button>\n ) : null}\n />\n ) : visible.map((c) => (\n <TableRow key={c.id} hover>\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, letterSpacing: 0.4,\n maxWidth: '100%', wordBreak: 'break-all',\n }}>\n {c.code}\n </Box>\n </TableCell>\n <TableCell sx={{ maxWidth: 220 }}>\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n {c.icon ? (\n <Box sx={{ color: 'primary.main', width: 18, textAlign: 'center', flexShrink: 0 }}>\n <FontAwesomeIcons iconName={c.icon} />\n </Box>\n ) : null}\n <Typography variant=\"body2\" sx={{ fontWeight: 700, wordBreak: 'break-word' }}>{c.name}</Typography>\n </Stack>\n </TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {c.description\n ? <Typography variant=\"caption\" color=\"text.secondary\"\n sx={{ display: 'block', wordBreak: 'break-word' }}>\n {c.description}\n </Typography>\n : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={c.isActive ? 'Active' : 'Inactive'}\n color={c.isActive ? 'success' : 'default'}\n variant={c.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(c)}>Edit</Button>\n ) : null}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n\n <Dialog open={openDialog} onClose={() => setOpenDialog(false)} fullWidth maxWidth=\"sm\">\n <DialogTitle>{editing ? 'Edit Category' : 'New Category'}</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) => setForm({ ...form, name: e.target.value })}\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=\"Code (uppercase, A-Z, 0-9, _)\"\n size=\"small\" fullWidth\n value={form.code}\n inputProps={{ maxLength: 100 }}\n onChange={(e) => setForm({ ...form, code: e.target.value.toUpperCase() })}\n onBlur={fieldErrors.onBlur('code')}\n error={fieldErrors.show('code') && !!formErrors.code}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message={fieldErrors.show('code') ? formErrors.code : 'Must be unique.'} value={form.code} max={100} />}\n />\n <TextField label=\"Description (optional)\" size=\"small\" multiline minRows={2} fullWidth value={form.description}\n inputProps={{ maxLength: 500 }}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message=\"\" value={form.description} max={500} />} />\n <Autocomplete\n size=\"small\"\n options={CATEGORY_ICONS}\n value={form.icon || null}\n onChange={(_, next) => setForm({ ...form, icon: next ?? '' })}\n getOptionLabel={(opt) => iconLabel(opt)}\n renderOption={(props, opt) => (\n <Box component=\"li\" {...props} sx={{ display: 'flex', alignItems: 'center', gap: 1.25 }}>\n <Box sx={{ width: 20, textAlign: 'center', color: 'primary.main' }}>\n <FontAwesomeIcons iconName={opt} />\n </Box>\n <span>{iconLabel(opt)}</span>\n </Box>\n )}\n renderInput={(params) => (\n <TextField\n {...params}\n label=\"Icon (optional)\"\n placeholder=\"Search icons…\"\n helperText=\"Shown next to the category across the app.\"\n InputProps={{\n ...params.InputProps,\n startAdornment: form.icon ? (\n <InputAdornment position=\"start\">\n <Box sx={{ color: 'primary.main', display: 'flex' }}>\n <FontAwesomeIcons iconName={form.icon} />\n </Box>\n </InputAdornment>\n ) : null,\n }}\n />\n )}\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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"}
|