@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.
Files changed (115) hide show
  1. package/README.md +4 -0
  2. package/dist/117.js +1 -0
  3. package/dist/117.js.map +1 -0
  4. package/dist/132.js +1 -0
  5. package/dist/132.js.map +1 -0
  6. package/dist/152.js +1 -0
  7. package/dist/152.js.map +1 -0
  8. package/dist/16.js +1 -0
  9. package/dist/16.js.map +1 -0
  10. package/dist/209.js +1 -0
  11. package/dist/209.js.map +1 -0
  12. package/dist/317.js +1 -0
  13. package/dist/317.js.map +1 -0
  14. package/dist/349.js +1 -0
  15. package/dist/349.js.map +1 -0
  16. package/dist/358.js +1 -0
  17. package/dist/358.js.map +1 -0
  18. package/dist/371.js +1 -0
  19. package/dist/371.js.map +1 -0
  20. package/dist/378.js +1 -0
  21. package/dist/378.js.map +1 -0
  22. package/dist/442.js +1 -0
  23. package/dist/442.js.map +1 -0
  24. package/dist/45.js +1 -0
  25. package/dist/45.js.map +1 -0
  26. package/dist/466.js +1 -0
  27. package/dist/466.js.map +1 -0
  28. package/dist/496.js +12 -0
  29. package/dist/496.js.map +1 -0
  30. package/dist/508.js +1 -0
  31. package/dist/508.js.map +1 -0
  32. package/dist/61.js +1 -0
  33. package/dist/61.js.map +1 -0
  34. package/dist/640.js +1 -0
  35. package/dist/640.js.map +1 -0
  36. package/dist/689.js +1 -0
  37. package/dist/689.js.map +1 -0
  38. package/dist/709.js +1 -0
  39. package/dist/709.js.map +1 -0
  40. package/dist/712.js +1 -0
  41. package/dist/712.js.map +1 -0
  42. package/dist/720.js +1 -0
  43. package/dist/720.js.map +1 -0
  44. package/dist/742.js +1 -0
  45. package/dist/742.js.map +1 -0
  46. package/dist/771.js +1 -0
  47. package/dist/771.js.map +1 -0
  48. package/dist/806.js +1 -0
  49. package/dist/806.js.map +1 -0
  50. package/dist/839.js +1 -0
  51. package/dist/839.js.map +1 -0
  52. package/dist/912.js +1 -0
  53. package/dist/912.js.map +1 -0
  54. package/dist/913.js +1 -0
  55. package/dist/913.js.map +1 -0
  56. package/dist/940.js +1 -0
  57. package/dist/940.js.map +1 -0
  58. package/dist/965.js +15 -0
  59. package/dist/965.js.map +1 -0
  60. package/dist/digihmis-esm-billing-app.js +6 -0
  61. package/dist/digihmis-esm-billing-app.js.buildmanifest.json +827 -0
  62. package/dist/digihmis-esm-billing-app.js.map +1 -0
  63. package/dist/main.js +17 -0
  64. package/dist/main.js.map +1 -0
  65. package/dist/routes.json +1 -0
  66. package/jest.config.js +26 -0
  67. package/package.json +51 -0
  68. package/rspack.config.js +1 -0
  69. package/src/billing-checkin-form/billing-checkin-form-schema/index.ts +11 -0
  70. package/src/billing-checkin-form/billing-checkin-form.extension.tsx +179 -0
  71. package/src/billing-checkin-form/billing-checkin-form.resource.ts +42 -0
  72. package/src/billing-checkin-form/billing-checkin-form.scss +82 -0
  73. package/src/billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.component.tsx +39 -0
  74. package/src/billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.resource.ts +57 -0
  75. package/src/billing-checkin-form/billing-patient-type-tag/billing-patient-type-tag.scss +4 -0
  76. package/src/billing-checkin-form/helper/index.ts +2 -0
  77. package/src/billing-checkin-form/type/index.ts +42 -0
  78. package/src/billing-checkin-form/visit-attributes/visit-attributes-form.component.tsx +244 -0
  79. package/src/billing-checkin-form/visit-attributes/visit-attributes-form.resource.ts +23 -0
  80. package/src/billing-checkin-form/visit-attributes/visit-attributes-form.scss +186 -0
  81. package/src/billing-dashboard/billing-dashboard.component.tsx +224 -0
  82. package/src/billing-dashboard/billing-dashboard.resource.ts +101 -0
  83. package/src/billing-dashboard/billing-dashboard.scss +166 -0
  84. package/src/billing-dashboard/metrics/metrics.resource.ts +142 -0
  85. package/src/billing-dashboard/type/index.ts +176 -0
  86. package/src/billing-header/page-header/page-header.component.tsx +35 -0
  87. package/src/billing-header/page-header/page-header.scss +76 -0
  88. package/src/billing-header/page-header/page-icon/icon-wrapper.extension.tsx +17 -0
  89. package/src/billing-timesheet-modal/billing-timesheet-modal.scss +56 -0
  90. package/src/billing-timesheet-modal/billing-timesheet-modal.tsx +281 -0
  91. package/src/billing-timesheet-modal/billing-timesheet-resource-modal.ts +37 -0
  92. package/src/bills-table/bills-table.component.tsx +323 -0
  93. package/src/bills-table/bills-table.scss +252 -0
  94. package/src/config-schema.ts +148 -0
  95. package/src/constants/index.ts +2 -0
  96. package/src/dashboard.meta.ts +16 -0
  97. package/src/declarations.d.ts +6 -0
  98. package/src/index.ts +37 -0
  99. package/src/leftpanel/left-panel.component.tsx +98 -0
  100. package/src/leftpanel/left-panel.scss +13 -0
  101. package/src/routes.json +58 -0
  102. package/src/setup-tests.ts +1 -0
  103. package/src/utils/index.ts +270 -0
  104. package/translations/am.json +18 -0
  105. package/translations/ar.json +18 -0
  106. package/translations/en.json +18 -0
  107. package/translations/es.json +18 -0
  108. package/translations/fr.json +18 -0
  109. package/translations/he.json +18 -0
  110. package/translations/km.json +18 -0
  111. package/translations/pt.json +18 -0
  112. package/translations/sw.json +18 -0
  113. package/translations/vi.json +18 -0
  114. package/translations/zh.json +18 -0
  115. 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,2 @@
1
+ export const PENDING_PAYMENT_STATUS = 'PENDING';
2
+ export const EXEMPTED_PAYMENT_STATUS = 'EXEMPTED';
@@ -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
+ };
@@ -0,0 +1,6 @@
1
+ declare module '@carbon/react';
2
+ declare module '*.css';
3
+ declare module '*.scss';
4
+ declare module '*.png';
5
+
6
+ declare type SideNavProps = object;
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;
@@ -0,0 +1,13 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+
4
+ .menu {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ }
9
+
10
+ .icon {
11
+ margin-right: layout.$spacing-05;
12
+ fill: colors.$gray-70;
13
+ }
@@ -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';