@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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button, ModalBody, ModalFooter, ModalHeader } from '@carbon/react';
|
|
4
|
+
import { getCoreTranslation } from '@openmrs/esm-framework';
|
|
5
|
+
import { type BillableService } from '../../types';
|
|
6
|
+
import AddBillableService from './add-billable-service.component';
|
|
7
|
+
|
|
8
|
+
interface EditBillableServiceModalProps {
|
|
9
|
+
closeModal: () => void;
|
|
10
|
+
onServiceUpdated: () => void;
|
|
11
|
+
serviceToEdit?: BillableService;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const EditBillableServiceModal: React.FC<EditBillableServiceModalProps> = ({
|
|
15
|
+
closeModal,
|
|
16
|
+
serviceToEdit,
|
|
17
|
+
onServiceUpdated,
|
|
18
|
+
}) => {
|
|
19
|
+
const { t } = useTranslation();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<ModalHeader closeModal={closeModal} title={t('billableService', 'Billable service')} />
|
|
24
|
+
<ModalBody>
|
|
25
|
+
<AddBillableService
|
|
26
|
+
serviceToEdit={serviceToEdit}
|
|
27
|
+
isModal
|
|
28
|
+
onClose={closeModal}
|
|
29
|
+
onServiceUpdated={onServiceUpdated}
|
|
30
|
+
/>
|
|
31
|
+
</ModalBody>
|
|
32
|
+
<ModalFooter>
|
|
33
|
+
<Button kind="secondary" onClick={closeModal}>
|
|
34
|
+
{getCoreTranslation('cancel')}
|
|
35
|
+
</Button>
|
|
36
|
+
<Button
|
|
37
|
+
onClick={() => {
|
|
38
|
+
// Trigger form submission programmatically
|
|
39
|
+
const form = document.getElementById('billable-service-form') as HTMLFormElement;
|
|
40
|
+
if (form) {
|
|
41
|
+
form.requestSubmit();
|
|
42
|
+
}
|
|
43
|
+
}}>
|
|
44
|
+
{getCoreTranslation('save')}
|
|
45
|
+
</Button>
|
|
46
|
+
</ModalFooter>
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default EditBillableServiceModal;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import BillableServices from '../billable-services.component';
|
|
3
3
|
import styles from './dashboard.scss';
|
|
4
|
-
import { ExtensionSlot } from '@openmrs/esm-framework';
|
|
5
4
|
|
|
6
5
|
export default function BillableServicesDashboard() {
|
|
7
6
|
return (
|
|
8
7
|
<main className={styles.container}>
|
|
9
|
-
<ExtensionSlot name="billing-home-tiles-slot" />
|
|
10
8
|
<main className={styles.servicesTableContainer}>
|
|
11
9
|
<BillableServices />
|
|
12
10
|
</main>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
6
|
+
import { Button, Form, ModalBody, ModalFooter, ModalHeader, Stack, TextInput } from '@carbon/react';
|
|
7
|
+
import { showSnackbar, openmrsFetch, restBaseUrl, getCoreTranslation } from '@openmrs/esm-framework';
|
|
8
|
+
|
|
9
|
+
type PaymentModeFormValues = {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
interface AddPaymentModeModalProps {
|
|
15
|
+
closeModal: () => void;
|
|
16
|
+
onPaymentModeAdded: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const AddPaymentModeModal: React.FC<AddPaymentModeModalProps> = ({ closeModal, onPaymentModeAdded }) => {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
|
|
22
|
+
const paymentModeSchema = z.object({
|
|
23
|
+
name: z.string().min(1, t('paymentModeNameRequired', 'Payment Mode Name is required')),
|
|
24
|
+
description: z.string().optional(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
control,
|
|
29
|
+
handleSubmit,
|
|
30
|
+
reset,
|
|
31
|
+
formState: { errors, isSubmitting },
|
|
32
|
+
} = useForm<PaymentModeFormValues>({
|
|
33
|
+
resolver: zodResolver(paymentModeSchema),
|
|
34
|
+
defaultValues: {
|
|
35
|
+
name: '',
|
|
36
|
+
description: '',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const onSubmit = async (data: PaymentModeFormValues) => {
|
|
41
|
+
try {
|
|
42
|
+
await openmrsFetch(`${restBaseUrl}/billing/paymentMode`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
},
|
|
47
|
+
body: {
|
|
48
|
+
name: data.name,
|
|
49
|
+
description: data.description || '',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
showSnackbar({
|
|
54
|
+
title: t('success', 'Success'),
|
|
55
|
+
subtitle: t('paymentModeSaved', 'Payment mode was successfully saved.'),
|
|
56
|
+
kind: 'success',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
closeModal();
|
|
60
|
+
reset({ name: '', description: '' });
|
|
61
|
+
onPaymentModeAdded();
|
|
62
|
+
} catch (err) {
|
|
63
|
+
showSnackbar({
|
|
64
|
+
title: getCoreTranslation('error'),
|
|
65
|
+
subtitle: err?.message || t('errorSavingPaymentMode', 'An error occurred while saving the payment mode.'),
|
|
66
|
+
kind: 'error',
|
|
67
|
+
isLowContrast: false,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
<ModalHeader closeModal={closeModal} title={t('addPaymentMode', 'Add Payment Mode')} />
|
|
75
|
+
<Form onSubmit={handleSubmit(onSubmit)}>
|
|
76
|
+
<ModalBody>
|
|
77
|
+
<Stack gap={5}>
|
|
78
|
+
<Controller
|
|
79
|
+
name="name"
|
|
80
|
+
control={control}
|
|
81
|
+
render={({ field }) => (
|
|
82
|
+
<TextInput
|
|
83
|
+
id="payment-mode-name"
|
|
84
|
+
labelText={t('paymentModeNameLabel', 'Payment Mode Name')}
|
|
85
|
+
placeholder={t('paymentModeNamePlaceholder', 'For example, Cash, Credit Card')}
|
|
86
|
+
invalid={!!errors.name}
|
|
87
|
+
invalidText={errors.name?.message}
|
|
88
|
+
{...field}
|
|
89
|
+
/>
|
|
90
|
+
)}
|
|
91
|
+
/>
|
|
92
|
+
<Controller
|
|
93
|
+
name="description"
|
|
94
|
+
control={control}
|
|
95
|
+
render={({ field }) => (
|
|
96
|
+
<TextInput
|
|
97
|
+
id="payment-mode-description"
|
|
98
|
+
labelText={t('description', 'Description')}
|
|
99
|
+
placeholder={t('descriptionPlaceholder', 'For example, Used for all cash transactions')}
|
|
100
|
+
invalid={!!errors.description}
|
|
101
|
+
invalidText={errors.description?.message}
|
|
102
|
+
{...field}
|
|
103
|
+
/>
|
|
104
|
+
)}
|
|
105
|
+
/>
|
|
106
|
+
</Stack>
|
|
107
|
+
</ModalBody>
|
|
108
|
+
<ModalFooter>
|
|
109
|
+
<Button kind="secondary" onClick={closeModal}>
|
|
110
|
+
{getCoreTranslation('cancel')}
|
|
111
|
+
</Button>
|
|
112
|
+
<Button type="submit" disabled={isSubmitting}>
|
|
113
|
+
{isSubmitting ? t('saving', 'Saving') + '...' : getCoreTranslation('save')}
|
|
114
|
+
</Button>
|
|
115
|
+
</ModalFooter>
|
|
116
|
+
</Form>
|
|
117
|
+
</>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export default AddPaymentModeModal;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button, ModalBody, ModalFooter, ModalHeader } from '@carbon/react';
|
|
4
|
+
import { showSnackbar, openmrsFetch, restBaseUrl, getCoreTranslation } from '@openmrs/esm-framework';
|
|
5
|
+
|
|
6
|
+
interface DeletePaymentModeModalProps {
|
|
7
|
+
closeModal: () => void;
|
|
8
|
+
paymentModeUuid: string;
|
|
9
|
+
paymentModeName: string;
|
|
10
|
+
onPaymentModeDeleted: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const DeletePaymentModeModal: React.FC<DeletePaymentModeModalProps> = ({
|
|
14
|
+
closeModal,
|
|
15
|
+
paymentModeUuid,
|
|
16
|
+
paymentModeName,
|
|
17
|
+
onPaymentModeDeleted,
|
|
18
|
+
}) => {
|
|
19
|
+
const { t } = useTranslation();
|
|
20
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
21
|
+
|
|
22
|
+
const handleDelete = async () => {
|
|
23
|
+
setIsDeleting(true);
|
|
24
|
+
try {
|
|
25
|
+
await openmrsFetch(`${restBaseUrl}/billing/paymentMode/${paymentModeUuid}`, {
|
|
26
|
+
method: 'DELETE',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
showSnackbar({
|
|
30
|
+
title: t('success', 'Success'),
|
|
31
|
+
subtitle: t('paymentModeDeleted', 'Payment mode was successfully deleted.'),
|
|
32
|
+
kind: 'success',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
closeModal();
|
|
36
|
+
onPaymentModeDeleted();
|
|
37
|
+
} catch (err) {
|
|
38
|
+
showSnackbar({
|
|
39
|
+
title: getCoreTranslation('error'),
|
|
40
|
+
subtitle: err?.message || t('errorDeletingPaymentMode', 'An error occurred while deleting the payment mode.'),
|
|
41
|
+
kind: 'error',
|
|
42
|
+
isLowContrast: false,
|
|
43
|
+
});
|
|
44
|
+
} finally {
|
|
45
|
+
setIsDeleting(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
<ModalHeader closeModal={closeModal} title={t('deletePaymentMode', 'Delete Payment Mode')} />
|
|
52
|
+
<ModalBody>
|
|
53
|
+
<p>{t('confirmDeleteMessage', 'Are you sure you want to delete this payment mode? Proceed cautiously.')}</p>
|
|
54
|
+
{paymentModeName && (
|
|
55
|
+
<p>
|
|
56
|
+
<strong>
|
|
57
|
+
{t('paymentModeNameToDelete', 'Payment Mode Name: {{paymentModeName}}', { paymentModeName })}
|
|
58
|
+
</strong>
|
|
59
|
+
</p>
|
|
60
|
+
)}
|
|
61
|
+
</ModalBody>
|
|
62
|
+
<ModalFooter>
|
|
63
|
+
<Button kind="secondary" onClick={closeModal}>
|
|
64
|
+
{getCoreTranslation('cancel')}
|
|
65
|
+
</Button>
|
|
66
|
+
<Button kind="danger" onClick={handleDelete} disabled={isDeleting}>
|
|
67
|
+
{isDeleting ? t('deleting', 'Deleting') + '...' : getCoreTranslation('delete')}
|
|
68
|
+
</Button>
|
|
69
|
+
</ModalFooter>
|
|
70
|
+
</>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default DeletePaymentModeModal;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
DataTable,
|
|
5
|
+
OverflowMenu,
|
|
6
|
+
OverflowMenuItem,
|
|
7
|
+
Table,
|
|
8
|
+
TableBody,
|
|
9
|
+
TableCell,
|
|
10
|
+
TableContainer,
|
|
11
|
+
TableHead,
|
|
12
|
+
TableHeader,
|
|
13
|
+
TableRow,
|
|
14
|
+
} from '@carbon/react';
|
|
15
|
+
import { Add } from '@carbon/react/icons';
|
|
16
|
+
import { useTranslation } from 'react-i18next';
|
|
17
|
+
import { showSnackbar, openmrsFetch, restBaseUrl, showModal, getCoreTranslation } from '@openmrs/esm-framework';
|
|
18
|
+
import { CardHeader } from '@openmrs/esm-patient-common-lib';
|
|
19
|
+
import styles from './payment-modes-config.scss';
|
|
20
|
+
|
|
21
|
+
const PaymentModesConfig: React.FC = () => {
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const [paymentModes, setPaymentModes] = useState([]);
|
|
24
|
+
|
|
25
|
+
const fetchPaymentModes = useCallback(async () => {
|
|
26
|
+
try {
|
|
27
|
+
const response = await openmrsFetch(`${restBaseUrl}/billing/paymentMode?v=full`);
|
|
28
|
+
setPaymentModes(response.data.results || []);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
showSnackbar({
|
|
31
|
+
title: getCoreTranslation('error'),
|
|
32
|
+
subtitle: t('errorFetchingPaymentModes', 'An error occurred while fetching payment modes.'),
|
|
33
|
+
kind: 'error',
|
|
34
|
+
isLowContrast: false,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}, [t]);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
fetchPaymentModes();
|
|
41
|
+
}, [fetchPaymentModes]);
|
|
42
|
+
|
|
43
|
+
const handleAddPaymentMode = () => {
|
|
44
|
+
const dispose = showModal('add-payment-mode-modal', {
|
|
45
|
+
onPaymentModeAdded: fetchPaymentModes,
|
|
46
|
+
closeModal: () => dispose(),
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleDeletePaymentMode = (paymentMode) => {
|
|
51
|
+
const dispose = showModal('delete-payment-mode-modal', {
|
|
52
|
+
paymentModeUuid: paymentMode.uuid,
|
|
53
|
+
paymentModeName: paymentMode.name,
|
|
54
|
+
onPaymentModeDeleted: fetchPaymentModes,
|
|
55
|
+
closeModal: () => dispose(),
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const rowData = paymentModes.map((mode) => ({
|
|
60
|
+
id: mode.uuid,
|
|
61
|
+
name: mode.name,
|
|
62
|
+
description: mode.description || '--',
|
|
63
|
+
}));
|
|
64
|
+
|
|
65
|
+
const headerData = [
|
|
66
|
+
{ key: 'name', header: t('name', 'Name') },
|
|
67
|
+
{ key: 'description', header: t('description', 'Description') },
|
|
68
|
+
{ key: 'actions', header: getCoreTranslation('actions') },
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className={styles.container}>
|
|
73
|
+
<div className={styles.card}>
|
|
74
|
+
<CardHeader title={t('paymentModeHistory', 'Payment mode history')}>
|
|
75
|
+
<Button renderIcon={Add} onClick={handleAddPaymentMode} kind="ghost">
|
|
76
|
+
{t('addNewPaymentMode', 'Add new payment mode')}
|
|
77
|
+
</Button>
|
|
78
|
+
</CardHeader>
|
|
79
|
+
<DataTable rows={rowData} headers={headerData} isSortable size="lg">
|
|
80
|
+
{({ rows, headers, getTableProps, getHeaderProps, getRowProps }) => (
|
|
81
|
+
<TableContainer>
|
|
82
|
+
<Table className={styles.table} {...getTableProps()}>
|
|
83
|
+
<TableHead>
|
|
84
|
+
<TableRow>
|
|
85
|
+
{headers.map((header) => (
|
|
86
|
+
<TableHeader key={header.key} {...getHeaderProps({ header })}>
|
|
87
|
+
{header.header}
|
|
88
|
+
</TableHeader>
|
|
89
|
+
))}
|
|
90
|
+
</TableRow>
|
|
91
|
+
</TableHead>
|
|
92
|
+
<TableBody>
|
|
93
|
+
{rows.map((row) => (
|
|
94
|
+
<TableRow key={row.id} {...getRowProps({ row })}>
|
|
95
|
+
{row.cells.map((cell) =>
|
|
96
|
+
cell.info.header !== 'actions' ? (
|
|
97
|
+
<TableCell key={cell.id}>{cell.value}</TableCell>
|
|
98
|
+
) : (
|
|
99
|
+
<TableCell key={cell.id}>
|
|
100
|
+
<OverflowMenu>
|
|
101
|
+
<OverflowMenuItem
|
|
102
|
+
className={styles.menuItem}
|
|
103
|
+
itemText={getCoreTranslation('delete')}
|
|
104
|
+
onClick={() => {
|
|
105
|
+
const selected = paymentModes.find((p) => p.uuid === row.id);
|
|
106
|
+
handleDeletePaymentMode(selected);
|
|
107
|
+
}}
|
|
108
|
+
/>
|
|
109
|
+
</OverflowMenu>
|
|
110
|
+
</TableCell>
|
|
111
|
+
),
|
|
112
|
+
)}
|
|
113
|
+
</TableRow>
|
|
114
|
+
))}
|
|
115
|
+
</TableBody>
|
|
116
|
+
</Table>
|
|
117
|
+
</TableContainer>
|
|
118
|
+
)}
|
|
119
|
+
</DataTable>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default PaymentModesConfig;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React, { useCallback, useState } from 'react';
|
|
2
2
|
import { Dropdown, InlineLoading, InlineNotification } from '@carbon/react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
|
-
import { showSnackbar,
|
|
4
|
+
import { showSnackbar, getCoreTranslation } from '@openmrs/esm-framework';
|
|
5
5
|
import { useCashPoint, useBillableItems, createPatientBill } from './billing-form.resource';
|
|
6
6
|
import VisitAttributesForm from './visit-attributes/visit-attributes-form.component';
|
|
7
7
|
import styles from './billing-checkin-form.scss';
|
|
8
8
|
|
|
9
|
-
const DEFAULT_PRICE = 500.00001;
|
|
10
9
|
const PENDING_PAYMENT_STATUS = 'PENDING';
|
|
11
10
|
|
|
12
11
|
type BillingCheckInFormProps = {
|
|
@@ -22,20 +21,25 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
22
21
|
const [paymentMethod, setPaymentMethod] = useState<any>();
|
|
23
22
|
let lineList = [];
|
|
24
23
|
|
|
25
|
-
const handleCreateExtraVisitInfo = useCallback(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
(error) => {
|
|
24
|
+
const handleCreateExtraVisitInfo = useCallback(
|
|
25
|
+
async (createBillPayload) => {
|
|
26
|
+
try {
|
|
27
|
+
await createPatientBill(createBillPayload);
|
|
31
28
|
showSnackbar({
|
|
32
|
-
title: 'Patient
|
|
33
|
-
subtitle: '
|
|
29
|
+
title: t('patientBill', 'Patient bill'),
|
|
30
|
+
subtitle: t('billCreatedSuccessfully', 'Bill created successfully'),
|
|
31
|
+
kind: 'success',
|
|
32
|
+
});
|
|
33
|
+
} catch (error) {
|
|
34
|
+
showSnackbar({
|
|
35
|
+
title: t('billCreationError', 'Bill creation error'),
|
|
36
|
+
subtitle: t('errorCreatingBill', 'An error occurred while creating the bill'),
|
|
34
37
|
kind: 'error',
|
|
35
38
|
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
[t],
|
|
42
|
+
);
|
|
39
43
|
|
|
40
44
|
const handleBillingService = ({ selectedItem }) => {
|
|
41
45
|
const cashPointUuid = cashPoints?.[0]?.uuid ?? '';
|
|
@@ -74,8 +78,8 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
74
78
|
return (
|
|
75
79
|
<InlineLoading
|
|
76
80
|
status="active"
|
|
77
|
-
iconDescription={
|
|
78
|
-
description={t('loadingBillingServices', 'Loading billing services
|
|
81
|
+
iconDescription={getCoreTranslation('loading')}
|
|
82
|
+
description={`${t('loadingBillingServices', 'Loading billing services')}...`}
|
|
79
83
|
/>
|
|
80
84
|
);
|
|
81
85
|
}
|
|
@@ -97,7 +101,7 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
97
101
|
<InlineNotification
|
|
98
102
|
kind="error"
|
|
99
103
|
lowContrast
|
|
100
|
-
title={t('billErrorService', '
|
|
104
|
+
title={t('billErrorService', 'Billing service error')}
|
|
101
105
|
subtitle={t('errorLoadingBillServices', 'Error loading bill services')}
|
|
102
106
|
/>
|
|
103
107
|
);
|
|
@@ -111,7 +115,7 @@ const BillingCheckInForm: React.FC<BillingCheckInFormProps> = ({ patientUuid, se
|
|
|
111
115
|
<div className={styles.sectionTitle}>{t('billing', 'Billing')}</div>
|
|
112
116
|
<div className={styles.sectionField}></div>
|
|
113
117
|
<Dropdown
|
|
114
|
-
label={t('selectBillableService', 'Select a billable service
|
|
118
|
+
label={t('selectBillableService', 'Select a billable service')}
|
|
115
119
|
onChange={handleBillingService}
|
|
116
120
|
id="billable-items"
|
|
117
121
|
items={lineList}
|