@argusoft/medplat-product-management 1.0.11 → 1.0.12

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.
@@ -0,0 +1,465 @@
1
+ import { H as listFacilities, R as listAssignableUsers, W as listMyOpenPickups, r as usePmSettings, st as recordPickup, z as listBatches } from "./settingsStore-C1aUfwS9.js";
2
+ import { l as showToast, o as PmSelect, r as PmFormSection } from "./PmTable-nWK5C3ew.js";
3
+ import { a as CODE_OTHER } from "./constants-Dvu1Zd5X.js";
4
+ import { a as PmPageShell, n as PmNav, r as usePermissionedEffect, t as PmGuard } from "./PmGuard-DzOloo0T.js";
5
+ import { t as usePmListValues } from "./listValueStore-BW6BS4BN.js";
6
+ import { i as validatePickupLines, n as emptyPickupLine, r as isPickableBatch, t as PickupBatchLinesEditor } from "./PickupBatchLinesEditor-CR_5BIOa.js";
7
+ import { useEffect, useMemo, useState } from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { Alert, Autocomplete, Box, Button, Card, CardContent, Chip, Divider, Grid, Stack, TextField, ToggleButton, ToggleButtonGroup, Typography } from "@mui/material";
10
+ import { v4 } from "uuid";
11
+ import AddRoundedIcon from "@mui/icons-material/AddRounded";
12
+ import { useNavigate } from "react-router-dom";
13
+ import SaveRoundedIcon from "@mui/icons-material/SaveRounded";
14
+ import GroupsRoundedIcon from "@mui/icons-material/GroupsRounded";
15
+ import { DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers";
16
+ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
17
+ import dayjs from "dayjs";
18
+ import PersonRoundedIcon from "@mui/icons-material/PersonRounded";
19
+ function emptyLine() {
20
+ return emptyPickupLine(v4);
21
+ }
22
+ function PickupCreatePage() {
23
+ let h = useNavigate(), g = usePmSettings(), { sessionSites: _ } = usePmListValues(), v = g?.allowGroupSessions === !0, [y, b] = useState([]), [x, S] = useState([]), [C, w] = useState([]), [T, E] = useState([]), [D, O] = useState(!0), [k, A] = useState(!1), [j, M] = useState(""), [N, P] = useState({
24
+ id: v4(),
25
+ sessionType: "INDIVIDUAL",
26
+ facilityId: "",
27
+ memberUserIds: [],
28
+ lines: [emptyLine()],
29
+ notes: "",
30
+ sessionName: "",
31
+ sessionDescription: "",
32
+ sessionStartTime: dayjs(),
33
+ sessionExpectedEndTime: null,
34
+ sessionSiteCode: "",
35
+ sessionSite: ""
36
+ });
37
+ usePermissionedEffect("update.manage.productManagement.pickup", () => {
38
+ async function d() {
39
+ try {
40
+ let [d, p, m] = await Promise.all([
41
+ listFacilities(),
42
+ listBatches(),
43
+ listMyOpenPickups().catch(() => [])
44
+ ]);
45
+ b(d), S(p), E(m);
46
+ } catch (e) {
47
+ M(e?.response?.data?.message ?? e?.message ?? "Failed to load reference data");
48
+ } finally {
49
+ O(!1);
50
+ }
51
+ }
52
+ d();
53
+ }, []), useEffect(() => {
54
+ let e = !0;
55
+ if (!N.facilityId) {
56
+ w([]);
57
+ return;
58
+ }
59
+ return listAssignableUsers(N.facilityId).then((d) => {
60
+ e && w(d);
61
+ }).catch(() => {
62
+ e && w([]);
63
+ }), () => {
64
+ e = !1;
65
+ };
66
+ }, [N.facilityId]);
67
+ let F = T.length > 0, I = v && N.sessionType === "GROUP", L = useMemo(() => N.facilityId ? x.filter(isPickableBatch).filter((e) => e.ownerId === N.facilityId) : [], [x, N.facilityId]);
68
+ function R(e, d) {
69
+ P((f) => ({
70
+ ...f,
71
+ [e]: d
72
+ }));
73
+ }
74
+ function z(e) {
75
+ P((d) => ({
76
+ ...d,
77
+ facilityId: e,
78
+ memberUserIds: [],
79
+ lines: [emptyLine()]
80
+ }));
81
+ }
82
+ function B(e, d, f) {
83
+ P((p) => {
84
+ let m = p.lines.slice();
85
+ return m[e] = {
86
+ ...m[e],
87
+ [d]: f
88
+ }, {
89
+ ...p,
90
+ lines: m
91
+ };
92
+ });
93
+ }
94
+ function V() {
95
+ P((e) => ({
96
+ ...e,
97
+ lines: [...e.lines, emptyLine()]
98
+ }));
99
+ }
100
+ function H(e) {
101
+ P((d) => ({
102
+ ...d,
103
+ lines: d.lines.filter((d, f) => f !== e)
104
+ }));
105
+ }
106
+ let U = validatePickupLines(N.lines, L), W = N.lines.length > 0 && U.every((e) => Object.keys(e).length === 0), G = N.sessionName.trim() ? "" : "Session name is required.", K = N.sessionStartTime && dayjs.isDayjs(N.sessionStartTime) && N.sessionStartTime.isValid(), q = K ? N.sessionStartTime.valueOf() < Date.now() - 300 * 1e3 ? "Start time cannot be in the past." : "" : "Start time is required.", J = N.sessionExpectedEndTime && dayjs.isDayjs(N.sessionExpectedEndTime) && N.sessionExpectedEndTime.isValid(), Y = J ? K && !N.sessionExpectedEndTime.isAfter(N.sessionStartTime) ? "Expected end must be after the start time." : "" : "Expected end time is required.", X = I && N.memberUserIds.length === 0 ? "Pick at least one member for a group session." : "", Z = N.sessionSiteCode === "OTHER" && !N.sessionSite.trim(), Q = !!N.facilityId && W && !F && !G && !q && !Y && !X && !Z;
107
+ async function $() {
108
+ if (Q) {
109
+ A(!0), M("");
110
+ try {
111
+ await recordPickup({
112
+ id: N.id,
113
+ sessionType: I ? "GROUP" : "INDIVIDUAL",
114
+ memberUserIds: I ? N.memberUserIds : null,
115
+ lines: N.lines.map((e) => ({
116
+ sourceBatchId: e.sourceBatchId,
117
+ personalBatchId: e.personalBatchId,
118
+ pickedQty: Number(e.pickedQty)
119
+ })),
120
+ notes: N.notes || null,
121
+ sessionName: N.sessionName.trim(),
122
+ sessionDescription: N.sessionDescription.trim() || null,
123
+ sessionStartTime: K ? N.sessionStartTime.toISOString() : null,
124
+ sessionExpectedEndTime: J ? N.sessionExpectedEndTime.toISOString() : null,
125
+ sessionSiteCode: N.sessionSiteCode || null,
126
+ sessionSite: N.sessionSiteCode === "OTHER" && N.sessionSite.trim() || null
127
+ }), showToast({
128
+ message: "Session started successfully",
129
+ type: "success"
130
+ }), h("/ui/medplat/manage/pm/pickups");
131
+ } catch (e) {
132
+ M(e?.response?.data?.message ?? e?.message ?? "Failed to start session");
133
+ } finally {
134
+ A(!1);
135
+ }
136
+ }
137
+ }
138
+ return /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(PmNav, {}), /* @__PURE__ */ jsx(PmGuard, {
139
+ perm: "update.manage.productManagement.pickup",
140
+ title: "You don’t have permission to record pickups",
141
+ children: /* @__PURE__ */ jsxs(PmPageShell, {
142
+ title: "Start Session",
143
+ subtitle: "Check out stock from a facility for field work. It can be your own session or a shared group session. Record returns and wastage when stock comes back.",
144
+ actions: /* @__PURE__ */ jsxs(Stack, {
145
+ direction: "row",
146
+ spacing: 1,
147
+ children: [/* @__PURE__ */ jsx(Button, {
148
+ variant: "outlined",
149
+ onClick: () => h("/ui/medplat/manage/pm/pickups"),
150
+ children: "Cancel"
151
+ }), /* @__PURE__ */ jsx(Button, {
152
+ variant: "contained",
153
+ startIcon: /* @__PURE__ */ jsx(SaveRoundedIcon, {}),
154
+ disabled: !Q || k,
155
+ onClick: () => void $(),
156
+ children: k ? "Starting…" : "Start Session"
157
+ })]
158
+ }),
159
+ children: [
160
+ j ? /* @__PURE__ */ jsx(Alert, {
161
+ severity: "error",
162
+ sx: { mb: 2 },
163
+ children: j
164
+ }) : null,
165
+ F ? /* @__PURE__ */ jsxs(Alert, {
166
+ severity: "warning",
167
+ sx: { mb: 2 },
168
+ action: /* @__PURE__ */ jsx(Button, {
169
+ color: "inherit",
170
+ size: "small",
171
+ onClick: () => h("/ui/medplat/manage/pm/pickups"),
172
+ children: "Go to Pickups"
173
+ }),
174
+ children: [
175
+ "You are already part of an open session. End it before starting a new one, or use ",
176
+ /* @__PURE__ */ jsx("strong", { children: "Top Up" }),
177
+ " on the Pickups page to add more stock to it."
178
+ ]
179
+ }) : null,
180
+ /* @__PURE__ */ jsx(Card, {
181
+ sx: {
182
+ borderRadius: 1.5,
183
+ mb: 2,
184
+ border: "1px solid",
185
+ borderColor: "divider",
186
+ boxShadow: "0 12px 32px rgba(15, 23, 42, 0.045)"
187
+ },
188
+ children: /* @__PURE__ */ jsxs(CardContent, {
189
+ sx: { p: 2.5 },
190
+ children: [
191
+ /* @__PURE__ */ jsx(PmFormSection, {
192
+ eyebrow: "Step 1",
193
+ title: v ? "Session type & source" : "Session source",
194
+ hint: v ? "Run the session yourself or share it with colleagues from the same facility." : "Pick the facility whose stock you are checking out for this outreach session.",
195
+ sx: { mb: 2 }
196
+ }),
197
+ v ? /* @__PURE__ */ jsxs(ToggleButtonGroup, {
198
+ exclusive: !0,
199
+ size: "small",
200
+ color: "primary",
201
+ value: N.sessionType,
202
+ onChange: (e, d) => {
203
+ d && R("sessionType", d);
204
+ },
205
+ sx: { mb: 2 },
206
+ children: [/* @__PURE__ */ jsxs(ToggleButton, {
207
+ value: "INDIVIDUAL",
208
+ children: [/* @__PURE__ */ jsx(PersonRoundedIcon, {
209
+ fontSize: "small",
210
+ sx: { mr: .75 }
211
+ }), "Individual"]
212
+ }), /* @__PURE__ */ jsxs(ToggleButton, {
213
+ value: "GROUP",
214
+ children: [/* @__PURE__ */ jsx(GroupsRoundedIcon, {
215
+ fontSize: "small",
216
+ sx: { mr: .75 }
217
+ }), "Group"]
218
+ })]
219
+ }) : null,
220
+ /* @__PURE__ */ jsxs(Grid, {
221
+ container: !0,
222
+ spacing: 2,
223
+ children: [/* @__PURE__ */ jsx(Grid, {
224
+ item: !0,
225
+ xs: 12,
226
+ md: I ? 5 : 12,
227
+ children: /* @__PURE__ */ jsx(Autocomplete, {
228
+ size: "small",
229
+ options: y,
230
+ getOptionLabel: (e) => e?.name ?? "",
231
+ isOptionEqualToValue: (e, d) => e?.id === d?.id,
232
+ value: y.find((e) => e.id === N.facilityId) ?? null,
233
+ onChange: (e, d) => z(d?.id ?? ""),
234
+ loading: D,
235
+ renderInput: (e) => /* @__PURE__ */ jsx(TextField, {
236
+ ...e,
237
+ required: !0,
238
+ label: "Source Facility",
239
+ placeholder: "Pick a facility you're assigned to"
240
+ })
241
+ })
242
+ }), I ? /* @__PURE__ */ jsx(Grid, {
243
+ item: !0,
244
+ xs: 12,
245
+ md: 7,
246
+ children: /* @__PURE__ */ jsx(Autocomplete, {
247
+ multiple: !0,
248
+ size: "small",
249
+ disabled: !N.facilityId,
250
+ options: C,
251
+ getOptionLabel: (e) => e?.name ?? String(e?.id ?? ""),
252
+ isOptionEqualToValue: (e, d) => e?.id === d?.id,
253
+ value: C.filter((e) => N.memberUserIds.includes(e.id)),
254
+ onChange: (e, d) => R("memberUserIds", d.map((e) => e.id)),
255
+ renderInput: (e) => /* @__PURE__ */ jsx(TextField, {
256
+ ...e,
257
+ required: !0,
258
+ label: "Members",
259
+ placeholder: N.facilityId ? "Add colleagues" : "Pick a facility first",
260
+ error: !!X,
261
+ helperText: X || "Anyone here can administer from the shared stock. You alone can end or top up the session."
262
+ })
263
+ })
264
+ }) : null]
265
+ })
266
+ ]
267
+ })
268
+ }),
269
+ /* @__PURE__ */ jsx(Card, {
270
+ sx: {
271
+ borderRadius: 1.5,
272
+ mb: 2,
273
+ border: "1px solid",
274
+ borderColor: "divider",
275
+ boxShadow: "0 12px 32px rgba(15, 23, 42, 0.045)"
276
+ },
277
+ children: /* @__PURE__ */ jsxs(CardContent, {
278
+ sx: { p: 2.5 },
279
+ children: [
280
+ /* @__PURE__ */ jsxs(Stack, {
281
+ direction: "row",
282
+ justifyContent: "space-between",
283
+ alignItems: "flex-start",
284
+ sx: { mb: 2 },
285
+ children: [/* @__PURE__ */ jsx(PmFormSection, {
286
+ eyebrow: "Step 2",
287
+ title: "Batches",
288
+ hint: "Add one or more batches to take on this session. They can be the same vaccine (different lots) or different vaccines."
289
+ }), /* @__PURE__ */ jsx(Button, {
290
+ variant: "outlined",
291
+ startIcon: /* @__PURE__ */ jsx(AddRoundedIcon, {}),
292
+ disabled: !N.facilityId,
293
+ onClick: V,
294
+ children: "Add Batch"
295
+ })]
296
+ }),
297
+ /* @__PURE__ */ jsx(Divider, { sx: { mb: 2 } }),
298
+ N.facilityId ? /* @__PURE__ */ jsx(PickupBatchLinesEditor, {
299
+ lines: N.lines,
300
+ batches: L,
301
+ errors: U,
302
+ onPatch: B,
303
+ onRemove: H
304
+ }) : /* @__PURE__ */ jsx(Typography, {
305
+ variant: "body2",
306
+ color: "text.secondary",
307
+ children: "Pick a facility first to choose batches."
308
+ })
309
+ ]
310
+ })
311
+ }),
312
+ /* @__PURE__ */ jsx(Card, {
313
+ sx: {
314
+ borderRadius: 1.5,
315
+ mb: 2,
316
+ border: "1px solid",
317
+ borderColor: "divider",
318
+ boxShadow: "0 12px 32px rgba(15, 23, 42, 0.045)"
319
+ },
320
+ children: /* @__PURE__ */ jsxs(CardContent, {
321
+ sx: { p: 2.5 },
322
+ children: [/* @__PURE__ */ jsx(PmFormSection, {
323
+ eyebrow: "Session",
324
+ title: "Outreach session details",
325
+ hint: "Records the purpose, timing and location of this session. Shown when administering from this stock.",
326
+ sx: { mb: 2 }
327
+ }), /* @__PURE__ */ jsxs(Grid, {
328
+ container: !0,
329
+ spacing: 2,
330
+ children: [
331
+ /* @__PURE__ */ jsx(Grid, {
332
+ item: !0,
333
+ xs: 12,
334
+ md: 6,
335
+ children: /* @__PURE__ */ jsx(TextField, {
336
+ required: !0,
337
+ fullWidth: !0,
338
+ size: "small",
339
+ label: "Session name",
340
+ inputProps: { maxLength: 150 },
341
+ value: N.sessionName,
342
+ onChange: (e) => R("sessionName", e.target.value),
343
+ error: !!G && N.sessionName !== "",
344
+ helperText: N.sessionName === "" ? "e.g. Anganwadi camp – Ward 4" : G
345
+ })
346
+ }),
347
+ /* @__PURE__ */ jsx(Grid, {
348
+ item: !0,
349
+ xs: 12,
350
+ md: 6,
351
+ children: /* @__PURE__ */ jsxs(Stack, {
352
+ spacing: 1.5,
353
+ children: [/* @__PURE__ */ jsx(PmSelect, {
354
+ label: "Session site (optional)",
355
+ value: N.sessionSiteCode,
356
+ onChange: (e) => P((d) => ({
357
+ ...d,
358
+ sessionSiteCode: e,
359
+ sessionSite: e === "OTHER" ? d.sessionSite : ""
360
+ })),
361
+ options: _,
362
+ helperText: _.length <= 1 ? "No sites have been set up yet. Choose Other to type one." : "Choose Other if the site is not listed."
363
+ }), N.sessionSiteCode === "OTHER" ? /* @__PURE__ */ jsx(TextField, {
364
+ fullWidth: !0,
365
+ size: "small",
366
+ required: !0,
367
+ label: "Site name",
368
+ placeholder: "Location / site reference",
369
+ inputProps: { maxLength: 200 },
370
+ value: N.sessionSite,
371
+ onChange: (e) => R("sessionSite", e.target.value),
372
+ error: Z && N.sessionSite !== "",
373
+ helperText: Z ? "Type the site name." : ""
374
+ }) : null]
375
+ })
376
+ }),
377
+ /* @__PURE__ */ jsx(Grid, {
378
+ item: !0,
379
+ xs: 12,
380
+ md: 6,
381
+ children: /* @__PURE__ */ jsx(LocalizationProvider, {
382
+ dateAdapter: AdapterDayjs,
383
+ adapterLocale: "en",
384
+ children: /* @__PURE__ */ jsx(DateTimePicker, {
385
+ label: "Start time",
386
+ value: N.sessionStartTime,
387
+ onChange: (e) => R("sessionStartTime", e),
388
+ ampm: !1,
389
+ minDateTime: dayjs().subtract(5, "minute"),
390
+ slotProps: {
391
+ actionBar: { actions: ["clear"] },
392
+ textField: {
393
+ size: "small",
394
+ fullWidth: !0,
395
+ required: !0,
396
+ error: !!q && N.sessionStartTime !== null,
397
+ helperText: N.sessionStartTime !== null && q || "Cannot be in the past. (5 minutes buffer allowed)"
398
+ }
399
+ }
400
+ })
401
+ })
402
+ }),
403
+ /* @__PURE__ */ jsx(Grid, {
404
+ item: !0,
405
+ xs: 12,
406
+ md: 6,
407
+ children: /* @__PURE__ */ jsx(LocalizationProvider, {
408
+ dateAdapter: AdapterDayjs,
409
+ adapterLocale: "en",
410
+ children: /* @__PURE__ */ jsx(DateTimePicker, {
411
+ label: "Expected End Time",
412
+ value: N.sessionExpectedEndTime,
413
+ onChange: (e) => R("sessionExpectedEndTime", e),
414
+ ampm: !1,
415
+ minDateTime: K ? N.sessionStartTime : void 0,
416
+ slotProps: {
417
+ actionBar: { actions: ["clear"] },
418
+ textField: {
419
+ size: "small",
420
+ fullWidth: !0,
421
+ required: !0,
422
+ error: !!Y && N.sessionExpectedEndTime !== null,
423
+ helperText: N.sessionExpectedEndTime !== null && Y || "When the session is expected to end."
424
+ }
425
+ }
426
+ })
427
+ })
428
+ }),
429
+ /* @__PURE__ */ jsx(Grid, {
430
+ item: !0,
431
+ xs: 12,
432
+ md: 6,
433
+ children: /* @__PURE__ */ jsx(TextField, {
434
+ fullWidth: !0,
435
+ size: "small",
436
+ label: "Notes (optional)",
437
+ placeholder: "Anything worth recording about this session",
438
+ value: N.notes,
439
+ onChange: (e) => R("notes", e.target.value)
440
+ })
441
+ }),
442
+ /* @__PURE__ */ jsx(Grid, {
443
+ item: !0,
444
+ xs: 12,
445
+ children: /* @__PURE__ */ jsx(TextField, {
446
+ fullWidth: !0,
447
+ size: "small",
448
+ multiline: !0,
449
+ minRows: 2,
450
+ label: "Purpose / description (optional)",
451
+ value: N.sessionDescription,
452
+ onChange: (e) => R("sessionDescription", e.target.value)
453
+ })
454
+ })
455
+ ]
456
+ })]
457
+ })
458
+ })
459
+ ]
460
+ })
461
+ })] });
462
+ }
463
+ export { PickupCreatePage as default };
464
+
465
+ //# sourceMappingURL=PickupCreatePage-B9DfGUJ_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PickupCreatePage-B9DfGUJ_.js","names":[],"sources":["../src/views/PickupCreatePage.jsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Card,\n CardContent,\n Chip,\n Divider,\n Grid,\n Stack,\n ToggleButton,\n ToggleButtonGroup,\n TextField,\n Typography,\n} from '@mui/material';\nimport { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';\nimport { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';\nimport dayjs from 'dayjs';\nimport SaveRoundedIcon from '@mui/icons-material/SaveRounded';\nimport AddRoundedIcon from '@mui/icons-material/AddRounded';\nimport PersonRoundedIcon from '@mui/icons-material/PersonRounded';\nimport GroupsRoundedIcon from '@mui/icons-material/GroupsRounded';\nimport { showToast } from '@pm/utils/pmToast';\nimport PmPageShell from '@pm/components/PmPageShell';\nimport PmNav from '@pm/components/PmNav';\nimport PmGuard from '@pm/components/PmGuard';\nimport { usePermissionedEffect } from '@pm/utils/permissions';\nimport { usePmSettings } from '@pm/utils/settingsStore';\nimport { usePmListValues } from '@pm/utils/listValueStore';\nimport { CODE_OTHER } from '@pm/utils/constants';\nimport { PmFormSection, PmSelect } from '@pm/components/PmTable';\nimport {\n listAssignableUsers,\n listBatches,\n listFacilities,\n listMyOpenPickups,\n recordPickup,\n} from '@pm/services/pmApi';\nimport PickupBatchLinesEditor, {\n emptyPickupLine,\n isPickableBatch,\n validatePickupLines,\n} from '@pm/components/PickupBatchLinesEditor';\n\nfunction emptyLine() {\n return emptyPickupLine(uuidv4);\n}\n\nexport default function PickupCreatePage() {\n const navigate = useNavigate();\n const settings = usePmSettings();\n // Falls back to just Other when the list is unseeded or the fetch fails, so\n // the free-text entry this dropdown replaced is always still reachable.\n const { sessionSites } = usePmListValues();\n const allowGroupSessions = settings?.allowGroupSessions === true;\n const [facilities, setFacilities] = useState([]);\n const [batches, setBatches] = useState([]);\n const [assignableUsers, setAssignableUsers] = useState([]);\n // OPEN sessions the user is already in (created or joined) — one open session\n // per user, so any open session blocks a new one.\n const [openSessions, setOpenSessions] = useState([]);\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState('');\n const [form, setForm] = useState({\n id: uuidv4(),\n sessionType: 'INDIVIDUAL',\n facilityId: '',\n memberUserIds: [],\n lines: [emptyLine()],\n notes: '',\n // Outreach session metadata.\n sessionName: '',\n sessionDescription: '',\n sessionStartTime: dayjs(),\n sessionExpectedEndTime: null,\n // A code from the configurable site list. Other reveals sessionSite, the\n // free-text box that used to be the only way to enter a site.\n sessionSiteCode: '',\n sessionSite: '',\n });\n\n usePermissionedEffect('update.manage.productManagement.pickup', () => {\n async function load() {\n try {\n const [f, b, open] = await Promise.all([\n listFacilities(),\n listBatches(),\n listMyOpenPickups().catch(() => []),\n ]);\n setFacilities(f);\n setBatches(b);\n setOpenSessions(open);\n } catch (err) {\n setError(err?.response?.data?.message ?? err?.message ?? 'Failed to load reference data');\n } finally {\n setLoading(false);\n }\n }\n void load();\n }, []);\n\n // Load the facility's assignable users whenever the facility changes (used\n // for the group member picker). Cleared when no facility is chosen.\n useEffect(() => {\n let active = true;\n if (!form.facilityId) {\n setAssignableUsers([]);\n return undefined;\n }\n listAssignableUsers(form.facilityId)\n .then((users) => { if (active) setAssignableUsers(users); })\n .catch(() => { if (active) setAssignableUsers([]); });\n return () => { active = false; };\n }, [form.facilityId]);\n\n const hasOpenSession = openSessions.length > 0;\n // Group is only possible when the deployment setting allows it; otherwise\n // every session is individual (and the type toggle is hidden).\n const isGroup = allowGroupSessions && form.sessionType === 'GROUP';\n\n // Batches limited to the picked facility. Reset lines when the facility\n // changes so a stale batch can't carry over.\n const eligibleBatches = useMemo(() => {\n if (!form.facilityId) return [];\n return batches.filter(isPickableBatch).filter((b) => b.ownerId === form.facilityId);\n }, [batches, form.facilityId]);\n\n function patch(k, v) {\n setForm((f) => ({ ...f, [k]: v }));\n }\n\n function patchFacility(id) {\n // Facility drives both the batch options and the member pool, so reset both.\n setForm((f) => ({ ...f, facilityId: id, memberUserIds: [], lines: [emptyLine()] }));\n }\n\n function patchLine(idx, k, v) {\n setForm((f) => {\n const lines = f.lines.slice();\n lines[idx] = { ...lines[idx], [k]: v };\n return { ...f, lines };\n });\n }\n function addLine() {\n setForm((f) => ({ ...f, lines: [...f.lines, emptyLine()] }));\n }\n function removeLine(idx) {\n setForm((f) => ({ ...f, lines: f.lines.filter((_, i) => i !== idx) }));\n }\n\n // Per-line validation: a source batch and a quantity within its remaining.\n const lineErrors = validatePickupLines(form.lines, eligibleBatches);\n const linesValid = form.lines.length > 0 && lineErrors.every((e) => Object.keys(e).length === 0);\n\n const sessionNameError = form.sessionName.trim() ? '' : 'Session name is required.';\n const startValid = form.sessionStartTime && dayjs.isDayjs(form.sessionStartTime) && form.sessionStartTime.isValid();\n const sessionStartError = !startValid\n ? 'Start time is required.'\n : form.sessionStartTime.valueOf() < Date.now() - 5 * 60 * 1000\n ? 'Start time cannot be in the past.'\n : '';\n const endValid = form.sessionExpectedEndTime && dayjs.isDayjs(form.sessionExpectedEndTime) && form.sessionExpectedEndTime.isValid();\n const sessionEndError = !endValid\n ? 'Expected end time is required.'\n : (startValid && !form.sessionExpectedEndTime.isAfter(form.sessionStartTime))\n ? 'Expected end must be after the start time.'\n : '';\n const membersError = isGroup && form.memberUserIds.length === 0\n ? 'Pick at least one member for a group session.' : '';\n\n // The site itself stays optional; only choosing Other makes the name required,\n // mirroring the backend's refusal of an Other with no name.\n const siteNameMissing = form.sessionSiteCode === CODE_OTHER && !form.sessionSite.trim();\n\n const formIsValid = !!form.facilityId && linesValid && !hasOpenSession\n && !sessionNameError && !sessionStartError && !sessionEndError && !membersError\n && !siteNameMissing;\n\n async function save() {\n if (!formIsValid) return;\n setSubmitting(true);\n setError('');\n try {\n await recordPickup({\n id: form.id,\n sessionType: isGroup ? 'GROUP' : 'INDIVIDUAL',\n memberUserIds: isGroup ? form.memberUserIds : null,\n lines: form.lines.map((l) => ({\n sourceBatchId: l.sourceBatchId,\n personalBatchId: l.personalBatchId,\n pickedQty: Number(l.pickedQty),\n })),\n notes: form.notes || null,\n sessionName: form.sessionName.trim(),\n sessionDescription: form.sessionDescription.trim() || null,\n sessionStartTime: startValid ? form.sessionStartTime.toISOString() : null,\n sessionExpectedEndTime: endValid ? form.sessionExpectedEndTime.toISOString() : null,\n sessionSiteCode: form.sessionSiteCode || null,\n // Only meaningful alongside Other; a listed site carries its own label.\n sessionSite: form.sessionSiteCode === CODE_OTHER ? (form.sessionSite.trim() || null) : null,\n });\n showToast({ message: 'Session started successfully', type: 'success' });\n navigate('/ui/medplat/manage/pm/pickups');\n } catch (err) {\n setError(err?.response?.data?.message ?? err?.message ?? 'Failed to start session');\n } finally {\n setSubmitting(false);\n }\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'update.manage.productManagement.pickup'} title=\"You don’t have permission to record pickups\">\n <PmPageShell\n title=\"Start Session\"\n subtitle=\"Check out stock from a facility for field work. It can be your own session or a shared group session. Record returns and wastage when stock comes back.\"\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\" onClick={() => navigate('/ui/medplat/manage/pm/pickups')}>Cancel</Button>\n <Button variant=\"contained\" startIcon={<SaveRoundedIcon />}\n disabled={!formIsValid || submitting}\n onClick={() => void save()}>\n {submitting ? 'Starting…' : 'Start Session'}\n </Button>\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n {hasOpenSession ? (\n <Alert\n severity=\"warning\"\n sx={{ mb: 2 }}\n action={\n <Button color=\"inherit\" size=\"small\"\n onClick={() => navigate('/ui/medplat/manage/pm/pickups')}>\n Go to Pickups\n </Button>\n }\n >\n You are already part of an open session. End it before starting a new one,\n or use <strong>Top Up</strong> on the Pickups page to add more stock to it.\n </Alert>\n ) : null}\n\n {/* ---------- Step 1: type + source + members ---------- */}\n <Card sx={{ borderRadius: 1.5, mb: 2, border: '1px solid', borderColor: 'divider', boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)' }}>\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Step 1\"\n title={allowGroupSessions ? 'Session type & source' : 'Session source'}\n hint={allowGroupSessions\n ? 'Run the session yourself or share it with colleagues from the same facility.'\n : 'Pick the facility whose stock you are checking out for this outreach session.'}\n sx={{ mb: 2 }}\n />\n {allowGroupSessions ? (\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n color=\"primary\"\n value={form.sessionType}\n onChange={(_, v) => { if (v) patch('sessionType', v); }}\n sx={{ mb: 2 }}\n >\n <ToggleButton value=\"INDIVIDUAL\"><PersonRoundedIcon fontSize=\"small\" sx={{ mr: 0.75 }} />Individual</ToggleButton>\n <ToggleButton value=\"GROUP\"><GroupsRoundedIcon fontSize=\"small\" sx={{ mr: 0.75 }} />Group</ToggleButton>\n </ToggleButtonGroup>\n ) : null}\n <Grid container spacing={2}>\n <Grid item xs={12} md={isGroup ? 5 : 12}>\n <Autocomplete\n size=\"small\"\n options={facilities}\n getOptionLabel={(f) => f?.name ?? ''}\n isOptionEqualToValue={(a, b) => a?.id === b?.id}\n value={facilities.find((f) => f.id === form.facilityId) ?? null}\n onChange={(_, next) => patchFacility(next?.id ?? '')}\n loading={loading}\n renderInput={(params) => (\n <TextField {...params} required label=\"Source Facility\" placeholder=\"Pick a facility you're assigned to\" />\n )}\n />\n </Grid>\n {isGroup ? (\n <Grid item xs={12} md={7}>\n <Autocomplete\n multiple\n size=\"small\"\n disabled={!form.facilityId}\n options={assignableUsers}\n getOptionLabel={(u) => u?.name ?? String(u?.id ?? '')}\n isOptionEqualToValue={(a, b) => a?.id === b?.id}\n value={assignableUsers.filter((u) => form.memberUserIds.includes(u.id))}\n onChange={(_, next) => patch('memberUserIds', next.map((u) => u.id))}\n renderInput={(params) => (\n <TextField {...params} required label=\"Members\" placeholder={form.facilityId ? 'Add colleagues' : 'Pick a facility first'}\n error={!!membersError}\n helperText={membersError || 'Anyone here can administer from the shared stock. You alone can end or top up the session.'} />\n )}\n />\n </Grid>\n ) : null}\n </Grid>\n </CardContent>\n </Card>\n\n {/* ---------- Step 2: batches ---------- */}\n <Card sx={{ borderRadius: 1.5, mb: 2, border: '1px solid', borderColor: 'divider', boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)' }}>\n <CardContent sx={{ p: 2.5 }}>\n <Stack direction=\"row\" justifyContent=\"space-between\" alignItems=\"flex-start\" sx={{ mb: 2 }}>\n <PmFormSection\n eyebrow=\"Step 2\"\n title=\"Batches\"\n hint=\"Add one or more batches to take on this session. They can be the same vaccine (different lots) or different vaccines.\"\n />\n <Button variant=\"outlined\" startIcon={<AddRoundedIcon />} disabled={!form.facilityId} onClick={addLine}>Add Batch</Button>\n </Stack>\n <Divider sx={{ mb: 2 }} />\n {!form.facilityId ? (\n <Typography variant=\"body2\" color=\"text.secondary\">Pick a facility first to choose batches.</Typography>\n ) : (\n <PickupBatchLinesEditor\n lines={form.lines}\n batches={eligibleBatches}\n errors={lineErrors}\n onPatch={patchLine}\n onRemove={removeLine}\n />\n )}\n </CardContent>\n </Card>\n\n {/* ---------- Session details ---------- */}\n <Card sx={{ borderRadius: 1.5, mb: 2, border: '1px solid', borderColor: 'divider', boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)' }}>\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Session\"\n title=\"Outreach session details\"\n hint=\"Records the purpose, timing and location of this session. Shown when administering from this stock.\"\n sx={{ mb: 2 }}\n />\n <Grid container spacing={2}>\n <Grid item xs={12} md={6}>\n <TextField\n required fullWidth size=\"small\"\n label=\"Session name\"\n inputProps={{ maxLength: 150 }}\n value={form.sessionName}\n onChange={(e) => patch('sessionName', e.target.value)}\n error={!!sessionNameError && form.sessionName !== ''}\n helperText={form.sessionName === '' ? 'e.g. Anganwadi camp – Ward 4' : sessionNameError}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Stack spacing={1.5}>\n <PmSelect\n label=\"Session site (optional)\"\n value={form.sessionSiteCode}\n onChange={(v) => setForm((f) => ({\n ...f,\n sessionSiteCode: v,\n // Leaving Other discards the typed name, so a listed\n // site is never saved with stale text beside it.\n sessionSite: v === CODE_OTHER ? f.sessionSite : '',\n }))}\n options={sessionSites}\n helperText={sessionSites.length <= 1\n ? 'No sites have been set up yet. Choose Other to type one.'\n : 'Choose Other if the site is not listed.'}\n />\n {form.sessionSiteCode === CODE_OTHER ? (\n <TextField\n fullWidth size=\"small\" required\n label=\"Site name\"\n placeholder=\"Location / site reference\"\n inputProps={{ maxLength: 200 }}\n value={form.sessionSite}\n onChange={(e) => patch('sessionSite', e.target.value)}\n error={siteNameMissing && form.sessionSite !== ''}\n helperText={siteNameMissing ? 'Type the site name.' : ''}\n />\n ) : null}\n </Stack>\n </Grid>\n <Grid item xs={12} md={6}>\n <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale=\"en\">\n <DateTimePicker\n label=\"Start time\"\n value={form.sessionStartTime}\n onChange={(newVal) => patch('sessionStartTime', newVal)}\n ampm={false}\n minDateTime={dayjs().subtract(5, 'minute')}\n slotProps={{\n actionBar: { actions: ['clear'] },\n textField: {\n size: 'small',\n fullWidth: true,\n required: true,\n error: !!sessionStartError && form.sessionStartTime !== null,\n helperText: (form.sessionStartTime !== null && sessionStartError) || 'Cannot be in the past. (5 minutes buffer allowed)',\n },\n }}\n />\n </LocalizationProvider>\n </Grid>\n <Grid item xs={12} md={6}>\n <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale=\"en\">\n <DateTimePicker\n label=\"Expected End Time\"\n value={form.sessionExpectedEndTime}\n onChange={(newVal) => patch('sessionExpectedEndTime', newVal)}\n ampm={false}\n minDateTime={startValid ? form.sessionStartTime : undefined}\n slotProps={{\n actionBar: { actions: ['clear'] },\n textField: {\n size: 'small',\n fullWidth: true,\n required: true,\n error: !!sessionEndError && form.sessionExpectedEndTime !== null,\n helperText: (form.sessionExpectedEndTime !== null && sessionEndError) || 'When the session is expected to end.',\n },\n }}\n />\n </LocalizationProvider>\n </Grid>\n <Grid item xs={12} md={6}>\n <TextField\n fullWidth size=\"small\"\n label=\"Notes (optional)\"\n placeholder=\"Anything worth recording about this session\"\n value={form.notes}\n onChange={(e) => patch('notes', e.target.value)}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth size=\"small\" multiline minRows={2}\n label=\"Purpose / description (optional)\"\n value={form.sessionDescription}\n onChange={(e) => patch('sessionDescription', e.target.value)}\n />\n </Grid>\n </Grid>\n </CardContent>\n </Card>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import PropTypes from "prop-types";
10
10
  import { Alert, Box, Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle, LinearProgress, Radio, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Tooltip, Typography } from "@mui/material";
11
11
  import VaccinesRoundedIcon from "@mui/icons-material/VaccinesRounded";
12
12
  import EventBusyRoundedIcon from "@mui/icons-material/EventBusyRounded";
13
- var VerifyRoute = lazy(() => import("@/views/feature-components/VerifyRoute.jsx")), DashboardPage = lazy(() => import("./DashboardPage-Dw_xutHp.js")), CategoriesPage = lazy(() => import("./CategoriesPage-DbR56Dxb.js")), BrandsPage = lazy(() => import("./BrandsPage-DBFBor6L.js")), ProductsPage = lazy(() => import("./ProductsPage-Cr-Ay4tP.js")), ProductEditPage = lazy(() => import("./ProductEditPage-mCCCmDyz.js")), StorageUnitsPage = lazy(() => import("./StorageUnitsPage-CqlGFV83.js")), InventoryPage = lazy(() => import("./InventoryPage-BETRRdVj.js")), PurchasesPage = lazy(() => import("./PurchasesPage-DpMPd8JH.js")), PurchaseCreatePage = lazy(() => import("./PurchaseCreatePage-djceX_Mi.js")), PurchaseRequestsPage = lazy(() => import("./PurchaseRequestsPage-dQDeAWYz.js")), PurchaseRequestDetailPage = lazy(() => import("./PurchaseRequestDetailPage-Cc3vdQ33.js")), PickupsPage = lazy(() => import("./PickupsPage-cIBMy6kz.js")), PickupCreatePage = lazy(() => import("./PickupCreatePage-BNK2p8Wj.js")), TransfersPage = lazy(() => import("./TransfersPage-Pvjid97y.js")), TransferCreatePage = lazy(() => import("./TransferCreatePage-C84ze-RN.js")), SalesPage = lazy(() => import("./SalesPage-CelCu5Tw.js")), SaleCreatePage = lazy(() => import("./SaleCreatePage-DDedCbwe.js")), PaymentsPage = lazy(() => import("./PaymentsPage-CYSXziah.js")), PaymentCreatePage = lazy(() => import("./PaymentCreatePage--WFg0fgT.js")), VialsPage = lazy(() => import("./VialsPage-VjNQ4SGI.js")), TransactionsPage = lazy(() => import("./TransactionsPage-CdidHnRk.js")), SettingsPage = lazy(() => import("./SettingsPage-BEyiYNFC.js")), HEADER = "Product Management";
13
+ var VerifyRoute = lazy(() => import("@/views/feature-components/VerifyRoute.jsx")), DashboardPage = lazy(() => import("./DashboardPage-Dw_xutHp.js")), CategoriesPage = lazy(() => import("./CategoriesPage-DbR56Dxb.js")), BrandsPage = lazy(() => import("./BrandsPage-DBFBor6L.js")), ProductsPage = lazy(() => import("./ProductsPage-Cr-Ay4tP.js")), ProductEditPage = lazy(() => import("./ProductEditPage-mCCCmDyz.js")), StorageUnitsPage = lazy(() => import("./StorageUnitsPage-CqlGFV83.js")), InventoryPage = lazy(() => import("./InventoryPage-BETRRdVj.js")), PurchasesPage = lazy(() => import("./PurchasesPage-DpMPd8JH.js")), PurchaseCreatePage = lazy(() => import("./PurchaseCreatePage-djceX_Mi.js")), PurchaseRequestsPage = lazy(() => import("./PurchaseRequestsPage-dQDeAWYz.js")), PurchaseRequestDetailPage = lazy(() => import("./PurchaseRequestDetailPage-Cc3vdQ33.js")), PickupsPage = lazy(() => import("./PickupsPage-cIBMy6kz.js")), PickupCreatePage = lazy(() => import("./PickupCreatePage-B9DfGUJ_.js")), TransfersPage = lazy(() => import("./TransfersPage-Pvjid97y.js")), TransferCreatePage = lazy(() => import("./TransferCreatePage-C84ze-RN.js")), SalesPage = lazy(() => import("./SalesPage-CelCu5Tw.js")), SaleCreatePage = lazy(() => import("./SaleCreatePage-DDedCbwe.js")), PaymentsPage = lazy(() => import("./PaymentsPage-CYSXziah.js")), PaymentCreatePage = lazy(() => import("./PaymentCreatePage--WFg0fgT.js")), VialsPage = lazy(() => import("./VialsPage-VjNQ4SGI.js")), TransactionsPage = lazy(() => import("./TransactionsPage-CdidHnRk.js")), SettingsPage = lazy(() => import("./SettingsPage-BEyiYNFC.js")), HEADER = "Product Management";
14
14
  function pmRoute(e, t, n = "General") {
15
15
  return {
16
16
  path: e,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@argusoft/medplat-product-management",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "license": "MIT",
5
5
  "description": "MEDplat Product Management",
6
6
  "type": "module",
@@ -31,12 +31,12 @@
31
31
  "react-router-dom": "^6",
32
32
  "redux": "^5",
33
33
  "@mui/x-date-pickers": "^7",
34
- "prop-types": "15"
34
+ "prop-types": "15",
35
+ "dayjs": "^1"
35
36
  },
36
37
  "devDependencies": {
37
38
  "vite": "npm:rolldown-vite@7.3.1",
38
39
  "vite-plugin-lib-inject-css": "^2.2.2",
39
- "@vitejs/plugin-react": "^4.3.2",
40
- "dayjs": "^1"
40
+ "@vitejs/plugin-react": "^4.3.2"
41
41
  }
42
42
  }