@digihmis/esm-billing-app 1.0.0
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/README.md +4 -0
- package/dist/117.js +1 -0
- package/dist/117.js.map +1 -0
- package/dist/132.js +1 -0
- package/dist/132.js.map +1 -0
- package/dist/152.js +1 -0
- package/dist/152.js.map +1 -0
- package/dist/16.js +1 -0
- package/dist/16.js.map +1 -0
- package/dist/209.js +1 -0
- package/dist/209.js.map +1 -0
- package/dist/317.js +1 -0
- package/dist/317.js.map +1 -0
- package/dist/349.js +1 -0
- package/dist/349.js.map +1 -0
- package/dist/358.js +1 -0
- package/dist/358.js.map +1 -0
- package/dist/371.js +1 -0
- package/dist/371.js.map +1 -0
- package/dist/378.js +1 -0
- package/dist/378.js.map +1 -0
- package/dist/442.js +1 -0
- package/dist/442.js.map +1 -0
- package/dist/45.js +1 -0
- package/dist/45.js.map +1 -0
- package/dist/466.js +1 -0
- package/dist/466.js.map +1 -0
- package/dist/496.js +12 -0
- package/dist/496.js.map +1 -0
- package/dist/508.js +1 -0
- package/dist/508.js.map +1 -0
- package/dist/61.js +1 -0
- package/dist/61.js.map +1 -0
- package/dist/640.js +1 -0
- package/dist/640.js.map +1 -0
- package/dist/689.js +1 -0
- package/dist/689.js.map +1 -0
- package/dist/709.js +1 -0
- package/dist/709.js.map +1 -0
- package/dist/712.js +1 -0
- package/dist/712.js.map +1 -0
- package/dist/720.js +1 -0
- package/dist/720.js.map +1 -0
- package/dist/742.js +1 -0
- package/dist/742.js.map +1 -0
- package/dist/771.js +1 -0
- package/dist/771.js.map +1 -0
- package/dist/806.js +1 -0
- package/dist/806.js.map +1 -0
- package/dist/839.js +1 -0
- package/dist/839.js.map +1 -0
- package/dist/912.js +1 -0
- package/dist/912.js.map +1 -0
- package/dist/913.js +1 -0
- package/dist/913.js.map +1 -0
- package/dist/940.js +1 -0
- package/dist/940.js.map +1 -0
- package/dist/965.js +15 -0
- package/dist/965.js.map +1 -0
- package/dist/digihmis-esm-billing-app.js +6 -0
- package/dist/digihmis-esm-billing-app.js.buildmanifest.json +827 -0
- package/dist/digihmis-esm-billing-app.js.map +1 -0
- package/dist/main.js +17 -0
- package/dist/main.js.map +1 -0
- package/dist/routes.json +1 -0
- package/jest.config.js +26 -0
- package/package.json +51 -0
- package/rspack.config.js +1 -0
- package/src/billing-checkin-form/billing-checkin-form-schema/index.ts +11 -0
- package/src/billing-checkin-form/billing-checkin-form.extension.tsx +179 -0
- package/src/billing-checkin-form/billing-checkin-form.resource.ts +42 -0
- package/src/billing-checkin-form/billing-checkin-form.scss +82 -0
- package/src/billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.component.tsx +39 -0
- package/src/billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.resource.ts +57 -0
- package/src/billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.scss +4 -0
- package/src/billing-checkin-form/helper/index.ts +2 -0
- package/src/billing-checkin-form/type/index.ts +42 -0
- package/src/billing-checkin-form/visit-attributes/visit-attributes-form.component.tsx +244 -0
- package/src/billing-checkin-form/visit-attributes/visit-attributes-form.resource.ts +23 -0
- package/src/billing-checkin-form/visit-attributes/visit-attributes-form.scss +186 -0
- package/src/billing-dashboard/billing-dashboard.component.tsx +224 -0
- package/src/billing-dashboard/billing-dashboard.resource.ts +101 -0
- package/src/billing-dashboard/billing-dashboard.scss +166 -0
- package/src/billing-dashboard/metrics/metrics.resource.ts +142 -0
- package/src/billing-dashboard/type/index.ts +176 -0
- package/src/billing-header/page-header/page-header.component.tsx +35 -0
- package/src/billing-header/page-header/page-header.scss +76 -0
- package/src/billing-header/page-header/page-icon/icon-wrapper.extension.tsx +17 -0
- package/src/billing-timesheet-modal/billing-timesheet-modal.scss +56 -0
- package/src/billing-timesheet-modal/billing-timesheet-modal.tsx +281 -0
- package/src/billing-timesheet-modal/billing-timesheet-resource-modal.ts +37 -0
- package/src/bills-table/bills-table.component.tsx +323 -0
- package/src/bills-table/bills-table.scss +252 -0
- package/src/config-schema.ts +148 -0
- package/src/constants/index.ts +2 -0
- package/src/dashboard.meta.ts +16 -0
- package/src/declarations.d.ts +6 -0
- package/src/index.ts +37 -0
- package/src/leftpanel/left-panel.component.tsx +98 -0
- package/src/leftpanel/left-panel.scss +13 -0
- package/src/routes.json +58 -0
- package/src/setup-tests.ts +1 -0
- package/src/utils/index.ts +270 -0
- package/translations/am.json +18 -0
- package/translations/ar.json +18 -0
- package/translations/en.json +18 -0
- package/translations/es.json +18 -0
- package/translations/fr.json +18 -0
- package/translations/he.json +18 -0
- package/translations/km.json +18 -0
- package/translations/pt.json +18 -0
- package/translations/sw.json +18 -0
- package/translations/vi.json +18 -0
- package/translations/zh.json +18 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@carbon/type';
|
|
3
|
+
@use '@carbon/colors';
|
|
4
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
5
|
+
|
|
6
|
+
.container {
|
|
7
|
+
// margin-top: layout.$spacing-05;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.emptyStateContainer,
|
|
11
|
+
.loaderContainer {
|
|
12
|
+
@extend .container;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.billListContainer {
|
|
16
|
+
background-color: $ui-02;
|
|
17
|
+
border: 1px solid $ui-03;
|
|
18
|
+
width: 100%;
|
|
19
|
+
margin: 0 auto;
|
|
20
|
+
max-width: 95vw;
|
|
21
|
+
padding-bottom: 0;
|
|
22
|
+
|
|
23
|
+
:has(.filterEmptyState) {
|
|
24
|
+
border-bottom: none;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.filterDropdown {
|
|
29
|
+
margin-left: 1rem;
|
|
30
|
+
}
|
|
31
|
+
.filterContainer {
|
|
32
|
+
flex: 1;
|
|
33
|
+
|
|
34
|
+
:global(.cds--dropdown__wrapper--inline) {
|
|
35
|
+
gap: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:global(.cds--list-box__menu-icon) {
|
|
39
|
+
height: 1rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:global(.cds--list-box__menu) {
|
|
43
|
+
min-width: max-content;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:global(.cds--list-box) {
|
|
47
|
+
margin-left: layout.$spacing-03;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.menu {
|
|
52
|
+
margin-left: layout.$spacing-03;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.headerContainer {
|
|
56
|
+
display: flex;
|
|
57
|
+
justify-content: space-between;
|
|
58
|
+
align-items: center;
|
|
59
|
+
padding: layout.$spacing-04 layout.$spacing-05;
|
|
60
|
+
background-color: $ui-02;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.backgroundDataFetchingIndicator {
|
|
64
|
+
align-items: center;
|
|
65
|
+
display: flex;
|
|
66
|
+
flex: 1;
|
|
67
|
+
justify-content: space-between;
|
|
68
|
+
|
|
69
|
+
&:global(.cds--inline-loading) {
|
|
70
|
+
max-height: 1rem;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.tableContainer section {
|
|
75
|
+
position: relative;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.tableContainer a {
|
|
79
|
+
text-decoration: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.pagination {
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
|
|
85
|
+
&:global(.cds--pagination) {
|
|
86
|
+
border-top: none;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.hiddenRow {
|
|
91
|
+
display: none;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.emptyRow {
|
|
95
|
+
padding: 0 1rem;
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.visitSummaryContainer {
|
|
101
|
+
width: 100%;
|
|
102
|
+
max-width: 768px;
|
|
103
|
+
margin: 1rem auto;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.expandedActiveVisitRow > td > div {
|
|
107
|
+
max-height: max-content !important;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.expandedActiveVisitRow td {
|
|
111
|
+
padding: 0 2rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.expandedActiveVisitRow th[colspan] td[colspan] > div:first-child {
|
|
115
|
+
padding: 0 1rem;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.action {
|
|
119
|
+
margin-bottom: layout.$spacing-03;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.illo {
|
|
123
|
+
margin-top: layout.$spacing-05;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.content {
|
|
127
|
+
@include type.type-style('heading-compact-01');
|
|
128
|
+
color: $text-02;
|
|
129
|
+
margin-top: layout.$spacing-05;
|
|
130
|
+
margin-bottom: layout.$spacing-03;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.desktopHeading,
|
|
134
|
+
.tabletHeading {
|
|
135
|
+
text-align: left;
|
|
136
|
+
text-transform: capitalize;
|
|
137
|
+
flex: 1;
|
|
138
|
+
|
|
139
|
+
h4 {
|
|
140
|
+
@include type.type-style('heading-compact-02');
|
|
141
|
+
color: $text-02;
|
|
142
|
+
|
|
143
|
+
&:after {
|
|
144
|
+
content: '';
|
|
145
|
+
display: block;
|
|
146
|
+
width: 2rem;
|
|
147
|
+
padding-top: 3px;
|
|
148
|
+
border-bottom: 0.375rem solid;
|
|
149
|
+
@include brand-03(border-bottom-color);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.tile {
|
|
155
|
+
text-align: center;
|
|
156
|
+
// border: 1px solid $ui-03;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.menuitem {
|
|
160
|
+
max-width: none;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.filterEmptyState {
|
|
164
|
+
display: flex;
|
|
165
|
+
justify-content: center;
|
|
166
|
+
align-items: center;
|
|
167
|
+
padding: layout.$spacing-05;
|
|
168
|
+
margin: layout.$spacing-09;
|
|
169
|
+
text-align: center;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.filterEmptyStateTile {
|
|
173
|
+
margin: auto;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.filterEmptyStateContent {
|
|
177
|
+
@include type.type-style('heading-compact-02');
|
|
178
|
+
color: $text-02;
|
|
179
|
+
margin-bottom: 0.5rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.filterEmptyStateHelper {
|
|
183
|
+
@include type.type-style('body-compact-01');
|
|
184
|
+
color: $text-02;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.expendableRow {
|
|
188
|
+
padding-left: 1rem;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.scalpel {
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Status badge styles
|
|
196
|
+
.statusBadge {
|
|
197
|
+
display: inline-flex;
|
|
198
|
+
align-items: center;
|
|
199
|
+
justify-content: center;
|
|
200
|
+
padding: layout.$spacing-02 layout.$spacing-03;
|
|
201
|
+
border-radius: 12px;
|
|
202
|
+
@include type.type-style('label-01');
|
|
203
|
+
font-weight: 600;
|
|
204
|
+
text-transform: uppercase;
|
|
205
|
+
letter-spacing: 0.5px;
|
|
206
|
+
white-space: nowrap;
|
|
207
|
+
line-height: 1.2;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.statusPaid {
|
|
211
|
+
// background-color: $support-success;
|
|
212
|
+
// color: $inverse-02;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.statusPending {
|
|
216
|
+
background-color: #fff3cd;
|
|
217
|
+
color: #856404;
|
|
218
|
+
border: 1px solid #ffeaa7;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.statusExempted {
|
|
222
|
+
background-color: #e7d6f8;
|
|
223
|
+
color: #4a1d7a;
|
|
224
|
+
border: 1px solid #d4b5f0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.statusPosted {
|
|
228
|
+
// background-color: $support-info;
|
|
229
|
+
// color: $inverse-02;
|
|
230
|
+
}
|
|
231
|
+
.emptyStateContainer {
|
|
232
|
+
border: 1px solid colors.$gray-20;
|
|
233
|
+
padding: 3rem 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.tile {
|
|
237
|
+
margin: auto;
|
|
238
|
+
width: fit-content;
|
|
239
|
+
background: colors.$gray-20;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.tileContent {
|
|
243
|
+
display: flex;
|
|
244
|
+
flex-direction: column;
|
|
245
|
+
align-items: center;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.content {
|
|
249
|
+
@include type.type-style('heading-compact-02');
|
|
250
|
+
color: colors.$gray-70;
|
|
251
|
+
margin-bottom: layout.$spacing-03;
|
|
252
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { ConfigSchema, Type, validators } from '@openmrs/esm-framework';
|
|
2
|
+
export interface BillingConfig {
|
|
3
|
+
visitAttributeTypes: {
|
|
4
|
+
isPatientExempted: string;
|
|
5
|
+
paymentMethods: string;
|
|
6
|
+
insuranceScheme: string;
|
|
7
|
+
policyNumber: string;
|
|
8
|
+
exemptionCategory: string;
|
|
9
|
+
billPaymentStatus: string;
|
|
10
|
+
shaBenefitPackagesAndInterventions: string;
|
|
11
|
+
};
|
|
12
|
+
insurancePaymentMethod: string;
|
|
13
|
+
patientExemptionCategories: Array<{ value: string; label: string }>;
|
|
14
|
+
insuranceSchemes: Array<string>;
|
|
15
|
+
excludedPaymentMode: Array<{ uuid: string; label: string }>;
|
|
16
|
+
registrationServiceType: string;
|
|
17
|
+
localeCurrencyMapping: Record<string, string>;
|
|
18
|
+
billingIcon: {
|
|
19
|
+
src: string;
|
|
20
|
+
alt?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const configSchema: ConfigSchema = {
|
|
25
|
+
billingIcon: {
|
|
26
|
+
src: {
|
|
27
|
+
_type: Type.String,
|
|
28
|
+
_default: '/openmrs/spa/billing.svg',
|
|
29
|
+
_description:
|
|
30
|
+
'The path or URL to the logo image. If set to an empty string, the default OpenMRS SVG sprite will be used.',
|
|
31
|
+
_validators: [validators.isUrl],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
visitAttributeTypes: {
|
|
35
|
+
isPatientExempted: {
|
|
36
|
+
_type: Type.String,
|
|
37
|
+
_default: '3b9dfac8-9e4d-11ee-8c90-0242ac120002',
|
|
38
|
+
_description: 'Whether the patient should be exempted from paying for service i.e Prisoners',
|
|
39
|
+
},
|
|
40
|
+
paymentMethods: {
|
|
41
|
+
_type: Type.String,
|
|
42
|
+
_description: 'The payment methods visit attribute uuid',
|
|
43
|
+
_default: 'e6cb0c3b-04b0-4117-9bc6-ce24adbda802',
|
|
44
|
+
},
|
|
45
|
+
insuranceScheme: {
|
|
46
|
+
_type: Type.String,
|
|
47
|
+
_description: 'The insurance scheme visit attribute uuid',
|
|
48
|
+
_default: '2d0fa959-6780-41f1-85b1-402045935068',
|
|
49
|
+
},
|
|
50
|
+
policyNumber: {
|
|
51
|
+
_type: Type.String,
|
|
52
|
+
_description: 'The policy number visit attribute uuid',
|
|
53
|
+
_default: '0f4f3306-f01b-43c6-af5b-fdb60015cb02',
|
|
54
|
+
},
|
|
55
|
+
exemptionCategory: {
|
|
56
|
+
_type: Type.String,
|
|
57
|
+
_description: 'The exemption category visit attribute uuid',
|
|
58
|
+
_default: 'df0362f9-782e-4d92-8bb2-3112e9e9eb3c',
|
|
59
|
+
},
|
|
60
|
+
billPaymentStatus: {
|
|
61
|
+
_type: Type.String,
|
|
62
|
+
_description: 'The bill payment status visit attribute uuid',
|
|
63
|
+
_default: '919b51c9-8e2e-468f-8354-181bf3e55786',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
insurancePaymentMethod: {
|
|
67
|
+
_type: Type.String,
|
|
68
|
+
_description: 'Insurance Payment method UUID',
|
|
69
|
+
_default: 'beac329b-f1dc-4a33-9e7c-d95821a137a6',
|
|
70
|
+
},
|
|
71
|
+
patientExemptionCategories: {
|
|
72
|
+
_type: Type.Array,
|
|
73
|
+
_elements: {
|
|
74
|
+
value: {
|
|
75
|
+
_type: Type.String,
|
|
76
|
+
_description: 'The value of the exemption category',
|
|
77
|
+
},
|
|
78
|
+
label: {
|
|
79
|
+
_type: Type.String,
|
|
80
|
+
_default: null,
|
|
81
|
+
_description: 'The label of the exemption category',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
_default: [{ value: 'IN_PRISON', label: 'In Prison' }],
|
|
85
|
+
},
|
|
86
|
+
excludedPaymentMode: {
|
|
87
|
+
_type: Type.Array,
|
|
88
|
+
_elements: {
|
|
89
|
+
uuid: {
|
|
90
|
+
_type: Type.UUID,
|
|
91
|
+
_description: 'The value of the payment mode to be excluded',
|
|
92
|
+
},
|
|
93
|
+
label: {
|
|
94
|
+
_type: Type.String,
|
|
95
|
+
_default: null,
|
|
96
|
+
_description: 'The label of the payment mode to be excluded',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
_default: [
|
|
100
|
+
{
|
|
101
|
+
uuid: 'eb6173cb-9678-4614-bbe1-0ccf7ed9d1d4',
|
|
102
|
+
label: 'Waiver',
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
insuranceSchemes: {
|
|
107
|
+
_type: Type.Array,
|
|
108
|
+
_elements: {
|
|
109
|
+
_type: Type.String,
|
|
110
|
+
},
|
|
111
|
+
_default: [
|
|
112
|
+
'Jubilee Insurance',
|
|
113
|
+
'AAR Insurance',
|
|
114
|
+
'Old Mutual Insurance',
|
|
115
|
+
'Britam Insurance',
|
|
116
|
+
'CIC Insurance',
|
|
117
|
+
'Madison Insurance',
|
|
118
|
+
'APA Insurance',
|
|
119
|
+
'ICEA LION Insurance',
|
|
120
|
+
],
|
|
121
|
+
_description: 'List of insurance schemes',
|
|
122
|
+
},
|
|
123
|
+
registrationServiceType: {
|
|
124
|
+
_type: Type.UUID,
|
|
125
|
+
_description: 'Registrationn service type concept Uuid',
|
|
126
|
+
_default: 'b4b020ed-24a1-4c50-bcbd-12695cbe89d5',
|
|
127
|
+
},
|
|
128
|
+
localeCurrencyMapping: {
|
|
129
|
+
_type: Type.Object,
|
|
130
|
+
_description: 'Mapping of locale codes to currency codes for internationalization',
|
|
131
|
+
_default: {
|
|
132
|
+
en: 'KES',
|
|
133
|
+
sw: 'KES',
|
|
134
|
+
am: 'ETB',
|
|
135
|
+
ar: 'SAR',
|
|
136
|
+
es: 'EUR',
|
|
137
|
+
fr: 'EUR',
|
|
138
|
+
he: 'ILS',
|
|
139
|
+
km: 'KHR',
|
|
140
|
+
pt: 'EUR',
|
|
141
|
+
vi: 'VND',
|
|
142
|
+
zh: 'CNY',
|
|
143
|
+
'en-KE': 'KES',
|
|
144
|
+
'sw-KE': 'KES',
|
|
145
|
+
'am-ET': 'ETB',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PiggyBank, PiggyBankSlot } from '@carbon/react/icons';
|
|
2
|
+
|
|
3
|
+
export const billingQueueMeta = {
|
|
4
|
+
name: 'billing',
|
|
5
|
+
slot: 'billing-dashboard-slot',
|
|
6
|
+
title: 'Billing queue',
|
|
7
|
+
icon: PiggyBankSlot,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const billingFileMeta = {
|
|
11
|
+
name: 'billing/patient/:patientUuid/bill',
|
|
12
|
+
slot: 'billing-file-dashboard-slot',
|
|
13
|
+
title: 'Patient Bills',
|
|
14
|
+
icon: PiggyBank,
|
|
15
|
+
showOnlyOnRoute: '/bill',
|
|
16
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defineConfigSchema, getSyncLifecycle } from '@openmrs/esm-framework';
|
|
2
|
+
import { configSchema } from './config-schema';
|
|
3
|
+
import BillingCheckInForm from './billing-checkin-form/billing-checkin-form.extension';
|
|
4
|
+
import PaymentTypeTag from './billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.component';
|
|
5
|
+
import { createDashboardLink } from './leftpanel/left-panel.component';
|
|
6
|
+
import { billingFileMeta, billingQueueMeta } from './dashboard.meta';
|
|
7
|
+
import BillingDashboard from './billing-dashboard/billing-dashboard.component';
|
|
8
|
+
import { BillingTimesheetModal } from './billing-timesheet-modal/billing-timesheet-modal';
|
|
9
|
+
const moduleName = '@digihmis/esm-billing-app';
|
|
10
|
+
const pageName = 'billing';
|
|
11
|
+
|
|
12
|
+
const options = {
|
|
13
|
+
featureName: pageName,
|
|
14
|
+
moduleName,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Core Components
|
|
18
|
+
export const billingCheckInForm = getSyncLifecycle(BillingCheckInForm, options);
|
|
19
|
+
|
|
20
|
+
export const paymentTypeTag = getSyncLifecycle(PaymentTypeTag, options);
|
|
21
|
+
|
|
22
|
+
// left panel component
|
|
23
|
+
export const billingQueueleftPanelLink = getSyncLifecycle(createDashboardLink(billingQueueMeta), options);
|
|
24
|
+
export const patientBillingLeftPanelLink = getSyncLifecycle(createDashboardLink(billingFileMeta), options);
|
|
25
|
+
|
|
26
|
+
// billing dashboard components
|
|
27
|
+
export const billingDashboard = getSyncLifecycle(BillingDashboard, options);
|
|
28
|
+
|
|
29
|
+
// Billing modals
|
|
30
|
+
export const billingCheckInFormModal = getSyncLifecycle(BillingCheckInForm, options);
|
|
31
|
+
export const billingTimesheetModal = getSyncLifecycle(BillingTimesheetModal, options);
|
|
32
|
+
|
|
33
|
+
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
34
|
+
|
|
35
|
+
export function startupApp() {
|
|
36
|
+
defineConfigSchema(moduleName, configSchema);
|
|
37
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { ConfigurableLink, MaybeIcon } from '@openmrs/esm-framework';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { BrowserRouter, useLocation, useParams } from 'react-router-dom';
|
|
5
|
+
import { type CarbonIconType } from '@carbon/react/icons';
|
|
6
|
+
import last from 'lodash-es/last';
|
|
7
|
+
import styles from './left-panel.scss';
|
|
8
|
+
|
|
9
|
+
export interface DashboardLinkConfig {
|
|
10
|
+
name: string;
|
|
11
|
+
title: string;
|
|
12
|
+
icon?: string | CarbonIconType;
|
|
13
|
+
showOnlyOnRoute?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const DashboardLink = ({ dashboardLinkConfig }: { dashboardLinkConfig: DashboardLinkConfig }) => {
|
|
17
|
+
const { t } = useTranslation();
|
|
18
|
+
const { name, title, icon, showOnlyOnRoute } = dashboardLinkConfig;
|
|
19
|
+
const location = useLocation();
|
|
20
|
+
const params = useParams();
|
|
21
|
+
const spaBasePath = window.getOpenmrsSpaBase() + 'home';
|
|
22
|
+
|
|
23
|
+
const patientUuid = useMemo(() => {
|
|
24
|
+
if (params.patientUuid) {
|
|
25
|
+
return params.patientUuid;
|
|
26
|
+
}
|
|
27
|
+
const pathParts = location.pathname.split('/');
|
|
28
|
+
const billingIndex = pathParts.indexOf('billing');
|
|
29
|
+
if (billingIndex !== -1 && pathParts.length > billingIndex + 1) {
|
|
30
|
+
const nextPart = pathParts[billingIndex + 1];
|
|
31
|
+
// Check if it's a UUID pattern (basic check)
|
|
32
|
+
if (nextPart && nextPart.length > 20 && nextPart.includes('-')) {
|
|
33
|
+
return nextPart;
|
|
34
|
+
}
|
|
35
|
+
// Check if path is /billing/patient/UUID/file
|
|
36
|
+
if (nextPart === 'patient' && pathParts.length > billingIndex + 2) {
|
|
37
|
+
const uuidPart = pathParts[billingIndex + 2];
|
|
38
|
+
if (uuidPart && uuidPart.length > 20 && uuidPart.includes('-')) {
|
|
39
|
+
return uuidPart;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}, [params.patientUuid, location.pathname]);
|
|
45
|
+
|
|
46
|
+
const shouldShow = useMemo(() => {
|
|
47
|
+
if (!showOnlyOnRoute) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return location.pathname.includes(showOnlyOnRoute);
|
|
51
|
+
}, [showOnlyOnRoute, location.pathname]);
|
|
52
|
+
|
|
53
|
+
const linkPath = useMemo(() => {
|
|
54
|
+
let path = name;
|
|
55
|
+
if (name.includes(':patientUuid') && patientUuid) {
|
|
56
|
+
path = name.replace(':patientUuid', patientUuid);
|
|
57
|
+
}
|
|
58
|
+
return path;
|
|
59
|
+
}, [name, patientUuid]);
|
|
60
|
+
|
|
61
|
+
const isActive = useMemo(() => {
|
|
62
|
+
if (name.includes(':patientUuid')) {
|
|
63
|
+
return location.pathname.includes('/bill');
|
|
64
|
+
}
|
|
65
|
+
const urlSegment = decodeURIComponent(last(location.pathname.split('/')));
|
|
66
|
+
const nameSegment = name.split('/').at(-1);
|
|
67
|
+
return nameSegment === urlSegment;
|
|
68
|
+
}, [location.pathname, name]);
|
|
69
|
+
|
|
70
|
+
if (!shouldShow) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const IconComp = typeof icon !== 'string' ? (icon as CarbonIconType) : null;
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<ConfigurableLink
|
|
78
|
+
to={`${spaBasePath}/${linkPath}`}
|
|
79
|
+
className={`cds--side-nav__link ${isActive && 'active-left-nav-link'}`}>
|
|
80
|
+
{typeof icon === 'string' ? (
|
|
81
|
+
<MaybeIcon icon={icon} className={styles.icon} size={16} />
|
|
82
|
+
) : (
|
|
83
|
+
IconComp && <IconComp className={styles.icon} />
|
|
84
|
+
)}
|
|
85
|
+
{t(title)}
|
|
86
|
+
</ConfigurableLink>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const createDashboardLink = (dashboardLinkConfig: DashboardLinkConfig) => () => {
|
|
91
|
+
return (
|
|
92
|
+
<BrowserRouter>
|
|
93
|
+
<DashboardLink dashboardLinkConfig={dashboardLinkConfig} />
|
|
94
|
+
</BrowserRouter>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default DashboardLink;
|
package/src/routes.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.openmrs.org/routes.schema.json",
|
|
3
|
+
"backendDependencies": {
|
|
4
|
+
"fhir2": ">=1.2",
|
|
5
|
+
"webservices.rest": "^2.24.0"
|
|
6
|
+
},
|
|
7
|
+
"extensions": [
|
|
8
|
+
{
|
|
9
|
+
"name": "billing-check-in-form",
|
|
10
|
+
"slot": "extra-visit-attribute-slot",
|
|
11
|
+
"component": "billingCheckInForm",
|
|
12
|
+
"order": 0
|
|
13
|
+
},{
|
|
14
|
+
"name": "payment-type-tag",
|
|
15
|
+
"slot": "patient-banner-tags-slot",
|
|
16
|
+
"component": "paymentTypeTag",
|
|
17
|
+
"online": true,
|
|
18
|
+
"offline": true
|
|
19
|
+
},{
|
|
20
|
+
"name": "billing-db-link",
|
|
21
|
+
"slot": "billing-dashboard-slot",
|
|
22
|
+
"component": "billingQueueleftPanelLink",
|
|
23
|
+
"meta": {
|
|
24
|
+
"name": "billing",
|
|
25
|
+
"slot": "billing-homepage-dashboard-slot",
|
|
26
|
+
"title": "Billing queue"
|
|
27
|
+
},
|
|
28
|
+
"order": 1,
|
|
29
|
+
"online": true,
|
|
30
|
+
"offline": true
|
|
31
|
+
}, {
|
|
32
|
+
"name": "care-panel-link",
|
|
33
|
+
"slot": "billing-dashboard-slot",
|
|
34
|
+
"component": "carePanelLink",
|
|
35
|
+
"meta": {
|
|
36
|
+
"name": "billing/patient/:patientUuid/bill",
|
|
37
|
+
"slot": "patient-bill-dashboard-slot",
|
|
38
|
+
"title": "Patient Bill",
|
|
39
|
+
"showOnlyOnRoute": "/bill"
|
|
40
|
+
},
|
|
41
|
+
"order": 2,
|
|
42
|
+
"online": true,
|
|
43
|
+
"offline": true
|
|
44
|
+
},{
|
|
45
|
+
"name": "billing-dashboard",
|
|
46
|
+
"slot": "billing-homepage-dashboard-slot",
|
|
47
|
+
"component": "billingDashboard",
|
|
48
|
+
"online": true,
|
|
49
|
+
"offline": true
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"modals": [
|
|
53
|
+
{
|
|
54
|
+
"name": "billing-timesheet-modal",
|
|
55
|
+
"component": "billingTimesheetModal"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/extend-expect';
|