@argusoft/medplat-product-management 1.0.0 → 1.0.2

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 (77) hide show
  1. package/dist/BrandsPage-CSA3meke.js +385 -0
  2. package/dist/BrandsPage-CSA3meke.js.map +1 -0
  3. package/dist/CategoriesPage-BrspzkJL.js +340 -0
  4. package/dist/CategoriesPage-BrspzkJL.js.map +1 -0
  5. package/dist/{DashboardPage-BNKUQj46.js → DashboardPage-CqaquOs2.js} +21 -22
  6. package/dist/{DashboardPage-BNKUQj46.js.map → DashboardPage-CqaquOs2.js.map} +1 -1
  7. package/dist/{FacilityPicker-Coi8I3yE.js → FacilityPicker-Dv_H95WW.js} +13 -13
  8. package/dist/{FacilityPicker-Coi8I3yE.js.map → FacilityPicker-Dv_H95WW.js.map} +1 -1
  9. package/dist/{InventoryPage-BR6jOzg2.js → InventoryPage-CPbzfDMR.js} +12 -12
  10. package/dist/{InventoryPage-BR6jOzg2.js.map → InventoryPage-CPbzfDMR.js.map} +1 -1
  11. package/dist/{MemberProfileCard-DbHZCS5n.js → MemberProfileCard-0vjO3Gzd.js} +2 -2
  12. package/dist/{MemberProfileCard-DbHZCS5n.js.map → MemberProfileCard-0vjO3Gzd.js.map} +1 -1
  13. package/dist/{PaymentCreatePage-Ci3ERnby.js → PaymentCreatePage-BYmDZAIB.js} +9 -10
  14. package/dist/{PaymentCreatePage-Ci3ERnby.js.map → PaymentCreatePage-BYmDZAIB.js.map} +1 -1
  15. package/dist/{PaymentsPage-sdg902zX.js → PaymentsPage-BXPvKon-.js} +16 -16
  16. package/dist/{PaymentsPage-sdg902zX.js.map → PaymentsPage-BXPvKon-.js.map} +1 -1
  17. package/dist/PickupCreatePage-CMGwoAXj.js +426 -0
  18. package/dist/PickupCreatePage-CMGwoAXj.js.map +1 -0
  19. package/dist/{PickupsPage-Ci2Ll0Kn.js → PickupsPage-D66_Wta4.js} +84 -39
  20. package/dist/PickupsPage-D66_Wta4.js.map +1 -0
  21. package/dist/PmTable-B9970kPY.js +375 -0
  22. package/dist/PmTable-B9970kPY.js.map +1 -0
  23. package/dist/{ProductEditPage-DL8gy85Y.js → ProductEditPage-B8qFTCW9.js} +226 -243
  24. package/dist/ProductEditPage-B8qFTCW9.js.map +1 -0
  25. package/dist/ProductsPage-C7_r9cKn.js +254 -0
  26. package/dist/ProductsPage-C7_r9cKn.js.map +1 -0
  27. package/dist/{PurchaseCreatePage-C3KMfBxJ.js → PurchaseCreatePage-CDfNDcKG.js} +150 -149
  28. package/dist/PurchaseCreatePage-CDfNDcKG.js.map +1 -0
  29. package/dist/{PurchaseRequestDetailPage-C0GYFJDl.js → PurchaseRequestDetailPage-C7aAwEqw.js} +15 -15
  30. package/dist/{PurchaseRequestDetailPage-C0GYFJDl.js.map → PurchaseRequestDetailPage-C7aAwEqw.js.map} +1 -1
  31. package/dist/{PurchaseRequestsPage-DvFH_tWe.js → PurchaseRequestsPage-BwCkbpaX.js} +14 -14
  32. package/dist/{PurchaseRequestsPage-DvFH_tWe.js.map → PurchaseRequestsPage-BwCkbpaX.js.map} +1 -1
  33. package/dist/{PurchasesPage-BCvLvSp4.js → PurchasesPage-CvaZouVy.js} +11 -12
  34. package/dist/{PurchasesPage-BCvLvSp4.js.map → PurchasesPage-CvaZouVy.js.map} +1 -1
  35. package/dist/{SaleCreatePage-DpkQMoTq.js → SaleCreatePage-DP1Qmltu.js} +30 -31
  36. package/dist/{SaleCreatePage-DpkQMoTq.js.map → SaleCreatePage-DP1Qmltu.js.map} +1 -1
  37. package/dist/{SalesPage-DUwgkEO-.js → SalesPage-CO3cdYX5.js} +18 -19
  38. package/dist/{SalesPage-DUwgkEO-.js.map → SalesPage-CO3cdYX5.js.map} +1 -1
  39. package/dist/{SettingsPage-CusC0jqJ.js → SettingsPage-DvVRwSFw.js} +104 -103
  40. package/dist/SettingsPage-DvVRwSFw.js.map +1 -0
  41. package/dist/StorageUnitsPage-B9Hr_RkW.js +470 -0
  42. package/dist/StorageUnitsPage-B9Hr_RkW.js.map +1 -0
  43. package/dist/{TransactionsPage-DDaK4VyY.js → TransactionsPage-HKIGwEZN.js} +127 -123
  44. package/dist/TransactionsPage-HKIGwEZN.js.map +1 -0
  45. package/dist/{TransferCreatePage-BxudLfhS.js → TransferCreatePage-DMuZqQ3c.js} +9 -9
  46. package/dist/{TransferCreatePage-BxudLfhS.js.map → TransferCreatePage-DMuZqQ3c.js.map} +1 -1
  47. package/dist/{TransfersPage-zgmt7teZ.js → TransfersPage-COIyouL4.js} +16 -16
  48. package/dist/{TransfersPage-zgmt7teZ.js.map → TransfersPage-COIyouL4.js.map} +1 -1
  49. package/dist/{VialsPage-CjqPfgpV.js → VialsPage-BNPUwGCU.js} +291 -224
  50. package/dist/VialsPage-BNPUwGCU.js.map +1 -0
  51. package/dist/{constants-BrA_hfAI.js → constants-5ZCZo-Zm.js} +5 -2
  52. package/dist/{constants-BrA_hfAI.js.map → constants-5ZCZo-Zm.js.map} +1 -1
  53. package/dist/{PmGuard-CjJBisaN.js → currency-ClRLIEg2.js} +186 -9
  54. package/dist/currency-ClRLIEg2.js.map +1 -0
  55. package/dist/index.js +1 -1
  56. package/package.json +1 -1
  57. package/dist/BrandsPage-DCMCVvDY.js +0 -334
  58. package/dist/BrandsPage-DCMCVvDY.js.map +0 -1
  59. package/dist/CategoriesPage-BpRhwfrc.js +0 -284
  60. package/dist/CategoriesPage-BpRhwfrc.js.map +0 -1
  61. package/dist/PickupCreatePage-CieMsgWV.js +0 -310
  62. package/dist/PickupCreatePage-CieMsgWV.js.map +0 -1
  63. package/dist/PickupsPage-Ci2Ll0Kn.js.map +0 -1
  64. package/dist/PmGuard-CjJBisaN.js.map +0 -1
  65. package/dist/PmTable-BuXZQZCU.js +0 -302
  66. package/dist/PmTable-BuXZQZCU.js.map +0 -1
  67. package/dist/ProductEditPage-DL8gy85Y.js.map +0 -1
  68. package/dist/ProductsPage-BANTKxLb.js +0 -221
  69. package/dist/ProductsPage-BANTKxLb.js.map +0 -1
  70. package/dist/PurchaseCreatePage-C3KMfBxJ.js.map +0 -1
  71. package/dist/SettingsPage-CusC0jqJ.js.map +0 -1
  72. package/dist/StorageUnitsPage-BlC2AgrJ.js +0 -469
  73. package/dist/StorageUnitsPage-BlC2AgrJ.js.map +0 -1
  74. package/dist/TransactionsPage-DDaK4VyY.js.map +0 -1
  75. package/dist/VialsPage-CjqPfgpV.js.map +0 -1
  76. package/dist/currency-BDDCDgeE.js +0 -169
  77. package/dist/currency-BDDCDgeE.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"ProductEditPage-DL8gy85Y.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 FormControl,\n FormControlLabel,\n FormHelperText,\n Grid,\n InputLabel,\n MenuItem,\n Select,\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';\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 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 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 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 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 }\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 }\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 };\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 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={form.id ? 'Edit Product' : 'New Product'}\n subtitle={`Category: ${selectedCategory?.code ?? '—'}`}\n chips={isVaccine ? ['Vaccine'] : ['Generic']}\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: 4, 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 onChange={(e) => patch('name', e.target.value)}\n onBlur={fieldErrors.onBlur('name')}\n error={fieldErrors.show('name') && !!errors.name}\n helperText={fieldErrors.show('name') ? errors.name : ''}\n />\n </Grid>\n <Grid item xs={12} md={3}>\n <FormControl required fullWidth size=\"small\"\n error={fieldErrors.show('categoryId') && !!errors.categoryId}>\n <InputLabel>Category</InputLabel>\n <Select label=\"Category\" value={form.categoryId}\n onChange={(e) => patch('categoryId', e.target.value)}\n onBlur={fieldErrors.onBlur('categoryId')}>\n {categories.map((c) => <MenuItem key={c.id} value={c.id}>{c.name} ({c.code})</MenuItem>)}\n </Select>\n {fieldErrors.show('categoryId') && errors.categoryId\n ? <FormHelperText>{errors.categoryId}</FormHelperText> : null}\n </FormControl>\n </Grid>\n <Grid item xs={12} md={3}>\n <FormControl required fullWidth size=\"small\"\n error={fieldErrors.show('brandId') && !!errors.brandId}>\n <InputLabel>Brand</InputLabel>\n <Select label=\"Brand\" value={form.brandId}\n onChange={(e) => patch('brandId', e.target.value)}\n onBlur={fieldErrors.onBlur('brandId')}>\n {brands.map((b) => <MenuItem key={b.id} value={b.id}>{b.name}</MenuItem>)}\n </Select>\n {fieldErrors.show('brandId') && errors.brandId\n ? <FormHelperText>{errors.brandId}</FormHelperText> : null}\n </FormControl>\n </Grid>\n <Grid item xs={12} md={3}>\n <FormControl required fullWidth size=\"small\"\n disabled={isVaccine}\n error={fieldErrors.show('unit') && !!errors.unit}>\n <InputLabel>Unit</InputLabel>\n <Select label=\"Unit\" value={form.unit}\n onChange={(e) => patch('unit', e.target.value)}\n onBlur={fieldErrors.onBlur('unit')}>\n {PRODUCT_UNITS.map((u) => <MenuItem key={u.value} value={u.value}>{u.label}</MenuItem>)}\n </Select>\n <FormHelperText>\n {fieldErrors.show('unit') && errors.unit\n ? errors.unit\n : isVaccine ? 'Vaccines must use VIAL' : ''}\n </FormHelperText>\n </FormControl>\n </Grid>\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: 4 }}>\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 <FormControl required fullWidth size=\"small\"\n error={fieldErrors.show('vaccineCode') && !!errors.vaccineCode}>\n <InputLabel>Vaccine</InputLabel>\n <Select\n label=\"Vaccine\"\n value={form.vaccineConfig?.vaccineCode || ''}\n onChange={(e) => patchVaccine('vaccineCode', e.target.value)}\n onBlur={fieldErrors.onBlur('vaccineCode')}\n >\n {vaccineMaster.length === 0 ? (\n <MenuItem value=\"\" disabled>\n <em>No vaccines configured in immunization master</em>\n </MenuItem>\n ) : null}\n {vaccineMaster.map((v) => (\n <MenuItem key={v.id} value={v.vaccineCode}>\n {v.vaccineName} ({v.vaccineCode})\n </MenuItem>\n ))}\n </Select>\n <FormHelperText>\n {fieldErrors.show('vaccineCode') && errors.vaccineCode\n ? errors.vaccineCode\n : 'Sourced from medplat_immunization_master'}\n </FormHelperText>\n </FormControl>\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 <FormControl fullWidth size=\"small\">\n <InputLabel>Route of Administration</InputLabel>\n <Select label=\"Route of Administration\" value={form.vaccineConfig?.route || ''}\n onChange={(e) => patchVaccine('route', e.target.value)}>\n <MenuItem value=\"\"><em>—</em></MenuItem>\n {VACCINE_ROUTES.map((r) => (\n <MenuItem key={r.value} value={r.value}>{r.label}</MenuItem>\n ))}\n </Select>\n </FormControl>\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,221 +0,0 @@
1
- import { A as e, a as t, i as n, n as r, r as i, t as a } from "./PmGuard-CjJBisaN.js";
2
- import { a as o, o as s, t as c } from "./PmTable-BuXZQZCU.js";
3
- import { useState as l } from "react";
4
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
5
- import { v4 as f } from "uuid";
6
- import { Alert as p, Box as m, Button as h, Chip as g, InputAdornment as _, Skeleton as v, Stack as y, TableBody as b, TableCell as x, TableHead as S, TableRow as C, TextField as w, Typography as T } from "@mui/material";
7
- import E from "@mui/icons-material/AddRounded";
8
- import D from "@mui/icons-material/RefreshRounded";
9
- import { showToast as O } from "@/common/toaster/toaster";
10
- import { useNavigate as k } from "react-router-dom";
11
- import A from "@mui/icons-material/Inventory2Rounded";
12
- import j from "@mui/icons-material/VaccinesRounded";
13
- import M from "@mui/icons-material/SearchRounded";
14
- //#region src/views/ProductsPage.jsx
15
- function N() {
16
- let N = k(), P = n().has("update.manage.productManagement.product"), [F, I] = l([]), [L, R] = l(!1), [z, B] = l(""), [V, H] = l("");
17
- async function U() {
18
- R(!0), B("");
19
- try {
20
- I(await e());
21
- } catch (e) {
22
- let t = e?.response?.data?.message ?? e?.message ?? "Failed to load products";
23
- B(t), O({
24
- message: t,
25
- type: "error"
26
- });
27
- } finally {
28
- R(!1);
29
- }
30
- }
31
- i("view.manage.productManagement.product", () => {
32
- U();
33
- }, []);
34
- let W = F.filter((e) => {
35
- if (!V.trim()) return !0;
36
- let t = V.toLowerCase();
37
- return e.name?.toLowerCase().includes(t) || e.categoryName?.toLowerCase().includes(t) || e.brandName?.toLowerCase().includes(t) || e.vaccineConfig?.vaccineCode?.toLowerCase().includes(t);
38
- });
39
- function G() {
40
- N(`/ui/medplat/manage/pm/products/${f()}`);
41
- }
42
- return /* @__PURE__ */ d(m, { children: [/* @__PURE__ */ u(r, {}), /* @__PURE__ */ u(a, {
43
- perm: "view.manage.productManagement.product",
44
- children: /* @__PURE__ */ d(t, {
45
- title: "Products",
46
- subtitle: "Each product is tracked separately. Vaccines need additional setup for vial size and dosing.",
47
- chips: ["Catalog"],
48
- actions: /* @__PURE__ */ d(y, {
49
- direction: "row",
50
- spacing: 1,
51
- children: [/* @__PURE__ */ u(h, {
52
- variant: "outlined",
53
- startIcon: /* @__PURE__ */ u(D, {}),
54
- onClick: () => void U(),
55
- children: "Refresh"
56
- }), P ? /* @__PURE__ */ u(h, {
57
- variant: "contained",
58
- startIcon: /* @__PURE__ */ u(E, {}),
59
- onClick: G,
60
- children: "New Product"
61
- }) : null]
62
- }),
63
- children: [z ? /* @__PURE__ */ u(p, {
64
- severity: "error",
65
- sx: { mb: 2 },
66
- children: z
67
- }) : null, /* @__PURE__ */ u(s, {
68
- eyebrow: "Catalog",
69
- title: "Products",
70
- subtitle: L ? "Loading…" : `${W.length} of ${F.length} ${F.length === 1 ? "product" : "products"}${V.trim() ? ` matching "${V.trim()}"` : ""}`,
71
- toolbar: /* @__PURE__ */ u(w, {
72
- size: "small",
73
- fullWidth: !0,
74
- placeholder: "Search by name, category, brand, or vaccine code",
75
- value: V,
76
- onChange: (e) => H(e.target.value),
77
- InputProps: { startAdornment: /* @__PURE__ */ u(_, {
78
- position: "start",
79
- children: /* @__PURE__ */ u(M, {
80
- fontSize: "small",
81
- color: "action"
82
- })
83
- }) },
84
- sx: { maxWidth: 540 }
85
- }),
86
- children: /* @__PURE__ */ d(o, { children: [/* @__PURE__ */ u(S, { children: /* @__PURE__ */ d(C, { children: [
87
- /* @__PURE__ */ u(x, { children: "Product" }),
88
- /* @__PURE__ */ u(x, { children: "Category" }),
89
- /* @__PURE__ */ u(x, { children: "Brand" }),
90
- /* @__PURE__ */ u(x, { children: "Unit" }),
91
- /* @__PURE__ */ u(x, { children: "Expiry" }),
92
- /* @__PURE__ */ u(x, { children: "Vaccine config" }),
93
- /* @__PURE__ */ u(x, { children: "Status" }),
94
- /* @__PURE__ */ u(x, {
95
- align: "right",
96
- children: "Action"
97
- })
98
- ] }) }), /* @__PURE__ */ u(b, { children: L ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ u(C, { children: Array.from({ length: 8 }).map((e, t) => /* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(v, { height: 22 }) }, t)) }, t)) : W.length === 0 ? /* @__PURE__ */ u(c, {
99
- colSpan: 8,
100
- icon: A,
101
- title: F.length === 0 ? "No products yet" : "No matches",
102
- hint: F.length === 0 ? "Create categories and brands first, then add products." : "Try a different search term.",
103
- action: F.length === 0 && P ? /* @__PURE__ */ u(h, {
104
- variant: "contained",
105
- size: "small",
106
- startIcon: /* @__PURE__ */ u(E, {}),
107
- onClick: G,
108
- children: "Create first product"
109
- }) : null
110
- }) : W.map((e) => /* @__PURE__ */ d(C, {
111
- hover: !0,
112
- children: [
113
- /* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(T, {
114
- variant: "body2",
115
- sx: { fontWeight: 700 },
116
- children: e.name
117
- }) }),
118
- /* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(T, {
119
- variant: "caption",
120
- color: "text.secondary",
121
- children: e.categoryName
122
- }) }),
123
- /* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(T, {
124
- variant: "caption",
125
- color: "text.secondary",
126
- children: e.brandName
127
- }) }),
128
- /* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(g, {
129
- size: "small",
130
- label: e.unit,
131
- variant: "outlined",
132
- sx: {
133
- fontWeight: 700,
134
- borderRadius: 1.5,
135
- height: 22
136
- }
137
- }) }),
138
- /* @__PURE__ */ u(x, { children: e.hasExpiry ? /* @__PURE__ */ u(g, {
139
- size: "small",
140
- label: "Yes",
141
- color: "warning",
142
- variant: "outlined",
143
- sx: {
144
- fontWeight: 700,
145
- borderRadius: 1.5,
146
- height: 22
147
- }
148
- }) : /* @__PURE__ */ u(g, {
149
- size: "small",
150
- label: "No",
151
- variant: "outlined",
152
- sx: {
153
- fontWeight: 700,
154
- borderRadius: 1.5,
155
- height: 22
156
- }
157
- }) }),
158
- /* @__PURE__ */ u(x, { children: e.vaccineConfig ? /* @__PURE__ */ d(y, {
159
- direction: "row",
160
- alignItems: "center",
161
- spacing: 1,
162
- children: [/* @__PURE__ */ u(j, { sx: {
163
- fontSize: 18,
164
- color: "info.main"
165
- } }), /* @__PURE__ */ d(m, { children: [/* @__PURE__ */ u(T, {
166
- variant: "caption",
167
- sx: {
168
- fontFamily: "monospace",
169
- fontWeight: 800,
170
- display: "block",
171
- lineHeight: 1.2
172
- },
173
- children: e.vaccineConfig.vaccineCode
174
- }), /* @__PURE__ */ d(T, {
175
- variant: "caption",
176
- color: "text.secondary",
177
- sx: { fontVariantNumeric: "tabular-nums" },
178
- children: [
179
- e.vaccineConfig.vialVolumeMl,
180
- "ml · ",
181
- e.vaccineConfig.adultDoseMl ?? "—",
182
- "/",
183
- e.vaccineConfig.childDoseMl ?? "—",
184
- " ml"
185
- ]
186
- })] })]
187
- }) : /* @__PURE__ */ u(T, {
188
- variant: "caption",
189
- color: "text.disabled",
190
- children: "—"
191
- }) }),
192
- /* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(g, {
193
- size: "small",
194
- label: e.isActive ? "Active" : "Inactive",
195
- color: e.isActive ? "success" : "default",
196
- variant: e.isActive ? "filled" : "outlined",
197
- sx: {
198
- fontWeight: 700,
199
- borderRadius: 1.5,
200
- height: 22
201
- }
202
- }) }),
203
- /* @__PURE__ */ u(x, {
204
- align: "right",
205
- children: P ? /* @__PURE__ */ u(h, {
206
- size: "small",
207
- variant: "outlined",
208
- onClick: () => N(`/ui/medplat/manage/pm/products/${e.id}`),
209
- children: "Edit"
210
- }) : null
211
- })
212
- ]
213
- }, e.id)) })] })
214
- })]
215
- })
216
- })] });
217
- }
218
- //#endregion
219
- export { N as default };
220
-
221
- //# sourceMappingURL=ProductsPage-BANTKxLb.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ProductsPage-BANTKxLb.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 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 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 { 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\n async function load() {\n setLoading(true);\n setError('');\n try {\n setItems(await getProducts());\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 (!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 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>\n <Typography variant=\"body2\" sx={{ fontWeight: 700 }}>{p.name}</Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"caption\" color=\"text.secondary\">{p.categoryName}</Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"caption\" color=\"text.secondary\">{p.brandName}</Typography>\n </TableCell>\n <TableCell>\n <Chip size=\"small\" label={p.unit} 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":";;;;;;;;;;;;;;AA+BA,SAAwB,IAAe;CACrC,IAAM,IAAW,EAAY,GAEvB,IADQ,EACG,EAAM,IAAI,yCAAyC,GAC9D,CAAC,GAAO,KAAY,EAAS,CAAC,CAAC,GAC/B,CAAC,GAAS,KAAc,EAAS,EAAK,GACtC,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,CAAC,GAAQ,KAAa,EAAS,EAAE;CAEvC,eAAe,IAAO;EAEpB,AADA,EAAW,EAAI,GACf,EAAS,EAAE;EACX,IAAI;GACF,EAAS,MAAM,EAAY,CAAC;EAC9B,SAAS,GAAK;GACZ,IAAM,IAAU,GAAK,UAAU,MAAM,WAAW,GAAK,WAAW;GAEhE,AADA,EAAS,CAAO,GAChB,EAAU;IAAE;IAAS,MAAM;GAAQ,CAAC;EACtC,UAAU;GACR,EAAW,EAAK;EAClB;CACF;CAEA,EAAsB,+CAA+C;EACnE,EAAU;CACZ,GAAG,CAAC,CAAC;CAEL,IAAM,IAAW,EAAM,QAAQ,MAAM;EACnC,IAAI,CAAC,EAAO,KAAK,GAAG,OAAO;EAC3B,IAAM,IAAI,EAAO,YAAY;EAC7B,OAAQ,EAAE,MAAM,YAAY,EAAE,SAAS,CAAC,KAClC,EAAE,cAAc,YAAY,EAAE,SAAS,CAAC,KACxC,EAAE,WAAW,YAAY,EAAE,SAAS,CAAC,KACrC,EAAE,eAAe,aAAa,YAAY,EAAE,SAAS,CAAC;CAC9D,CAAC;CAED,SAAS,IAAY;EACnB,EAAS,kCAAkC,EAAO,GAAG;CACvD;CAEA,OACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,CAAQ,CAAA,GACR,kBAAC,GAAD;EAAS,MAAM;YACf,kBAAC,GAAD;GACE,OAAM;GACN,UAAS;GACT,OAAO,CAAC,SAAS;GACjB,SACE,kBAAC,GAAD;IAAO,WAAU;IAAM,SAAS;cAAhC,CACE,kBAAC,GAAD;KAAQ,SAAQ;KAAW,WAAW,kBAAC,GAAD,CAAqB,CAAA;KAAG,eAAe,KAAK,EAAK;eAAG;IAAe,CAAA,GACxG,IACC,kBAAC,GAAD;KAAQ,SAAQ;KAAY,WAAW,kBAAC,GAAD,CAAiB,CAAA;KAAG,SAAS;eAAW;IAAmB,CAAA,IAChG,IACC;;aAVX,CAaG,IAAQ,kBAAC,GAAD;IAAO,UAAS;IAAQ,IAAI,EAAE,IAAI,EAAE;cAAI;GAAa,CAAA,IAAI,MAElE,kBAAC,GAAD;IACE,SAAQ;IACR,OAAM;IACN,UAAU,IACN,aACA,GAAG,EAAS,OAAO,MAAM,EAAM,OAAO,GAAG,EAAM,WAAW,IAAI,YAAY,aAAa,EAAO,KAAK,IAAI,cAAc,EAAO,KAAK,EAAE,KAAK;IAC5I,SACE,kBAAC,GAAD;KACE,MAAK;KACL,WAAA;KACA,aAAY;KACZ,OAAO;KACP,WAAW,MAAM,EAAU,EAAE,OAAO,KAAK;KACzC,YAAY,EACV,gBACE,kBAAC,GAAD;MAAgB,UAAS;gBACvB,kBAAC,GAAD;OAAmB,UAAS;OAAQ,OAAM;MAAU,CAAA;KACtC,CAAA,EAEpB;KACA,IAAI,EAAE,UAAU,IAAI;IACrB,CAAA;cAGH,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;KACE,kBAAC,GAAD,EAAA,UAAW,UAAkB,CAAA;KAC7B,kBAAC,GAAD,EAAA,UAAW,WAAmB,CAAA;KAC9B,kBAAC,GAAD,EAAA,UAAW,QAAgB,CAAA;KAC3B,kBAAC,GAAD,EAAA,UAAW,OAAe,CAAA;KAC1B,kBAAC,GAAD,EAAA,UAAW,SAAiB,CAAA;KAC5B,kBAAC,GAAD,EAAA,UAAW,iBAAyB,CAAA;KACpC,kBAAC,GAAD,EAAA,UAAW,SAAiB,CAAA;KAC5B,kBAAC,GAAD;MAAW,OAAM;gBAAQ;KAAiB,CAAA;IAClC,EAAA,CAAA,EACD,CAAA,GACX,kBAAC,GAAD,EAAA,UACG,IACC,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,GAAG,MAChC,kBAAC,GAAD,EAAA,UACG,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,GAAI,MAClC,kBAAC,GAAD,EAAA,UAAmB,kBAAC,GAAD,EAAU,QAAQ,GAAK,CAAA,EAAY,GAAtC,CAAsC,CACvD,EACO,GAJK,CAIL,CACX,IACC,EAAS,WAAW,IACtB,kBAAC,GAAD;KACE,SAAS;KACT,MAAM;KACN,OAAO,EAAM,WAAW,IAAI,oBAAoB;KAChD,MAAM,EAAM,WAAW,IACnB,2DACA;KACJ,QAAQ,EAAM,WAAW,KAAK,IAC5B,kBAAC,GAAD;MAAQ,SAAQ;MAAY,MAAK;MAAQ,WAAW,kBAAC,GAAD,CAAiB,CAAA;MAAG,SAAS;gBAAW;KAEpF,CAAA,IACN;IACL,CAAA,IACC,EAAS,KAAK,MAChB,kBAAC,GAAD;KAAqB,OAAA;eAArB;MACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAY,SAAQ;OAAQ,IAAI,EAAE,YAAY,IAAI;iBAAI,EAAE;MAAiB,CAAA,EAChE,CAAA;MACX,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAY,SAAQ;OAAU,OAAM;iBAAkB,EAAE;MAAyB,CAAA,EACxE,CAAA;MACX,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAY,SAAQ;OAAU,OAAM;iBAAkB,EAAE;MAAsB,CAAA,EACrE,CAAA;MACX,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAM,MAAK;OAAQ,OAAO,EAAE;OAAM,SAAQ;OAAW,IAAI;QAAE,YAAY;QAAK,cAAc;QAAK,QAAQ;OAAG;MAAI,CAAA,EACrG,CAAA;MACX,kBAAC,GAAD,EAAA,UACG,EAAE,YACC,kBAAC,GAAD;OAAM,MAAK;OAAQ,OAAM;OAAM,OAAM;OAAU,SAAQ;OAAW,IAAI;QAAE,YAAY;QAAK,cAAc;QAAK,QAAQ;OAAG;MAAI,CAAA,IAC3H,kBAAC,GAAD;OAAM,MAAK;OAAQ,OAAM;OAAK,SAAQ;OAAW,IAAI;QAAE,YAAY;QAAK,cAAc;QAAK,QAAQ;OAAG;MAAI,CAAA,EACrG,CAAA;MACX,kBAAC,GAAD,EAAA,UACG,EAAE,gBACD,kBAAC,GAAD;OAAO,WAAU;OAAM,YAAW;OAAS,SAAS;iBAApD,CACE,kBAAC,GAAD,EAAqB,IAAI;QAAE,UAAU;QAAI,OAAO;OAAY,EAAI,CAAA,GAChE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;QAAY,SAAQ;QAAU,IAAI;SAAE,YAAY;SAAa,YAAY;SAAK,SAAS;SAAS,YAAY;QAAI;kBAC7G,EAAE,cAAc;OACP,CAAA,GACZ,kBAAC,GAAD;QAAY,SAAQ;QAAU,OAAM;QAAiB,IAAI,EAAE,oBAAoB,eAAe;kBAA9F;SACG,EAAE,cAAc;SAAa;SAAM,EAAE,cAAc,eAAe;SAAI;SAAE,EAAE,cAAc,eAAe;SAAI;QAClG;SACT,EAAA,CAAA,CACA;WACL,kBAAC,GAAD;OAAY,SAAQ;OAAU,OAAM;iBAAgB;MAAa,CAAA,EAC5D,CAAA;MACX,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OACE,MAAK;OACL,OAAO,EAAE,WAAW,WAAW;OAC/B,OAAO,EAAE,WAAW,YAAY;OAChC,SAAS,EAAE,WAAW,WAAW;OACjC,IAAI;QAAE,YAAY;QAAK,cAAc;QAAK,QAAQ;OAAG;MACtD,CAAA,EACQ,CAAA;MACX,kBAAC,GAAD;OAAW,OAAM;iBACd,IACC,kBAAC,GAAD;QAAQ,MAAK;QAAQ,SAAQ;QAC3B,eAAe,EAAS,kCAAkC,EAAE,IAAI;kBAAG;OAAY,CAAA,IAC/E;MACK,CAAA;KACH;OAhDK,EAAE,EAgDP,CACX,EACQ,CAAA,CACJ,EAAA,CAAA;GACE,CAAA,CACF;;CACJ,CAAA,CACN,EAAA,CAAA;AAET"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"PurchaseCreatePage-C3KMfBxJ.js","names":[],"sources":["../src/views/PurchaseCreatePage.jsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n Alert,\n Box,\n Button,\n Card,\n CardContent,\n Chip,\n Divider,\n FormControl,\n FormHelperText,\n Grid,\n IconButton,\n InputLabel,\n MenuItem,\n Select,\n Stack,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material';\nimport DeleteOutlineRoundedIcon from '@mui/icons-material/DeleteOutlineRounded';\nimport AddRoundedIcon from '@mui/icons-material/AddRounded';\nimport SaveRoundedIcon from '@mui/icons-material/SaveRounded';\nimport Inventory2RoundedIcon from '@mui/icons-material/Inventory2Rounded';\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 createPurchase,\n getProducts,\n getStorageUnits,\n listBatches,\n submitPurchaseRequest,\n} from '@pm/services/pmApi';\nimport FacilityPicker from '@pm/components/FacilityPicker';\nimport { BATCH_STATUSES, PAYMENT_MODES, labelOf } from '@pm/utils/constants';\nimport {\n isClean,\n validateFutureDate,\n validatePastOrTodayDate,\n validatePrice,\n validateQuantity,\n validateRequired,\n} from '@pm/utils/validation';\nimport { formatDate, formatNumber, statusColor } from '@pm/utils/format';\nimport { PmFormSection } from '@pm/components/PmTable';\nimport { useFieldErrors } from '@pm/utils/useFieldErrors';\nimport { usePermissionedEffect } from '@pm/utils/permissions';\nimport { usePmSettings } from '@pm/utils/settingsStore';\n\n// Purchase type → backend owner_type mapping. \"Personal Use\" puts the stock\n// against the acting user; \"Facility Use\" puts it against a facility the user\n// has access to. The Personal option is filtered out when the deployment-level\n// allowPersonalPurchase setting is off (see PURCHASE_TYPES filter below).\nconst ALL_PURCHASE_TYPES = [\n { value: 'USER', label: 'Personal Use' },\n { value: 'FACILITY', label: 'Facility Use' },\n];\n\nfunction emptyLine() {\n return {\n key: uuidv4(),\n batchId: uuidv4(),\n productId: '',\n quantity: 1,\n buyPrice: '',\n expiryDate: '',\n lotNumber: '',\n manufactureDate: '',\n storageUnitId: '',\n };\n}\n\nexport default function PurchaseCreatePage() {\n const navigate = useNavigate();\n const settings = usePmSettings();\n const manageAmounts = settings?.managePurchaseAmounts !== false;\n const allowPersonalPurchase = settings?.allowPersonalPurchase !== false;\n // When confirmation is on, the form submits to the request endpoint and\n // the user lands on the request detail page instead of the purchases list.\n const requireConfirmation = settings?.requirePurchaseConfirmation === true;\n // Personal Use is hidden entirely when the deployment doesn't allow it; the\n // dropdown then has a single option and the form defaults to FACILITY.\n const PURCHASE_TYPES = useMemo(\n () => (allowPersonalPurchase ? ALL_PURCHASE_TYPES : ALL_PURCHASE_TYPES.filter((t) => t.value !== 'USER')),\n [allowPersonalPurchase],\n );\n const [products, setProducts] = useState([]);\n const [storageUnits, setStorageUnits] = useState([]);\n const [batches, setBatches] = useState([]);\n const [error, setError] = useState('');\n const fieldErrors = useFieldErrors();\n const today = new Date().toISOString().substring(0, 10);\n const [form, setForm] = useState({\n id: uuidv4(),\n ownerType: allowPersonalPurchase ? 'USER' : 'FACILITY',\n ownerId: '',\n purchaseDate: today,\n paymentMode: 'CASH',\n notes: '',\n items: [emptyLine()],\n });\n\n // When the deployment setting flips from allowing personal purchases to not\n // allowing them (or vice-versa) after the form has rendered, snap the\n // ownerType back to a valid choice so the user can't end up submitting USER\n // against a deployment that doesn't accept it.\n useEffect(() => {\n if (!allowPersonalPurchase && form.ownerType === 'USER') {\n setForm((f) => ({ ...f, ownerType: 'FACILITY', ownerId: '' }));\n }\n }, [allowPersonalPurchase, form.ownerType]);\n\n usePermissionedEffect('update.manage.productManagement.purchase', () => {\n async function load() {\n try {\n const [p, su, b] = await Promise.all([\n getProducts(),\n getStorageUnits({ activeOnly: true }),\n // Pulled here so the existing-inventory panel renders alongside the\n // purchase form — the operator can see what they / the facility\n // already hold before deciding what to buy.\n listBatches().catch(() => []),\n ]);\n setProducts(p);\n setStorageUnits(su);\n setBatches(b);\n } catch (err) {\n setError(err?.response?.data?.message ?? err?.message ?? 'Failed to load reference data');\n }\n }\n void load();\n }, []);\n\n // Existing-stock view for the currently-selected owner. Personal purchases\n // show the operator's USER-owned batches; facility purchases show batches\n // owned by the picked facility. Exhausted/expired rows are skipped to keep\n // the panel decision-relevant.\n const existingInventory = useMemo(() => {\n if (form.ownerType === 'USER') {\n return batches.filter((b) => b.ownerType === 'USER' && Number(b.qtyRemaining ?? 0) > 0\n && b.status !== 'EXPIRED' && b.status !== 'EXHAUSTED');\n }\n if (form.ownerType === 'FACILITY' && form.ownerId) {\n return batches.filter((b) => b.ownerType === 'FACILITY' && b.ownerId === form.ownerId\n && Number(b.qtyRemaining ?? 0) > 0\n && b.status !== 'EXPIRED' && b.status !== 'EXHAUSTED');\n }\n return [];\n }, [batches, form.ownerType, form.ownerId]);\n\n // Storage units filtered by the selected facility (when applicable).\n // Personal purchases don't reference a storage unit at all.\n const eligibleStorageUnits = useMemo(() => {\n if (form.ownerType !== 'FACILITY' || !form.ownerId) return [];\n return storageUnits.filter((u) => u.ownerId === form.ownerId);\n }, [storageUnits, form.ownerType, form.ownerId]);\n\n function patchLine(idx, k, v) {\n setForm((f) => {\n const items = f.items.slice();\n items[idx] = { ...items[idx], [k]: v };\n return { ...f, items };\n });\n }\n\n function removeLine(idx) {\n setForm((f) => ({ ...f, items: f.items.filter((_, i) => i !== idx) }));\n }\n\n function addLine() {\n setForm((f) => ({ ...f, items: [...f.items, emptyLine()] }));\n }\n\n // Sum of (qty * buy price) for lines that have a price. Used to validate\n // the optional Total Amount header field.\n const computedLineTotal = useMemo(() => {\n let priced = false;\n const sum = form.items.reduce((acc, line) => {\n if (line.buyPrice === '' || line.quantity === '' || line.quantity == null) return acc;\n const qty = Number(line.quantity);\n const price = Number(line.buyPrice);\n if (Number.isNaN(qty) || Number.isNaN(price)) return acc;\n priced = true;\n return acc + qty * price;\n }, 0);\n return { sum, priced };\n }, [form.items]);\n\n // Header + per-line errors. The total is auto-derived from the line items so it\n // never needs its own validation message.\n const headerErrors = {\n ownerType: validateRequired(form.ownerType, 'Purchase type'),\n ownerId: form.ownerType === 'FACILITY' ? validateRequired(form.ownerId, 'Facility') : '',\n purchaseDate: validateRequired(form.purchaseDate, 'Purchase date'),\n };\n const lineErrors = form.items.map((line) => {\n const product = products.find((p) => p.id === line.productId);\n const expiryRequired = product?.hasExpiry === true;\n // Storage units only apply to facility-owned stock — personal purchases keep\n // the field disabled, so the requirement is only enforced for facility flows.\n const storageRequired = product?.needsStorageUnit === true && form.ownerType === 'FACILITY';\n let storageErr = storageRequired ? validateRequired(line.storageUnitId, 'Storage unit') : '';\n // Cold-chain check: if the product has a vaccine config with a required\n // storage range, the selected storage unit's operating range must fit\n // inside it. Mirror the backend STORAGE_UNIT_TEMP_MISMATCH rule.\n if (!storageErr && line.storageUnitId && product?.vaccineConfig) {\n const cfg = product.vaccineConfig;\n const unit = storageUnits.find((u) => u.id === line.storageUnitId);\n if (cfg.storageTempMinCelsius != null && cfg.storageTempMaxCelsius != null && unit) {\n const uMin = unit.operatingTempMinCelsius;\n const uMax = unit.operatingTempMaxCelsius;\n // Unit must be able to reach every temp the vaccine tolerates: its\n // operating range must contain the vaccine's required range.\n if (uMin == null || uMax == null\n || Number(uMin) > Number(cfg.storageTempMinCelsius)\n || Number(uMax) < Number(cfg.storageTempMaxCelsius)) {\n storageErr = `Unit operates ${uMin ?? '?'}°C → ${uMax ?? '?'}°C, which cannot cover this product's required ${cfg.storageTempMinCelsius}°C → ${cfg.storageTempMaxCelsius}°C.`;\n }\n }\n }\n return {\n productId: validateRequired(line.productId, 'Product'),\n quantity: validateQuantity(line.quantity),\n buyPrice: validatePrice(line.buyPrice),\n // In request mode the approver fills expiry at confirmation, so we\n // don't require it from the requester even when the product carries\n // hasExpiry. The approver gets to enter the actual expiry off the\n // packaging on PurchaseRequestDetailPage.\n expiryDate: requireConfirmation\n ? ''\n : expiryRequired\n ? (validateRequired(line.expiryDate, 'Expiry date')\n || validateFutureDate(line.expiryDate, { label: 'Expiry' }))\n : validateFutureDate(line.expiryDate, { label: 'Expiry' }),\n manufactureDate: validatePastOrTodayDate(line.manufactureDate, { label: 'Manufacture date' }),\n storageUnitId: storageErr,\n };\n });\n const formIsValid = isClean(headerErrors) && lineErrors.every(isClean) && form.items.length > 0;\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 // Payload shape is the same for direct purchase and request submission —\n // the difference is the endpoint and what we navigate to afterwards.\n const payload = {\n id: form.id,\n ownerType: form.ownerType,\n ownerId: form.ownerType === 'FACILITY' ? form.ownerId : null,\n purchaseDate: form.purchaseDate,\n paymentMode: manageAmounts ? (form.paymentMode || null) : null,\n // Amount tracking is a per-deployment toggle. When it's off, scrub money\n // values to null so the backend's validatePurchaseTotal stays a no-op\n // and inventory rows don't carry stale prices that aren't surfaced anywhere.\n totalAmount: manageAmounts && computedLineTotal.priced ? Number(computedLineTotal.sum.toFixed(2)) : null,\n notes: form.notes || null,\n items: form.items.map((line) => ({\n batchId: line.batchId,\n productId: line.productId,\n quantity: Number(line.quantity),\n buyPrice: manageAmounts && line.buyPrice !== '' ? Number(line.buyPrice) : null,\n expiryDate: line.expiryDate || null,\n lotNumber: line.lotNumber || null,\n manufactureDate: line.manufactureDate || null,\n storageUnitId: line.storageUnitId || null,\n })),\n };\n try {\n if (requireConfirmation) {\n const submitted = await submitPurchaseRequest(payload);\n showToast({ message: 'Purchase request submitted for approval.', type: 'success' });\n navigate(`/ui/medplat/manage/pm/purchase-requests/${submitted?.id ?? form.id}`);\n } else {\n await createPurchase(payload);\n showToast({ message: 'Purchase recorded.', type: 'success' });\n navigate('/ui/medplat/manage/pm/purchases');\n }\n } catch (err) {\n setError(err?.response?.data?.message\n ?? err?.message\n ?? (requireConfirmation ? 'Failed to submit purchase request' : 'Failed to record purchase'));\n }\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard\n perm={'update.manage.productManagement.purchase'}\n title={requireConfirmation\n ? \"You don’t have permission to submit purchase requests\"\n : \"You don’t have permission to record purchases\"}>\n <PmPageShell\n title={requireConfirmation ? 'Submit Purchase Request' : 'Record Purchase'}\n subtitle={requireConfirmation\n ? 'Purchases need approval before stock is added. Submit the request and wait for a manager to confirm.'\n : 'Each item creates a batch that you can track and a record in your ledger.'}\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\"\n onClick={() => navigate(requireConfirmation\n ? '/ui/medplat/manage/pm/purchase-requests'\n : '/ui/medplat/manage/pm/purchases')}>Cancel</Button>\n <Button variant=\"contained\" startIcon={<SaveRoundedIcon />}\n disabled={!formIsValid}\n onClick={() => void save()}>{requireConfirmation ? 'Submit Request' : 'Save'}</Button>\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n {/* ---------- Ownership ---------- */}\n <Card sx={{ borderRadius: 4, 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=\"Purchase for\"\n hint=\"Choose who will own this stock: yourself or a facility.\"\n sx={{ mb: 2 }}\n />\n <Grid container spacing={2}>\n <Grid item xs={12} md={4}>\n <FormControl required fullWidth size=\"small\"\n error={fieldErrors.show('ownerType') && !!headerErrors.ownerType}>\n <InputLabel>Purchase Type</InputLabel>\n <Select label=\"Purchase Type\" value={form.ownerType}\n onChange={(e) => setForm({ ...form, ownerType: e.target.value, ownerId: '' })}\n onBlur={fieldErrors.onBlur('ownerType')}>\n {PURCHASE_TYPES.map((t) => (\n <MenuItem key={t.value} value={t.value}>{t.label}</MenuItem>\n ))}\n </Select>\n <FormHelperText>\n {fieldErrors.show('ownerType') && headerErrors.ownerType\n ? headerErrors.ownerType\n : 'Personal stock vs. facility stock'}\n </FormHelperText>\n </FormControl>\n </Grid>\n {form.ownerType === 'FACILITY' ? (\n <Grid item xs={12} md={4}>\n <FacilityPicker\n required\n value={form.ownerId}\n onChange={(id) => setForm({ ...form, ownerId: id })}\n onBlur={fieldErrors.onBlur('ownerId')}\n error={fieldErrors.show('ownerId') && !!headerErrors.ownerId}\n helperText={\n fieldErrors.show('ownerId') && headerErrors.ownerId\n ? headerErrors.ownerId\n : 'Search for the facility.'\n }\n />\n </Grid>\n ) : null}\n </Grid>\n </CardContent>\n </Card>\n\n {/* ---------- Existing inventory for the picked owner ---------- */}\n {(form.ownerType === 'USER' || (form.ownerType === 'FACILITY' && form.ownerId)) ? (\n <Card sx={{ borderRadius: 4, 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=\"Context\"\n title=\"Existing inventory\"\n hint={form.ownerType === 'USER'\n ? 'Your current stock.'\n : 'What this facility already has, including where it is stored.'}\n sx={{ mb: 1.5 }}\n />\n {existingInventory.length === 0 ? (\n <Stack direction=\"row\" spacing={1.25} alignItems=\"center\" sx={{ py: 1.5, color: 'text.secondary' }}>\n <Inventory2RoundedIcon fontSize=\"small\" />\n <Typography variant=\"body2\">No active stock yet for this owner.</Typography>\n </Stack>\n ) : (\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Product</TableCell>\n <TableCell>Lot</TableCell>\n <TableCell align=\"right\">Remaining</TableCell>\n <TableCell>Expiry</TableCell>\n {form.ownerType === 'FACILITY' ? <TableCell>Storage</TableCell> : null}\n <TableCell>Status</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {existingInventory.map((b) => (\n <TableRow key={b.id}>\n <TableCell sx={{ fontWeight: 700 }}>{b.productName}</TableCell>\n <TableCell sx={{ fontFamily: 'monospace', fontSize: '0.78rem' }}>{b.lotNumber || '—'}</TableCell>\n <TableCell align=\"right\" sx={{ fontVariantNumeric: 'tabular-nums', fontWeight: 700 }}>\n {b.qtyRemaining}\n </TableCell>\n <TableCell>{b.expiryDate ? formatDate(b.expiryDate) : '—'}</TableCell>\n {form.ownerType === 'FACILITY' ? (\n <TableCell>{b.storageUnitName || '—'}</TableCell>\n ) : null}\n <TableCell>\n <Chip size=\"small\" label={labelOf(BATCH_STATUSES, b.status)} color={statusColor(b.status)} />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n ) : null}\n\n {/* ---------- Lines ---------- */}\n <Card sx={{ borderRadius: 4, 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=\"Line items\"\n hint=\"Each item creates one batch in your inventory and a receipt record.\"\n />\n <Button variant=\"outlined\" startIcon={<AddRoundedIcon />} onClick={addLine}>Add Line</Button>\n </Stack>\n <Divider sx={{ mb: 2 }} />\n <Stack spacing={2}>\n {form.items.map((line, idx) => {\n const lerr = lineErrors[idx] || {};\n const product = products.find((p) => p.id === line.productId);\n const expiryRequired = product?.hasExpiry === true;\n const storageRequired = product?.needsStorageUnit === true && form.ownerType === 'FACILITY';\n return (\n <Card key={line.key} variant=\"outlined\" sx={{ p: 2, borderRadius: 3 }}>\n <Grid container spacing={2}>\n <Grid item xs={12} md={3}>\n <FormControl required fullWidth size=\"small\"\n error={fieldErrors.show(`items.${idx}.productId`) && !!lerr.productId}>\n <InputLabel>Product</InputLabel>\n <Select label=\"Product\" value={line.productId}\n onChange={(e) => patchLine(idx, 'productId', e.target.value)}\n onBlur={fieldErrors.onBlur(`items.${idx}.productId`)}>\n {products.map((p) => <MenuItem key={p.id} value={p.id}>{p.name}</MenuItem>)}\n </Select>\n {fieldErrors.show(`items.${idx}.productId`) && lerr.productId\n ? <FormHelperText>{lerr.productId}</FormHelperText> : null}\n </FormControl>\n </Grid>\n <Grid item xs={6} md={1}>\n <TextField required fullWidth size=\"small\" type=\"number\" label=\"Qty\"\n inputProps={{ min: 1 }}\n value={line.quantity}\n onChange={(e) => patchLine(idx, 'quantity', e.target.value)}\n onBlur={fieldErrors.onBlur(`items.${idx}.quantity`)}\n error={fieldErrors.show(`items.${idx}.quantity`) && !!lerr.quantity}\n helperText={fieldErrors.show(`items.${idx}.quantity`) ? lerr.quantity : ''} />\n </Grid>\n {manageAmounts ? (\n <Grid item xs={6} md={2}>\n <TextField fullWidth size=\"small\" type=\"number\" inputProps={{ step: '0.01', min: 0 }}\n label=\"Buy Price\"\n value={line.buyPrice}\n onChange={(e) => patchLine(idx, 'buyPrice', e.target.value)}\n onBlur={fieldErrors.onBlur(`items.${idx}.buyPrice`)}\n error={fieldErrors.show(`items.${idx}.buyPrice`) && !!lerr.buyPrice}\n helperText={fieldErrors.show(`items.${idx}.buyPrice`) ? lerr.buyPrice : ''} />\n </Grid>\n ) : null}\n {/* Expiry is captured at confirmation time alongside Lot —\n the requester is asking for stock they don't yet have,\n so they can't read the expiry off the packaging. */}\n {requireConfirmation ? null : (\n <Grid item xs={6} md={2}>\n <TextField required={expiryRequired} fullWidth size=\"small\" type=\"date\" label=\"Expiry\"\n InputLabelProps={{ shrink: true }}\n inputProps={{ min: today }}\n value={line.expiryDate}\n onChange={(e) => patchLine(idx, 'expiryDate', e.target.value)}\n onBlur={fieldErrors.onBlur(`items.${idx}.expiryDate`)}\n error={fieldErrors.show(`items.${idx}.expiryDate`) && !!lerr.expiryDate}\n helperText={\n fieldErrors.show(`items.${idx}.expiryDate`) && lerr.expiryDate\n ? lerr.expiryDate\n : (expiryRequired ? 'Required for this product' : '')\n } />\n </Grid>\n )}\n {/* Lot # is captured at confirmation time by the approver,\n who physically receives the goods. Hidden when this\n form is in request-mode so the requester doesn't waste\n time guessing a lot they don't have yet. */}\n {requireConfirmation ? null : (\n <Grid item xs={6} md={2}>\n <TextField fullWidth size=\"small\" label=\"Lot #\"\n value={line.lotNumber}\n onChange={(e) => patchLine(idx, 'lotNumber', e.target.value)} />\n </Grid>\n )}\n <Grid item xs={10} md={1}>\n <FormControl fullWidth size=\"small\"\n required={storageRequired}\n disabled={form.ownerType !== 'FACILITY' || !form.ownerId}\n error={fieldErrors.show(`items.${idx}.storageUnitId`) && !!lerr.storageUnitId}>\n <InputLabel>Storage</InputLabel>\n <Select label=\"Storage\" value={line.storageUnitId || ''}\n onChange={(e) => patchLine(idx, 'storageUnitId', e.target.value)}\n onBlur={fieldErrors.onBlur(`items.${idx}.storageUnitId`)}>\n <MenuItem value=\"\"><em>—</em></MenuItem>\n {eligibleStorageUnits.map((u) => <MenuItem key={u.id} value={u.id}>{u.unitName}</MenuItem>)}\n </Select>\n {fieldErrors.show(`items.${idx}.storageUnitId`) && lerr.storageUnitId ? (\n <FormHelperText>{lerr.storageUnitId}</FormHelperText>\n ) : storageRequired ? (\n <FormHelperText>Required for this product</FormHelperText>\n ) : null}\n </FormControl>\n </Grid>\n <Grid item xs={2} md={1} sx={{ textAlign: 'right' }}>\n <IconButton color=\"error\" onClick={() => removeLine(idx)} disabled={form.items.length === 1}>\n <DeleteOutlineRoundedIcon />\n </IconButton>\n </Grid>\n </Grid>\n </Card>\n );\n })}\n </Stack>\n </CardContent>\n </Card>\n\n {/* ---------- Summary footer (like a bill) ---------- */}\n <Card sx={{\n borderRadius: 4,\n bgcolor: 'grey.50',\n border: '1px solid',\n borderColor: 'divider',\n boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)',\n }}>\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Step 3\"\n title={manageAmounts ? 'Bill summary' : 'Receipt details'}\n hint={manageAmounts\n ? 'The total is calculated from items. Add payment mode and notes. The date is set automatically.'\n : 'Add notes about this receipt. The date is set automatically.'}\n sx={{ mb: 2 }}\n />\n <Grid container spacing={2}>\n {manageAmounts ? (\n <Grid item xs={12} md={6}>\n <FormControl fullWidth size=\"small\">\n <InputLabel>Payment Mode</InputLabel>\n <Select label=\"Payment Mode\" value={form.paymentMode || ''}\n onChange={(e) => setForm({ ...form, paymentMode: e.target.value })}>\n <MenuItem value=\"\"><em>—</em></MenuItem>\n {PAYMENT_MODES.map((m) => <MenuItem key={m.value} value={m.value}>{m.label}</MenuItem>)}\n </Select>\n </FormControl>\n </Grid>\n ) : null}\n <Grid item xs={12} md={manageAmounts ? 6 : 12}>\n <TextField fullWidth size=\"small\" label=\"Notes\" value={form.notes}\n onChange={(e) => setForm({ ...form, notes: e.target.value })} />\n </Grid>\n </Grid>\n\n {manageAmounts ? (\n <>\n <Divider sx={{ my: 2 }} />\n\n <Stack direction=\"row\" justifyContent=\"flex-end\" alignItems=\"baseline\" spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n Total ({form.items.length} {form.items.length === 1 ? 'line' : 'lines'})\n </Typography>\n <Typography variant=\"h4\" sx={{ fontWeight: 800, fontVariantNumeric: 'tabular-nums' }}>\n {computedLineTotal.priced ? formatNumber(computedLineTotal.sum) : '—'}\n </Typography>\n </Stack>\n {!computedLineTotal.priced ? (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ display: 'block', textAlign: 'right' }}>\n Add a Buy Price on at least one line to compute the total.\n </Typography>\n ) : null}\n </>\n ) : null}\n </CardContent>\n </Card>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"SettingsPage-CusC0jqJ.js","names":[],"sources":["../src/views/SettingsPage.jsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Card,\n CardContent,\n Grid,\n Stack,\n TextField,\n Typography,\n} from '@mui/material';\nimport CustomSwitch from '@/views/custom-components/CustomSwitch';\nimport { alpha } from '@mui/material/styles';\nimport SaveRoundedIcon from '@mui/icons-material/SaveRounded';\nimport RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';\nimport PaymentsRoundedIcon from '@mui/icons-material/PaymentsRounded';\nimport PhoneIphoneRoundedIcon from '@mui/icons-material/PhoneIphoneRounded';\nimport { showToast } from '@/common/toaster/toaster';\nimport PmPageShell from '@pm/components/PmPageShell';\nimport PmNav from '@pm/components/PmNav';\nimport PmGuard from '@pm/components/PmGuard';\nimport { usePermissionedEffect, usePmPermissions } from '@pm/utils/permissions';\nimport { PmFormSection } from '@pm/components/PmTable';\nimport {\n getSettings,\n listDateColumns,\n listPublicTables,\n listTextColumns,\n listUuidColumns,\n upsertSettings,\n} from '@pm/services/pmApi';\nimport { loadPmSettings, updateLocalPmSettings } from '@pm/utils/settingsStore';\nimport { COUNTRIES, findCountry } from '@pm/utils/countries';\n\nfunction emptyForm() {\n return {\n memberTableName: '',\n memberIdColumn: '',\n memberIdentifierColumn: '',\n memberFamilyIdColumn: '',\n memberNameColumn: '',\n memberDobColumn: '',\n countryCode: 'IN',\n managePurchaseAmounts: true,\n manageSales: true,\n allowPersonalPurchase: true,\n requirePurchaseConfirmation: false,\n };\n}\n\nfunction applySettings(s) {\n return {\n memberTableName: s?.memberTableName ?? '',\n memberIdColumn: s?.memberIdColumn ?? '',\n memberIdentifierColumn: s?.memberIdentifierColumn ?? '',\n memberFamilyIdColumn: s?.memberFamilyIdColumn ?? '',\n memberNameColumn: s?.memberNameColumn ?? '',\n memberDobColumn: s?.memberDobColumn ?? '',\n countryCode: s?.countryCode ?? 'IN',\n managePurchaseAmounts: s?.managePurchaseAmounts !== false,\n manageSales: s?.manageSales !== false,\n allowPersonalPurchase: s?.allowPersonalPurchase !== false,\n requirePurchaseConfirmation: s?.requirePurchaseConfirmation === true,\n };\n}\n\nexport default function SettingsPage() {\n const perms = usePmPermissions();\n const canWrite = perms.has('update.manage.productManagement.settings');\n const [form, setForm] = useState(emptyForm());\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState('');\n const [tables, setTables] = useState([]);\n // Cache: tableName -> UUID column list. We fetch lazily when a subject's\n // table is set and reuse on rerenders.\n const [uuidColsByTable, setUuidColsByTable] = useState({});\n // Cache: tableName -> text column list. Member uses it for the\n // identifier / family-id / name columns. Cache is keyed by table name\n // so each table fetches once.\n const [textColsByTable, setTextColsByTable] = useState({});\n // Cache: tableName -> date/timestamp column list. Today only the member\n // table needs it (DOB picker). Same lazy-load pattern as the other caches.\n const [dateColsByTable, setDateColsByTable] = useState({});\n\n async function load() {\n setLoading(true);\n setError('');\n try {\n const [s, t] = await Promise.all([getSettings(), listPublicTables().catch(() => [])]);\n setForm(applySettings(s));\n setTables(t);\n } catch (err) {\n setError(err?.response?.data?.message ?? err?.message ?? 'Failed to load settings');\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect('view.manage.productManagement.settings', () => { void load(); }, []);\n\n // Whenever a subject's table is set, lazy-load its UUID columns (idempotent).\n useEffect(() => {\n const needed = [form.memberTableName]\n .filter(Boolean)\n .filter((t) => uuidColsByTable[t] === undefined);\n if (needed.length === 0) return;\n let cancelled = false;\n (async () => {\n const updates = {};\n await Promise.all(needed.map(async (t) => {\n try {\n updates[t] = await listUuidColumns(t);\n } catch {\n updates[t] = [];\n }\n }));\n if (!cancelled) {\n setUuidColsByTable((prev) => ({ ...prev, ...updates }));\n }\n })();\n return () => { cancelled = true; };\n }, [form.memberTableName, uuidColsByTable]);\n\n // Lazy-load text columns for tables that need a text-column picker. Today\n // facility uses it for its display-name column and member uses it for its\n // search column. Cache is keyed by table name so each table is fetched once.\n useEffect(() => {\n const needed = [form.memberTableName]\n .filter(Boolean)\n .filter((t) => textColsByTable[t] === undefined);\n if (needed.length === 0) return;\n let cancelled = false;\n (async () => {\n const updates = {};\n await Promise.all(needed.map(async (t) => {\n try {\n updates[t] = await listTextColumns(t);\n } catch {\n updates[t] = [];\n }\n }));\n if (!cancelled) {\n setTextColsByTable((prev) => ({ ...prev, ...updates }));\n }\n })();\n return () => { cancelled = true; };\n }, [form.memberTableName, textColsByTable]);\n\n // Lazy-load date columns for the member table — drives the DOB picker.\n useEffect(() => {\n const needed = [form.memberTableName]\n .filter(Boolean)\n .filter((t) => dateColsByTable[t] === undefined);\n if (needed.length === 0) return;\n let cancelled = false;\n (async () => {\n const updates = {};\n await Promise.all(needed.map(async (t) => {\n try {\n updates[t] = await listDateColumns(t);\n } catch {\n updates[t] = [];\n }\n }));\n if (!cancelled) {\n setDateColsByTable((prev) => ({ ...prev, ...updates }));\n }\n })();\n return () => { cancelled = true; };\n }, [form.memberTableName, dateColsByTable]);\n\n function patch(k, v) {\n setForm((f) => ({ ...f, [k]: v }));\n }\n\n // When the table changes, clear every column previously mapped against the\n // old table so the operator can't ship a stale (now-invalid) mapping.\n function patchTable(tableKey, columnKeys, nextTable) {\n const keys = Array.isArray(columnKeys) ? columnKeys : [columnKeys];\n setForm((f) => {\n const cleared = keys.reduce((acc, k) => ({ ...acc, [k]: '' }), {});\n return { ...f, [tableKey]: nextTable, ...cleared };\n });\n }\n\n const countryErr = !form.countryCode ? 'Country is required.' : '';\n const formIsValid = !countryErr;\n const previewCountry = findCountry(form.countryCode);\n\n async function save() {\n if (!formIsValid) return;\n setSaving(true);\n setError('');\n try {\n const saved = await upsertSettings({\n memberTableName: form.memberTableName || null,\n memberIdColumn: form.memberIdColumn || null,\n memberIdentifierColumn: form.memberIdentifierColumn || null,\n memberFamilyIdColumn: form.memberFamilyIdColumn || null,\n memberNameColumn: form.memberNameColumn || null,\n memberDobColumn: form.memberDobColumn || null,\n countryCode: form.countryCode,\n // Sales-on always implies purchase-amounts-on; enforce it at save time\n // too so direct API callers can't ship an inconsistent pair.\n managePurchaseAmounts: form.manageSales ? true : !!form.managePurchaseAmounts,\n manageSales: !!form.manageSales,\n allowPersonalPurchase: !!form.allowPersonalPurchase,\n requirePurchaseConfirmation: !!form.requirePurchaseConfirmation,\n });\n setForm(applySettings(saved));\n updateLocalPmSettings(saved);\n void loadPmSettings(true).catch(() => {});\n showToast({ message: 'Settings saved.', type: 'success' });\n } catch (err) {\n const message = err?.response?.data?.message ?? err?.message ?? 'Failed to save settings';\n setError(message);\n showToast({ message, type: 'error' });\n } finally {\n setSaving(false);\n }\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={'view.manage.productManagement.settings'}>\n <PmPageShell\n title=\"Settings\"\n subtitle=\"Set up the module for your deployment. Choose your country, link to your database, and enable the features you need.\"\n chips={['Configuration']}\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"outlined\" startIcon={<RefreshRoundedIcon />} onClick={() => void load()}>Refresh</Button>\n <Button variant=\"contained\" startIcon={<SaveRoundedIcon />} disabled={!formIsValid || saving || loading || !canWrite}\n onClick={() => void save()}>\n {saving ? 'Saving…' : 'Save'}\n </Button>\n </Stack>\n }\n >\n {error ? <Alert severity=\"error\" sx={{ mb: 2 }}>{error}</Alert> : null}\n\n {/* ---------- Country (drives currency + phone) ---------- */}\n <Card sx={{\n borderRadius: 4, mb: 2,\n border: '1px solid', borderColor: 'divider',\n boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)',\n }}>\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Locale\"\n title=\"Implementation country\"\n hint=\"The country controls currency display and phone number formats.\"\n sx={{ mb: 2 }}\n />\n <Grid container spacing={2}>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n options={COUNTRIES}\n value={previewCountry}\n onChange={(_, next) => patch('countryCode', next?.code ?? '')}\n disableClearable\n getOptionLabel={(c) => (c ? `${c.name} (${c.code})` : '')}\n isOptionEqualToValue={(a, b) => a?.code === b?.code}\n filterOptions={(opts, { inputValue }) => {\n const q = inputValue.trim().toLowerCase();\n if (!q) return opts;\n return opts.filter((c) =>\n c.name.toLowerCase().includes(q)\n || c.code.toLowerCase().includes(q)\n || c.currencyCode.toLowerCase().includes(q)\n || c.phoneCode.includes(q)\n );\n }}\n renderOption={(props, c) => (\n <Box component=\"li\" {...props} key={c.code}>\n <Stack direction=\"row\" alignItems=\"baseline\" spacing={1.25} sx={{ width: '100%' }}>\n <Box component=\"span\" sx={{ fontWeight: 800, minWidth: 32 }}>{c.code}</Box>\n <Box component=\"span\" sx={{ fontWeight: 700 }}>{c.name}</Box>\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\" sx={{ ml: 'auto' }}>\n {c.currencyCode} · {c.currencySymbol} · {c.phoneCode}\n </Typography>\n </Stack>\n </Box>\n )}\n renderInput={(params) => (\n <TextField\n {...params}\n required\n label=\"Country\"\n error={!!countryErr}\n helperText={countryErr || 'Type to search by name, code, currency, or dial code.'}\n />\n )}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Stack direction=\"row\" spacing={1.5} sx={{ height: '100%' }}>\n <PreviewTile\n icon={<PaymentsRoundedIcon fontSize=\"small\" />}\n label=\"Currency\"\n primary={`${previewCountry?.currencySymbol ?? '—'} 1,234.50`}\n secondary={previewCountry?.currencyCode ?? '—'}\n />\n <PreviewTile\n icon={<PhoneIphoneRoundedIcon fontSize=\"small\" />}\n label=\"Phone\"\n primary={previewCountry?.phoneCode ?? '—'}\n secondary={previewCountry\n ? `${previewCountry.phoneMin}${previewCountry.phoneMin === previewCountry.phoneMax ? '' : `–${previewCountry.phoneMax}`} digits`\n : '—'}\n />\n </Stack>\n </Grid>\n </Grid>\n </CardContent>\n </Card>\n\n {/* ---------- Feature toggles ---------- */}\n <Card sx={{\n borderRadius: 4, mb: 2,\n border: '1px solid', borderColor: 'divider',\n boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)',\n }}>\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Scope\"\n title=\"Features\"\n hint=\"Turn on only the features you need.\"\n sx={{ mb: 2 }}\n />\n <Stack spacing={1.5}>\n <ToggleRow\n label=\"Manage sales and payments\"\n hint=\"Turn off to hide sales and payment features.\"\n value={form.manageSales}\n onChange={(v) => patch('manageSales', v)}\n />\n <ToggleRow\n label=\"Manage purchase amounts\"\n hint=\"Turn off if you only track stock, not money.\"\n value={form.manageSales ? true : form.managePurchaseAmounts}\n onChange={(v) => patch('managePurchaseAmounts', v)}\n disabled={form.manageSales}\n lockNote=\"Required while sales and payments are on — sales need purchase costs to compute margins.\"\n />\n <ToggleRow\n label=\"Allow personal purchases\"\n hint=\"Turn off to hide the personal purchase option.\"\n value={form.allowPersonalPurchase}\n onChange={(v) => patch('allowPersonalPurchase', v)}\n />\n <ToggleRow\n label=\"Require purchase confirmation\"\n hint=\"Turn on to require a manager to approve purchases before stock is added.\"\n value={form.requirePurchaseConfirmation}\n onChange={(v) => patch('requirePurchaseConfirmation', v)}\n />\n </Stack>\n </CardContent>\n </Card>\n\n {/* ---------- Subject mappings ---------- */}\n <Card sx={{\n borderRadius: 4,\n border: '1px solid', borderColor: 'divider',\n boxShadow: '0 12px 32px rgba(15, 23, 42, 0.045)',\n }}>\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Identity mappings\"\n title=\"Subjects\"\n hint=\"Connect customer, user, and facility data from your system. This links real people to the app.\"\n sx={{ mb: 2 }}\n />\n\n <Stack spacing={3}>\n <MemberSubjectRow\n tables={tables}\n tableValue={form.memberTableName}\n onTableChange={(v) => patchTable(\n 'memberTableName',\n ['memberIdColumn', 'memberIdentifierColumn', 'memberFamilyIdColumn', 'memberNameColumn', 'memberDobColumn'],\n v,\n )}\n uuidColumns={uuidColsByTable[form.memberTableName]}\n textColumns={textColsByTable[form.memberTableName]}\n dateColumns={dateColsByTable[form.memberTableName]}\n idColumnValue={form.memberIdColumn}\n onIdColumnChange={(v) => patch('memberIdColumn', v)}\n identifierColumnValue={form.memberIdentifierColumn}\n onIdentifierColumnChange={(v) => patch('memberIdentifierColumn', v)}\n familyIdColumnValue={form.memberFamilyIdColumn}\n onFamilyIdColumnChange={(v) => patch('memberFamilyIdColumn', v)}\n nameColumnValue={form.memberNameColumn}\n onNameColumnChange={(v) => patch('memberNameColumn', v)}\n dobColumnValue={form.memberDobColumn}\n onDobColumnChange={(v) => patch('memberDobColumn', v)}\n />\n </Stack>\n </CardContent>\n </Card>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n\nfunction ToggleRow({ label, hint, value, onChange, disabled = false, lockNote = '' }) {\n const checked = !!value;\n const interactive = !disabled;\n return (\n <Box\n role=\"button\"\n tabIndex={interactive ? 0 : -1}\n aria-disabled={disabled || undefined}\n onClick={interactive ? () => onChange(!checked) : undefined}\n onKeyDown={interactive ? (e) => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n onChange(!checked);\n }\n } : undefined}\n sx={(theme) => ({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n p: 2,\n borderRadius: 3,\n cursor: interactive ? 'pointer' : 'not-allowed',\n opacity: interactive ? 1 : 0.75,\n border: '1px solid',\n borderColor: checked ? alpha(theme.palette.primary.main, 0.35) : 'divider',\n bgcolor: checked ? alpha(theme.palette.primary.main, 0.04) : 'transparent',\n transition: 'all 180ms ease',\n '&:hover': interactive ? {\n borderColor: checked ? theme.palette.primary.main : alpha(theme.palette.primary.main, 0.35),\n bgcolor: checked ? alpha(theme.palette.primary.main, 0.06) : alpha(theme.palette.primary.main, 0.02),\n } : undefined,\n })}\n >\n <Box sx={{ flexGrow: 1, minWidth: 0 }}>\n <Stack direction=\"row\" alignItems=\"center\" spacing={1}>\n <Typography variant=\"subtitle1\" sx={{ fontWeight: 800, lineHeight: 1.2 }}>{label}</Typography>\n <Box\n sx={(theme) => ({\n px: 0.9,\n py: 0.15,\n borderRadius: 999,\n fontSize: '0.65rem',\n fontWeight: 800,\n letterSpacing: 0.6,\n textTransform: 'uppercase',\n color: checked ? theme.palette.success.dark : theme.palette.text.disabled,\n bgcolor: checked ? alpha(theme.palette.success.main, 0.12) : alpha(theme.palette.text.disabled, 0.1),\n })}\n >\n {checked ? 'Enabled' : 'Disabled'}\n </Box>\n {disabled && lockNote ? (\n <Box\n sx={(theme) => ({\n px: 0.9,\n py: 0.15,\n borderRadius: 999,\n fontSize: '0.65rem',\n fontWeight: 800,\n letterSpacing: 0.6,\n textTransform: 'uppercase',\n color: theme.palette.warning.dark,\n bgcolor: alpha(theme.palette.warning.main, 0.14),\n })}\n >\n Locked\n </Box>\n ) : null}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ display: 'block', mt: 0.5 }}>\n {disabled && lockNote ? lockNote : hint}\n </Typography>\n </Box>\n <CustomSwitch\n checked={checked}\n disabled={disabled}\n onClick={(e) => e.stopPropagation()}\n onChange={(e) => onChange(e.target.checked)}\n />\n </Box>\n );\n}\n\nfunction PreviewTile({ icon, label, primary, secondary }) {\n return (\n <Box\n sx={(theme) => ({\n flex: 1,\n minWidth: 0,\n p: 1.25,\n borderRadius: 3,\n border: '1px solid',\n borderColor: 'divider',\n bgcolor: alpha(theme.palette.primary.main, 0.03),\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n })}\n >\n <Stack direction=\"row\" alignItems=\"center\" spacing={0.75} sx={{ color: 'text.secondary', mb: 0.25 }}>\n {icon}\n <Typography variant=\"caption\" sx={{ fontWeight: 800, letterSpacing: 0.6, textTransform: 'uppercase' }}>\n {label}\n </Typography>\n </Stack>\n <Typography sx={{ fontWeight: 800, fontSize: '1.1rem', fontVariantNumeric: 'tabular-nums', lineHeight: 1.2 }} noWrap>\n {primary}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>{secondary}</Typography>\n </Box>\n );\n}\n\n// Dedicated members row — five column mappings (uuid + identifier + family\n// id + name + dob), one of which is sourced from date-typed columns. Sales\n// and Payments build the member profile card off these.\nfunction MemberSubjectRow({\n tables,\n tableValue,\n onTableChange,\n uuidColumns,\n textColumns,\n dateColumns,\n idColumnValue,\n onIdColumnChange,\n identifierColumnValue,\n onIdentifierColumnChange,\n familyIdColumnValue,\n onFamilyIdColumnChange,\n nameColumnValue,\n onNameColumnChange,\n dobColumnValue,\n onDobColumnChange,\n}) {\n const uuidLoaded = Array.isArray(uuidColumns);\n const textLoaded = Array.isArray(textColumns);\n const dateLoaded = Array.isArray(dateColumns);\n const noUuid = uuidLoaded && uuidColumns.length === 0;\n const noText = textLoaded && textColumns.length === 0;\n const noDate = dateLoaded && dateColumns.length === 0;\n\n const tableOptions = useMemo(() => {\n const base = tables ?? [];\n if (!tableValue || base.includes(tableValue)) return base;\n return [tableValue, ...base];\n }, [tableValue, tables]);\n\n // Pin the currently-saved value into options even if the live list doesn't\n // know about it, so a setting picked before a schema change still renders.\n function withSavedValue(list, value) {\n const arr = list ?? [];\n if (!value || arr.includes(value)) return arr;\n return [value, ...arr];\n }\n\n const uuidOptions = useMemo(\n () => withSavedValue(uuidLoaded ? uuidColumns : [], idColumnValue),\n [uuidColumns, uuidLoaded, idColumnValue],\n );\n const identifierOptions = useMemo(\n () => withSavedValue(textLoaded ? textColumns : [], identifierColumnValue),\n [textColumns, textLoaded, identifierColumnValue],\n );\n const familyIdOptions = useMemo(\n () => withSavedValue(textLoaded ? textColumns : [], familyIdColumnValue),\n [textColumns, textLoaded, familyIdColumnValue],\n );\n const nameOptions = useMemo(\n () => withSavedValue(textLoaded ? textColumns : [], nameColumnValue),\n [textColumns, textLoaded, nameColumnValue],\n );\n const dobOptions = useMemo(\n () => withSavedValue(dateLoaded ? dateColumns : [], dobColumnValue),\n [dateColumns, dateLoaded, dobColumnValue],\n );\n\n const uuidHelp = !tableValue\n ? 'Pick a table first.'\n : !uuidLoaded ? 'Loading columns…'\n : noUuid ? 'No UUID columns found in this table.'\n : 'Column that holds the member’s primary key.';\n\n function textHelp(description) {\n if (!tableValue) return 'Pick a table first.';\n if (!textLoaded) return 'Loading columns…';\n if (noText) return 'No text columns found in this table.';\n return description;\n }\n\n const dobHelp = !tableValue\n ? 'Pick a table first.'\n : !dateLoaded ? 'Loading columns…'\n : noDate ? 'No date/timestamp columns found in this table.'\n : 'Age is derived from this column in the UI.';\n\n return (\n <Box>\n <Typography variant=\"subtitle1\" sx={{ fontWeight: 800, lineHeight: 1.2 }}>Members</Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ display: 'block', mb: 1.5 }}>\n Patients / customers who can be sold to, charged dues, and administered vaccines. These columns build the member profile card on Sales and Payments.\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n options={tableOptions}\n value={tableValue || null}\n onChange={(_, next) => onTableChange(next ?? '')}\n renderInput={(params) => (\n <TextField {...params} label=\"Table name\" placeholder=\"Type to search…\"\n helperText=\"Public-schema table that holds members.\" />\n )}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n disabled={!tableValue || !uuidLoaded || noUuid}\n options={uuidOptions}\n value={idColumnValue || null}\n onChange={(_, next) => onIdColumnChange(next ?? '')}\n renderInput={(params) => (\n <TextField {...params} label=\"UUID column\" placeholder=\"Type to search…\" helperText={uuidHelp} />\n )}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n disabled={!tableValue || !textLoaded || noText}\n options={identifierOptions}\n value={identifierColumnValue || null}\n onChange={(_, next) => onIdentifierColumnChange(next ?? '')}\n renderInput={(params) => (\n <TextField {...params} label=\"Identifier column\" placeholder=\"Type to search…\"\n helperText={textHelp('Unique identifier shown on the profile card (e.g. national id).')} />\n )}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n disabled={!tableValue || !textLoaded || noText}\n options={familyIdOptions}\n value={familyIdColumnValue || null}\n onChange={(_, next) => onFamilyIdColumnChange(next ?? '')}\n renderInput={(params) => (\n <TextField {...params} label=\"Family ID column\" placeholder=\"Type to search…\"\n helperText={textHelp('Groups members by household.')} />\n )}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n disabled={!tableValue || !textLoaded || noText}\n options={nameOptions}\n value={nameColumnValue || null}\n onChange={(_, next) => onNameColumnChange(next ?? '')}\n renderInput={(params) => (\n <TextField {...params} label=\"Name column\" placeholder=\"Type to search…\"\n helperText={textHelp('Display name. Also used by the recent-payments / sales tables.')} />\n )}\n />\n </Grid>\n <Grid item xs={12} md={6}>\n <Autocomplete\n size=\"small\"\n disabled={!tableValue || !dateLoaded || noDate}\n options={dobOptions}\n value={dobColumnValue || null}\n onChange={(_, next) => onDobColumnChange(next ?? '')}\n renderInput={(params) => (\n <TextField {...params} label=\"Date of birth column\" placeholder=\"Type to search…\"\n helperText={dobHelp} />\n )}\n />\n </Grid>\n </Grid>\n </Box>\n );\n}\n"],"mappings":"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"}