@kenyaemr/esm-billing-app 5.4.1-pre.2092 → 5.4.1-pre.2096
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/.turbo/turbo-build.log +78 -78
- package/dist/{421.js → 912.js} +1 -1
- package/dist/912.js.map +1 -0
- package/dist/kenyaemr-esm-billing-app.js +1 -1
- package/dist/kenyaemr-esm-billing-app.js.buildmanifest.json +28 -28
- package/dist/main.js +3 -3
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/claims/claims-management/table/claim-table.component.tsx +262 -0
- package/src/claims/claims-management/table/claims-list-table.component.tsx +258 -200
- package/src/claims/claims-management/table/manage-claim-request.modal.tsx +111 -0
- package/src/claims/claims-management/table/preauth-table.tmp.component.tsx +8 -200
- package/src/claims/claims-management/table/use-facility-claims.ts +1 -1
- package/src/claims/dashboard/form/claims-form.component.tsx +7 -3
- package/src/claims/dashboard/form/claims-form.resource.ts +7 -0
- package/src/claims/utils.ts +7 -0
- package/src/index.ts +2 -4
- package/src/routes.json +2 -2
- package/src/types/index.ts +38 -0
- package/dist/421.js.map +0 -1
- package/src/claims/claims-management/table/retry-claim-request.modal.tsx +0 -63
|
@@ -1,207 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
DataTableSkeleton,
|
|
4
|
-
OverflowMenu,
|
|
5
|
-
OverflowMenuItem,
|
|
6
|
-
Pagination,
|
|
7
|
-
Table,
|
|
8
|
-
TableBody,
|
|
9
|
-
TableCell,
|
|
10
|
-
TableContainer,
|
|
11
|
-
TableHead,
|
|
12
|
-
TableHeader,
|
|
13
|
-
TableRow,
|
|
14
|
-
Tag,
|
|
15
|
-
} from '@carbon/react';
|
|
16
|
-
import { formatDate, isDesktop, parseDate, showModal, useLayoutType, usePagination } from '@openmrs/esm-framework';
|
|
17
|
-
import { CardHeader, EmptyState, usePaginationInfo } from '@openmrs/esm-patient-common-lib';
|
|
18
|
-
import React, { useMemo, useState } from 'react';
|
|
19
|
-
import { useTranslation } from 'react-i18next';
|
|
20
|
-
import { ClaimsPreAuthFilter } from '../../../types';
|
|
21
|
-
import ClaimsFilterHeader from '../header/filter-header.component';
|
|
22
|
-
import styles from './claims-list-table.scss';
|
|
23
|
-
import { useFacilityClaims } from './use-facility-claims';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ClaimsTable from './claim-table.component';
|
|
24
3
|
|
|
25
4
|
const PreauthTableTemporary: React.FC = () => {
|
|
26
|
-
const { claims, isLoading } = useFacilityClaims();
|
|
27
|
-
const { t } = useTranslation();
|
|
28
|
-
const [filters, setFilters] = useState<ClaimsPreAuthFilter>({
|
|
29
|
-
status: 'all',
|
|
30
|
-
});
|
|
31
|
-
const status = useMemo(
|
|
32
|
-
() => [
|
|
33
|
-
{ value: 'all', label: t('all', 'All') },
|
|
34
|
-
{ value: 'ENTERED', label: t('entered', 'Entered') },
|
|
35
|
-
{ value: 'ERRORED', label: t('errored', 'Errored') },
|
|
36
|
-
{ value: 'REJECTED', label: t('rejected', 'Rejected') },
|
|
37
|
-
{ value: 'CHECKED', label: t('checked', 'Checked') },
|
|
38
|
-
{ value: 'VALUATED', label: t('valuated', 'Valuated') },
|
|
39
|
-
],
|
|
40
|
-
[t],
|
|
41
|
-
);
|
|
42
|
-
const [pageSize, setPageSize] = useState(5);
|
|
43
|
-
const filterClaims = (claim) => {
|
|
44
|
-
const status = filters?.status;
|
|
45
|
-
const search = filters?.search?.toLowerCase();
|
|
46
|
-
const fromDate = filters?.fromDate ? new Date(filters.fromDate) : null;
|
|
47
|
-
const toDate = filters?.toDate ? new Date(filters.toDate) : null;
|
|
48
|
-
|
|
49
|
-
const patientName = claim.patientName?.toLowerCase();
|
|
50
|
-
const providerName = claim.providerName?.toLowerCase();
|
|
51
|
-
const timeStamp = new Date(claim.dateFrom);
|
|
52
|
-
const preauthStatus = claim.status;
|
|
53
|
-
|
|
54
|
-
// Check status (allow 'all' to bypass the filter)
|
|
55
|
-
const statusMatch = status === 'all' || preauthStatus === status;
|
|
56
|
-
|
|
57
|
-
// Check search filter (patient name or provider name contains the search term)
|
|
58
|
-
const searchMatch = !search || patientName?.includes(search) || providerName?.includes(search);
|
|
59
|
-
|
|
60
|
-
// Check date range filter (timestamp is between fromDate and toDate if provided)
|
|
61
|
-
const dateMatch = (!fromDate || timeStamp >= fromDate) && (!toDate || timeStamp <= toDate);
|
|
62
|
-
|
|
63
|
-
// Return true if all conditions match
|
|
64
|
-
return statusMatch && searchMatch && dateMatch;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const filteredClaims = claims.filter(filterClaims);
|
|
68
|
-
const { paginated, goTo, results, currentPage } = usePagination(filteredClaims, pageSize);
|
|
69
|
-
const { pageSizes } = usePaginationInfo(pageSize, claims.length, currentPage, results.length);
|
|
70
|
-
const responsiveSize = isDesktop(useLayoutType()) ? 'sm' : 'lg';
|
|
71
|
-
const layout = useLayoutType();
|
|
72
|
-
const size = layout === 'tablet' ? 'lg' : 'md';
|
|
73
|
-
|
|
74
|
-
const headers = [
|
|
75
|
-
{ key: 'status', header: t('status', 'Status') },
|
|
76
|
-
{ key: 'providerName', header: t('provider', 'Provider') },
|
|
77
|
-
{ key: 'patientName', header: t('patient', 'Patient') },
|
|
78
|
-
{ key: 'claimedTotal', header: t('claimedAmount', 'Claimed Amount') },
|
|
79
|
-
{ key: 'approvedTotal', header: t('approvedTotal', 'Approved Total') },
|
|
80
|
-
{ key: 'dateFrom', header: t('dateCreated', 'Date Created') },
|
|
81
|
-
{ key: 'action', header: t('action', 'Action') },
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
if (isLoading) {
|
|
85
|
-
return (
|
|
86
|
-
<div className={styles.dataTableSkeleton}>
|
|
87
|
-
<DataTableSkeleton
|
|
88
|
-
headers={headers}
|
|
89
|
-
showToolbar={false}
|
|
90
|
-
showHeader={false}
|
|
91
|
-
columnCount={Object.keys(headers).length}
|
|
92
|
-
zebra
|
|
93
|
-
rowCount={pageSize}
|
|
94
|
-
/>
|
|
95
|
-
</div>
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (claims.length === 0) {
|
|
100
|
-
return (
|
|
101
|
-
<div className={styles.claimsTable}>
|
|
102
|
-
<EmptyState
|
|
103
|
-
displayText={t('emptyPreauthState', 'There are no preauth to display')}
|
|
104
|
-
headerTitle={t('emptyPreauthHeader', 'No Preauths')}
|
|
105
|
-
/>
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const handleRetry = (claimId: string) => {
|
|
111
|
-
const dispose = showModal('retry-claim-request-modal', {
|
|
112
|
-
closeModal: () => dispose(),
|
|
113
|
-
claimId,
|
|
114
|
-
});
|
|
115
|
-
};
|
|
116
|
-
|
|
117
5
|
return (
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{({ rows, headers, getHeaderProps, getRowProps, getTableProps }) => (
|
|
125
|
-
<TableContainer className={styles.claimsTable}>
|
|
126
|
-
<Table {...getTableProps()} aria-label="sample table">
|
|
127
|
-
<TableHead>
|
|
128
|
-
<TableRow>
|
|
129
|
-
{headers.map((header) => (
|
|
130
|
-
<TableHeader
|
|
131
|
-
key={header.key}
|
|
132
|
-
{...getHeaderProps({
|
|
133
|
-
header,
|
|
134
|
-
})}>
|
|
135
|
-
{header.header}
|
|
136
|
-
</TableHeader>
|
|
137
|
-
))}
|
|
138
|
-
</TableRow>
|
|
139
|
-
</TableHead>
|
|
140
|
-
<TableBody>
|
|
141
|
-
{rows.map((row) => {
|
|
142
|
-
const rowStatus = row.cells.find((cell) => cell.info.header === 'status')?.value;
|
|
143
|
-
return (
|
|
144
|
-
<TableRow
|
|
145
|
-
{...getRowProps({
|
|
146
|
-
row,
|
|
147
|
-
})}>
|
|
148
|
-
{row.cells.map((cell) => (
|
|
149
|
-
<TableCell key={cell.id}>
|
|
150
|
-
{cell.info.header === 'status' ? (
|
|
151
|
-
<ClaimStatus cell={cell} row={row} />
|
|
152
|
-
) : cell.info.header === 'action' && ['ENTERED', 'ERRORED'].includes(rowStatus) ? (
|
|
153
|
-
<OverflowMenu size={size} flipped>
|
|
154
|
-
<OverflowMenuItem
|
|
155
|
-
itemText={t('retryRequest', 'Retry request')}
|
|
156
|
-
onClick={() => handleRetry(row.id)}
|
|
157
|
-
/>
|
|
158
|
-
</OverflowMenu>
|
|
159
|
-
) : cell.info.header === 'dateFrom' ? (
|
|
160
|
-
formatDate(parseDate(cell.value))
|
|
161
|
-
) : (
|
|
162
|
-
cell.value
|
|
163
|
-
)}
|
|
164
|
-
</TableCell>
|
|
165
|
-
))}
|
|
166
|
-
</TableRow>
|
|
167
|
-
);
|
|
168
|
-
})}
|
|
169
|
-
</TableBody>
|
|
170
|
-
</Table>
|
|
171
|
-
{paginated && !isLoading && (
|
|
172
|
-
<Pagination
|
|
173
|
-
forwardText=""
|
|
174
|
-
backwardText=""
|
|
175
|
-
page={currentPage}
|
|
176
|
-
pageSize={pageSize}
|
|
177
|
-
pageSizes={pageSizes}
|
|
178
|
-
totalItems={filteredClaims.length}
|
|
179
|
-
size={responsiveSize}
|
|
180
|
-
onChange={({ page: newPage, pageSize }) => {
|
|
181
|
-
if (newPage !== currentPage) {
|
|
182
|
-
goTo(newPage);
|
|
183
|
-
}
|
|
184
|
-
setPageSize(pageSize);
|
|
185
|
-
}}
|
|
186
|
-
/>
|
|
187
|
-
)}
|
|
188
|
-
</TableContainer>
|
|
189
|
-
)}
|
|
190
|
-
</DataTable>
|
|
191
|
-
</div>
|
|
6
|
+
<ClaimsTable
|
|
7
|
+
title="preauthsRequests"
|
|
8
|
+
emptyStateText="emptyPreauthState"
|
|
9
|
+
emptyStateHeader="emptyPreauthHeader"
|
|
10
|
+
includeClaimCode={false}
|
|
11
|
+
/>
|
|
192
12
|
);
|
|
193
13
|
};
|
|
194
14
|
|
|
195
15
|
export default PreauthTableTemporary;
|
|
196
|
-
|
|
197
|
-
const ClaimStatus = ({ cell, row }: { cell: { value: string }; row: any }) => {
|
|
198
|
-
const { claims } = useFacilityClaims();
|
|
199
|
-
|
|
200
|
-
const claim = claims.find((claim) => claim.id === row.id);
|
|
201
|
-
return (
|
|
202
|
-
<div className={styles.claimStatus}>
|
|
203
|
-
<p>{cell.value}</p>
|
|
204
|
-
{claim.externalId && <Tag type="blue">{claim.externalId}</Tag>}
|
|
205
|
-
</div>
|
|
206
|
-
);
|
|
207
|
-
};
|
|
@@ -4,7 +4,7 @@ import { FacilityClaim } from '../../../types';
|
|
|
4
4
|
|
|
5
5
|
export const useFacilityClaims = () => {
|
|
6
6
|
const customPresentation =
|
|
7
|
-
'custom:(uuid,claimCode,dateFrom,dateTo,claimedTotal,approvedTotal,status,externalId,provider:(display),patient:(display))';
|
|
7
|
+
'custom:(uuid,claimCode,dateFrom,dateTo,claimedTotal,approvedTotal,status,externalId,responseUUID,provider:(display),patient:(display))';
|
|
8
8
|
const url = `${restBaseUrl}/claim?v=${customPresentation}`;
|
|
9
9
|
|
|
10
10
|
const { data, error, isLoading, mutate, isValidating } = useSWR<FetchResponse<{ results: Array<FacilityClaim> }>>(
|
|
@@ -411,7 +411,6 @@ const ClaimsForm: React.FC<ClaimsFormProps> = ({ bill, selectedLineItems }) => {
|
|
|
411
411
|
name="provider"
|
|
412
412
|
render={({ field }) => (
|
|
413
413
|
<ComboBox
|
|
414
|
-
{...field}
|
|
415
414
|
id="provider"
|
|
416
415
|
invalid={shouldShowError('provider')}
|
|
417
416
|
invalidText={errors.provider?.message}
|
|
@@ -419,11 +418,16 @@ const ClaimsForm: React.FC<ClaimsFormProps> = ({ bill, selectedLineItems }) => {
|
|
|
419
418
|
titleText={t('provider', 'Provider')}
|
|
420
419
|
items={providers}
|
|
421
420
|
itemToString={(item) => item?.display?.split('-')?.at(-1)?.trim() ?? ''}
|
|
422
|
-
|
|
421
|
+
initialSelectedItem={
|
|
422
|
+
field.value && providers ? providers.find((p) => p.uuid === field.value) : null
|
|
423
|
+
}
|
|
423
424
|
onChange={({ selectedItem }) => {
|
|
424
|
-
field.onChange(selectedItem?.
|
|
425
|
+
field.onChange(selectedItem?.uuid || '');
|
|
425
426
|
setValidationEnabled(true);
|
|
426
427
|
}}
|
|
428
|
+
name={field.name}
|
|
429
|
+
onBlur={field.onBlur}
|
|
430
|
+
ref={field.ref}
|
|
427
431
|
/>
|
|
428
432
|
)}
|
|
429
433
|
/>
|
|
@@ -90,3 +90,10 @@ export const usePackages = () => {
|
|
|
90
90
|
error: undefined,
|
|
91
91
|
};
|
|
92
92
|
};
|
|
93
|
+
|
|
94
|
+
export const updateClaimStatus = (responseUUID: string) => {
|
|
95
|
+
const url = `/ws/rest/v1/insuranceclaims/claim/update-status?externalId=${responseUUID}`;
|
|
96
|
+
return openmrsFetch(url, {
|
|
97
|
+
method: 'GET',
|
|
98
|
+
});
|
|
99
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -53,9 +53,7 @@ import OrderActionButton from './billable-services/billiable-item/order-actions/
|
|
|
53
53
|
|
|
54
54
|
// Claims Management Components
|
|
55
55
|
import ClaimsManagementOverview from './claims/claims-management/main/claims-overview-main.component';
|
|
56
|
-
import {
|
|
57
|
-
|
|
58
|
-
// Payment Components
|
|
56
|
+
import { ManageClaimRequest } from './claims/claims-management/table/manage-claim-request.modal';
|
|
59
57
|
import InitiatePaymentDialog from './invoice/payments/initiate-payment/initiate-payment.component';
|
|
60
58
|
import VisitAttributeTags from './invoice/payments/visit-tags/visit-attribute.component';
|
|
61
59
|
import ReceiptPrintPreviewModal from './invoice/print-bill-receipt/receipt-print-preview.modal';
|
|
@@ -232,7 +230,7 @@ export const bulkImportBillableServicesModal = getSyncLifecycle(BulkImportBillab
|
|
|
232
230
|
|
|
233
231
|
// Claims Management Components
|
|
234
232
|
export const claimsOverview = getSyncLifecycle(ClaimsManagementOverview, options);
|
|
235
|
-
export const
|
|
233
|
+
export const manageClaimRequestModal = getSyncLifecycle(ManageClaimRequest, options);
|
|
236
234
|
|
|
237
235
|
// App Startup
|
|
238
236
|
export function startupApp() {
|
package/src/routes.json
CHANGED
|
@@ -309,8 +309,8 @@
|
|
|
309
309
|
"component": "deletePaymentModeModal"
|
|
310
310
|
},
|
|
311
311
|
{
|
|
312
|
-
"name": "
|
|
313
|
-
"component": "
|
|
312
|
+
"name": "manage-claim-request-modal",
|
|
313
|
+
"component": "manageClaimRequestModal"
|
|
314
314
|
},
|
|
315
315
|
{
|
|
316
316
|
"name": "paid-bill-receipt-print-preview-modal",
|
package/src/types/index.ts
CHANGED
|
@@ -548,6 +548,7 @@ export type FacilityClaim = {
|
|
|
548
548
|
} | null;
|
|
549
549
|
patient?: { display: string };
|
|
550
550
|
externalId: string;
|
|
551
|
+
responseUUID: string;
|
|
551
552
|
};
|
|
552
553
|
export type BillingPromptType = 'patient-chart' | 'billing-orders';
|
|
553
554
|
|
|
@@ -568,3 +569,40 @@ export interface Filter {
|
|
|
568
569
|
cashiers?: Array<string>;
|
|
569
570
|
status?: string;
|
|
570
571
|
}
|
|
572
|
+
export interface DataTableRow {
|
|
573
|
+
id: string;
|
|
574
|
+
cells: Array<Cell>;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
export interface Cell {
|
|
578
|
+
id: string;
|
|
579
|
+
value: any;
|
|
580
|
+
info: Info;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
export interface Info {
|
|
584
|
+
header: string;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export interface Claim {
|
|
588
|
+
id: string;
|
|
589
|
+
status: string;
|
|
590
|
+
claimCode?: string;
|
|
591
|
+
providerName?: string;
|
|
592
|
+
patientName?: string;
|
|
593
|
+
claimedTotal?: number | string;
|
|
594
|
+
approvedTotal?: number | string;
|
|
595
|
+
dateFrom: string;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export interface Header {
|
|
599
|
+
key: string;
|
|
600
|
+
header: string;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export interface TableProps {
|
|
604
|
+
title: string;
|
|
605
|
+
emptyStateText: string;
|
|
606
|
+
emptyStateHeader: string;
|
|
607
|
+
includeClaimCode?: boolean;
|
|
608
|
+
}
|