@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.
- package/dist/{BrandsPage-CSA3meke.js → BrandsPage-BE3kn-8b.js} +77 -75
- package/dist/BrandsPage-BE3kn-8b.js.map +1 -0
- package/dist/{CategoriesPage-BrspzkJL.js → CategoriesPage-COqi3pMi.js} +71 -70
- package/dist/{CategoriesPage-BrspzkJL.js.map → CategoriesPage-COqi3pMi.js.map} +1 -1
- package/dist/{DashboardPage-CqaquOs2.js → DashboardPage-C_H1Jrey.js} +90 -89
- package/dist/DashboardPage-C_H1Jrey.js.map +1 -0
- package/dist/{FacilityPicker-Dv_H95WW.js → FacilityPicker-Diq2hnYg.js} +2 -2
- package/dist/{FacilityPicker-Dv_H95WW.js.map → FacilityPicker-Diq2hnYg.js.map} +1 -1
- package/dist/{InventoryPage-CPbzfDMR.js → InventoryPage-Bjpw6vTz.js} +106 -115
- package/dist/InventoryPage-Bjpw6vTz.js.map +1 -0
- package/dist/{MemberProfileCard-0vjO3Gzd.js → MemberProfileCard-BLUVRILO.js} +10 -9
- package/dist/MemberProfileCard-BLUVRILO.js.map +1 -0
- package/dist/{PaymentCreatePage-BYmDZAIB.js → PaymentCreatePage-B5VOgTx9.js} +173 -177
- package/dist/PaymentCreatePage-B5VOgTx9.js.map +1 -0
- package/dist/{PaymentsPage-BXPvKon-.js → PaymentsPage-DY6BclkN.js} +24 -23
- package/dist/{PaymentsPage-BXPvKon-.js.map → PaymentsPage-DY6BclkN.js.map} +1 -1
- package/dist/PickupCreatePage-CCSiyFQF.js +706 -0
- package/dist/PickupCreatePage-CCSiyFQF.js.map +1 -0
- package/dist/{PickupsPage-D66_Wta4.js → PickupsPage-DGi6T5Of.js} +83 -90
- package/dist/PickupsPage-DGi6T5Of.js.map +1 -0
- package/dist/PmGuard-C90yhpsN.js +592 -0
- package/dist/PmGuard-C90yhpsN.js.map +1 -0
- package/dist/{PmTable-B9970kPY.js → PmTable-BkK65bJQ.js} +98 -98
- package/dist/PmTable-BkK65bJQ.js.map +1 -0
- package/dist/{ProductEditPage-B8qFTCW9.js → ProductEditPage-CQj9egzW.js} +138 -137
- package/dist/ProductEditPage-CQj9egzW.js.map +1 -0
- package/dist/{ProductsPage-C7_r9cKn.js → ProductsPage-i8QVw_Jm.js} +65 -64
- package/dist/{ProductsPage-C7_r9cKn.js.map → ProductsPage-i8QVw_Jm.js.map} +1 -1
- package/dist/PurchaseCreatePage-Bp6bl9n8.js +591 -0
- package/dist/PurchaseCreatePage-Bp6bl9n8.js.map +1 -0
- package/dist/{PurchaseRequestDetailPage-C7aAwEqw.js → PurchaseRequestDetailPage-CNAqIFef.js} +216 -215
- package/dist/PurchaseRequestDetailPage-CNAqIFef.js.map +1 -0
- package/dist/{PurchaseRequestsPage-BwCkbpaX.js → PurchaseRequestsPage-BJqDlNrc.js} +57 -56
- package/dist/{PurchaseRequestsPage-BwCkbpaX.js.map → PurchaseRequestsPage-BJqDlNrc.js.map} +1 -1
- package/dist/{PurchasesPage-CvaZouVy.js → PurchasesPage-BQEToymQ.js} +76 -75
- package/dist/{PurchasesPage-CvaZouVy.js.map → PurchasesPage-BQEToymQ.js.map} +1 -1
- package/dist/{SaleCreatePage-DP1Qmltu.js → SaleCreatePage-DbfBK4PH.js} +149 -173
- package/dist/SaleCreatePage-DbfBK4PH.js.map +1 -0
- package/dist/{SalesPage-CO3cdYX5.js → SalesPage-CTBJMxZe.js} +50 -49
- package/dist/SalesPage-CTBJMxZe.js.map +1 -0
- package/dist/SettingsPage-CiwVmzM3.js +663 -0
- package/dist/SettingsPage-CiwVmzM3.js.map +1 -0
- package/dist/{StorageUnitsPage-B9Hr_RkW.js → StorageUnitsPage-BV7nK_iE.js} +57 -56
- package/dist/{StorageUnitsPage-B9Hr_RkW.js.map → StorageUnitsPage-BV7nK_iE.js.map} +1 -1
- package/dist/{TransactionsPage-HKIGwEZN.js → TransactionsPage-Cocn4901.js} +55 -54
- package/dist/TransactionsPage-Cocn4901.js.map +1 -0
- package/dist/TransferCreatePage-DbjcjuOg.js +316 -0
- package/dist/TransferCreatePage-DbjcjuOg.js.map +1 -0
- package/dist/TransfersPage-BFVF7Xvc.js +471 -0
- package/dist/TransfersPage-BFVF7Xvc.js.map +1 -0
- package/dist/VialsPage-BNzYTLVd.js +321 -0
- package/dist/VialsPage-BNzYTLVd.js.map +1 -0
- package/dist/index.js +652 -34
- package/dist/index.js.map +1 -1
- package/dist/settingsStore-KW217unV.js +417 -0
- package/dist/settingsStore-KW217unV.js.map +1 -0
- package/package.json +1 -1
- package/dist/BrandsPage-CSA3meke.js.map +0 -1
- package/dist/DashboardPage-CqaquOs2.js.map +0 -1
- package/dist/InventoryPage-CPbzfDMR.js.map +0 -1
- package/dist/MemberProfileCard-0vjO3Gzd.js.map +0 -1
- package/dist/PaymentCreatePage-BYmDZAIB.js.map +0 -1
- package/dist/PickupCreatePage-CMGwoAXj.js +0 -426
- package/dist/PickupCreatePage-CMGwoAXj.js.map +0 -1
- package/dist/PickupsPage-D66_Wta4.js.map +0 -1
- package/dist/PmTable-B9970kPY.js.map +0 -1
- package/dist/ProductEditPage-B8qFTCW9.js.map +0 -1
- package/dist/PurchaseCreatePage-CDfNDcKG.js +0 -627
- package/dist/PurchaseCreatePage-CDfNDcKG.js.map +0 -1
- package/dist/PurchaseRequestDetailPage-C7aAwEqw.js.map +0 -1
- package/dist/SaleCreatePage-DP1Qmltu.js.map +0 -1
- package/dist/SalesPage-CO3cdYX5.js.map +0 -1
- package/dist/SettingsPage-DvVRwSFw.js +0 -711
- package/dist/SettingsPage-DvVRwSFw.js.map +0 -1
- package/dist/TransactionsPage-HKIGwEZN.js.map +0 -1
- package/dist/TransferCreatePage-DMuZqQ3c.js +0 -363
- package/dist/TransferCreatePage-DMuZqQ3c.js.map +0 -1
- package/dist/TransfersPage-COIyouL4.js +0 -480
- package/dist/TransfersPage-COIyouL4.js.map +0 -1
- package/dist/VialsPage-BNPUwGCU.js +0 -922
- package/dist/VialsPage-BNPUwGCU.js.map +0 -1
- package/dist/currency-ClRLIEg2.js +0 -1372
- package/dist/currency-ClRLIEg2.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SaleCreatePage-DbfBK4PH.js","names":[],"sources":["../src/views/SaleCreatePage.jsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { useNavigate, useParams } from \"react-router-dom\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport {\n Alert,\n Box,\n Button,\n Card,\n CardContent,\n Divider,\n Grid,\n IconButton,\n InputAdornment,\n Stack,\n TextField,\n Typography,\n} from \"@mui/material\";\nimport AddRoundedIcon from \"@mui/icons-material/AddRounded\";\nimport DeleteOutlineRoundedIcon from \"@mui/icons-material/DeleteOutlineRounded\";\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 { usePermissionedEffect, usePmPermissions } from \"@pm/utils/permissions\";\nimport {\n createSale,\n getMemberOutstandingDues,\n getProducts,\n listBatches,\n} from \"@pm/services/pmApi\";\nimport MemberProfileCard from \"@pm/components/MemberProfileCard\";\nimport { PAYMENT_MODES } from \"@pm/utils/constants\";\nimport { formatNumber, isPastExpiry } from \"@pm/utils/format\";\nimport { currencySymbol } from \"@pm/utils/currency\";\nimport { usePmSettings } from \"@pm/utils/settingsStore\";\nimport { PmFormSection, PmSelect } from \"@pm/components/PmTable\";\nimport {\n isClean,\n validateInteger,\n validatePrice,\n validateRequired,\n} from \"@pm/utils/validation\";\nimport { useFieldErrors } from \"@pm/utils/useFieldErrors\";\n\nfunction emptyLine() {\n return { key: uuidv4(), batchId: \"\", quantity: 1, salePrice: \"\" };\n}\n\nexport default function SaleCreatePage() {\n const navigate = useNavigate();\n const { memberId } = useParams();\n const settings = usePmSettings();\n const cur = currencySymbol(settings?.currencyCode);\n const [batches, setBatches] = useState([]);\n const [products, setProducts] = useState([]);\n // Map of memberId -> previousDue. The dues endpoint only returns members\n // with non-zero dues so the map stays small. Looked up by route memberId.\n const [duesByMember, setDuesByMember] = useState({});\n // Cached after MemberProfileCard fetches — used by the warning Alert that\n // references the member by name when remaining dues will be recorded.\n const [memberName, setMemberName] = useState(\"\");\n const [error, setError] = useState(\"\");\n const perms = usePmPermissions();\n // When the operator can't see dues, previousDue gracefully degrades to 0\n // instead of populating duesByMember from a 403'ing call.\n const canSeeDues = perms.has(\"view.manage.productManagement.dues\");\n const fieldErrors = useFieldErrors();\n const today = new Date().toISOString().substring(0, 10);\n const [form, setForm] = useState({\n id: uuidv4(),\n saleDate: today,\n paymentMode: \"CASH\",\n collectingNow: \"\",\n notes: \"\",\n items: [emptyLine()],\n });\n\n usePermissionedEffect(\n \"update.manage.productManagement.sale\",\n () => {\n async function load() {\n try {\n // Members are picked via async search now — no upfront load. Dues\n // come from the (aggregated) backend query and get attached to a\n // picked member by id.\n const [b, p, dues] = await Promise.all([\n listBatches(),\n getProducts().catch(() => []),\n // Silent degrade when the operator lacks the dues permission —\n // previousDue will stay 0 and the sale itself still works.\n canSeeDues\n ? getMemberOutstandingDues().catch(() => [])\n : Promise.resolve([]),\n ]);\n setBatches(b);\n setProducts(p);\n setDuesByMember(\n Object.fromEntries(\n (dues ?? []).map((d) => [d.memberId, Number(d.totalDue)]),\n ),\n );\n } catch (err) {\n setError(\n err?.response?.data?.message ??\n err?.message ??\n \"Failed to load reference data\",\n );\n }\n }\n void load();\n },\n [],\n );\n\n const batchById = (id) => batches.find((b) => b.id === id);\n\n // Batches that can be sold: stock on hand, not quarantined, not past expiry, and\n // the underlying product is not flagged as not-for-sale. Computed once per render.\n const sellableBatches = useMemo(() => {\n const notForSaleProductIds = new Set(\n products.filter((p) => p.notForSale === true).map((p) => p.id),\n );\n return batches.filter((b) => {\n if (b.qtyRemaining <= 0) return false;\n if (b.isQuarantined) return false;\n if (notForSaleProductIds.has(b.productId)) return false;\n // A batch is sellable on the day of its printed expiry; only the\n // following day counts as expired (matches the unit packaging rule).\n if (isPastExpiry(b.expiryDate)) return false;\n return true;\n });\n }, [batches, products]);\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 // -------- Money math --------\n const saleAmount = useMemo(\n () =>\n form.items.reduce((sum, line) => {\n if (!line.salePrice || !line.quantity) return sum;\n return sum + Number(line.salePrice) * Number(line.quantity);\n }, 0),\n [form.items],\n );\n\n const previousDue = Number(memberId ? (duesByMember[memberId] ?? 0) : 0);\n const collectedRaw = Number(form.collectingNow || 0);\n // Clip the collected amount at the current sale's total — anything more would\n // need to be applied to the member's old dues, which is a separate Payment flow.\n const collected = Math.min(Math.max(collectedRaw, 0), saleAmount);\n const saleDue = Math.max(saleAmount - collected, 0);\n const remainingDue = saleDue + previousDue;\n\n // -------- Validation --------\n const headerErrors = {\n saleDate: validateRequired(form.saleDate, \"Sale date\"),\n member: memberId ? \"\" : \"No member selected\",\n };\n // Collecting Now: optional; if filled, must be a non-negative number ≤ sale amount.\n const collectingErr =\n form.collectingNow === \"\" ? \"\" : validatePrice(form.collectingNow);\n if (\n !collectingErr &&\n form.collectingNow !== \"\" &&\n Number(form.collectingNow) > saleAmount\n ) {\n headerErrors.collectingNow = `Cannot collect more than the sale amount (${formatNumber(saleAmount)}). Settle old dues via Payments.`;\n } else if (collectingErr) {\n headerErrors.collectingNow = collectingErr;\n }\n\n const sellableBatchIds = new Set(sellableBatches.map((b) => b.id));\n const lineErrors = form.items.map((line) => {\n const batch = batchById(line.batchId);\n const qty = validateInteger(line.quantity, \"Quantity\", {\n required: true,\n min: 1,\n });\n let qtyErr = qty;\n if (!qtyErr && batch && Number(line.quantity) > batch.qtyRemaining) {\n qtyErr = `Only ${batch.qtyRemaining} available in selected batch`;\n }\n let batchErr = validateRequired(line.batchId, \"Batch\");\n if (!batchErr && line.batchId && !sellableBatchIds.has(line.batchId)) {\n batchErr =\n \"Batch is not available for sale (expired, quarantined, out of stock, or not-for-sale).\";\n }\n return {\n batchId: batchErr,\n quantity: qtyErr,\n salePrice:\n validatePrice(line.salePrice) ||\n validateRequired(line.salePrice, \"Unit price\"),\n };\n });\n const formIsValid =\n isClean(headerErrors) &&\n lineErrors.every(isClean) &&\n form.items.length > 0 &&\n saleAmount > 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 try {\n await createSale({\n id: form.id,\n saleDate: form.saleDate,\n memberId,\n paymentMode: form.paymentMode || null,\n totalAmount: Number(saleAmount.toFixed(2)),\n paidAmount: Number(collected.toFixed(2)),\n dueAmount: Number(saleDue.toFixed(2)),\n notes: form.notes || null,\n items: form.items.map((l) => {\n const batch = batchById(l.batchId);\n return {\n batchId: l.batchId,\n productId: batch?.productId,\n quantity: Number(l.quantity),\n salePrice: Number(l.salePrice),\n };\n }),\n });\n showToast({ message: \"Sale recorded.\", type: \"success\" });\n navigate(\"/ui/medplat/manage/pm/sales\");\n } catch (err) {\n setError(\n err?.response?.data?.message ?? err?.message ?? \"Failed to record sale\",\n );\n }\n }\n\n return (\n <Box>\n <PmNav />\n <PmGuard\n perm={\"update.manage.productManagement.sale\"}\n title=\"You don’t have permission to record sales\"\n >\n <PmPageShell\n title=\"Record Sale\"\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button\n variant=\"outlined\"\n onClick={() => navigate(\"/ui/medplat/manage/pm/sales\")}\n >\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n startIcon={<SaveRoundedIcon />}\n disabled={!formIsValid}\n onClick={() => void save()}\n >\n Save\n </Button>\n </Stack>\n }\n >\n {error ? (\n <Alert severity=\"error\" sx={{ mb: 2 }}>\n {error}\n </Alert>\n ) : null}\n\n {/* ---------- Member ---------- */}\n <Card\n sx={{\n borderRadius: 1.5,\n mb: 2,\n border: \"1px solid\",\n borderColor: \"divider\",\n boxShadow: \"0 12px 32px rgba(15, 23, 42, 0.045)\",\n }}\n >\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Step 1\"\n title=\"Customer\"\n hint=\"The customer is set from the link you opened. Their balance shows below.\"\n sx={{ mb: 2 }}\n />\n {memberId ? (\n <MemberProfileCard\n memberId={memberId}\n previousDue={previousDue}\n currencySymbol={cur}\n onLoad={(p) => setMemberName(p?.name ?? \"\")}\n />\n ) : (\n <Alert severity=\"warning\">No member selected</Alert>\n )}\n </CardContent>\n </Card>\n\n {/* ---------- Line items ---------- */}\n <Card\n sx={{\n borderRadius: 1.5,\n mb: 2,\n border: \"1px solid\",\n borderColor: \"divider\",\n boxShadow: \"0 12px 32px rgba(15, 23, 42, 0.045)\",\n }}\n >\n <CardContent sx={{ p: 2.5 }}>\n <Stack\n direction=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"flex-start\"\n sx={{ mb: 2 }}\n >\n <PmFormSection\n eyebrow=\"Step 2\"\n title=\"Line items\"\n hint=\"Each item comes from a batch. Buy price is shown as a cost reference.\"\n />\n <Button\n variant=\"outlined\"\n startIcon={<AddRoundedIcon />}\n onClick={() =>\n setForm({ ...form, items: [...form.items, emptyLine()] })\n }\n >\n Add Line\n </Button>\n </Stack>\n <Divider sx={{ mb: 2 }} />\n <Stack spacing={2}>\n {form.items.map((line, idx) => {\n const batch = batchById(line.batchId);\n const lerr = lineErrors[idx] || {};\n const subtotal =\n line.salePrice && line.quantity\n ? Number(line.salePrice) * Number(line.quantity)\n : 0;\n return (\n <Card\n key={line.key}\n variant=\"outlined\"\n sx={{ p: 2, borderRadius: 1.5 }}\n >\n <Grid container spacing={2} alignItems=\"center\">\n <Grid item xs={12} md={5}>\n <PmSelect\n label=\"Batch\"\n required\n value={line.batchId}\n onChange={(v) => patchLine(idx, \"batchId\", v)}\n onBlur={fieldErrors.onBlur(`items.${idx}.batchId`)}\n error={fieldErrors.show(`items.${idx}.batchId`) && !!lerr.batchId}\n options={sellableBatches.map((b) => ({\n value: b.id,\n label: `${b.productName} · lot ${b.lotNumber || \"—\"} · ${b.qtyRemaining} left`,\n }))}\n helperText={fieldErrors.show(`items.${idx}.batchId`) && lerr.batchId\n ? lerr.batchId\n : batch?.buyPrice != null\n ? `Buy price: ${cur}${formatNumber(batch.buyPrice)} / unit`\n : \" \"}\n />\n </Grid>\n <Grid item xs={6} md={2}>\n <TextField\n required\n fullWidth\n size=\"small\"\n type=\"number\"\n label=\"Qty\"\n inputProps={{ min: 1, max: batch?.qtyRemaining }}\n value={line.quantity}\n onChange={(e) =>\n patchLine(idx, \"quantity\", e.target.value)\n }\n onBlur={fieldErrors.onBlur(`items.${idx}.quantity`)}\n error={\n fieldErrors.show(`items.${idx}.quantity`) &&\n !!lerr.quantity\n }\n helperText={\n fieldErrors.show(`items.${idx}.quantity`)\n ? lerr.quantity\n : \"\"\n }\n />\n </Grid>\n <Grid item xs={6} md={2}>\n <TextField\n required\n fullWidth\n size=\"small\"\n type=\"number\"\n inputProps={{ step: \"0.01\", min: 0 }}\n label=\"Unit Price\"\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">\n {cur}\n </InputAdornment>\n ),\n }}\n value={line.salePrice}\n onChange={(e) =>\n patchLine(idx, \"salePrice\", e.target.value)\n }\n onBlur={fieldErrors.onBlur(\n `items.${idx}.salePrice`,\n )}\n error={\n fieldErrors.show(`items.${idx}.salePrice`) &&\n !!lerr.salePrice\n }\n helperText={\n fieldErrors.show(`items.${idx}.salePrice`)\n ? lerr.salePrice\n : \"\"\n }\n />\n </Grid>\n <Grid item xs={6} md={2} sx={{ textAlign: \"right\" }}>\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: \"block\" }}\n >\n Subtotal\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 800,\n fontVariantNumeric: \"tabular-nums\",\n }}\n >\n {cur}\n {formatNumber(subtotal)}\n </Typography>\n </Grid>\n <Grid item xs={6} md={1} sx={{ textAlign: \"right\" }}>\n <IconButton\n color=\"error\"\n onClick={() =>\n setForm({\n ...form,\n items: form.items.filter((_, i) => i !== idx),\n })\n }\n disabled={form.items.length === 1}\n >\n <DeleteOutlineRoundedIcon />\n </IconButton>\n </Grid>\n </Grid>\n </Card>\n );\n })}\n </Stack>\n </CardContent>\n </Card>\n\n {/* ---------- Bill Summary footer ---------- */}\n <Card\n sx={{\n borderRadius: 1.5,\n bgcolor: \"grey.50\",\n border: \"1px solid\",\n borderColor: \"divider\",\n boxShadow: \"0 12px 32px rgba(15, 23, 42, 0.045)\",\n }}\n >\n <CardContent sx={{ p: 2.5 }}>\n <PmFormSection\n eyebrow=\"Step 3\"\n title=\"Bill summary\"\n hint=\"Shows totals, previous balance, and what you're collecting. Any remainder becomes a note of what they owe.\"\n sx={{ mb: 2 }}\n />\n <Grid container spacing={2}>\n <Grid item xs={12} md={4}>\n <TextField\n required\n fullWidth\n size=\"small\"\n type=\"date\"\n label=\"Date\"\n InputLabelProps={{ shrink: true }}\n value={form.saleDate}\n onChange={(e) =>\n setForm({ ...form, saleDate: e.target.value })\n }\n onBlur={fieldErrors.onBlur(\"saleDate\")}\n error={\n fieldErrors.show(\"saleDate\") && !!headerErrors.saleDate\n }\n helperText={\n fieldErrors.show(\"saleDate\") ? headerErrors.saleDate : \"\"\n }\n />\n </Grid>\n <Grid item xs={12} md={4}>\n <PmSelect\n label=\"Payment Mode\"\n value={form.paymentMode || \"\"}\n onChange={(v) => setForm({ ...form, paymentMode: v })}\n options={PAYMENT_MODES}\n />\n </Grid>\n <Grid item xs={12} md={4}>\n <TextField\n fullWidth\n size=\"small\"\n label=\"Notes\"\n value={form.notes}\n onChange={(e) =>\n setForm({ ...form, notes: e.target.value })\n }\n />\n </Grid>\n </Grid>\n\n <Divider sx={{ my: 2 }} />\n\n <Stack spacing={1.25}>\n <Stack\n direction=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"baseline\"\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n Sale Amount ({form.items.length}{\" \"}\n {form.items.length === 1 ? \"line\" : \"lines\"})\n </Typography>\n <Typography\n variant=\"h5\"\n sx={{ fontWeight: 800, fontVariantNumeric: \"tabular-nums\" }}\n >\n {cur}\n {formatNumber(saleAmount)}\n </Typography>\n </Stack>\n\n <Stack\n direction=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"baseline\"\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n Previous Due\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 700,\n fontVariantNumeric: \"tabular-nums\",\n color: previousDue > 0 ? \"warning.dark\" : \"text.primary\",\n }}\n >\n {cur}\n {formatNumber(previousDue)}\n </Typography>\n </Stack>\n\n <Divider sx={{ my: 0.5 }} />\n\n <Stack\n direction=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n spacing={2}\n >\n <Typography\n variant=\"body2\"\n color=\"text.secondary\"\n sx={{ flexShrink: 0 }}\n >\n Amount Collecting Now\n </Typography>\n <TextField\n size=\"small\"\n type=\"number\"\n inputProps={{\n step: \"0.01\",\n min: 0,\n max: saleAmount,\n style: { textAlign: \"right\", fontWeight: 700 },\n }}\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">{cur}</InputAdornment>\n ),\n }}\n sx={{ width: 200 }}\n value={form.collectingNow}\n placeholder=\"0.00\"\n onChange={(e) =>\n setForm({ ...form, collectingNow: e.target.value })\n }\n onBlur={fieldErrors.onBlur(\"collectingNow\")}\n error={\n fieldErrors.show(\"collectingNow\") &&\n !!headerErrors.collectingNow\n }\n helperText={\n fieldErrors.show(\"collectingNow\")\n ? headerErrors.collectingNow\n : \"\"\n }\n />\n </Stack>\n\n <Stack\n direction=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"baseline\"\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n Remaining Due (after this sale)\n </Typography>\n <Typography\n variant=\"h5\"\n sx={{\n fontWeight: 800,\n fontVariantNumeric: \"tabular-nums\",\n color: remainingDue > 0 ? \"warning.dark\" : \"success.dark\",\n }}\n >\n {cur}\n {formatNumber(remainingDue)}\n </Typography>\n </Stack>\n </Stack>\n\n {memberId && remainingDue > 0 ? (\n <Alert severity=\"warning\" sx={{ mt: 2 }}>\n {cur}\n {formatNumber(remainingDue)} will be recorded as pending dues\n {memberName ? (\n <>\n {\" \"}\n for <strong>{memberName}</strong>\n </>\n ) : null}\n {saleDue > 0 && previousDue > 0\n ? ` (${cur}${formatNumber(saleDue)} from this sale + ${cur}${formatNumber(previousDue)} previously outstanding).`\n : saleDue > 0\n ? \" from this sale.\"\n : \" from previously outstanding dues.\"}\n </Alert>\n ) : null}\n </CardContent>\n </Card>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
import { r as
|
|
1
|
+
import { L as e, b as t, i as n, r } from "./settingsStore-KW217unV.js";
|
|
2
|
+
import { a as i, c as a, i as o, s, t as ee } from "./PmTable-BkK65bJQ.js";
|
|
3
|
+
import { r as c, t as l } from "./format-UOyOu75i.js";
|
|
4
|
+
import { a as u, n as d, r as f, t as p } from "./PmGuard-C90yhpsN.js";
|
|
4
5
|
import { useMemo as m, useState as h } from "react";
|
|
5
6
|
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
6
|
-
import { Alert as v, Avatar as y, Box as b, Button as x, Chip as S, Skeleton as C, Stack as w, TableBody as T, TableCell as E, TableHead as
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
7
|
+
import { Alert as v, Avatar as y, Box as b, Button as x, Chip as S, Skeleton as C, Stack as w, TableBody as T, TableCell as E, TableHead as D, TableRow as O, Typography as k } from "@mui/material";
|
|
8
|
+
import { showToast as A } from "@/common/toaster/toaster";
|
|
9
|
+
import { alpha as j, useTheme as M } from "@mui/material/styles";
|
|
10
|
+
import N from "@mui/icons-material/AddRounded";
|
|
11
|
+
import P from "@mui/icons-material/RefreshRounded";
|
|
12
|
+
import { useNavigate as te } from "react-router-dom";
|
|
12
13
|
import F from "@mui/icons-material/PointOfSaleRounded";
|
|
13
14
|
import I from "@mui/icons-material/PaymentsRounded";
|
|
14
15
|
import L from "@mui/icons-material/ReceiptLongRounded";
|
|
@@ -18,15 +19,15 @@ function z(e) {
|
|
|
18
19
|
return e ? e.split(/\s+/).filter(Boolean).slice(0, 2).map((e) => e[0]).join("").toUpperCase() : "?";
|
|
19
20
|
}
|
|
20
21
|
function B({ icon: e, label: t, value: n, accent: r = "primary", loading: i }) {
|
|
21
|
-
let a =
|
|
22
|
+
let a = M(), o = a.palette[r]?.main ?? r, s = a.palette[r]?.dark ?? r;
|
|
22
23
|
return /* @__PURE__ */ g(b, {
|
|
23
24
|
sx: {
|
|
24
25
|
flex: 1,
|
|
25
26
|
p: 2,
|
|
26
|
-
borderRadius:
|
|
27
|
+
borderRadius: 1.5,
|
|
27
28
|
border: "1px solid",
|
|
28
|
-
borderColor:
|
|
29
|
-
background: `linear-gradient(135deg, ${
|
|
29
|
+
borderColor: j(o, .18),
|
|
30
|
+
background: `linear-gradient(135deg, ${j(o, .05)} 0%, ${j(a.palette.background.paper, 1)} 70%)`,
|
|
30
31
|
position: "relative",
|
|
31
32
|
overflow: "hidden"
|
|
32
33
|
},
|
|
@@ -43,12 +44,12 @@ function B({ icon: e, label: t, value: n, accent: r = "primary", loading: i }) {
|
|
|
43
44
|
placeItems: "center",
|
|
44
45
|
background: `linear-gradient(135deg, ${o} 0%, ${s} 100%)`,
|
|
45
46
|
color: "#fff",
|
|
46
|
-
boxShadow: `0 6px 14px ${
|
|
47
|
+
boxShadow: `0 6px 14px ${j(o, .32)}`
|
|
47
48
|
},
|
|
48
49
|
children: /* @__PURE__ */ g(e, { sx: { fontSize: 18 } })
|
|
49
50
|
}), /* @__PURE__ */ _(b, {
|
|
50
51
|
sx: { minWidth: 0 },
|
|
51
|
-
children: [/* @__PURE__ */ g(
|
|
52
|
+
children: [/* @__PURE__ */ g(k, {
|
|
52
53
|
variant: "caption",
|
|
53
54
|
color: "text.secondary",
|
|
54
55
|
sx: {
|
|
@@ -60,7 +61,7 @@ function B({ icon: e, label: t, value: n, accent: r = "primary", loading: i }) {
|
|
|
60
61
|
}), i ? /* @__PURE__ */ g(C, {
|
|
61
62
|
width: 80,
|
|
62
63
|
height: 26
|
|
63
|
-
}) : /* @__PURE__ */ g(
|
|
64
|
+
}) : /* @__PURE__ */ g(k, {
|
|
64
65
|
variant: "h6",
|
|
65
66
|
sx: {
|
|
66
67
|
fontWeight: 800,
|
|
@@ -74,25 +75,25 @@ function B({ icon: e, label: t, value: n, accent: r = "primary", loading: i }) {
|
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
77
|
function V() {
|
|
77
|
-
let V =
|
|
78
|
+
let V = te(), H = M(), U = n(r()?.currencyCode), [W, G] = h([]), [K, q] = h({}), [J, Y] = h(!0), [X, Z] = h("");
|
|
78
79
|
async function Q() {
|
|
79
80
|
Y(!0), Z("");
|
|
80
81
|
try {
|
|
81
|
-
let
|
|
82
|
-
G(
|
|
83
|
-
let r = Array.from(new Set(
|
|
82
|
+
let n = await e(0, 50);
|
|
83
|
+
G(n);
|
|
84
|
+
let r = Array.from(new Set(n.map((e) => e.memberId).filter(Boolean)));
|
|
84
85
|
if (r.length === 0) q({});
|
|
85
86
|
else try {
|
|
86
|
-
let e = await
|
|
87
|
+
let e = await t(r), n = {};
|
|
87
88
|
e.forEach((e) => {
|
|
88
|
-
|
|
89
|
-
}), q(
|
|
89
|
+
n[e.id] = e.name;
|
|
90
|
+
}), q(n);
|
|
90
91
|
} catch {
|
|
91
92
|
q({});
|
|
92
93
|
}
|
|
93
94
|
} catch (e) {
|
|
94
95
|
let t = e?.response?.data?.message ?? e?.message ?? "Failed to load sales";
|
|
95
|
-
Z(t),
|
|
96
|
+
Z(t), A({
|
|
96
97
|
message: t,
|
|
97
98
|
type: "error"
|
|
98
99
|
});
|
|
@@ -100,7 +101,7 @@ function V() {
|
|
|
100
101
|
Y(!1);
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
+
f("view.manage.productManagement.sale", () => {
|
|
104
105
|
Q();
|
|
105
106
|
}, []);
|
|
106
107
|
let $ = m(() => ({
|
|
@@ -109,9 +110,9 @@ function V() {
|
|
|
109
110
|
openSales: W.filter((e) => Number(e.dueAmount) > 0).length,
|
|
110
111
|
count: W.length
|
|
111
112
|
}), [W]);
|
|
112
|
-
return /* @__PURE__ */ _(b, { children: [/* @__PURE__ */ g(
|
|
113
|
+
return /* @__PURE__ */ _(b, { children: [/* @__PURE__ */ g(d, {}), /* @__PURE__ */ g(p, {
|
|
113
114
|
perm: "view.manage.productManagement.sale",
|
|
114
|
-
children: /* @__PURE__ */ _(
|
|
115
|
+
children: /* @__PURE__ */ _(u, {
|
|
115
116
|
title: "Sales",
|
|
116
117
|
subtitle: "Customer sales and payments. Each sale is tracked with the batches used.",
|
|
117
118
|
actions: /* @__PURE__ */ _(w, {
|
|
@@ -119,7 +120,7 @@ function V() {
|
|
|
119
120
|
spacing: 1,
|
|
120
121
|
children: [/* @__PURE__ */ g(x, {
|
|
121
122
|
variant: "outlined",
|
|
122
|
-
startIcon: /* @__PURE__ */ g(
|
|
123
|
+
startIcon: /* @__PURE__ */ g(P, {}),
|
|
123
124
|
onClick: () => void Q(),
|
|
124
125
|
children: "Refresh"
|
|
125
126
|
}), !1]
|
|
@@ -143,14 +144,14 @@ function V() {
|
|
|
143
144
|
/* @__PURE__ */ g(B, {
|
|
144
145
|
icon: R,
|
|
145
146
|
label: "Total billed",
|
|
146
|
-
value: `${U}${
|
|
147
|
+
value: `${U}${c($.totalRevenue)}`,
|
|
147
148
|
accent: "success",
|
|
148
149
|
loading: J
|
|
149
150
|
}),
|
|
150
151
|
/* @__PURE__ */ g(B, {
|
|
151
152
|
icon: I,
|
|
152
153
|
label: "Outstanding dues",
|
|
153
|
-
value: `${U}${
|
|
154
|
+
value: `${U}${c($.totalDue)}`,
|
|
154
155
|
accent: "warning",
|
|
155
156
|
loading: J
|
|
156
157
|
}),
|
|
@@ -168,13 +169,13 @@ function V() {
|
|
|
168
169
|
sx: { mb: 2 },
|
|
169
170
|
children: X
|
|
170
171
|
}) : null,
|
|
171
|
-
/* @__PURE__ */ g(
|
|
172
|
+
/* @__PURE__ */ g(a, {
|
|
172
173
|
eyebrow: "Recent activity",
|
|
173
174
|
title: "Sales transactions",
|
|
174
175
|
subtitle: J ? "Loading…" : `${$.count} ${$.count === 1 ? "sale" : "sales"} in the last window`,
|
|
175
|
-
children: /* @__PURE__ */ _(
|
|
176
|
+
children: /* @__PURE__ */ _(s, {
|
|
176
177
|
dense: !0,
|
|
177
|
-
children: [/* @__PURE__ */ g(
|
|
178
|
+
children: [/* @__PURE__ */ g(D, { children: /* @__PURE__ */ _(O, { children: [
|
|
178
179
|
/* @__PURE__ */ g(E, { children: "Ref" }),
|
|
179
180
|
/* @__PURE__ */ g(E, { children: "Date" }),
|
|
180
181
|
/* @__PURE__ */ g(E, { children: "Customer" }),
|
|
@@ -191,7 +192,7 @@ function V() {
|
|
|
191
192
|
align: "right",
|
|
192
193
|
children: "Due"
|
|
193
194
|
})
|
|
194
|
-
] }) }), /* @__PURE__ */ g(T, { children: J ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ g(
|
|
195
|
+
] }) }), /* @__PURE__ */ g(T, { children: J ? Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ g(O, { children: Array.from({ length: 7 }).map((e, t) => /* @__PURE__ */ g(E, { children: /* @__PURE__ */ g(C, { height: 22 }) }, t)) }, t)) : W.length === 0 ? /* @__PURE__ */ g(ee, {
|
|
195
196
|
colSpan: 7,
|
|
196
197
|
icon: F,
|
|
197
198
|
title: "No sales yet",
|
|
@@ -199,20 +200,20 @@ function V() {
|
|
|
199
200
|
action: /* @__PURE__ */ g(x, {
|
|
200
201
|
variant: "contained",
|
|
201
202
|
size: "small",
|
|
202
|
-
startIcon: /* @__PURE__ */ g(
|
|
203
|
+
startIcon: /* @__PURE__ */ g(N, {}),
|
|
203
204
|
onClick: () => V("/ui/medplat/manage/pm/sales/new"),
|
|
204
205
|
children: "Record first sale"
|
|
205
206
|
})
|
|
206
207
|
}) : W.map((e) => {
|
|
207
208
|
let t = Number(e.dueAmount || 0), n = t <= 0, r = K[e.memberId];
|
|
208
|
-
return /* @__PURE__ */ _(
|
|
209
|
+
return /* @__PURE__ */ _(O, {
|
|
209
210
|
hover: !0,
|
|
210
211
|
children: [
|
|
211
|
-
/* @__PURE__ */ g(E, { children: /* @__PURE__ */ g(
|
|
212
|
-
/* @__PURE__ */ g(E, { children: /* @__PURE__ */ g(
|
|
212
|
+
/* @__PURE__ */ g(E, { children: /* @__PURE__ */ g(i, { id: e.serialId }) }),
|
|
213
|
+
/* @__PURE__ */ g(E, { children: /* @__PURE__ */ g(k, {
|
|
213
214
|
variant: "body2",
|
|
214
215
|
sx: { fontWeight: 700 },
|
|
215
|
-
children:
|
|
216
|
+
children: l(e.saleDate)
|
|
216
217
|
}) }),
|
|
217
218
|
/* @__PURE__ */ g(E, { children: r ? /* @__PURE__ */ _(w, {
|
|
218
219
|
direction: "row",
|
|
@@ -224,13 +225,13 @@ function V() {
|
|
|
224
225
|
height: 28,
|
|
225
226
|
fontSize: 11,
|
|
226
227
|
fontWeight: 700,
|
|
227
|
-
bgcolor:
|
|
228
|
+
bgcolor: j(H.palette.primary.main, .12),
|
|
228
229
|
color: "primary.dark"
|
|
229
230
|
},
|
|
230
231
|
children: z(r)
|
|
231
232
|
}), /* @__PURE__ */ g(b, {
|
|
232
233
|
sx: { minWidth: 0 },
|
|
233
|
-
children: /* @__PURE__ */ g(
|
|
234
|
+
children: /* @__PURE__ */ g(k, {
|
|
234
235
|
variant: "body2",
|
|
235
236
|
sx: {
|
|
236
237
|
fontWeight: 700,
|
|
@@ -239,7 +240,7 @@ function V() {
|
|
|
239
240
|
children: r
|
|
240
241
|
})
|
|
241
242
|
})]
|
|
242
|
-
}) : e.memberId ? /* @__PURE__ */ _(
|
|
243
|
+
}) : e.memberId ? /* @__PURE__ */ _(k, {
|
|
243
244
|
variant: "caption",
|
|
244
245
|
sx: {
|
|
245
246
|
fontFamily: "monospace",
|
|
@@ -262,22 +263,22 @@ function V() {
|
|
|
262
263
|
fontWeight: 700,
|
|
263
264
|
borderRadius: 1.5,
|
|
264
265
|
height: 22,
|
|
265
|
-
bgcolor:
|
|
266
|
+
bgcolor: j(H.palette.primary.main, .08),
|
|
266
267
|
color: "primary.dark",
|
|
267
|
-
border: `1px solid ${
|
|
268
|
+
border: `1px solid ${j(H.palette.primary.main, .18)}`
|
|
268
269
|
}
|
|
269
|
-
}) : /* @__PURE__ */ g(
|
|
270
|
+
}) : /* @__PURE__ */ g(k, {
|
|
270
271
|
variant: "caption",
|
|
271
272
|
color: "text.disabled",
|
|
272
273
|
children: "—"
|
|
273
274
|
}) }),
|
|
274
275
|
/* @__PURE__ */ g(E, {
|
|
275
276
|
align: "right",
|
|
276
|
-
children: /* @__PURE__ */ g(
|
|
277
|
+
children: /* @__PURE__ */ g(o, { value: e.totalAmount })
|
|
277
278
|
}),
|
|
278
279
|
/* @__PURE__ */ g(E, {
|
|
279
280
|
align: "right",
|
|
280
|
-
children: /* @__PURE__ */ g(
|
|
281
|
+
children: /* @__PURE__ */ g(o, {
|
|
281
282
|
value: e.paidAmount,
|
|
282
283
|
tone: n ? "success" : "muted"
|
|
283
284
|
})
|
|
@@ -293,7 +294,7 @@ function V() {
|
|
|
293
294
|
borderRadius: 1.5,
|
|
294
295
|
height: 22
|
|
295
296
|
}
|
|
296
|
-
}) : /* @__PURE__ */ g(
|
|
297
|
+
}) : /* @__PURE__ */ g(o, {
|
|
297
298
|
value: t,
|
|
298
299
|
tone: "warning",
|
|
299
300
|
size: "big"
|
|
@@ -311,4 +312,4 @@ function V() {
|
|
|
311
312
|
//#endregion
|
|
312
313
|
export { V as default };
|
|
313
314
|
|
|
314
|
-
//# sourceMappingURL=SalesPage-
|
|
315
|
+
//# sourceMappingURL=SalesPage-CTBJMxZe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SalesPage-CTBJMxZe.js","names":[],"sources":["../src/views/SalesPage.jsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport {\n Alert,\n Avatar,\n Box,\n Button,\n Chip,\n Skeleton,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from \"@mui/material\";\nimport { alpha, useTheme } from \"@mui/material/styles\";\nimport AddRoundedIcon from \"@mui/icons-material/AddRounded\";\nimport RefreshRoundedIcon from \"@mui/icons-material/RefreshRounded\";\nimport PointOfSaleRoundedIcon from \"@mui/icons-material/PointOfSaleRounded\";\nimport ReceiptLongRoundedIcon from \"@mui/icons-material/ReceiptLongRounded\";\nimport PaymentsRoundedIcon from \"@mui/icons-material/PaymentsRounded\";\nimport TrendingUpRoundedIcon from \"@mui/icons-material/TrendingUpRounded\";\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 } from \"@pm/utils/permissions\";\nimport {\n PmEmptyRow,\n PmMoney,\n PmRef,\n PmTable,\n PmTableCard,\n} from \"@pm/components/PmTable\";\nimport { getMembersByIds, listSales } from \"@pm/services/pmApi\";\nimport { formatDate, formatNumber } from \"@pm/utils/format\";\nimport { currencySymbol } from \"@pm/utils/currency\";\nimport { usePmSettings } from \"@pm/utils/settingsStore\";\n\nfunction initials(name) {\n if (!name) return \"?\";\n return name\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((s) => s[0])\n .join(\"\")\n .toUpperCase();\n}\n\n// Mini KPI tile shown above the table. Compact, accent-tinted icon, big\n// number — gives the operator a \"what happened lately\" read at a glance.\nfunction SummaryTile({\n icon: Icon,\n label,\n value,\n accent = \"primary\",\n loading,\n}) {\n const theme = useTheme();\n const accentMain = theme.palette[accent]?.main ?? accent;\n const accentDark = theme.palette[accent]?.dark ?? accent;\n return (\n <Box\n sx={{\n flex: 1,\n p: 2,\n borderRadius: 1.5,\n border: \"1px solid\",\n borderColor: alpha(accentMain, 0.18),\n background: `linear-gradient(135deg, ${alpha(accentMain, 0.05)} 0%, ${alpha(theme.palette.background.paper, 1)} 70%)`,\n position: \"relative\",\n overflow: \"hidden\",\n }}\n >\n <Stack direction=\"row\" alignItems=\"center\" spacing={1.5}>\n <Box\n sx={{\n width: 36,\n height: 36,\n borderRadius: 2,\n display: \"grid\",\n placeItems: \"center\",\n background: `linear-gradient(135deg, ${accentMain} 0%, ${accentDark} 100%)`,\n color: \"#fff\",\n boxShadow: `0 6px 14px ${alpha(accentMain, 0.32)}`,\n }}\n >\n <Icon sx={{ fontSize: 18 }} />\n </Box>\n <Box sx={{ minWidth: 0 }}>\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{\n fontWeight: 700,\n letterSpacing: 0.6,\n textTransform: \"uppercase\",\n }}\n >\n {label}\n </Typography>\n {loading ? (\n <Skeleton width={80} height={26} />\n ) : (\n <Typography\n variant=\"h6\"\n sx={{\n fontWeight: 800,\n fontVariantNumeric: \"tabular-nums\",\n lineHeight: 1.2,\n }}\n >\n {value}\n </Typography>\n )}\n </Box>\n </Stack>\n </Box>\n );\n}\n\nexport default function SalesPage() {\n const navigate = useNavigate();\n const theme = useTheme();\n const settings = usePmSettings();\n const cur = currencySymbol(settings?.currencyCode);\n const [items, setItems] = useState([]);\n // Map of memberId -> display name, hydrated for memberIds present on the\n // loaded sales. Avoids loading the entire member directory just to render\n // the \"Customer\" column.\n const [memberNames, setMemberNames] = useState({});\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(\"\");\n\n async function load() {\n setLoading(true);\n setError(\"\");\n try {\n const list = await listSales(0, 50);\n setItems(list);\n const ids = Array.from(\n new Set(list.map((s) => s.memberId).filter(Boolean)),\n );\n if (ids.length === 0) {\n setMemberNames({});\n } else {\n try {\n const refs = await getMembersByIds(ids);\n const map = {};\n refs.forEach((r) => {\n map[r.id] = r.name;\n });\n setMemberNames(map);\n } catch {\n setMemberNames({});\n }\n }\n } catch (err) {\n const message =\n err?.response?.data?.message ?? err?.message ?? \"Failed to load sales\";\n setError(message);\n showToast({ message, type: \"error\" });\n } finally {\n setLoading(false);\n }\n }\n\n usePermissionedEffect(\n \"view.manage.productManagement.sale\",\n () => {\n void load();\n },\n [],\n );\n\n const summary = useMemo(() => {\n const totalRevenue = items.reduce(\n (s, x) => s + Number(x.totalAmount || 0),\n 0,\n );\n const totalDue = items.reduce((s, x) => s + Number(x.dueAmount || 0), 0);\n const openSales = items.filter((x) => Number(x.dueAmount) > 0).length;\n return { totalRevenue, totalDue, openSales, count: items.length };\n }, [items]);\n\n return (\n <Box>\n <PmNav />\n <PmGuard perm={\"view.manage.productManagement.sale\"}>\n <PmPageShell\n title=\"Sales\"\n subtitle=\"Customer sales and payments. Each sale is tracked with the batches used.\"\n actions={\n <Stack direction=\"row\" spacing={1}>\n <Button\n variant=\"outlined\"\n startIcon={<RefreshRoundedIcon />}\n onClick={() => void load()}\n >\n Refresh\n </Button>\n {/* DEMO-ONLY: in production a sale is started by passing the member id\n via the URL (/sales/new/:memberId) from an outside flow. Unhide\n this button to launch the create page directly for demos. */}\n {false && (\n <Button\n variant=\"contained\"\n startIcon={<AddRoundedIcon />}\n onClick={() => navigate(\"/ui/medplat/manage/pm/sales/new\")}\n >\n New Sale\n </Button>\n )}\n </Stack>\n }\n >\n {/* ---------- Summary strip ---------- */}\n <Stack\n direction={{ xs: \"column\", md: \"row\" }}\n spacing={2}\n sx={{ mb: 2 }}\n >\n <SummaryTile\n icon={ReceiptLongRoundedIcon}\n label=\"Sales (last 50)\"\n value={summary.count}\n accent=\"primary\"\n loading={loading}\n />\n <SummaryTile\n icon={TrendingUpRoundedIcon}\n label=\"Total billed\"\n value={`${cur}${formatNumber(summary.totalRevenue)}`}\n accent=\"success\"\n loading={loading}\n />\n <SummaryTile\n icon={PaymentsRoundedIcon}\n label=\"Outstanding dues\"\n value={`${cur}${formatNumber(summary.totalDue)}`}\n accent=\"warning\"\n loading={loading}\n />\n <SummaryTile\n icon={PointOfSaleRoundedIcon}\n label=\"Open sales\"\n value={summary.openSales}\n accent=\"info\"\n loading={loading}\n />\n </Stack>\n\n {error ? (\n <Alert severity=\"error\" sx={{ mb: 2 }}>\n {error}\n </Alert>\n ) : null}\n\n {/* ---------- Table ---------- */}\n <PmTableCard\n eyebrow=\"Recent activity\"\n title=\"Sales transactions\"\n subtitle={\n loading\n ? \"Loading…\"\n : `${summary.count} ${summary.count === 1 ? \"sale\" : \"sales\"} in the last window`\n }\n >\n <PmTable dense>\n <TableHead>\n <TableRow>\n <TableCell>Ref</TableCell>\n <TableCell>Date</TableCell>\n <TableCell>Customer</TableCell>\n <TableCell>Payment</TableCell>\n <TableCell align=\"right\">Total</TableCell>\n <TableCell align=\"right\">Paid</TableCell>\n <TableCell align=\"right\">Due</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n Array.from({ length: 5 }).map((_, i) => (\n <TableRow key={i}>\n {Array.from({ length: 7 }).map((__, j) => (\n <TableCell key={j}>\n <Skeleton height={22} />\n </TableCell>\n ))}\n </TableRow>\n ))\n ) : items.length === 0 ? (\n <PmEmptyRow\n colSpan={7}\n icon={PointOfSaleRoundedIcon}\n title=\"No sales yet\"\n hint=\"Record a sale to see it here with payment details.\"\n action={\n <Button\n variant=\"contained\"\n size=\"small\"\n startIcon={<AddRoundedIcon />}\n onClick={() =>\n navigate(\"/ui/medplat/manage/pm/sales/new\")\n }\n >\n Record first sale\n </Button>\n }\n />\n ) : (\n items.map((s) => {\n const due = Number(s.dueAmount || 0);\n const isPaid = due <= 0;\n const memberName = memberNames[s.memberId];\n return (\n <TableRow key={s.id} hover>\n <TableCell>\n <PmRef id={s.serialId} />\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" sx={{ fontWeight: 700 }}>\n {formatDate(s.saleDate)}\n </Typography>\n </TableCell>\n <TableCell>\n {memberName ? (\n <Stack\n direction=\"row\"\n alignItems=\"center\"\n spacing={1.25}\n >\n <Avatar\n sx={{\n width: 28,\n height: 28,\n fontSize: 11,\n fontWeight: 700,\n bgcolor: alpha(\n theme.palette.primary.main,\n 0.12,\n ),\n color: \"primary.dark\",\n }}\n >\n {initials(memberName)}\n </Avatar>\n <Box sx={{ minWidth: 0 }}>\n <Typography\n variant=\"body2\"\n sx={{ fontWeight: 700, lineHeight: 1.2 }}\n >\n {memberName}\n </Typography>\n </Box>\n </Stack>\n ) : s.memberId ? (\n <Typography\n variant=\"caption\"\n sx={{\n fontFamily: \"monospace\",\n color: \"text.secondary\",\n }}\n >\n {s.memberId.slice(0, 8)}…\n </Typography>\n ) : (\n <Chip\n size=\"small\"\n label=\"Walk-in\"\n variant=\"outlined\"\n sx={{ fontWeight: 700, borderRadius: 1.5 }}\n />\n )}\n </TableCell>\n <TableCell>\n {s.paymentMode ? (\n <Chip\n size=\"small\"\n label={s.paymentMode}\n sx={{\n fontWeight: 700,\n borderRadius: 1.5,\n height: 22,\n bgcolor: alpha(\n theme.palette.primary.main,\n 0.08,\n ),\n color: \"primary.dark\",\n border: `1px solid ${alpha(theme.palette.primary.main, 0.18)}`,\n }}\n />\n ) : (\n <Typography variant=\"caption\" color=\"text.disabled\">\n —\n </Typography>\n )}\n </TableCell>\n <TableCell align=\"right\">\n <PmMoney value={s.totalAmount} />\n </TableCell>\n <TableCell align=\"right\">\n <PmMoney\n value={s.paidAmount}\n tone={isPaid ? \"success\" : \"muted\"}\n />\n </TableCell>\n <TableCell align=\"right\">\n {isPaid ? (\n <Chip\n size=\"small\"\n color=\"success\"\n label=\"Paid\"\n sx={{\n fontWeight: 700,\n borderRadius: 1.5,\n height: 22,\n }}\n />\n ) : (\n <PmMoney value={due} tone=\"warning\" size=\"big\" />\n )}\n </TableCell>\n </TableRow>\n );\n })\n )}\n </TableBody>\n </PmTable>\n </PmTableCard>\n </PmPageShell>\n </PmGuard>\n </Box>\n );\n}\n"],"mappings":"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"}
|