@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.
@@ -1,207 +1,15 @@
1
- import {
2
- DataTable,
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
- <div className={styles.dataTableSkeleton}>
119
- <div className={styles.tableHeader}>
120
- <CardHeader title={t('preathsRequests', 'Preauth Requests')}>{''}</CardHeader>
121
- <ClaimsFilterHeader filters={filters} onFilterChanged={setFilters} statusOptions={status} />
122
- </div>
123
- <DataTable rows={results} headers={headers} isSortable useZebraStyles>
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
- selectedItem={providers?.find((p) => p?.uuid === field.value)}
421
+ initialSelectedItem={
422
+ field.value && providers ? providers.find((p) => p.uuid === field.value) : null
423
+ }
423
424
  onChange={({ selectedItem }) => {
424
- field.onChange(selectedItem?.display?.split('-')?.at(-1)?.trim() ?? '');
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
+ };
@@ -0,0 +1,7 @@
1
+ export const statusColors = {
2
+ ENTERED: 'blue',
3
+ ERRORED: 'red',
4
+ REJECTED: 'red',
5
+ CHECKED: 'green',
6
+ VALUATED: 'purple',
7
+ };
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 { RetryClaimRequest } from './claims/claims-management/table/retry-claim-request.modal';
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 retryClaimRequestModal = getSyncLifecycle(RetryClaimRequest, options);
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": "retry-claim-request-modal",
313
- "component": "retryClaimRequestModal"
312
+ "name": "manage-claim-request-modal",
313
+ "component": "manageClaimRequestModal"
314
314
  },
315
315
  {
316
316
  "name": "paid-bill-receipt-print-preview-modal",
@@ -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
+ }