@argusoft/medplat-product-management 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/{BrandsPage-CSA3meke.js → BrandsPage-BE3kn-8b.js} +77 -75
  2. package/dist/BrandsPage-BE3kn-8b.js.map +1 -0
  3. package/dist/{CategoriesPage-BrspzkJL.js → CategoriesPage-COqi3pMi.js} +71 -70
  4. package/dist/{CategoriesPage-BrspzkJL.js.map → CategoriesPage-COqi3pMi.js.map} +1 -1
  5. package/dist/{DashboardPage-CqaquOs2.js → DashboardPage-C_H1Jrey.js} +90 -89
  6. package/dist/DashboardPage-C_H1Jrey.js.map +1 -0
  7. package/dist/{FacilityPicker-Dv_H95WW.js → FacilityPicker-Diq2hnYg.js} +2 -2
  8. package/dist/{FacilityPicker-Dv_H95WW.js.map → FacilityPicker-Diq2hnYg.js.map} +1 -1
  9. package/dist/{InventoryPage-CPbzfDMR.js → InventoryPage-Bjpw6vTz.js} +106 -115
  10. package/dist/InventoryPage-Bjpw6vTz.js.map +1 -0
  11. package/dist/{MemberProfileCard-0vjO3Gzd.js → MemberProfileCard-BLUVRILO.js} +10 -9
  12. package/dist/MemberProfileCard-BLUVRILO.js.map +1 -0
  13. package/dist/{PaymentCreatePage-BYmDZAIB.js → PaymentCreatePage-B5VOgTx9.js} +173 -177
  14. package/dist/PaymentCreatePage-B5VOgTx9.js.map +1 -0
  15. package/dist/{PaymentsPage-BXPvKon-.js → PaymentsPage-DY6BclkN.js} +24 -23
  16. package/dist/{PaymentsPage-BXPvKon-.js.map → PaymentsPage-DY6BclkN.js.map} +1 -1
  17. package/dist/PickupCreatePage-CCSiyFQF.js +706 -0
  18. package/dist/PickupCreatePage-CCSiyFQF.js.map +1 -0
  19. package/dist/{PickupsPage-D66_Wta4.js → PickupsPage-DGi6T5Of.js} +83 -90
  20. package/dist/PickupsPage-DGi6T5Of.js.map +1 -0
  21. package/dist/PmGuard-C90yhpsN.js +592 -0
  22. package/dist/PmGuard-C90yhpsN.js.map +1 -0
  23. package/dist/{PmTable-B9970kPY.js → PmTable-BkK65bJQ.js} +98 -98
  24. package/dist/PmTable-BkK65bJQ.js.map +1 -0
  25. package/dist/{ProductEditPage-B8qFTCW9.js → ProductEditPage-CQj9egzW.js} +138 -137
  26. package/dist/ProductEditPage-CQj9egzW.js.map +1 -0
  27. package/dist/{ProductsPage-C7_r9cKn.js → ProductsPage-i8QVw_Jm.js} +65 -64
  28. package/dist/{ProductsPage-C7_r9cKn.js.map → ProductsPage-i8QVw_Jm.js.map} +1 -1
  29. package/dist/PurchaseCreatePage-Bp6bl9n8.js +591 -0
  30. package/dist/PurchaseCreatePage-Bp6bl9n8.js.map +1 -0
  31. package/dist/{PurchaseRequestDetailPage-C7aAwEqw.js → PurchaseRequestDetailPage-CNAqIFef.js} +216 -215
  32. package/dist/PurchaseRequestDetailPage-CNAqIFef.js.map +1 -0
  33. package/dist/{PurchaseRequestsPage-BwCkbpaX.js → PurchaseRequestsPage-BJqDlNrc.js} +57 -56
  34. package/dist/{PurchaseRequestsPage-BwCkbpaX.js.map → PurchaseRequestsPage-BJqDlNrc.js.map} +1 -1
  35. package/dist/{PurchasesPage-CvaZouVy.js → PurchasesPage-BQEToymQ.js} +76 -75
  36. package/dist/{PurchasesPage-CvaZouVy.js.map → PurchasesPage-BQEToymQ.js.map} +1 -1
  37. package/dist/{SaleCreatePage-DP1Qmltu.js → SaleCreatePage-DbfBK4PH.js} +149 -173
  38. package/dist/SaleCreatePage-DbfBK4PH.js.map +1 -0
  39. package/dist/{SalesPage-CO3cdYX5.js → SalesPage-CTBJMxZe.js} +50 -49
  40. package/dist/SalesPage-CTBJMxZe.js.map +1 -0
  41. package/dist/SettingsPage-CiwVmzM3.js +663 -0
  42. package/dist/SettingsPage-CiwVmzM3.js.map +1 -0
  43. package/dist/{StorageUnitsPage-B9Hr_RkW.js → StorageUnitsPage-BV7nK_iE.js} +57 -56
  44. package/dist/{StorageUnitsPage-B9Hr_RkW.js.map → StorageUnitsPage-BV7nK_iE.js.map} +1 -1
  45. package/dist/{TransactionsPage-HKIGwEZN.js → TransactionsPage-Cocn4901.js} +55 -54
  46. package/dist/TransactionsPage-Cocn4901.js.map +1 -0
  47. package/dist/TransferCreatePage-DbjcjuOg.js +316 -0
  48. package/dist/TransferCreatePage-DbjcjuOg.js.map +1 -0
  49. package/dist/TransfersPage-BFVF7Xvc.js +471 -0
  50. package/dist/TransfersPage-BFVF7Xvc.js.map +1 -0
  51. package/dist/VialsPage-BNzYTLVd.js +321 -0
  52. package/dist/VialsPage-BNzYTLVd.js.map +1 -0
  53. package/dist/index.js +652 -34
  54. package/dist/index.js.map +1 -1
  55. package/dist/settingsStore-KW217unV.js +417 -0
  56. package/dist/settingsStore-KW217unV.js.map +1 -0
  57. package/package.json +1 -1
  58. package/dist/BrandsPage-CSA3meke.js.map +0 -1
  59. package/dist/DashboardPage-CqaquOs2.js.map +0 -1
  60. package/dist/InventoryPage-CPbzfDMR.js.map +0 -1
  61. package/dist/MemberProfileCard-0vjO3Gzd.js.map +0 -1
  62. package/dist/PaymentCreatePage-BYmDZAIB.js.map +0 -1
  63. package/dist/PickupCreatePage-CMGwoAXj.js +0 -426
  64. package/dist/PickupCreatePage-CMGwoAXj.js.map +0 -1
  65. package/dist/PickupsPage-D66_Wta4.js.map +0 -1
  66. package/dist/PmTable-B9970kPY.js.map +0 -1
  67. package/dist/ProductEditPage-B8qFTCW9.js.map +0 -1
  68. package/dist/PurchaseCreatePage-CDfNDcKG.js +0 -627
  69. package/dist/PurchaseCreatePage-CDfNDcKG.js.map +0 -1
  70. package/dist/PurchaseRequestDetailPage-C7aAwEqw.js.map +0 -1
  71. package/dist/SaleCreatePage-DP1Qmltu.js.map +0 -1
  72. package/dist/SalesPage-CO3cdYX5.js.map +0 -1
  73. package/dist/SettingsPage-DvVRwSFw.js +0 -711
  74. package/dist/SettingsPage-DvVRwSFw.js.map +0 -1
  75. package/dist/TransactionsPage-HKIGwEZN.js.map +0 -1
  76. package/dist/TransferCreatePage-DMuZqQ3c.js +0 -363
  77. package/dist/TransferCreatePage-DMuZqQ3c.js.map +0 -1
  78. package/dist/TransfersPage-COIyouL4.js +0 -480
  79. package/dist/TransfersPage-COIyouL4.js.map +0 -1
  80. package/dist/VialsPage-BNPUwGCU.js +0 -922
  81. package/dist/VialsPage-BNPUwGCU.js.map +0 -1
  82. package/dist/currency-ClRLIEg2.js +0 -1372
  83. package/dist/currency-ClRLIEg2.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductEditPage-CQj9egzW.js","names":[],"sources":["../src/views/ProductEditPage.jsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { usePermissionedEffect } from '@pm/utils/permissions';\nimport {\n Alert,\n Box,\n Button,\n Card,\n CardContent,\n Checkbox,\n Divider,\n FormControlLabel,\n Grid,\n Stack,\n TextField,\n Typography,\n} from '@mui/material';\nimport SaveRoundedIcon from '@mui/icons-material/SaveRounded';\nimport { showToast } from '@/common/toaster/toaster';\nimport PmPageShell from '@pm/components/PmPageShell';\nimport PmNav from '@pm/components/PmNav';\nimport PmGuard from '@pm/components/PmGuard';\nimport {\n getBrands,\n getCategories,\n getImmunizationMaster,\n getProduct,\n upsertProduct,\n} from '@pm/services/pmApi';\nimport { PRODUCT_UNITS, VACCINES_CATEGORY_CODE, VACCINE_ROUTES } from '@pm/utils/constants';\nimport {\n isClean,\n validateDose,\n validateMaxConcurrentVials,\n validateOpenVialValidity,\n validateReconstitutedValidity,\n validateRequired,\n validateTempRange,\n validateVialVolume,\n} from '@pm/utils/validation';\nimport { useFieldErrors } from '@pm/utils/useFieldErrors';\nimport { usePmSettings } from '@pm/utils/settingsStore';\nimport { PmFieldHelp, PmSelect } from '@pm/components/PmTable';\n\nconst EMPTY_VACCINE = {\n vaccineCode: '',\n vialVolumeMl: '',\n adultDoseMl: '',\n childDoseMl: '',\n openVialValidityHours: 6,\n maxConcurrentOpenVials: 2,\n requiresReconstitution: false,\n reconstitutedValidityHours: '',\n route: '',\n storageTempMinCelsius: '',\n storageTempMaxCelsius: '',\n comments: '',\n};\n\nexport default function ProductEditPage() {\n const { productId } = useParams();\n const navigate = useNavigate();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n // Whether this page is creating a brand-new product (no existing row) vs\n // editing an existing one. Drives the \"Add\" vs \"Edit\" header. The route\n // always carries a product id (even for new), so we can't infer it from\n // the id alone — it's resolved by whether getProduct found a record.\n const [isNew, setIsNew] = useState(false);\n const [categories, setCategories] = useState([]);\n const [brands, setBrands] = useState([]);\n const [vaccineMaster, setVaccineMaster] = useState([]);\n const fieldErrors = useFieldErrors();\n const settings = usePmSettings();\n const manageSales = settings?.manageSales !== false;\n const [form, setForm] = useState({\n id: productId,\n name: '',\n categoryId: '',\n brandId: '',\n description: '',\n unit: '',\n unitOther: '',\n hasExpiry: true,\n needsStorageUnit: false,\n notForSale: false,\n isActive: true,\n imageUuids: [],\n vaccineConfig: null,\n });\n\n const selectedCategory = useMemo(\n () => categories.find((c) => c.id === form.categoryId),\n [categories, form.categoryId]\n );\n const isVaccine = selectedCategory?.code?.toUpperCase() === VACCINES_CATEGORY_CODE;\n\n usePermissionedEffect('update.manage.productManagement.product', () => {\n async function load() {\n setLoading(true);\n try {\n const [cats, brandList, vaccines] = await Promise.all([\n getCategories(),\n getBrands(),\n getImmunizationMaster().catch(() => []),\n ]);\n setCategories(cats);\n setBrands(brandList);\n setVaccineMaster(vaccines);\n\n // Try fetching existing product; if it returns 404 we treat it as new.\n try {\n const existing = await getProduct(productId);\n setIsNew(false);\n setForm({\n id: existing.id,\n name: existing.name ?? '',\n categoryId: existing.categoryId ?? '',\n brandId: existing.brandId ?? '',\n description: existing.description ?? '',\n unit: existing.unit ?? 'PIECE',\n unitOther: existing.unitOther ?? '',\n hasExpiry: existing.hasExpiry ?? false,\n needsStorageUnit: existing.needsStorageUnit ?? false,\n notForSale: existing.notForSale ?? false,\n isActive: existing.isActive ?? true,\n imageUuids: existing.imageUuids ?? [],\n vaccineConfig: existing.vaccineConfig\n ? {\n vaccineCode: existing.vaccineConfig.vaccineCode ?? '',\n vialVolumeMl: existing.vaccineConfig.vialVolumeMl ?? '',\n adultDoseMl: existing.vaccineConfig.adultDoseMl ?? '',\n childDoseMl: existing.vaccineConfig.childDoseMl ?? '',\n openVialValidityHours: existing.vaccineConfig.openVialValidityHours ?? 6,\n maxConcurrentOpenVials: existing.vaccineConfig.maxConcurrentOpenVials ?? 2,\n requiresReconstitution: existing.vaccineConfig.requiresReconstitution ?? false,\n reconstitutedValidityHours: existing.vaccineConfig.reconstitutedValidityHours ?? '',\n route: existing.vaccineConfig.route ?? '',\n storageTempMinCelsius: existing.vaccineConfig.storageTempMinCelsius ?? '',\n storageTempMaxCelsius: existing.vaccineConfig.storageTempMaxCelsius ?? '',\n comments: existing.vaccineConfig.comments ?? '',\n }\n : null,\n });\n } catch {\n // new product – fall through with default form\n setIsNew(true);\n }\n } catch (err) {\n setError(err?.response?.data?.message ?? err?.message ?? 'Failed to load product');\n } finally {\n setLoading(false);\n }\n }\n void load();\n }, [productId]);\n\n useEffect(() => {\n if (isVaccine) {\n // Vaccines are dispensed per vial and live in cold-chain storage — pin both\n // the unit and needsStorageUnit so they can't drift away from those rules.\n setForm((f) => ({\n ...f,\n unit: 'VIAL',\n needsStorageUnit: true,\n vaccineConfig: f.vaccineConfig ?? { ...EMPTY_VACCINE },\n }));\n } else {\n // Switched to (or loaded as) a non-vaccine category — drop any vaccine\n // config so it isn't sent on save. Persisting half-filled config for a\n // non-vaccine product would error on the backend.\n setForm((f) => (f.vaccineConfig ? { ...f, vaccineConfig: null } : f));\n }\n }, [isVaccine]);\n\n function patch(k, v) {\n setForm((f) => ({ ...f, [k]: v }));\n }\n\n function patchVaccine(k, v) {\n setForm((f) => ({ ...f, vaccineConfig: { ...(f.vaccineConfig ?? EMPTY_VACCINE), [k]: v } }));\n }\n\n // -------------------- Field-level error map --------------------\n const errors = useMemo(() => {\n const base = {\n name: validateRequired(form.name, 'Product name'),\n categoryId: validateRequired(form.categoryId, 'Category'),\n brandId: validateRequired(form.brandId, 'Brand'),\n unit: validateRequired(form.unit, 'Unit'),\n // Custom unit label is required only when unit is OTHER.\n unitOther: form.unit === 'OTHER' ? validateRequired(form.unitOther, 'Custom unit') : '',\n };\n if (isVaccine && form.vaccineConfig) {\n const v = form.vaccineConfig;\n const temps = validateTempRange(v.storageTempMinCelsius, v.storageTempMaxCelsius);\n Object.assign(base, {\n vaccineCode: validateRequired(v.vaccineCode, 'Vaccine'),\n vialVolumeMl: validateVialVolume(v.vialVolumeMl),\n adultDoseMl: validateDose(v.adultDoseMl, 'Adult dose', v.vialVolumeMl),\n childDoseMl: validateDose(v.childDoseMl, 'Child dose', v.vialVolumeMl),\n openVialValidityHours: validateOpenVialValidity(v.openVialValidityHours),\n maxConcurrentOpenVials: validateMaxConcurrentVials(v.maxConcurrentOpenVials),\n reconstitutedValidityHours: validateReconstitutedValidity(\n v.reconstitutedValidityHours,\n v.requiresReconstitution\n ),\n storageTempMinCelsius: temps.min,\n storageTempMaxCelsius: temps.max,\n });\n // Either an adult or a child dose must be configured.\n if (!v.adultDoseMl && !v.childDoseMl) {\n base.adultDoseMl = base.adultDoseMl || 'Provide at least one dose (adult or child)';\n base.childDoseMl = base.childDoseMl || 'Provide at least one dose (adult or child)';\n }\n }\n return base;\n }, [form, isVaccine]);\n\n const formIsValid = isClean(errors);\n\n async function save() {\n if (!formIsValid) {\n fieldErrors.markAllTouched();\n setError('Please fix the highlighted fields and try again.');\n return;\n }\n try {\n const payload = {\n id: form.id,\n name: form.name.trim(),\n categoryId: form.categoryId,\n brandId: form.brandId,\n description: form.description || null,\n unit: form.unit,\n unitOther: form.unit === 'OTHER' ? (form.unitOther?.trim() || null) : null,\n hasExpiry: !!form.hasExpiry,\n needsStorageUnit: !!form.needsStorageUnit,\n notForSale: manageSales ? !!form.notForSale : false,\n isActive: !!form.isActive,\n imageUuids: form.imageUuids ?? [],\n vaccineConfig: form.vaccineConfig\n ? {\n vaccineCode: form.vaccineConfig.vaccineCode?.trim().toUpperCase(),\n vialVolumeMl: Number(form.vaccineConfig.vialVolumeMl),\n adultDoseMl: form.vaccineConfig.adultDoseMl === '' ? null : Number(form.vaccineConfig.adultDoseMl),\n childDoseMl: form.vaccineConfig.childDoseMl === '' ? null : Number(form.vaccineConfig.childDoseMl),\n openVialValidityHours: Number(form.vaccineConfig.openVialValidityHours ?? 6),\n maxConcurrentOpenVials: Number(form.vaccineConfig.maxConcurrentOpenVials ?? 2),\n requiresReconstitution: !!form.vaccineConfig.requiresReconstitution,\n reconstitutedValidityHours: form.vaccineConfig.reconstitutedValidityHours === ''\n ? null\n : Number(form.vaccineConfig.reconstitutedValidityHours),\n route: form.vaccineConfig.route || null,\n storageTempMinCelsius: form.vaccineConfig.storageTempMinCelsius === ''\n ? null\n : Number(form.vaccineConfig.storageTempMinCelsius),\n storageTempMaxCelsius: form.vaccineConfig.storageTempMaxCelsius === ''\n ? null\n : Number(form.vaccineConfig.storageTempMaxCelsius),\n comments: form.vaccineConfig.comments || null,\n }\n : null,\n };\n await upsertProduct(payload);\n showToast({ message: 'Product saved.', type: 'success' });\n navigate('/ui/medplat/manage/pm/products');\n } catch (err) {\n setError(err?.response?.data?.message ?? err?.message ?? 'Failed to save product');\n }\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'update.manage.productManagement.product'} title=\"You don’t have permission to create or edit products\">\n <PmPageShell\n title={isNew ? 'Add Product' : 'Edit Product'}\n subtitle={`Category: ${selectedCategory?.code ?? '—'}`}\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\" onClick={() => navigate('/ui/medplat/manage/pm/products')}>Cancel</Button>\n <Button variant=\"contained\" startIcon={<SaveRoundedIcon />}\n disabled={!formIsValid}\n onClick={() => void save()}>Save</Button>\n </Stack>\n }\n >\n {loading ? <Alert severity=\"info\">Loading…</Alert> : null}\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n <Card sx={{ borderRadius: 1.5, mb: 2 }}>\n <CardContent>\n <Typography variant=\"h6\" sx={{ fontWeight: 800, mb: 2 }}>Basic Details</Typography>\n <Grid container spacing={2}>\n <Grid item xs={12} md={6}>\n <TextField\n required\n fullWidth size=\"small\" label=\"Product Name\"\n value={form.name}\n inputProps={{ maxLength: 255 }}\n onChange={(e) => patch('name', e.target.value)}\n onBlur={fieldErrors.onBlur('name')}\n error={fieldErrors.show('name') && !!errors.name}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp message={fieldErrors.show('name') ? errors.name : ''} value={form.name} max={255} />}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <PmSelect\n label=\"Category\"\n required\n value={form.categoryId}\n onChange={(v) => patch('categoryId', v)}\n onBlur={fieldErrors.onBlur('categoryId')}\n error={fieldErrors.show('categoryId') && !!errors.categoryId}\n helperText={fieldErrors.show('categoryId') ? errors.categoryId : ''}\n options={categories.map((c) => ({ value: c.id, label: `${c.name} (${c.code})` }))}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <PmSelect\n label=\"Brand\"\n required\n value={form.brandId}\n onChange={(v) => patch('brandId', v)}\n onBlur={fieldErrors.onBlur('brandId')}\n error={fieldErrors.show('brandId') && !!errors.brandId}\n helperText={fieldErrors.show('brandId') ? errors.brandId : ''}\n options={brands.map((b) => ({ value: b.id, label: b.name }))}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <PmSelect\n label=\"Unit\"\n required\n disabled={isVaccine}\n value={form.unit}\n onChange={(v) => patch('unit', v)}\n onBlur={fieldErrors.onBlur('unit')}\n error={fieldErrors.show('unit') && !!errors.unit}\n helperText={fieldErrors.show('unit') && errors.unit\n ? errors.unit\n : isVaccine ? 'Vaccines must use VIAL' : ''}\n options={PRODUCT_UNITS}\n />\n </Grid>\n {form.unit === 'OTHER' ? (\n <Grid item xs={12} md={3}>\n <TextField\n required fullWidth size=\"small\" label=\"Custom unit name\"\n value={form.unitOther}\n inputProps={{ maxLength: 50 }}\n onChange={(e) => patch('unitOther', e.target.value)}\n onBlur={fieldErrors.onBlur('unitOther')}\n error={fieldErrors.show('unitOther') && !!errors.unitOther}\n FormHelperTextProps={{ component: 'div' }}\n helperText={<PmFieldHelp\n message={fieldErrors.show('unitOther') && errors.unitOther ? errors.unitOther : 'e.g. Strip, Ampoule, Sachet'}\n value={form.unitOther} max={50} />}\n />\n </Grid>\n ) : null}\n <Grid item xs={6} md={3}>\n <FormControlLabel\n control={<Checkbox\n checked={!!form.hasExpiry}\n disabled={isVaccine}\n onChange={(e) => patch('hasExpiry', e.target.checked)} />}\n label={isVaccine ? 'Has expiry (vaccine)' : 'Has expiry'} />\n </Grid>\n <Grid item xs={6} md={3}>\n <FormControlLabel\n control={<Checkbox\n checked={!!form.needsStorageUnit}\n disabled={isVaccine}\n onChange={(e) => patch('needsStorageUnit', e.target.checked)} />}\n label={isVaccine ? 'Needs storage unit (vaccine)' : 'Needs storage unit'} />\n </Grid>\n {manageSales ? (\n <Grid item xs={6} md={3}>\n <FormControlLabel control={<Checkbox checked={!!form.notForSale}\n onChange={(e) => patch('notForSale', e.target.checked)} />} label=\"Not for sale\" />\n </Grid>\n ) : null}\n <Grid item xs={6} md={3}>\n <FormControlLabel control={<Checkbox checked={!!form.isActive}\n onChange={(e) => patch('isActive', e.target.checked)} />} label=\"Active\" />\n </Grid>\n <Grid item xs={12}>\n <TextField fullWidth size=\"small\" multiline minRows={2} label=\"Description\" value={form.description}\n onChange={(e) => patch('description', e.target.value)} />\n </Grid>\n </Grid>\n </CardContent>\n </Card>\n\n {isVaccine ? (\n <Card sx={{ borderRadius: 1.5 }}>\n <CardContent>\n <Stack direction=\"row\" justifyContent=\"space-between\" alignItems=\"center\" sx={{ mb: 2 }}>\n <Typography variant=\"h6\" sx={{ fontWeight: 800 }}>Vaccine Configuration</Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n Required for vaccine products. Controls vial size, dosing, and shelf life rules.\n </Typography>\n </Stack>\n <Divider sx={{ mb: 2 }} />\n <Grid container spacing={2}>\n <Grid item xs={12} md={3}>\n <PmSelect\n label=\"Vaccine\"\n required\n value={form.vaccineConfig?.vaccineCode || ''}\n onChange={(v) => patchVaccine('vaccineCode', v)}\n onBlur={fieldErrors.onBlur('vaccineCode')}\n error={fieldErrors.show('vaccineCode') && !!errors.vaccineCode}\n helperText={fieldErrors.show('vaccineCode') && errors.vaccineCode\n ? errors.vaccineCode\n : 'Sourced from medplat_immunization_master'}\n noOptionsText=\"No vaccines configured in immunization master\"\n options={vaccineMaster.map((v) => ({ value: v.vaccineCode, label: `${v.vaccineName} (${v.vaccineCode})` }))}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField required fullWidth size=\"small\" type=\"number\" inputProps={{ step: '0.01', min: 0 }}\n label=\"Vial Volume (ml)\"\n value={form.vaccineConfig?.vialVolumeMl ?? ''}\n onChange={(e) => patchVaccine('vialVolumeMl', e.target.value)}\n onBlur={fieldErrors.onBlur('vialVolumeMl')}\n error={fieldErrors.show('vialVolumeMl') && !!errors.vialVolumeMl}\n helperText={fieldErrors.show('vialVolumeMl') ? errors.vialVolumeMl : ''}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField fullWidth size=\"small\" type=\"number\" inputProps={{ step: '0.01', min: 0 }}\n label=\"Adult Dose (ml)\"\n value={form.vaccineConfig?.adultDoseMl ?? ''}\n onChange={(e) => patchVaccine('adultDoseMl', e.target.value)}\n onBlur={fieldErrors.onBlur('adultDoseMl')}\n error={fieldErrors.show('adultDoseMl') && !!errors.adultDoseMl}\n helperText={fieldErrors.show('adultDoseMl') ? errors.adultDoseMl : ''}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField fullWidth size=\"small\" type=\"number\" inputProps={{ step: '0.01', min: 0 }}\n label=\"Child Dose (ml)\"\n value={form.vaccineConfig?.childDoseMl ?? ''}\n onChange={(e) => patchVaccine('childDoseMl', e.target.value)}\n onBlur={fieldErrors.onBlur('childDoseMl')}\n error={fieldErrors.show('childDoseMl') && !!errors.childDoseMl}\n helperText={fieldErrors.show('childDoseMl') ? errors.childDoseMl : ''}\n />\n </Grid>\n\n <Grid item xs={12} md={3}>\n <TextField required fullWidth size=\"small\" type=\"number\" inputProps={{ min: 0, max: 720 }}\n label=\"Open vial validity (hours)\"\n value={form.vaccineConfig?.openVialValidityHours ?? ''}\n onChange={(e) => patchVaccine('openVialValidityHours', e.target.value)}\n onBlur={fieldErrors.onBlur('openVialValidityHours')}\n error={fieldErrors.show('openVialValidityHours') && !!errors.openVialValidityHours}\n helperText={\n fieldErrors.show('openVialValidityHours') && errors.openVialValidityHours\n ? errors.openVialValidityHours\n : '0 = single-use; max 720 (~30 days)'\n }\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField required fullWidth size=\"small\" type=\"number\" inputProps={{ min: 1, max: 20 }}\n label=\"Max concurrent open vials\"\n value={form.vaccineConfig?.maxConcurrentOpenVials ?? ''}\n onChange={(e) => patchVaccine('maxConcurrentOpenVials', e.target.value)}\n onBlur={fieldErrors.onBlur('maxConcurrentOpenVials')}\n error={fieldErrors.show('maxConcurrentOpenVials') && !!errors.maxConcurrentOpenVials}\n helperText={fieldErrors.show('maxConcurrentOpenVials') ? errors.maxConcurrentOpenVials : ''}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <FormControlLabel control={<Checkbox checked={!!form.vaccineConfig?.requiresReconstitution}\n onChange={(e) => patchVaccine('requiresReconstitution', e.target.checked)} />} label=\"Requires reconstitution\" />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField fullWidth size=\"small\" type=\"number\" inputProps={{ min: 1, max: 720 }}\n required={!!form.vaccineConfig?.requiresReconstitution}\n disabled={!form.vaccineConfig?.requiresReconstitution}\n label=\"Reconstituted validity (hours)\"\n value={form.vaccineConfig?.reconstitutedValidityHours ?? ''}\n onChange={(e) => patchVaccine('reconstitutedValidityHours', e.target.value)}\n onBlur={fieldErrors.onBlur('reconstitutedValidityHours')}\n error={fieldErrors.show('reconstitutedValidityHours') && !!errors.reconstitutedValidityHours}\n helperText={fieldErrors.show('reconstitutedValidityHours') ? errors.reconstitutedValidityHours : ''}\n />\n </Grid>\n\n <Grid item xs={12} md={3}>\n <PmSelect\n label=\"Route of Administration\"\n value={form.vaccineConfig?.route || ''}\n onChange={(v) => patchVaccine('route', v)}\n options={VACCINE_ROUTES}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField fullWidth size=\"small\" type=\"number\" inputProps={{ step: '0.1', min: -90, max: 30 }}\n label=\"Storage temp min (°C)\"\n value={form.vaccineConfig?.storageTempMinCelsius ?? ''}\n onChange={(e) => patchVaccine('storageTempMinCelsius', e.target.value)}\n onBlur={fieldErrors.onBlur('storageTempMinCelsius')}\n error={fieldErrors.show('storageTempMinCelsius') && !!errors.storageTempMinCelsius}\n helperText={\n fieldErrors.show('storageTempMinCelsius') && errors.storageTempMinCelsius\n ? errors.storageTempMinCelsius\n : 'Allowed range: −90°C to +30°C'\n }\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <TextField fullWidth size=\"small\" type=\"number\" inputProps={{ step: '0.1', min: -90, max: 30 }}\n label=\"Storage temp max (°C)\"\n value={form.vaccineConfig?.storageTempMaxCelsius ?? ''}\n onChange={(e) => patchVaccine('storageTempMaxCelsius', e.target.value)}\n onBlur={fieldErrors.onBlur('storageTempMaxCelsius')}\n error={fieldErrors.show('storageTempMaxCelsius') && !!errors.storageTempMaxCelsius}\n helperText={\n fieldErrors.show('storageTempMaxCelsius') && errors.storageTempMaxCelsius\n ? errors.storageTempMaxCelsius\n : 'Allowed range: −90°C to +30°C'\n }\n />\n </Grid>\n\n <Grid item xs={12}>\n <TextField fullWidth size=\"small\" multiline minRows={2}\n label=\"Comments\" value={form.vaccineConfig?.comments || ''}\n onChange={(e) => patchVaccine('comments', e.target.value)} />\n </Grid>\n </Grid>\n </CardContent>\n </Card>\n ) : null}\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
@@ -1,28 +1,29 @@
1
- import { a as e, i as t, j as n, n as r, o as i, r as a } from "./currency-ClRLIEg2.js";
2
- import { c as o, s, t as c } from "./PmTable-B9970kPY.js";
3
- import { m as l } from "./constants-5ZCZo-Zm.js";
1
+ import { S as e } from "./settingsStore-KW217unV.js";
2
+ import { c as t, s as n, t as r } from "./PmTable-BkK65bJQ.js";
3
+ import { m as i } from "./constants-5ZCZo-Zm.js";
4
+ import { a, i as o, n as s, r as c, t as l } from "./PmGuard-C90yhpsN.js";
4
5
  import { useState as u } from "react";
5
6
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
6
- import { v4 as p } from "uuid";
7
- import { Alert as m, Box as h, Button as g, Chip as _, FormControlLabel as v, InputAdornment as y, Skeleton as b, Stack as x, TableBody as S, TableCell as C, TableHead as w, TableRow as T, TextField as E, Typography as D } from "@mui/material";
8
- import O from "@mui/icons-material/AddRounded";
9
- import k from "@mui/icons-material/RefreshRounded";
10
- import { showToast as A } from "@/common/toaster/toaster";
11
- import j from "@/views/custom-components/CustomSwitch";
12
- import { useNavigate as M } from "react-router-dom";
13
- import N from "@mui/icons-material/Inventory2Rounded";
14
- import P from "@mui/icons-material/VaccinesRounded";
7
+ import { Alert as p, Box as m, Button as h, Chip as g, FormControlLabel as _, InputAdornment as v, Skeleton as y, Stack as b, TableBody as x, TableCell as S, TableHead as C, TableRow as w, TextField as T, Typography as E } from "@mui/material";
8
+ import D from "@mui/icons-material/VaccinesRounded";
9
+ import { showToast as O } from "@/common/toaster/toaster";
10
+ import { v4 as k } from "uuid";
11
+ import A from "@mui/icons-material/AddRounded";
12
+ import j from "@mui/icons-material/RefreshRounded";
13
+ import M from "@/views/custom-components/CustomSwitch";
14
+ import { useNavigate as N } from "react-router-dom";
15
+ import P from "@mui/icons-material/Inventory2Rounded";
15
16
  import F from "@mui/icons-material/SearchRounded";
16
17
  //#region src/views/ProductsPage.jsx
17
18
  function I() {
18
- let I = M(), L = e().has("update.manage.productManagement.product"), [R, z] = u([]), [B, V] = u(!1), [H, U] = u(""), [W, G] = u(""), [K, q] = u(!1);
19
+ let I = N(), L = o().has("update.manage.productManagement.product"), [R, z] = u([]), [B, V] = u(!1), [H, U] = u(""), [W, G] = u(""), [K, q] = u(!1);
19
20
  async function J() {
20
21
  V(!0), U("");
21
22
  try {
22
- z(await n(void 0, !0));
23
+ z(await e(void 0, !0));
23
24
  } catch (e) {
24
25
  let t = e?.response?.data?.message ?? e?.message ?? "Failed to load products";
25
- U(t), A({
26
+ U(t), O({
26
27
  message: t,
27
28
  type: "error"
28
29
  });
@@ -30,7 +31,7 @@ function I() {
30
31
  V(!1);
31
32
  }
32
33
  }
33
- t("view.manage.productManagement.product", () => {
34
+ c("view.manage.productManagement.product", () => {
34
35
  J();
35
36
  }, []);
36
37
  let Y = R.filter((e) => {
@@ -40,43 +41,43 @@ function I() {
40
41
  return e.name?.toLowerCase().includes(t) || e.categoryName?.toLowerCase().includes(t) || e.brandName?.toLowerCase().includes(t) || e.vaccineConfig?.vaccineCode?.toLowerCase().includes(t);
41
42
  });
42
43
  function X() {
43
- I(`/ui/medplat/manage/pm/products/${p()}`);
44
+ I(`/ui/medplat/manage/pm/products/${k()}`);
44
45
  }
45
- return /* @__PURE__ */ f(h, { children: [/* @__PURE__ */ d(a, {}), /* @__PURE__ */ d(r, {
46
+ return /* @__PURE__ */ f(m, { children: [/* @__PURE__ */ d(s, {}), /* @__PURE__ */ d(l, {
46
47
  perm: "view.manage.productManagement.product",
47
- children: /* @__PURE__ */ f(i, {
48
+ children: /* @__PURE__ */ f(a, {
48
49
  title: "Products",
49
50
  subtitle: "Each product is tracked separately. Vaccines need additional setup for vial size and dosing.",
50
51
  chips: ["Catalog"],
51
- actions: /* @__PURE__ */ f(x, {
52
+ actions: /* @__PURE__ */ f(b, {
52
53
  direction: "row",
53
54
  spacing: 1,
54
- children: [/* @__PURE__ */ d(g, {
55
+ children: [/* @__PURE__ */ d(h, {
55
56
  variant: "outlined",
56
- startIcon: /* @__PURE__ */ d(k, {}),
57
+ startIcon: /* @__PURE__ */ d(j, {}),
57
58
  onClick: () => void J(),
58
59
  children: "Refresh"
59
- }), L ? /* @__PURE__ */ d(g, {
60
+ }), L ? /* @__PURE__ */ d(h, {
60
61
  variant: "contained",
61
- startIcon: /* @__PURE__ */ d(O, {}),
62
+ startIcon: /* @__PURE__ */ d(A, {}),
62
63
  onClick: X,
63
64
  children: "New Product"
64
65
  }) : null]
65
66
  }),
66
- children: [H ? /* @__PURE__ */ d(m, {
67
+ children: [H ? /* @__PURE__ */ d(p, {
67
68
  severity: "error",
68
69
  sx: { mb: 2 },
69
70
  children: H
70
- }) : null, /* @__PURE__ */ d(o, {
71
+ }) : null, /* @__PURE__ */ d(t, {
71
72
  eyebrow: "Catalog",
72
73
  title: "Products",
73
74
  subtitle: B ? "Loading…" : `${Y.length} of ${R.length} ${R.length === 1 ? "product" : "products"}${W.trim() ? ` matching "${W.trim()}"` : ""}`,
74
- actions: /* @__PURE__ */ d(v, {
75
- control: /* @__PURE__ */ d(j, {
75
+ actions: /* @__PURE__ */ d(_, {
76
+ control: /* @__PURE__ */ d(M, {
76
77
  checked: K,
77
78
  onChange: (e) => q(e.target.checked)
78
79
  }),
79
- label: /* @__PURE__ */ d(D, {
80
+ label: /* @__PURE__ */ d(E, {
80
81
  variant: "body2",
81
82
  sx: { fontWeight: 600 },
82
83
  children: "Show inactive"
@@ -87,13 +88,13 @@ function I() {
87
88
  ml: 0
88
89
  }
89
90
  }),
90
- toolbar: /* @__PURE__ */ d(E, {
91
+ toolbar: /* @__PURE__ */ d(T, {
91
92
  size: "small",
92
93
  fullWidth: !0,
93
94
  placeholder: "Search by name, category, brand, or vaccine code",
94
95
  value: W,
95
96
  onChange: (e) => G(e.target.value),
96
- InputProps: { startAdornment: /* @__PURE__ */ d(y, {
97
+ InputProps: { startAdornment: /* @__PURE__ */ d(v, {
97
98
  position: "start",
98
99
  children: /* @__PURE__ */ d(F, {
99
100
  fontSize: "small",
@@ -102,36 +103,36 @@ function I() {
102
103
  }) },
103
104
  sx: { maxWidth: 540 }
104
105
  }),
105
- children: /* @__PURE__ */ f(s, { children: [/* @__PURE__ */ d(w, { children: /* @__PURE__ */ f(T, { children: [
106
- /* @__PURE__ */ d(C, { children: "Product" }),
107
- /* @__PURE__ */ d(C, { children: "Category" }),
108
- /* @__PURE__ */ d(C, { children: "Brand" }),
109
- /* @__PURE__ */ d(C, { children: "Unit" }),
110
- /* @__PURE__ */ d(C, { children: "Expiry" }),
111
- /* @__PURE__ */ d(C, { children: "Vaccine config" }),
112
- /* @__PURE__ */ d(C, { children: "Status" }),
113
- /* @__PURE__ */ d(C, {
106
+ children: /* @__PURE__ */ f(n, { children: [/* @__PURE__ */ d(C, { children: /* @__PURE__ */ f(w, { children: [
107
+ /* @__PURE__ */ d(S, { children: "Product" }),
108
+ /* @__PURE__ */ d(S, { children: "Category" }),
109
+ /* @__PURE__ */ d(S, { children: "Brand" }),
110
+ /* @__PURE__ */ d(S, { children: "Unit" }),
111
+ /* @__PURE__ */ d(S, { children: "Expiry" }),
112
+ /* @__PURE__ */ d(S, { children: "Vaccine config" }),
113
+ /* @__PURE__ */ d(S, { children: "Status" }),
114
+ /* @__PURE__ */ d(S, {
114
115
  align: "right",
115
116
  children: "Action"
116
117
  })
117
- ] }) }), /* @__PURE__ */ d(S, { children: B ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ d(T, { children: Array.from({ length: 8 }).map((e, t) => /* @__PURE__ */ d(C, { children: /* @__PURE__ */ d(b, { height: 22 }) }, t)) }, t)) : Y.length === 0 ? /* @__PURE__ */ d(c, {
118
+ ] }) }), /* @__PURE__ */ d(x, { children: B ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ d(w, { children: Array.from({ length: 8 }).map((e, t) => /* @__PURE__ */ d(S, { children: /* @__PURE__ */ d(y, { height: 22 }) }, t)) }, t)) : Y.length === 0 ? /* @__PURE__ */ d(r, {
118
119
  colSpan: 8,
119
- icon: N,
120
+ icon: P,
120
121
  title: R.length === 0 ? "No products yet" : "No matches",
121
122
  hint: R.length === 0 ? "Create categories and brands first, then add products." : "Try a different search term.",
122
- action: R.length === 0 && L ? /* @__PURE__ */ d(g, {
123
+ action: R.length === 0 && L ? /* @__PURE__ */ d(h, {
123
124
  variant: "contained",
124
125
  size: "small",
125
- startIcon: /* @__PURE__ */ d(O, {}),
126
+ startIcon: /* @__PURE__ */ d(A, {}),
126
127
  onClick: X,
127
128
  children: "Create first product"
128
129
  }) : null
129
- }) : Y.map((e) => /* @__PURE__ */ f(T, {
130
+ }) : Y.map((e) => /* @__PURE__ */ f(w, {
130
131
  hover: !0,
131
132
  children: [
132
- /* @__PURE__ */ d(C, {
133
+ /* @__PURE__ */ d(S, {
133
134
  sx: { maxWidth: 240 },
134
- children: /* @__PURE__ */ d(D, {
135
+ children: /* @__PURE__ */ d(E, {
135
136
  variant: "body2",
136
137
  sx: {
137
138
  fontWeight: 700,
@@ -140,27 +141,27 @@ function I() {
140
141
  children: e.name
141
142
  })
142
143
  }),
143
- /* @__PURE__ */ d(C, {
144
+ /* @__PURE__ */ d(S, {
144
145
  sx: { maxWidth: 160 },
145
- children: /* @__PURE__ */ d(D, {
146
+ children: /* @__PURE__ */ d(E, {
146
147
  variant: "caption",
147
148
  color: "text.secondary",
148
149
  sx: { wordBreak: "break-word" },
149
150
  children: e.categoryName
150
151
  })
151
152
  }),
152
- /* @__PURE__ */ d(C, {
153
+ /* @__PURE__ */ d(S, {
153
154
  sx: { maxWidth: 160 },
154
- children: /* @__PURE__ */ d(D, {
155
+ children: /* @__PURE__ */ d(E, {
155
156
  variant: "caption",
156
157
  color: "text.secondary",
157
158
  sx: { wordBreak: "break-word" },
158
159
  children: e.brandName
159
160
  })
160
161
  }),
161
- /* @__PURE__ */ d(C, { children: /* @__PURE__ */ d(_, {
162
+ /* @__PURE__ */ d(S, { children: /* @__PURE__ */ d(g, {
162
163
  size: "small",
163
- label: l(e.unit, e.unitOther),
164
+ label: i(e.unit, e.unitOther),
164
165
  variant: "outlined",
165
166
  sx: {
166
167
  fontWeight: 700,
@@ -168,7 +169,7 @@ function I() {
168
169
  height: 22
169
170
  }
170
171
  }) }),
171
- /* @__PURE__ */ d(C, { children: e.hasExpiry ? /* @__PURE__ */ d(_, {
172
+ /* @__PURE__ */ d(S, { children: e.hasExpiry ? /* @__PURE__ */ d(g, {
172
173
  size: "small",
173
174
  label: "Yes",
174
175
  color: "warning",
@@ -178,7 +179,7 @@ function I() {
178
179
  borderRadius: 1.5,
179
180
  height: 22
180
181
  }
181
- }) : /* @__PURE__ */ d(_, {
182
+ }) : /* @__PURE__ */ d(g, {
182
183
  size: "small",
183
184
  label: "No",
184
185
  variant: "outlined",
@@ -188,14 +189,14 @@ function I() {
188
189
  height: 22
189
190
  }
190
191
  }) }),
191
- /* @__PURE__ */ d(C, { children: e.vaccineConfig ? /* @__PURE__ */ f(x, {
192
+ /* @__PURE__ */ d(S, { children: e.vaccineConfig ? /* @__PURE__ */ f(b, {
192
193
  direction: "row",
193
194
  alignItems: "center",
194
195
  spacing: 1,
195
- children: [/* @__PURE__ */ d(P, { sx: {
196
+ children: [/* @__PURE__ */ d(D, { sx: {
196
197
  fontSize: 18,
197
198
  color: "info.main"
198
- } }), /* @__PURE__ */ f(h, { children: [/* @__PURE__ */ d(D, {
199
+ } }), /* @__PURE__ */ f(m, { children: [/* @__PURE__ */ d(E, {
199
200
  variant: "caption",
200
201
  sx: {
201
202
  fontFamily: "monospace",
@@ -204,7 +205,7 @@ function I() {
204
205
  lineHeight: 1.2
205
206
  },
206
207
  children: e.vaccineConfig.vaccineCode
207
- }), /* @__PURE__ */ f(D, {
208
+ }), /* @__PURE__ */ f(E, {
208
209
  variant: "caption",
209
210
  color: "text.secondary",
210
211
  sx: { fontVariantNumeric: "tabular-nums" },
@@ -217,12 +218,12 @@ function I() {
217
218
  " ml"
218
219
  ]
219
220
  })] })]
220
- }) : /* @__PURE__ */ d(D, {
221
+ }) : /* @__PURE__ */ d(E, {
221
222
  variant: "caption",
222
223
  color: "text.disabled",
223
224
  children: "—"
224
225
  }) }),
225
- /* @__PURE__ */ d(C, { children: /* @__PURE__ */ d(_, {
226
+ /* @__PURE__ */ d(S, { children: /* @__PURE__ */ d(g, {
226
227
  size: "small",
227
228
  label: e.isActive ? "Active" : "Inactive",
228
229
  color: e.isActive ? "success" : "default",
@@ -233,9 +234,9 @@ function I() {
233
234
  height: 22
234
235
  }
235
236
  }) }),
236
- /* @__PURE__ */ d(C, {
237
+ /* @__PURE__ */ d(S, {
237
238
  align: "right",
238
- children: L ? /* @__PURE__ */ d(g, {
239
+ children: L ? /* @__PURE__ */ d(h, {
239
240
  size: "small",
240
241
  variant: "outlined",
241
242
  onClick: () => I(`/ui/medplat/manage/pm/products/${e.id}`),
@@ -251,4 +252,4 @@ function I() {
251
252
  //#endregion
252
253
  export { I as default };
253
254
 
254
- //# sourceMappingURL=ProductsPage-C7_r9cKn.js.map
255
+ //# sourceMappingURL=ProductsPage-i8QVw_Jm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsPage-C7_r9cKn.js","names":[],"sources":["../src/views/ProductsPage.jsx"],"sourcesContent":["import { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Box,\n Button,\n Chip,\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 SearchRoundedIcon from '@mui/icons-material/SearchRounded';\nimport Inventory2RoundedIcon from '@mui/icons-material/Inventory2Rounded';\nimport VaccinesRoundedIcon from '@mui/icons-material/VaccinesRounded';\nimport { showToast } from '@/common/toaster/toaster';\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 { PmEmptyRow, PmTable, PmTableCard } from '@pm/components/PmTable';\nimport { getProducts } from '@pm/services/pmApi';\nimport { unitLabel } from '@pm/utils/constants';\nimport { usePermissionedEffect, usePmPermissions } from '@pm/utils/permissions';\n\nexport default function ProductsPage() {\n const navigate = useNavigate();\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.product');\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [search, setSearch] = useState('');\n // Default to active-only; the toggle above the table reveals inactive rows.\n const [showInactive, setShowInactive] = useState(false);\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n setItems(await getProducts(undefined, true));\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load products';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.product', () => {\n void load();\n }, []);\n\n const filtered = items.filter((p) => {\n if (!showInactive && p.isActive === false) return false;\n if (!search.trim()) return true;\n const q = search.toLowerCase();\n return (p.name?.toLowerCase().includes(q))\n || (p.categoryName?.toLowerCase().includes(q))\n || (p.brandName?.toLowerCase().includes(q))\n || (p.vaccineConfig?.vaccineCode?.toLowerCase().includes(q));\n });\n\n function createNew() {\n navigate(`/ui/medplat/manage/pm/products/${uuidv4()}`);\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.product'}>\n <PmPageShell\n title=\"Products\"\n subtitle=\"Each product is tracked separately. Vaccines need additional setup for vial size and dosing.\"\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={createNew}>New Product</Button>\n ) : null}\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n <PmTableCard\n eyebrow=\"Catalog\"\n title=\"Products\"\n subtitle={loading\n ? 'Loading…'\n : `${filtered.length} of ${items.length} ${items.length === 1 ? 'product' : 'products'}${search.trim() ? ` matching \"${search.trim()}\"` : ''}`}\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 toolbar={\n <TextField\n size=\"small\"\n fullWidth\n placeholder=\"Search by name, category, brand, or vaccine code\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchRoundedIcon fontSize=\"small\" color=\"action\" />\n </InputAdornment>\n ),\n }}\n sx={{ maxWidth: 540 }}\n />\n }\n >\n <PmTable>\n <TableHead>\n <TableRow>\n <TableCell>Product</TableCell>\n <TableCell>Category</TableCell>\n <TableCell>Brand</TableCell>\n <TableCell>Unit</TableCell>\n <TableCell>Expiry</TableCell>\n <TableCell>Vaccine config</TableCell>\n <TableCell>Status</TableCell>\n <TableCell align=\"right\">Action</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: 5 }).map((_, i) => (\n <TableRow key={i}>\n {Array.from({ length: 8 }).map((__, j) => (\n <TableCell key={j}><Skeleton height={22} /></TableCell>\n ))}\n </TableRow>\n ))\n ) : filtered.length === 0 ? (\n <PmEmptyRow\n colSpan={8}\n icon={Inventory2RoundedIcon}\n title={items.length === 0 ? 'No products yet' : 'No matches'}\n hint={items.length === 0\n ? 'Create categories and brands first, then add products.'\n : 'Try a different search term.'}\n action={items.length === 0 && canWrite ? (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={createNew}>\n Create first product\n </Button>\n ) : null}\n />\n ) : filtered.map((p) => (\n <TableRow key={p.id} hover>\n <TableCell sx={{ maxWidth: 240 }}>\n <Typography variant=\"body2\" sx={{ fontWeight: 700, wordBreak: 'break-word' }}>{p.name}</Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 160 }}>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-word' }}>{p.categoryName}</Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 160 }}>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-word' }}>{p.brandName}</Typography>\n </TableCell>\n <TableCell>\n <Chip size=\"small\" label={unitLabel(p.unit, p.unitOther)} variant=\"outlined\" sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }} />\n </TableCell>\n <TableCell>\n {p.hasExpiry\n ? <Chip size=\"small\" label=\"Yes\" color=\"warning\" variant=\"outlined\" sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }} />\n : <Chip size=\"small\" label=\"No\" variant=\"outlined\" sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }} />}\n </TableCell>\n <TableCell>\n {p.vaccineConfig ? (\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n <VaccinesRoundedIcon sx={{ fontSize: 18, color: 'info.main' }} />\n <Box>\n <Typography variant=\"caption\" sx={{ fontFamily: 'monospace', fontWeight: 800, display: 'block', lineHeight: 1.2 }}>\n {p.vaccineConfig.vaccineCode}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {p.vaccineConfig.vialVolumeMl}ml · {p.vaccineConfig.adultDoseMl ?? '—'}/{p.vaccineConfig.childDoseMl ?? '—'} ml\n </Typography>\n </Box>\n </Stack>\n ) : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={p.isActive ? 'Active' : 'Inactive'}\n color={p.isActive ? 'success' : 'default'}\n variant={p.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\"\n onClick={() => navigate(`/ui/medplat/manage/pm/products/${p.id}`)}>Edit</Button>\n ) : null}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProductsPage-i8QVw_Jm.js","names":[],"sources":["../src/views/ProductsPage.jsx"],"sourcesContent":["import { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Box,\n Button,\n Chip,\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 SearchRoundedIcon from '@mui/icons-material/SearchRounded';\nimport Inventory2RoundedIcon from '@mui/icons-material/Inventory2Rounded';\nimport VaccinesRoundedIcon from '@mui/icons-material/VaccinesRounded';\nimport { showToast } from '@/common/toaster/toaster';\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 { PmEmptyRow, PmTable, PmTableCard } from '@pm/components/PmTable';\nimport { getProducts } from '@pm/services/pmApi';\nimport { unitLabel } from '@pm/utils/constants';\nimport { usePermissionedEffect, usePmPermissions } from '@pm/utils/permissions';\n\nexport default function ProductsPage() {\n const navigate = useNavigate();\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.product');\n const [items, setItems] = useState([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [search, setSearch] = useState('');\n // Default to active-only; the toggle above the table reveals inactive rows.\n const [showInactive, setShowInactive] = useState(false);\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n setItems(await getProducts(undefined, true));\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to load products';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.product', () => {\n void load();\n }, []);\n\n const filtered = items.filter((p) => {\n if (!showInactive && p.isActive === false) return false;\n if (!search.trim()) return true;\n const q = search.toLowerCase();\n return (p.name?.toLowerCase().includes(q))\n || (p.categoryName?.toLowerCase().includes(q))\n || (p.brandName?.toLowerCase().includes(q))\n || (p.vaccineConfig?.vaccineCode?.toLowerCase().includes(q));\n });\n\n function createNew() {\n navigate(`/ui/medplat/manage/pm/products/${uuidv4()}`);\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.product'}>\n <PmPageShell\n title=\"Products\"\n subtitle=\"Each product is tracked separately. Vaccines need additional setup for vial size and dosing.\"\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={createNew}>New Product</Button>\n ) : null}\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n <PmTableCard\n eyebrow=\"Catalog\"\n title=\"Products\"\n subtitle={loading\n ? 'Loading…'\n : `${filtered.length} of ${items.length} ${items.length === 1 ? 'product' : 'products'}${search.trim() ? ` matching \"${search.trim()}\"` : ''}`}\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 toolbar={\n <TextField\n size=\"small\"\n fullWidth\n placeholder=\"Search by name, category, brand, or vaccine code\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchRoundedIcon fontSize=\"small\" color=\"action\" />\n </InputAdornment>\n ),\n }}\n sx={{ maxWidth: 540 }}\n />\n }\n >\n <PmTable>\n <TableHead>\n <TableRow>\n <TableCell>Product</TableCell>\n <TableCell>Category</TableCell>\n <TableCell>Brand</TableCell>\n <TableCell>Unit</TableCell>\n <TableCell>Expiry</TableCell>\n <TableCell>Vaccine config</TableCell>\n <TableCell>Status</TableCell>\n <TableCell align=\"right\">Action</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: 5 }).map((_, i) => (\n <TableRow key={i}>\n {Array.from({ length: 8 }).map((__, j) => (\n <TableCell key={j}><Skeleton height={22} /></TableCell>\n ))}\n </TableRow>\n ))\n ) : filtered.length === 0 ? (\n <PmEmptyRow\n colSpan={8}\n icon={Inventory2RoundedIcon}\n title={items.length === 0 ? 'No products yet' : 'No matches'}\n hint={items.length === 0\n ? 'Create categories and brands first, then add products.'\n : 'Try a different search term.'}\n action={items.length === 0 && canWrite ? (\n <Button variant=\"contained\" size=\"small\" startIcon={<AddRoundedIcon />} onClick={createNew}>\n Create first product\n </Button>\n ) : null}\n />\n ) : filtered.map((p) => (\n <TableRow key={p.id} hover>\n <TableCell sx={{ maxWidth: 240 }}>\n <Typography variant=\"body2\" sx={{ fontWeight: 700, wordBreak: 'break-word' }}>{p.name}</Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 160 }}>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-word' }}>{p.categoryName}</Typography>\n </TableCell>\n <TableCell sx={{ maxWidth: 160 }}>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ wordBreak: 'break-word' }}>{p.brandName}</Typography>\n </TableCell>\n <TableCell>\n <Chip size=\"small\" label={unitLabel(p.unit, p.unitOther)} variant=\"outlined\" sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }} />\n </TableCell>\n <TableCell>\n {p.hasExpiry\n ? <Chip size=\"small\" label=\"Yes\" color=\"warning\" variant=\"outlined\" sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }} />\n : <Chip size=\"small\" label=\"No\" variant=\"outlined\" sx={{ fontWeight: 700, borderRadius: 1.5, height: 22 }} />}\n </TableCell>\n <TableCell>\n {p.vaccineConfig ? (\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n <VaccinesRoundedIcon sx={{ fontSize: 18, color: 'info.main' }} />\n <Box>\n <Typography variant=\"caption\" sx={{ fontFamily: 'monospace', fontWeight: 800, display: 'block', lineHeight: 1.2 }}>\n {p.vaccineConfig.vaccineCode}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {p.vaccineConfig.vialVolumeMl}ml · {p.vaccineConfig.adultDoseMl ?? '—'}/{p.vaccineConfig.childDoseMl ?? '—'} ml\n </Typography>\n </Box>\n </Stack>\n ) : <Typography variant=\"caption\" color=\"text.disabled\">—</Typography>}\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={p.isActive ? 'Active' : 'Inactive'}\n color={p.isActive ? 'success' : 'default'}\n variant={p.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\"\n onClick={() => navigate(`/ui/medplat/manage/pm/products/${p.id}`)}>Edit</Button>\n ) : null}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}