Skip to content

Commit

Permalink
(Refactor) : Removed patient bills filter and fixed patient search cs…
Browse files Browse the repository at this point in the history
…s issue (#309)

* initial work on patient bills

* fix: override button height for patient search extension

* refactor: use carbon spacing for tile padding

* fix: applied changes from code-review
  • Loading branch information
amosmachora authored Aug 17, 2024
1 parent ff99bb3 commit 7752c71
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import styles from './bill-manager.scss';
import billTableStyles from '../../bills-table/bills-table.scss';
import { useBills } from '../../billing.resource';
import { DataTableSkeleton, Layer, Tile } from '@carbon/react';
import { EmptyDataIllustration } from '@openmrs/esm-patient-common-lib';
import { EmptyDataIllustration, EmptyState } from '@openmrs/esm-patient-common-lib';
import { useTranslation } from 'react-i18next';

type BillManagerProps = {};
Expand Down Expand Up @@ -36,18 +36,10 @@ const BillManager: React.FC<BillManagerProps> = () => {
}}
/>
{!patientUuid ? (
<div style={{ marginTop: '0.625rem' }}>
<Layer className={billTableStyles.emptyStateContainer}>
<Tile className={billTableStyles.tile}>
<div className={billTableStyles.illo}>
<EmptyDataIllustration />
</div>
<p className={billTableStyles.content}>
{t('notSearchedState', 'Please search for a patient in the input above')}
</p>
</Tile>
</Layer>
</div>
<EmptyState
displayText={t('notSearchedState', 'Please search for a patient in the input above')}
headerTitle="Not Searched"
/>
) : isLoading ? (
<DataTableSkeleton
headers={headers}
Expand Down
2 changes: 1 addition & 1 deletion packages/esm-billing-app/src/bills-table/bills-table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@import '~@openmrs/esm-styleguide/src/vars';

.container {
margin: 2rem 0;
margin-top: layout.$spacing-05;
}

.emptyStateContainer,
Expand Down
20 changes: 11 additions & 9 deletions packages/esm-billing-app/src/helpers/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,22 @@ export const getGender = (gender: string, t) => {
* @returns {string} The substring found after the first colon in the input string.
*/
export function extractString(input: string): string {
const parts = input.split(':');
return removeUUID(parts.length < 2 ? input : parts[1]);
}
const parts = input
.split(' ')
.map((s) => s.split(':')[1])
.filter((s) => Boolean(s));

const firstTwoBillableServices = parts.slice(0, 2);

function removeUUID(str) {
// Regular expression to match a UUID
const uuidPattern = /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
if (parts.length <= 2) {
return firstTwoBillableServices.join(', ');
}

// Replace the UUID with an empty string
return str.replace(uuidPattern, '');
return `${firstTwoBillableServices.join(', ')} & ${parts.length - 2} other services`;
}

// cleans the provider display name
export function extractNameString(formattedString) {
export function extractNameString(formattedString: string) {
if (!formattedString) {
return '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@

.container {
height: calc(100vh - 3rem);
button {
height: auto !important;
}
}

.billsTableContainer {
margin: layout.$spacing-03 layout.$spacing-01;
}

.loadingContainer,
.errorStateContainer,
.emptyStateContainer {
margin-top: layout.$spacing-05;
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,87 @@
import React, { useState } from 'react';
import styles from './patient-bills-dashboard.scss';
import { ExtensionSlot } from '@openmrs/esm-framework';
import PastPatientBills from '../filtered-patient-bills.component';
import { ErrorState, ExtensionSlot } from '@openmrs/esm-framework';
import { useBills } from '../../billing.resource';
import { Dropdown } from '@carbon/react';

const filterItems = [
{ id: 'PENDING', text: 'Pending bills' },
{ id: 'POSTED', text: 'Posted bills' },
];
import { useTranslation } from 'react-i18next';
import { DataTableSkeleton } from '@carbon/react';
import { patientBillsHeaders, PatientBills } from '../patient-bills.component';
import { EmptyState } from '@openmrs/esm-patient-common-lib';

const PatientBillsScreen: React.FC = () => {
const [patientUuid, setPatientUuid] = React.useState<string>('');
const { bills } = useBills(patientUuid);
const filterBills = bills.filter((bill) => bill.status !== 'PAID' && patientUuid === bill.patientUuid) ?? [];
const [patientUuid, setPatientUuid] = useState<string | undefined>();

return (
<main className={styles.container}>
<ExtensionSlot
name="patient-search-bar-slot"
state={{
selectPatientAction: (patientUuid) => setPatientUuid(patientUuid),
selectPatientAction: (patientUuid: string) => setPatientUuid(patientUuid),
buttonProps: {
kind: 'primary',
},
}}
/>
<PastPatientBills patientUuid={patientUuid} bills={filterBills} setPatientUuid={setPatientUuid} />
<PatientBillsWrapper patientUUID={patientUuid} />
</main>
);
};

const PatientBillsWrapper = ({ patientUUID }: { patientUUID?: string }) => {
const { bills, isLoading, error } = useBills(patientUUID);

const { t } = useTranslation();

if (!patientUUID) {
return (
<div className={styles.emptyStateContainer}>
<EmptyState
displayText={t('notSearchedState', 'Please search for a patient in the input above')}
headerTitle="Not Searched"
/>
</div>
);
}

if (isLoading) {
return (
<div className={styles.loadingContainer}>
<DataTableSkeleton
headers={patientBillsHeaders}
aria-label="patient bills table"
showToolbar={false}
showHeader={false}
rowCount={3}
zebra
columnCount={3}
className={styles.dataTableSkeleton}
/>
</div>
);
}

if (error) {
return (
<div className={styles.errorStateContainer}>
<ErrorState
error={t('anErrorOccurredLoadingPatientBills', 'An error occurred loading patient bills')}
headerTitle={t('errorLoadingPatientBills', 'Error loading patient bills')}
/>
</div>
);
}

if (bills.length === 0) {
return (
<div className={styles.emptyStateContainer}>
<EmptyState
headerTitle={t('noBillsState', 'No Patient Bills Found')}
displayText={t('noBillsFoundToDisplay', 'No bills to dipsplay')}
/>
</div>
);
}

return <PatientBills bills={bills} />;
};

export default PatientBillsScreen;
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,20 @@ import { useTranslation } from 'react-i18next';
import { MappedBill } from '../types';
import styles from '../bills-table/bills-table.scss';
import { ConfigurableLink } from '@openmrs/esm-framework';
import { EmptyState } from '@openmrs/esm-patient-common-lib';

type PatientBillsProps = {
patientUuid: string;
bills: Array<MappedBill>;
setPatientUuid: (patientUuid: string) => void;
};

const PastPatientBills: React.FC<PatientBillsProps> = ({ patientUuid, bills, setPatientUuid }) => {
const { t } = useTranslation();

if (!patientUuid) {
<h3>Missing patient information</h3>;
}
export const patientBillsHeaders = [
{ header: 'Date', key: 'date' },
{ header: 'Billable Service (s)', key: 'billableService' },
{ header: 'Total Amount', key: 'totalAmount' },
{ header: 'status', key: 'status' },
];

const tableHeaders = [
{ header: 'Date', key: 'date' },
{ header: 'Billable Service', key: 'billableService' },
{ header: 'Total Amount', key: 'totalAmount' },
];
export const PatientBills: React.FC<PatientBillsProps> = ({ bills }) => {
const { t } = useTranslation();

const billingUrl = '${openmrsSpaBase}/home/billing/patient/${patientUuid}/${uuid}';

Expand All @@ -52,37 +46,24 @@ const PastPatientBills: React.FC<PatientBillsProps> = ({ patientUuid, bills, set
),
billableService: extractString(bill.billingService),
totalAmount: convertToCurrency(bill.totalAmount),
status: bill.status,
}));

if (bills.length === 0 && patientUuid !== '') {
<EmptyState displayText={'Pending Patient Bills Found'} headerTitle={'No Pending Patient Bills Found'} />;
}

return (
<div className={styles.container}>
<DataTable
rows={tableRows}
headers={tableHeaders}
headers={patientBillsHeaders}
size="sm"
useZebraStyles
render={({
rows,
headers,
getHeaderProps,
getExpandHeaderProps,
getRowProps,
getExpandedRowProps,
getTableProps,
getTableContainerProps,
}) => (
render={({ rows, headers, getHeaderProps, getRowProps, getTableProps, getTableContainerProps }) => (
<TableContainer
title={t('patientBills', 'Patient bill')}
description={t('patientBillsDescription', 'List of patient bills')}
{...getTableContainerProps()}>
<Table {...getTableProps()} aria-label="sample table">
<TableHead>
<TableRow>
<TableHeader enableToggle={true} {...getExpandHeaderProps()} />
{headers.map((header, i) => (
<TableHeader
key={i}
Expand All @@ -96,16 +77,14 @@ const PastPatientBills: React.FC<PatientBillsProps> = ({ patientUuid, bills, set
</TableHead>
<TableBody>
{rows.map((row, index) => (
<React.Fragment key={row.id}>
<TableExpandRow
{...getRowProps({
row,
})}>
{row.cells.map((cell) => (
<TableCell key={cell.id}>{cell.value}</TableCell>
))}
</TableExpandRow>
</React.Fragment>
<TableRow
{...getRowProps({
row,
})}>
{row.cells.map((cell) => (
<TableCell key={cell.id}>{cell.value}</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
Expand All @@ -115,5 +94,3 @@ const PastPatientBills: React.FC<PatientBillsProps> = ({ patientUuid, bills, set
</div>
);
};

export default PastPatientBills;

0 comments on commit 7752c71

Please sign in to comment.