{"ast":null,"code":"var _jsxFileName = \"C:\\\\Users\\\\User\\\\Downloads\\\\medora5\\\\frontend\\\\src\\\\pages\\\\billing\\\\BillingList.js\",\n _s = $RefreshSig$();\nimport React, { useState, useEffect } from 'react';\nimport { Link, useSearchParams } from 'react-router-dom';\nimport { billingService } from '../../services/billingService';\nimport { patientService } from '../../services/patientService';\nimport Loading from '../../components/Loading';\nimport ErrorAlert from '../../components/ErrorAlert';\nimport SuccessAlert from '../../components/SuccessAlert';\nimport { jsxDEV as _jsxDEV } from \"react/jsx-dev-runtime\";\nfunction BillingList() {\n _s();\n const [billings, setBillings] = useState([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(null);\n const [success, setSuccess] = useState(null);\n const [searchParams] = useSearchParams();\n const patientId = searchParams.get('patientId');\n const user = JSON.parse(localStorage.getItem('user') || '{}');\n\n // Filters\n const [statusFilter, setStatusFilter] = useState('');\n const [patientFilter, setPatientFilter] = useState('');\n const [patients, setPatients] = useState([]);\n const [pageSize] = useState(50); // Limit to 50 records per page\n\n useEffect(() => {\n const fetchBillings = async () => {\n try {\n setLoading(true);\n let response;\n if (patientId) {\n response = await billingService.getBillingHistoryForPatient(patientId);\n } else if (user.role === 'PATIENT') {\n response = await billingService.getBillingHistoryForPatient(user.patientId);\n } else {\n response = await billingService.getAllBillings();\n }\n setBillings(response.data || []);\n } catch (err) {\n setError('Failed to fetch billing records');\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n fetchBillings();\n }, [patientId, user.role, user.patientId]);\n\n // Load patients for filter dropdown (for billing admin)\n useEffect(() => {\n if (user.role === 'BILLING_ADMIN') {\n const loadPatients = async () => {\n try {\n const response = await patientService.getAllPatients();\n setPatients(response.data || []);\n } catch (err) {\n console.error('Failed to load patients:', err);\n }\n };\n loadPatients();\n }\n }, [user.role]);\n\n // Filter billings based on selected filters\n const filteredBillings = billings.filter(billing => {\n if (statusFilter && billing.paymentStatus !== statusFilter) {\n return false;\n }\n if (patientFilter && billing.patientName !== patientFilter) {\n return false;\n }\n return true;\n }).slice(0, pageSize); // Limit to first 50 records for performance\n\n const pendingBillings = billings.filter(b => b.paymentStatus === 'PENDING');\n const handleUpdateStatus = async (billId, newStatus) => {\n try {\n const updateData = {\n paymentStatus: newStatus\n };\n if (newStatus === 'PAID') {\n updateData.paymentDate = new Date().toISOString().split('T')[0];\n }\n console.log('Updating billing status:', {\n billId,\n updateData\n });\n await billingService.updatePaymentStatus(billId, updateData);\n setSuccess(`Billing status updated to ${newStatus}`);\n\n // Refresh the list\n const response = user.role === 'BILLING_ADMIN' ? await billingService.getAllBillings() : await billingService.getBillingHistoryForPatient(patientId || user.patientId);\n setBillings(response.data || []);\n } catch (err) {\n var _err$response, _err$response$data;\n setError(`Failed to update billing status: ${((_err$response = err.response) === null || _err$response === void 0 ? void 0 : (_err$response$data = _err$response.data) === null || _err$response$data === void 0 ? void 0 : _err$response$data.error) || err.message}`);\n console.error('Update status error:', err);\n }\n };\n\n // Prevent unauthorized access to billing\n if (user.role === 'DOCTOR' || user.role === 'LAB_TECHNICIAN') {\n return /*#__PURE__*/_jsxDEV(\"div\", {\n style: {\n padding: '20px',\n textAlign: 'center'\n },\n children: [/*#__PURE__*/_jsxDEV(\"h1\", {\n className: \"text-2xl font-bold\",\n style: {\n color: '#7c3aed',\n marginBottom: '10px'\n },\n children: \"Access Denied\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 104,\n columnNumber: 9\n }, this), /*#__PURE__*/_jsxDEV(\"p\", {\n style: {\n color: 'var(--color-neutral-600)'\n },\n children: \"You do not have permission to access billing records.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 105,\n columnNumber: 9\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 103,\n columnNumber: 7\n }, this);\n }\n if (loading) return /*#__PURE__*/_jsxDEV(Loading, {}, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 110,\n columnNumber: 23\n }, this);\n return /*#__PURE__*/_jsxDEV(\"div\", {\n children: [/*#__PURE__*/_jsxDEV(\"h1\", {\n className: \"text-3xl font-bold mb-6\",\n style: {\n color: '#7c3aed'\n },\n children: patientId ? 'Patient Billing History' : 'Billing Records'\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 114,\n columnNumber: 7\n }, this), error && /*#__PURE__*/_jsxDEV(ErrorAlert, {\n message: error,\n onClose: () => setError(null)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 116,\n columnNumber: 17\n }, this), success && /*#__PURE__*/_jsxDEV(SuccessAlert, {\n message: success,\n onClose: () => setSuccess(null)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 117,\n columnNumber: 19\n }, this), user.role === 'BILLING_ADMIN' && /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"bg-white rounded-lg shadow p-6 mb-6\",\n children: [/*#__PURE__*/_jsxDEV(\"h2\", {\n className: \"text-lg font-bold mb-4\",\n children: \"Filters\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 122,\n columnNumber: 11\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"grid grid-cols-1 md:grid-cols-2 gap-4\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n children: [/*#__PURE__*/_jsxDEV(\"label\", {\n className: \"block text-sm font-semibold mb-2\",\n children: \"Status\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 125,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"select\", {\n value: statusFilter,\n onChange: e => setStatusFilter(e.target.value),\n className: \"w-full px-4 py-2 border rounded-lg\",\n children: [/*#__PURE__*/_jsxDEV(\"option\", {\n value: \"\",\n children: \"All Statuses\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 131,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"option\", {\n value: \"PENDING\",\n children: \"Pending\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 132,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"option\", {\n value: \"PAID\",\n children: \"Paid\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 133,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"option\", {\n value: \"PROCESSING\",\n children: \"Processing\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 134,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 126,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 124,\n columnNumber: 13\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n children: [/*#__PURE__*/_jsxDEV(\"label\", {\n className: \"block text-sm font-semibold mb-2\",\n children: \"Patient\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 138,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"select\", {\n value: patientFilter,\n onChange: e => setPatientFilter(e.target.value),\n className: \"w-full px-4 py-2 border rounded-lg\",\n children: [/*#__PURE__*/_jsxDEV(\"option\", {\n value: \"\",\n children: \"All Patients\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 144,\n columnNumber: 17\n }, this), patients.map(p => /*#__PURE__*/_jsxDEV(\"option\", {\n value: `${p.firstName} ${p.lastName}`,\n children: [p.firstName, \" \", p.lastName]\n }, p.patientId, true, {\n fileName: _jsxFileName,\n lineNumber: 146,\n columnNumber: 19\n }, this))]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 139,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 137,\n columnNumber: 13\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 123,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 121,\n columnNumber: 9\n }, this), user.role === 'BILLING_ADMIN' && pendingBillings.length > 0 && /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"bg-yellow-50 rounded-lg shadow p-6 mb-6 border-l-4 border-yellow-500\",\n children: [/*#__PURE__*/_jsxDEV(\"h2\", {\n className: \"text-lg font-bold mb-4\",\n children: [\"Pending Billing Records (\", pendingBillings.length, \")\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 159,\n columnNumber: 11\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"space-y-3\",\n children: pendingBillings.map(billing => /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"bg-white rounded p-4 flex justify-between items-center\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n children: [/*#__PURE__*/_jsxDEV(\"p\", {\n className: \"font-semibold\",\n children: billing.patientName\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 164,\n columnNumber: 19\n }, this), /*#__PURE__*/_jsxDEV(\"p\", {\n className: \"text-sm text-gray-600\",\n children: [\"$\", billing.totalCost]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 165,\n columnNumber: 19\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 163,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"button\", {\n onClick: () => handleUpdateStatus(billing.billId, 'PAID'),\n className: \"px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 text-sm\",\n children: \"Mark Paid\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 167,\n columnNumber: 17\n }, this)]\n }, billing.billId, true, {\n fileName: _jsxFileName,\n lineNumber: 162,\n columnNumber: 15\n }, this))\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 160,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 158,\n columnNumber: 9\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"bg-white rounded-lg shadow overflow-hidden\",\n children: [/*#__PURE__*/_jsxDEV(\"table\", {\n className: \"w-full\",\n children: [/*#__PURE__*/_jsxDEV(\"thead\", {\n className: \"bg-gray-100\",\n children: /*#__PURE__*/_jsxDEV(\"tr\", {\n children: [/*#__PURE__*/_jsxDEV(\"th\", {\n className: \"px-6 py-3 text-left text-sm font-semibold\",\n children: \"Patient\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 183,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"th\", {\n className: \"px-6 py-3 text-left text-sm font-semibold\",\n children: \"Total Cost\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 184,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"th\", {\n className: \"px-6 py-3 text-left text-sm font-semibold\",\n children: \"Payment Status\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 185,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"th\", {\n className: \"px-6 py-3 text-left text-sm font-semibold\",\n children: \"Payment Date\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 186,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"th\", {\n className: \"px-6 py-3 text-left text-sm font-semibold\",\n children: \"Actions\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 187,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 182,\n columnNumber: 13\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 181,\n columnNumber: 11\n }, this), /*#__PURE__*/_jsxDEV(\"tbody\", {\n children: filteredBillings.map(billing => /*#__PURE__*/_jsxDEV(\"tr\", {\n className: \"border-t hover:bg-gray-50\",\n children: [/*#__PURE__*/_jsxDEV(\"td\", {\n className: \"px-6 py-3\",\n children: billing.patientName\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 193,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"td\", {\n className: \"px-6 py-3\",\n children: [\"$\", billing.totalCost]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 194,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"td\", {\n className: \"px-6 py-3\",\n children: /*#__PURE__*/_jsxDEV(\"span\", {\n className: `px-3 py-1 rounded text-sm font-semibold ${billing.paymentStatus === 'PENDING' ? 'bg-yellow-100 text-yellow-800' : billing.paymentStatus === 'PAID' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}`,\n children: billing.paymentStatus\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 196,\n columnNumber: 19\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 195,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"td\", {\n className: \"px-6 py-3\",\n children: billing.paymentDate || 'Not paid'\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 204,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"td\", {\n className: \"px-6 py-3\",\n children: /*#__PURE__*/_jsxDEV(Link, {\n to: `/billing/${billing.billId}`,\n style: {\n color: '#7c3aed',\n textDecoration: 'none',\n fontWeight: '400'\n },\n onMouseEnter: e => e.currentTarget.style.textDecoration = 'underline',\n onMouseLeave: e => e.currentTarget.style.textDecoration = 'none',\n children: \"View\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 206,\n columnNumber: 19\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 205,\n columnNumber: 17\n }, this)]\n }, billing.billId, true, {\n fileName: _jsxFileName,\n lineNumber: 192,\n columnNumber: 15\n }, this))\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 190,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 180,\n columnNumber: 9\n }, this), filteredBillings.length === 0 && /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"p-6 text-center text-gray-500\",\n children: billings.length === 0 ? 'No billing records found' : 'No records match the selected filters'\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 216,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 179,\n columnNumber: 7\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 113,\n columnNumber: 5\n }, this);\n}\n_s(BillingList, \"CfwcvYuapN/c1Ra/YHKf1Y3al60=\", false, function () {\n return [useSearchParams];\n});\n_c = BillingList;\nexport default BillingList;\nvar _c;\n$RefreshReg$(_c, \"BillingList\");","map":{"version":3,"names":["React","useState","useEffect","Link","useSearchParams","billingService","patientService","Loading","ErrorAlert","SuccessAlert","jsxDEV","_jsxDEV","BillingList","_s","billings","setBillings","loading","setLoading","error","setError","success","setSuccess","searchParams","patientId","get","user","JSON","parse","localStorage","getItem","statusFilter","setStatusFilter","patientFilter","setPatientFilter","patients","setPatients","pageSize","fetchBillings","response","getBillingHistoryForPatient","role","getAllBillings","data","err","console","loadPatients","getAllPatients","filteredBillings","filter","billing","paymentStatus","patientName","slice","pendingBillings","b","handleUpdateStatus","billId","newStatus","updateData","paymentDate","Date","toISOString","split","log","updatePaymentStatus","_err$response","_err$response$data","message","style","padding","textAlign","children","className","color","marginBottom","fileName","_jsxFileName","lineNumber","columnNumber","onClose","value","onChange","e","target","map","p","firstName","lastName","length","totalCost","onClick","to","textDecoration","fontWeight","onMouseEnter","currentTarget","onMouseLeave","_c","$RefreshReg$"],"sources":["C:/Users/User/Downloads/medora5/frontend/src/pages/billing/BillingList.js"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { Link, useSearchParams } from 'react-router-dom';\nimport { billingService } from '../../services/billingService';\nimport { patientService } from '../../services/patientService';\nimport Loading from '../../components/Loading';\nimport ErrorAlert from '../../components/ErrorAlert';\nimport SuccessAlert from '../../components/SuccessAlert';\n\nfunction BillingList() {\n const [billings, setBillings] = useState([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(null);\n const [success, setSuccess] = useState(null);\n const [searchParams] = useSearchParams();\n const patientId = searchParams.get('patientId');\n const user = JSON.parse(localStorage.getItem('user') || '{}');\n\n // Filters\n const [statusFilter, setStatusFilter] = useState('');\n const [patientFilter, setPatientFilter] = useState('');\n const [patients, setPatients] = useState([]);\n const [pageSize] = useState(50); // Limit to 50 records per page\n\n useEffect(() => {\n const fetchBillings = async () => {\n try {\n setLoading(true);\n let response;\n if (patientId) {\n response = await billingService.getBillingHistoryForPatient(patientId);\n } else if (user.role === 'PATIENT') {\n response = await billingService.getBillingHistoryForPatient(user.patientId);\n } else {\n response = await billingService.getAllBillings();\n }\n setBillings(response.data || []);\n } catch (err) {\n setError('Failed to fetch billing records');\n console.error(err);\n } finally {\n setLoading(false);\n }\n };\n\n fetchBillings();\n }, [patientId, user.role, user.patientId]);\n\n // Load patients for filter dropdown (for billing admin)\n useEffect(() => {\n if (user.role === 'BILLING_ADMIN') {\n const loadPatients = async () => {\n try {\n const response = await patientService.getAllPatients();\n setPatients(response.data || []);\n } catch (err) {\n console.error('Failed to load patients:', err);\n }\n };\n loadPatients();\n }\n }, [user.role]);\n\n // Filter billings based on selected filters\n const filteredBillings = billings.filter(billing => {\n if (statusFilter && billing.paymentStatus !== statusFilter) {\n return false;\n }\n if (patientFilter && billing.patientName !== patientFilter) {\n return false;\n }\n return true;\n }).slice(0, pageSize); // Limit to first 50 records for performance\n\n const pendingBillings = billings.filter(b => b.paymentStatus === 'PENDING');\n\n const handleUpdateStatus = async (billId, newStatus) => {\n try {\n const updateData = {\n paymentStatus: newStatus\n };\n if (newStatus === 'PAID') {\n updateData.paymentDate = new Date().toISOString().split('T')[0];\n }\n\n console.log('Updating billing status:', { billId, updateData });\n await billingService.updatePaymentStatus(billId, updateData);\n setSuccess(`Billing status updated to ${newStatus}`);\n\n // Refresh the list\n const response = user.role === 'BILLING_ADMIN'\n ? await billingService.getAllBillings()\n : await billingService.getBillingHistoryForPatient(patientId || user.patientId);\n setBillings(response.data || []);\n } catch (err) {\n setError(`Failed to update billing status: ${err.response?.data?.error || err.message}`);\n console.error('Update status error:', err);\n }\n };\n\n // Prevent unauthorized access to billing\n if (user.role === 'DOCTOR' || user.role === 'LAB_TECHNICIAN') {\n return (\n
You do not have permission to access billing records.
\n{billing.patientName}
\n${billing.totalCost}
\n| Patient | \nTotal Cost | \nPayment Status | \nPayment Date | \nActions | \n
|---|---|---|---|---|
| {billing.patientName} | \n${billing.totalCost} | \n\n \n {billing.paymentStatus}\n \n | \n{billing.paymentDate || 'Not paid'} | \n\n e.currentTarget.style.textDecoration = 'underline'} onMouseLeave={(e) => e.currentTarget.style.textDecoration = 'none'}>\n View\n \n | \n