@openmrs/esm-billing-app 1.0.2-pre.88 → 1.0.2-pre.880
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/.eslintrc +16 -2
- package/README.md +54 -9
- package/__mocks__/bills.mock.ts +12 -0
- package/__mocks__/react-i18next.js +6 -5
- package/dist/1119.js +1 -1
- package/dist/1146.js +1 -2
- package/dist/1146.js.map +1 -1
- package/dist/1197.js +1 -1
- package/dist/1856.js +1 -0
- package/dist/1856.js.map +1 -0
- package/dist/2146.js +1 -1
- package/dist/2372.js +1 -0
- package/dist/2372.js.map +1 -0
- package/dist/2524.js +1 -0
- package/dist/2524.js.map +1 -0
- package/dist/2690.js +1 -1
- package/dist/3099.js +1 -1
- package/dist/3584.js +1 -1
- package/dist/3717.js +2 -0
- package/dist/3717.js.map +1 -0
- package/dist/4055.js +1 -1
- package/dist/4132.js +1 -1
- package/dist/4300.js +1 -1
- package/dist/4335.js +1 -1
- package/dist/4618.js +1 -1
- package/dist/4652.js +1 -1
- package/dist/4724.js +1 -0
- package/dist/4724.js.map +1 -0
- package/dist/4739.js +1 -1
- package/dist/4739.js.map +1 -1
- package/dist/4944.js +1 -1
- package/dist/5173.js +1 -1
- package/dist/5241.js +1 -1
- package/dist/5442.js +1 -1
- package/dist/5661.js +1 -1
- package/dist/6022.js +1 -1
- package/dist/6468.js +1 -1
- package/dist/6540.js +1 -1
- package/dist/6540.js.map +1 -1
- package/dist/6679.js +1 -1
- package/dist/6840.js +1 -1
- package/dist/6859.js +1 -1
- package/dist/7097.js +1 -1
- package/dist/7159.js +1 -1
- package/dist/723.js +1 -1
- package/dist/7255.js +1 -1
- package/dist/7255.js.map +1 -1
- package/dist/7617.js +1 -1
- package/dist/795.js +1 -1
- package/dist/8163.js +1 -1
- package/dist/8349.js +1 -1
- package/dist/8618.js +1 -1
- package/dist/8708.js +2 -0
- package/dist/{6557.js.LICENSE.txt → 8708.js.LICENSE.txt} +22 -0
- package/dist/8708.js.map +1 -0
- package/dist/890.js +1 -1
- package/dist/9214.js +1 -1
- package/dist/9538.js +1 -1
- package/dist/9569.js +1 -1
- package/dist/961.js +1 -1
- package/dist/961.js.map +1 -1
- package/dist/986.js +1 -1
- package/dist/9879.js +1 -1
- package/dist/9895.js +1 -1
- package/dist/9900.js +1 -1
- package/dist/9913.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js +1 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +263 -301
- package/dist/openmrs-esm-billing-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/e2e/README.md +19 -18
- package/e2e/core/test.ts +1 -1
- package/e2e/fixtures/api.ts +1 -1
- package/e2e/specs/sample-test.spec.ts +0 -1
- package/e2e/support/github/Dockerfile +1 -1
- package/package.json +18 -15
- package/src/bill-history/bill-history.component.tsx +20 -28
- package/src/bill-history/bill-history.scss +4 -94
- package/src/bill-history/bill-history.test.tsx +37 -78
- package/src/bill-item-actions/bill-item-actions.scss +21 -5
- package/src/bill-item-actions/edit-bill-item.modal.tsx +225 -0
- package/src/bill-item-actions/edit-bill-item.test.tsx +214 -40
- package/src/billable-services/bill-waiver/bill-selection.component.tsx +5 -5
- package/src/billable-services/bill-waiver/bill-waiver-form.component.tsx +28 -32
- package/src/billable-services/bill-waiver/patient-bills.component.tsx +7 -7
- package/src/billable-services/bill-waiver/utils.ts +13 -3
- package/src/billable-services/billable-service.resource.ts +42 -26
- package/src/billable-services/billable-services-home.component.tsx +12 -35
- package/src/billable-services/billable-services-left-panel-link.component.tsx +48 -0
- package/src/billable-services/billable-services-left-panel-menu.component.tsx +46 -0
- package/src/billable-services/billable-services.component.tsx +149 -148
- package/src/billable-services/billable-services.scss +29 -0
- package/src/billable-services/billable-services.test.tsx +6 -49
- package/src/billable-services/cash-point/add-cash-point.modal.tsx +168 -0
- package/src/billable-services/cash-point/cash-point-configuration.component.tsx +19 -193
- package/src/billable-services/cash-point/cash-point-configuration.scss +1 -5
- package/src/billable-services/create-edit/add-billable-service.component.tsx +388 -301
- package/src/billable-services/create-edit/add-billable-service.scss +7 -68
- package/src/billable-services/create-edit/add-billable-service.test.tsx +720 -77
- package/src/billable-services/create-edit/edit-billable-service.modal.tsx +51 -0
- package/src/billable-services/dashboard/dashboard.component.tsx +0 -2
- package/src/billable-services/payment-modes/add-payment-mode.modal.tsx +121 -0
- package/src/billable-services/payment-modes/delete-payment-mode.modal.tsx +74 -0
- package/src/billable-services/payment-modes/payment-modes-config.component.tsx +125 -0
- package/src/billable-services/{payyment-modes → payment-modes}/payment-modes-config.scss +5 -4
- package/src/billing-dashboard/billing-dashboard.scss +1 -1
- package/src/billing-form/billing-checkin-form.component.tsx +21 -17
- package/src/billing-form/billing-checkin-form.test.tsx +99 -26
- package/src/billing-form/billing-form.component.tsx +222 -292
- package/src/billing-form/billing-form.scss +143 -0
- package/src/billing-form/visit-attributes/visit-attributes-form.component.tsx +1 -1
- package/src/billing.resource.ts +69 -74
- package/src/bills-table/bills-table.component.tsx +3 -3
- package/src/bills-table/bills-table.test.tsx +98 -54
- package/src/config-schema.ts +52 -24
- package/src/dashboard.meta.ts +4 -2
- package/src/helpers/functions.ts +5 -4
- package/src/index.ts +67 -9
- package/src/invoice/invoice-table.component.tsx +36 -70
- package/src/invoice/invoice-table.scss +8 -5
- package/src/invoice/invoice-table.test.tsx +273 -62
- package/src/invoice/invoice.component.tsx +39 -32
- package/src/invoice/invoice.scss +11 -4
- package/src/invoice/invoice.test.tsx +324 -120
- package/src/invoice/payments/invoice-breakdown/invoice-breakdown.scss +9 -9
- package/src/invoice/payments/payment-form/payment-form.component.tsx +43 -34
- package/src/invoice/payments/payment-form/payment-form.scss +5 -6
- package/src/invoice/payments/payment-form/payment-form.test.tsx +216 -66
- package/src/invoice/payments/payment-history/payment-history.component.tsx +6 -4
- package/src/invoice/payments/payment-history/payment-history.test.tsx +9 -14
- package/src/invoice/payments/payments.component.tsx +55 -67
- package/src/invoice/payments/payments.scss +4 -3
- package/src/invoice/payments/payments.test.tsx +282 -0
- package/src/invoice/payments/utils.ts +15 -27
- package/src/invoice/printable-invoice/print-receipt.component.tsx +3 -2
- package/src/invoice/printable-invoice/print-receipt.test.tsx +14 -25
- package/src/invoice/printable-invoice/printable-footer.component.tsx +2 -2
- package/src/invoice/printable-invoice/printable-footer.test.tsx +4 -13
- package/src/invoice/printable-invoice/printable-invoice-header.component.tsx +12 -11
- package/src/invoice/printable-invoice/printable-invoice-header.test.tsx +16 -14
- package/src/invoice/printable-invoice/printable-invoice.component.tsx +20 -34
- package/src/left-panel-link.test.tsx +1 -4
- package/src/metrics-cards/metrics-cards.component.tsx +16 -6
- package/src/metrics-cards/metrics-cards.scss +4 -0
- package/src/metrics-cards/metrics-cards.test.tsx +18 -5
- package/src/modal/require-payment-modal.test.tsx +27 -22
- package/src/modal/{require-payment-modal.component.tsx → require-payment.modal.tsx} +18 -19
- package/src/routes.json +39 -8
- package/src/types/index.ts +81 -23
- package/translations/am.json +127 -75
- package/translations/ar.json +128 -76
- package/translations/ar_SY.json +128 -76
- package/translations/bn.json +130 -78
- package/translations/de.json +128 -76
- package/translations/en.json +128 -76
- package/translations/en_US.json +128 -76
- package/translations/es.json +127 -75
- package/translations/es_MX.json +128 -76
- package/translations/fr.json +133 -81
- package/translations/he.json +127 -75
- package/translations/hi.json +128 -76
- package/translations/hi_IN.json +128 -76
- package/translations/id.json +128 -76
- package/translations/it.json +154 -102
- package/translations/ka.json +128 -76
- package/translations/km.json +127 -75
- package/translations/ku.json +128 -76
- package/translations/ky.json +128 -76
- package/translations/lg.json +128 -76
- package/translations/ne.json +128 -76
- package/translations/pl.json +128 -76
- package/translations/pt.json +128 -76
- package/translations/pt_BR.json +128 -76
- package/translations/qu.json +128 -76
- package/translations/ro_RO.json +217 -165
- package/translations/ru_RU.json +128 -76
- package/translations/si.json +128 -76
- package/translations/sw.json +128 -76
- package/translations/sw_KE.json +128 -76
- package/translations/tr.json +128 -76
- package/translations/tr_TR.json +128 -76
- package/translations/uk.json +128 -76
- package/translations/uz.json +128 -76
- package/translations/uz@Latn.json +128 -76
- package/translations/uz_UZ.json +128 -76
- package/translations/vi.json +128 -76
- package/translations/zh.json +128 -76
- package/translations/zh_CN.json +159 -107
- package/dist/1146.js.LICENSE.txt +0 -21
- package/dist/2352.js +0 -1
- package/dist/2352.js.map +0 -1
- package/dist/246.js +0 -1
- package/dist/246.js.map +0 -1
- package/dist/4689.js +0 -2
- package/dist/4689.js.map +0 -1
- package/dist/6557.js +0 -2
- package/dist/6557.js.map +0 -1
- package/dist/8638.js +0 -1
- package/dist/8638.js.map +0 -1
- package/dist/9968.js +0 -1
- package/dist/9968.js.map +0 -1
- package/src/bill-item-actions/edit-bill-item.component.tsx +0 -221
- package/src/billable-services/dashboard/service-metrics.component.tsx +0 -41
- package/src/billable-services/payyment-modes/payment-modes-config.component.tsx +0 -280
- package/src/invoice/payments/payments.component.test.tsx +0 -121
- /package/dist/{4689.js.LICENSE.txt → 3717.js.LICENSE.txt} +0 -0
|
@@ -1,56 +1,32 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
2
3
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
3
|
-
import { SideNav, SideNavItems, SideNavLink, SideNavMenu, SideNavMenuItem } from '@carbon/react';
|
|
4
|
-
import { Wallet, Money, Settings } from '@carbon/react/icons';
|
|
5
4
|
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import {
|
|
5
|
+
import { useLeftNav, navigate, WorkspaceContainer, useLayoutType, isDesktop } from '@openmrs/esm-framework';
|
|
7
6
|
import AddBillableService from './create-edit/add-billable-service.component';
|
|
8
7
|
import BillWaiver from './bill-waiver/bill-waiver.component';
|
|
9
8
|
import BillableServicesDashboard from './dashboard/dashboard.component';
|
|
10
9
|
import BillingHeader from '../billing-header/billing-header.component';
|
|
11
10
|
import CashPointConfiguration from './cash-point/cash-point-configuration.component';
|
|
12
|
-
import PaymentModesConfig from './
|
|
11
|
+
import PaymentModesConfig from './payment-modes/payment-modes-config.component';
|
|
13
12
|
import styles from './billable-services.scss';
|
|
14
13
|
|
|
15
14
|
const BillableServiceHome: React.FC = () => {
|
|
16
15
|
const { t } = useTranslation();
|
|
16
|
+
const layout = useLayoutType();
|
|
17
17
|
const basePath = `${window.spaBase}/billable-services`;
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
navigate({ to: `${basePath}/${path}` });
|
|
21
|
-
};
|
|
19
|
+
useLeftNav({ name: 'billable-services-left-panel-slot', basePath });
|
|
22
20
|
|
|
23
21
|
const handleCloseAddService = () => {
|
|
24
22
|
navigate({ to: `${basePath}` });
|
|
25
23
|
};
|
|
26
24
|
|
|
27
25
|
return (
|
|
28
|
-
<BrowserRouter basename={
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
<SideNavItems>
|
|
33
|
-
<SideNavLink onClick={() => handleNavigation('')} renderIcon={Wallet} isActive>
|
|
34
|
-
{t('billableServices', 'Billable Services')}
|
|
35
|
-
</SideNavLink>
|
|
36
|
-
<UserHasAccess privilege="coreapps.systemAdministration">
|
|
37
|
-
<SideNavLink onClick={() => handleNavigation('waive-bill')} renderIcon={Money}>
|
|
38
|
-
{t('billWaiver', 'Bill waiver')}
|
|
39
|
-
</SideNavLink>
|
|
40
|
-
<SideNavMenu title={t('billingSettings', 'Billing Settings')} renderIcon={Settings}>
|
|
41
|
-
<SideNavMenuItem onClick={() => handleNavigation('cash-point-config')}>
|
|
42
|
-
{t('cashPointConfig', 'Cash Point Config')}
|
|
43
|
-
</SideNavMenuItem>
|
|
44
|
-
<SideNavMenuItem onClick={() => handleNavigation('payment-modes-config')}>
|
|
45
|
-
{t('paymentModesConfig', 'Payment Modes Config')}
|
|
46
|
-
</SideNavMenuItem>
|
|
47
|
-
</SideNavMenu>
|
|
48
|
-
</UserHasAccess>
|
|
49
|
-
</SideNavItems>
|
|
50
|
-
</SideNav>
|
|
51
|
-
</section>
|
|
52
|
-
<section>
|
|
53
|
-
<BillingHeader title={t('billServicesManagement', 'Bill services management')} />
|
|
26
|
+
<BrowserRouter basename={basePath}>
|
|
27
|
+
<div className={styles.pageWrapper}>
|
|
28
|
+
<main className={classNames(styles.pageContent, { [styles.hasLeftNav]: isDesktop(layout) })}>
|
|
29
|
+
<BillingHeader title={t('billableServicesManagement', 'Billable services management')} />
|
|
54
30
|
<Routes>
|
|
55
31
|
<Route path="/" element={<BillableServicesDashboard />} />
|
|
56
32
|
<Route path="/add-service" element={<AddBillableService onClose={handleCloseAddService} />} />
|
|
@@ -58,8 +34,9 @@ const BillableServiceHome: React.FC = () => {
|
|
|
58
34
|
<Route path="/cash-point-config" element={<CashPointConfiguration />} />
|
|
59
35
|
<Route path="/payment-modes-config" element={<PaymentModesConfig />} />
|
|
60
36
|
</Routes>
|
|
61
|
-
</
|
|
62
|
-
</
|
|
37
|
+
</main>
|
|
38
|
+
</div>
|
|
39
|
+
<WorkspaceContainer contextKey="billable-services" />
|
|
63
40
|
</BrowserRouter>
|
|
64
41
|
);
|
|
65
42
|
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { BrowserRouter, useLocation } from 'react-router-dom';
|
|
3
|
+
import { SideNavLink } from '@carbon/react';
|
|
4
|
+
import { navigate, UserHasAccess } from '@openmrs/esm-framework';
|
|
5
|
+
|
|
6
|
+
export interface BillableServicesLinkConfig {
|
|
7
|
+
name: string;
|
|
8
|
+
title: string;
|
|
9
|
+
path: string;
|
|
10
|
+
icon?: React.ComponentType;
|
|
11
|
+
privilege?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function BillableServicesLinkExtension({ config }: { config: BillableServicesLinkConfig }) {
|
|
15
|
+
const { title, path, icon: Icon, privilege } = config;
|
|
16
|
+
const location = useLocation();
|
|
17
|
+
const spaBasePath = `${window.spaBase}/billable-services`;
|
|
18
|
+
|
|
19
|
+
const isActive = useMemo(() => {
|
|
20
|
+
const currentPath = location.pathname.replace(spaBasePath, '');
|
|
21
|
+
if (path === '' || path === '/') {
|
|
22
|
+
return currentPath === '' || currentPath === '/';
|
|
23
|
+
}
|
|
24
|
+
return currentPath.startsWith(`/${path}`);
|
|
25
|
+
}, [location.pathname, path, spaBasePath]);
|
|
26
|
+
|
|
27
|
+
const handleNavigation = () => {
|
|
28
|
+
navigate({ to: `${spaBasePath}/${path}` });
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const link = (
|
|
32
|
+
<SideNavLink onClick={handleNavigation} renderIcon={Icon} isActive={isActive}>
|
|
33
|
+
{title}
|
|
34
|
+
</SideNavLink>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (privilege) {
|
|
38
|
+
return <UserHasAccess privilege={privilege}>{link}</UserHasAccess>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return link;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const createBillableServicesLeftPanelLink = (config: BillableServicesLinkConfig) => () => (
|
|
45
|
+
<BrowserRouter>
|
|
46
|
+
<BillableServicesLinkExtension config={config} />
|
|
47
|
+
</BrowserRouter>
|
|
48
|
+
);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
3
|
+
import { SideNavMenu, SideNavMenuItem } from '@carbon/react';
|
|
4
|
+
import { navigate, UserHasAccess } from '@openmrs/esm-framework';
|
|
5
|
+
|
|
6
|
+
export interface BillableServicesMenuConfig {
|
|
7
|
+
title: string;
|
|
8
|
+
icon?: React.ComponentType;
|
|
9
|
+
privilege?: string;
|
|
10
|
+
items: Array<{
|
|
11
|
+
name: string;
|
|
12
|
+
title: string;
|
|
13
|
+
path: string;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function BillableServicesMenuExtension({ config }: { config: BillableServicesMenuConfig }) {
|
|
18
|
+
const { title, icon: Icon, items, privilege } = config;
|
|
19
|
+
const spaBasePath = `${window.spaBase}/billable-services`;
|
|
20
|
+
|
|
21
|
+
const handleNavigation = (path: string) => {
|
|
22
|
+
navigate({ to: `${spaBasePath}/${path}` });
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const menu = (
|
|
26
|
+
<SideNavMenu title={title} renderIcon={Icon}>
|
|
27
|
+
{items.map((item) => (
|
|
28
|
+
<SideNavMenuItem key={item.name} onClick={() => handleNavigation(item.path)}>
|
|
29
|
+
{item.title}
|
|
30
|
+
</SideNavMenuItem>
|
|
31
|
+
))}
|
|
32
|
+
</SideNavMenu>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (privilege) {
|
|
36
|
+
return <UserHasAccess privilege={privilege}>{menu}</UserHasAccess>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return menu;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const createBillableServicesLeftPanelMenu = (config: BillableServicesMenuConfig) => () => (
|
|
43
|
+
<BrowserRouter>
|
|
44
|
+
<BillableServicesMenuExtension config={config} />
|
|
45
|
+
</BrowserRouter>
|
|
46
|
+
);
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
DataTable,
|
|
7
7
|
InlineLoading,
|
|
8
8
|
Layer,
|
|
9
|
-
Modal,
|
|
10
9
|
OverflowMenu,
|
|
11
10
|
OverflowMenuItem,
|
|
12
11
|
Pagination,
|
|
@@ -21,65 +20,75 @@ import {
|
|
|
21
20
|
Tile,
|
|
22
21
|
} from '@carbon/react';
|
|
23
22
|
import { ArrowRight } from '@carbon/react/icons';
|
|
24
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
ErrorState,
|
|
25
|
+
getCoreTranslation,
|
|
26
|
+
isDesktop,
|
|
27
|
+
navigate,
|
|
28
|
+
showModal,
|
|
29
|
+
useConfig,
|
|
30
|
+
useLayoutType,
|
|
31
|
+
usePagination,
|
|
32
|
+
type LayoutType,
|
|
33
|
+
} from '@openmrs/esm-framework';
|
|
25
34
|
import { EmptyState } from '@openmrs/esm-patient-common-lib';
|
|
26
35
|
import { type BillableService } from '../types/index';
|
|
27
36
|
import { useBillableServices } from './billable-service.resource';
|
|
28
|
-
import
|
|
37
|
+
import type { BillingConfig } from '../config-schema';
|
|
29
38
|
import styles from './billable-services.scss';
|
|
30
39
|
|
|
40
|
+
interface FilterableTableHeaderProps {
|
|
41
|
+
layout: LayoutType;
|
|
42
|
+
handleSearch: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
43
|
+
isValidating: boolean;
|
|
44
|
+
responsiveSize: 'sm' | 'md' | 'lg';
|
|
45
|
+
t: (key: string, fallback: string) => string;
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
const BillableServices = () => {
|
|
32
49
|
const { t } = useTranslation();
|
|
33
50
|
const { billableServices, isLoading, isValidating, error, mutate } = useBillableServices();
|
|
34
51
|
const layout = useLayoutType();
|
|
35
|
-
const
|
|
52
|
+
const { pageSize: configuredPageSize } = useConfig<BillingConfig>();
|
|
36
53
|
const [searchString, setSearchString] = useState('');
|
|
37
54
|
const responsiveSize = isDesktop(layout) ? 'lg' : 'sm';
|
|
38
|
-
const pageSizes =
|
|
39
|
-
const [pageSize, setPageSize] = useState(
|
|
40
|
-
|
|
41
|
-
const [showOverlay, setShowOverlay] = useState(false);
|
|
42
|
-
const [editingService, setEditingService] = useState(null);
|
|
55
|
+
const pageSizes = [10, 20, 30, 40, 50];
|
|
56
|
+
const [pageSize, setPageSize] = useState(configuredPageSize ?? 10);
|
|
43
57
|
|
|
44
58
|
const headerData = [
|
|
45
59
|
{
|
|
46
|
-
header: t('serviceName', 'Service
|
|
60
|
+
header: t('serviceName', 'Service name'),
|
|
47
61
|
key: 'serviceName',
|
|
48
62
|
},
|
|
49
63
|
{
|
|
50
|
-
header: t('shortName', 'Short
|
|
64
|
+
header: t('shortName', 'Short name'),
|
|
51
65
|
key: 'shortName',
|
|
52
66
|
},
|
|
53
67
|
{
|
|
54
|
-
header: t('serviceType', 'Service
|
|
68
|
+
header: t('serviceType', 'Service type'),
|
|
55
69
|
key: 'serviceType',
|
|
56
70
|
},
|
|
57
71
|
{
|
|
58
|
-
header: t('
|
|
72
|
+
header: t('serviceStatus', 'Service status'),
|
|
59
73
|
key: 'status',
|
|
60
74
|
},
|
|
61
75
|
{
|
|
62
76
|
header: t('prices', 'Prices'),
|
|
63
77
|
key: 'prices',
|
|
64
78
|
},
|
|
65
|
-
{
|
|
66
|
-
header: t('actions', 'Actions'),
|
|
67
|
-
key: 'actions',
|
|
68
|
-
},
|
|
69
79
|
];
|
|
70
80
|
|
|
71
81
|
const launchBillableServiceForm = useCallback(() => {
|
|
72
82
|
navigate({ to: window.getOpenmrsSpaBase() + 'billable-services/add-service' });
|
|
73
|
-
setEditingService(null);
|
|
74
|
-
setShowOverlay(true);
|
|
75
83
|
}, []);
|
|
76
84
|
|
|
77
85
|
const searchResults: BillableService[] = useMemo(() => {
|
|
78
86
|
const flatBillableServices = Array.isArray(billableServices) ? billableServices.flat() : billableServices;
|
|
79
87
|
|
|
80
88
|
if (flatBillableServices !== undefined && flatBillableServices.length > 0) {
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
const trimmedSearch = searchString.trim();
|
|
90
|
+
if (trimmedSearch) {
|
|
91
|
+
const search = trimmedSearch.toLowerCase();
|
|
83
92
|
return flatBillableServices.filter((service: BillableService) =>
|
|
84
93
|
Object.entries(service).some(([header, value]) => {
|
|
85
94
|
return header === 'uuid' ? false : `${value}`.toLowerCase().includes(search);
|
|
@@ -94,31 +103,16 @@ const BillableServices = () => {
|
|
|
94
103
|
const rowData = [];
|
|
95
104
|
|
|
96
105
|
if (results) {
|
|
97
|
-
results.forEach((service
|
|
106
|
+
results.forEach((service) => {
|
|
98
107
|
const s = {
|
|
99
|
-
id:
|
|
108
|
+
id: service.uuid,
|
|
100
109
|
uuid: service.uuid,
|
|
101
110
|
serviceName: service.name,
|
|
102
111
|
shortName: service.shortName,
|
|
103
112
|
serviceType: service?.serviceType?.display,
|
|
104
113
|
status: service.serviceStatus,
|
|
105
|
-
prices: '--',
|
|
106
|
-
actions: (
|
|
107
|
-
<TableCell>
|
|
108
|
-
<OverflowMenu size="sm" flipped>
|
|
109
|
-
<OverflowMenuItem
|
|
110
|
-
itemText={t('editBillableService', 'Edit Billable Service')}
|
|
111
|
-
onClick={() => handleEditService(service)}
|
|
112
|
-
/>
|
|
113
|
-
</OverflowMenu>
|
|
114
|
-
</TableCell>
|
|
115
|
-
),
|
|
114
|
+
prices: service.servicePrices.map((price) => `${price.name} (${price.price})`).join(', ') || '--',
|
|
116
115
|
};
|
|
117
|
-
let cost = '';
|
|
118
|
-
service.servicePrices.forEach((price) => {
|
|
119
|
-
cost += `${price.name} (${price.price}) `;
|
|
120
|
-
});
|
|
121
|
-
s.prices = cost;
|
|
122
116
|
rowData.push(s);
|
|
123
117
|
});
|
|
124
118
|
}
|
|
@@ -130,132 +124,138 @@ const BillableServices = () => {
|
|
|
130
124
|
},
|
|
131
125
|
[goTo, setSearchString],
|
|
132
126
|
);
|
|
133
|
-
const handleEditService = useCallback((service) => {
|
|
134
|
-
setEditingService(service);
|
|
135
|
-
setShowOverlay(true);
|
|
136
|
-
}, []);
|
|
137
127
|
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
128
|
+
const handleEditService = useCallback(
|
|
129
|
+
(service: BillableService) => {
|
|
130
|
+
const dispose = showModal('edit-billable-service-modal', {
|
|
131
|
+
serviceToEdit: service,
|
|
132
|
+
onServiceUpdated: mutate,
|
|
133
|
+
closeModal: () => dispose(),
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
[mutate],
|
|
137
|
+
);
|
|
142
138
|
|
|
143
139
|
if (isLoading) {
|
|
144
|
-
|
|
140
|
+
return (
|
|
141
|
+
<InlineLoading
|
|
142
|
+
status="active"
|
|
143
|
+
iconDescription={getCoreTranslation('loading')}
|
|
144
|
+
description={t('loading', 'Loading data') + '...'}
|
|
145
|
+
/>
|
|
146
|
+
);
|
|
145
147
|
}
|
|
148
|
+
|
|
146
149
|
if (error) {
|
|
147
|
-
<ErrorState headerTitle={t('billableService', 'Billable
|
|
150
|
+
return <ErrorState headerTitle={t('billableService', 'Billable service')} error={error} />;
|
|
148
151
|
}
|
|
152
|
+
|
|
149
153
|
if (billableServices.length === 0) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
return (
|
|
155
|
+
<EmptyState
|
|
156
|
+
displayText={t('billableServices__lower', 'billable services')}
|
|
157
|
+
headerTitle={t('billableService', 'Billable service')}
|
|
158
|
+
launchForm={launchBillableServiceForm}
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
return (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
164
|
+
<div className={styles.serviceContainer}>
|
|
165
|
+
<FilterableTableHeader
|
|
166
|
+
handleSearch={handleSearch}
|
|
167
|
+
isValidating={isValidating}
|
|
168
|
+
layout={layout}
|
|
169
|
+
responsiveSize={responsiveSize}
|
|
170
|
+
t={t}
|
|
171
|
+
/>
|
|
172
|
+
<DataTable
|
|
173
|
+
isSortable
|
|
174
|
+
rows={rowData}
|
|
175
|
+
headers={headerData}
|
|
176
|
+
overflowMenuOnHover={isDesktop(layout)}
|
|
177
|
+
size={responsiveSize}
|
|
178
|
+
useZebraStyles={rowData?.length > 1}>
|
|
179
|
+
{({ rows, headers, getHeaderProps, getRowProps, getTableProps }) => (
|
|
180
|
+
<TableContainer>
|
|
181
|
+
<Table {...getTableProps()} aria-label={t('serviceList', 'Service list')}>
|
|
182
|
+
<TableHead>
|
|
183
|
+
<TableRow>
|
|
184
|
+
{headers.map((header) => (
|
|
185
|
+
<TableHeader
|
|
186
|
+
{...getHeaderProps({
|
|
187
|
+
header,
|
|
188
|
+
})}
|
|
189
|
+
key={header.key}>
|
|
190
|
+
{header.header}
|
|
191
|
+
</TableHeader>
|
|
192
|
+
))}
|
|
193
|
+
<TableHeader aria-label={getCoreTranslation('actions')} />
|
|
194
|
+
</TableRow>
|
|
195
|
+
</TableHead>
|
|
196
|
+
<TableBody>
|
|
197
|
+
{rows.map((row) => (
|
|
198
|
+
<TableRow
|
|
199
|
+
key={row.id}
|
|
200
|
+
{...getRowProps({
|
|
201
|
+
row,
|
|
202
|
+
})}>
|
|
203
|
+
{row.cells.map((cell) => (
|
|
204
|
+
<TableCell key={cell.id}>{cell.value}</TableCell>
|
|
195
205
|
))}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
size={responsiveSize}
|
|
223
|
-
onChange={({ pageSize: newPageSize, page: newPage }) => {
|
|
224
|
-
if (newPageSize !== pageSize) {
|
|
225
|
-
setPageSize(newPageSize);
|
|
226
|
-
}
|
|
227
|
-
if (newPage !== currentPage) {
|
|
228
|
-
goTo(newPage);
|
|
229
|
-
}
|
|
230
|
-
}}
|
|
231
|
-
/>
|
|
232
|
-
)}
|
|
206
|
+
<TableCell className="cds--table-column-menu">
|
|
207
|
+
<OverflowMenu size="lg" flipped>
|
|
208
|
+
<OverflowMenuItem
|
|
209
|
+
className={styles.menuItem}
|
|
210
|
+
itemText={t('editBillableService', 'Edit billable service')}
|
|
211
|
+
onClick={() => handleEditService(results.find((service) => service.uuid === row.id))}
|
|
212
|
+
/>
|
|
213
|
+
</OverflowMenu>
|
|
214
|
+
</TableCell>
|
|
215
|
+
</TableRow>
|
|
216
|
+
))}
|
|
217
|
+
</TableBody>
|
|
218
|
+
</Table>
|
|
219
|
+
</TableContainer>
|
|
220
|
+
)}
|
|
221
|
+
</DataTable>
|
|
222
|
+
{searchResults?.length === 0 && (
|
|
223
|
+
<div className={styles.filterEmptyState}>
|
|
224
|
+
<Layer level={0}>
|
|
225
|
+
<Tile className={styles.filterEmptyStateTile}>
|
|
226
|
+
<p className={styles.filterEmptyStateContent}>
|
|
227
|
+
{t('noMatchingServicesToDisplay', 'No matching services to display')}
|
|
228
|
+
</p>
|
|
229
|
+
<p className={styles.filterEmptyStateHelper}>{t('checkFilters', 'Check the filters above')}</p>
|
|
230
|
+
</Tile>
|
|
231
|
+
</Layer>
|
|
233
232
|
</div>
|
|
234
|
-
) : (
|
|
235
|
-
<EmptyState
|
|
236
|
-
launchForm={launchBillableServiceForm}
|
|
237
|
-
displayText={t('noServicesToDisplay', 'There are no services to display')}
|
|
238
|
-
headerTitle={t('billableService', 'Billable service')}
|
|
239
|
-
/>
|
|
240
233
|
)}
|
|
241
|
-
{
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
234
|
+
{paginated && (
|
|
235
|
+
<Pagination
|
|
236
|
+
forwardText={t('nextPage', 'Next page')}
|
|
237
|
+
backwardText={t('previousPage', 'Previous page')}
|
|
238
|
+
page={currentPage}
|
|
239
|
+
pageSize={pageSize}
|
|
240
|
+
pageSizes={pageSizes}
|
|
241
|
+
totalItems={searchResults?.length}
|
|
242
|
+
className={styles.pagination}
|
|
243
|
+
size={responsiveSize}
|
|
244
|
+
onChange={({ pageSize: newPageSize, page: newPage }) => {
|
|
245
|
+
if (newPageSize !== pageSize) {
|
|
246
|
+
setPageSize(newPageSize);
|
|
247
|
+
}
|
|
248
|
+
if (newPage !== currentPage) {
|
|
249
|
+
goTo(newPage);
|
|
250
|
+
}
|
|
251
|
+
}}
|
|
252
|
+
/>
|
|
253
253
|
)}
|
|
254
|
-
|
|
254
|
+
</div>
|
|
255
255
|
);
|
|
256
256
|
};
|
|
257
257
|
|
|
258
|
-
function FilterableTableHeader({ layout, handleSearch, isValidating, responsiveSize, t }) {
|
|
258
|
+
function FilterableTableHeader({ layout, handleSearch, isValidating, responsiveSize, t }: FilterableTableHeaderProps) {
|
|
259
259
|
return (
|
|
260
260
|
<>
|
|
261
261
|
<div className={styles.headerContainer}>
|
|
@@ -291,4 +291,5 @@ function FilterableTableHeader({ layout, handleSearch, isValidating, responsiveS
|
|
|
291
291
|
</>
|
|
292
292
|
);
|
|
293
293
|
}
|
|
294
|
+
|
|
294
295
|
export default BillableServices;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@use '@carbon/colors';
|
|
1
2
|
@use '@carbon/layout';
|
|
2
3
|
@use '@carbon/type';
|
|
3
4
|
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
@@ -217,3 +218,31 @@
|
|
|
217
218
|
grid-template-columns: 16rem 1fr;
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
.menuItem {
|
|
222
|
+
max-width: none;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.pageWrapper {
|
|
226
|
+
display: flex;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.pageContent {
|
|
230
|
+
display: flex;
|
|
231
|
+
flex-grow: 1;
|
|
232
|
+
flex-direction: column;
|
|
233
|
+
margin: 0;
|
|
234
|
+
// Full vertical height minus the primary navigation menu height
|
|
235
|
+
height: calc(100vh - layout.$spacing-09);
|
|
236
|
+
// Ensure the width is fixed and does not expand based on children
|
|
237
|
+
width: calc(100% - 16rem);
|
|
238
|
+
background-color: colors.$gray-10;
|
|
239
|
+
|
|
240
|
+
& a {
|
|
241
|
+
width: 100%;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
&.hasLeftNav {
|
|
245
|
+
// Make space for the left nav menu
|
|
246
|
+
margin-inline-start: 16rem;
|
|
247
|
+
}
|
|
248
|
+
}
|