@openmrs/esm-billing-app 1.0.2-pre.880 → 1.0.2-pre.886
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/dist/1537.js +1 -0
- package/dist/1537.js.map +1 -0
- package/dist/4300.js +1 -1
- package/dist/{2372.js → 4692.js} +1 -1
- package/dist/4692.js.map +1 -0
- 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 +55 -31
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/billable-services/{create-edit/add-billable-service.scss → billable-service-form/billable-service-form.scss} +30 -1
- package/src/billable-services/{create-edit/add-billable-service.test.tsx → billable-service-form/billable-service-form.test.tsx} +178 -82
- package/src/billable-services/{create-edit/add-billable-service.component.tsx → billable-service-form/billable-service-form.workspace.tsx} +63 -47
- package/src/billable-services/billable-services-home.component.tsx +2 -8
- package/src/billable-services/billable-services-left-panel-menu.component.tsx +1 -1
- package/src/billable-services/billable-services-menu-item/item.component.tsx +5 -4
- package/src/billable-services/billable-services.component.tsx +14 -11
- package/src/billable-services/cash-point/add-cash-point.modal.tsx +47 -45
- package/src/billable-services-admin-card-link.component.test.tsx +2 -2
- package/src/billable-services-admin-card-link.component.tsx +1 -1
- package/src/index.ts +8 -4
- package/src/routes.json +7 -4
- package/translations/en.json +7 -2
- package/dist/2372.js.map +0 -1
- package/src/billable-services/create-edit/edit-billable-service.modal.tsx +0 -51
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
|
+
ButtonSet,
|
|
4
5
|
ComboBox,
|
|
5
6
|
Dropdown,
|
|
6
7
|
Form,
|
|
8
|
+
FormGroup,
|
|
7
9
|
FormLabel,
|
|
8
10
|
InlineLoading,
|
|
9
11
|
Layer,
|
|
@@ -19,7 +21,13 @@ import { useTranslation } from 'react-i18next';
|
|
|
19
21
|
import { Add, TrashCan } from '@carbon/react/icons';
|
|
20
22
|
import { z } from 'zod';
|
|
21
23
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
22
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
getCoreTranslation,
|
|
26
|
+
ResponsiveWrapper,
|
|
27
|
+
showSnackbar,
|
|
28
|
+
useDebounce,
|
|
29
|
+
useLayoutType,
|
|
30
|
+
} from '@openmrs/esm-framework';
|
|
23
31
|
import type { BillableService, ServicePrice } from '../../types';
|
|
24
32
|
import {
|
|
25
33
|
createBillableService,
|
|
@@ -28,13 +36,14 @@ import {
|
|
|
28
36
|
usePaymentModes,
|
|
29
37
|
useServiceTypes,
|
|
30
38
|
} from '../billable-service.resource';
|
|
31
|
-
import styles from './
|
|
39
|
+
import styles from './billable-service-form.scss';
|
|
32
40
|
|
|
33
|
-
interface
|
|
41
|
+
interface BillableServiceFormWorkspaceProps {
|
|
34
42
|
serviceToEdit?: BillableService;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
closeWorkspace: () => void;
|
|
44
|
+
closeWorkspaceWithSavedChanges?: () => void;
|
|
45
|
+
promptBeforeClosing?: (testFcn: () => boolean) => void;
|
|
46
|
+
onWorkspaceClose?: () => void;
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
interface BillableServiceFormData {
|
|
@@ -163,13 +172,15 @@ const createBillableServiceSchema = (t: TFunction) => {
|
|
|
163
172
|
});
|
|
164
173
|
};
|
|
165
174
|
|
|
166
|
-
const
|
|
175
|
+
const BillableServiceFormWorkspace: React.FC<BillableServiceFormWorkspaceProps> = ({
|
|
167
176
|
serviceToEdit,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
177
|
+
closeWorkspace,
|
|
178
|
+
closeWorkspaceWithSavedChanges,
|
|
179
|
+
onWorkspaceClose,
|
|
171
180
|
}) => {
|
|
172
181
|
const { t } = useTranslation();
|
|
182
|
+
const layout = useLayoutType();
|
|
183
|
+
const isTablet = layout === 'tablet';
|
|
173
184
|
const { paymentModes, isLoadingPaymentModes } = usePaymentModes();
|
|
174
185
|
const { serviceTypes, isLoadingServiceTypes } = useServiceTypes();
|
|
175
186
|
|
|
@@ -192,17 +203,13 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
192
203
|
const handleRemovePaymentMode = (index: number) => remove(index);
|
|
193
204
|
|
|
194
205
|
const searchInputRef = useRef(null);
|
|
206
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
195
207
|
|
|
196
208
|
const selectedConcept = useWatch({ control, name: 'concept' });
|
|
197
209
|
const [searchTerm, setSearchTerm] = useState('');
|
|
198
210
|
const debouncedSearchTerm = useDebounce(searchTerm.trim());
|
|
199
211
|
const { searchResults, isSearching } = useConceptsSearch(debouncedSearchTerm);
|
|
200
212
|
|
|
201
|
-
const handleNavigateToServiceDashboard = () =>
|
|
202
|
-
navigate({
|
|
203
|
-
to: window.getOpenmrsSpaBase() + 'billable-services',
|
|
204
|
-
});
|
|
205
|
-
|
|
206
213
|
// Re-initialize form when editing and dependencies load
|
|
207
214
|
// Needed because serviceTypes/paymentModes may not be available during initial render
|
|
208
215
|
useEffect(() => {
|
|
@@ -212,6 +219,8 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
212
219
|
}, [serviceToEdit, isLoadingPaymentModes, isLoadingServiceTypes, reset]);
|
|
213
220
|
|
|
214
221
|
const onSubmit = async (data: BillableServiceFormData) => {
|
|
222
|
+
setIsSubmitting(true);
|
|
223
|
+
|
|
215
224
|
const payload = {
|
|
216
225
|
name: data.name,
|
|
217
226
|
shortName: data.shortName || '',
|
|
@@ -236,27 +245,34 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
236
245
|
}
|
|
237
246
|
|
|
238
247
|
showSnackbar({
|
|
239
|
-
title:
|
|
248
|
+
title: serviceToEdit
|
|
249
|
+
? t('billableServiceUpdated', 'Billable service updated')
|
|
250
|
+
: t('billableServiceCreated', 'Billable service created'),
|
|
240
251
|
subtitle: serviceToEdit
|
|
241
|
-
? t('
|
|
242
|
-
: t('
|
|
252
|
+
? t('billableServiceUpdatedSuccessfully', 'Billable service updated successfully')
|
|
253
|
+
: t('billableServiceCreatedSuccessfully', 'Billable service created successfully'),
|
|
243
254
|
kind: 'success',
|
|
244
255
|
});
|
|
245
256
|
|
|
246
|
-
|
|
247
|
-
|
|
257
|
+
// Call onWorkspaceClose callback to refresh data in parent component
|
|
258
|
+
if (onWorkspaceClose) {
|
|
259
|
+
onWorkspaceClose();
|
|
248
260
|
}
|
|
249
261
|
|
|
250
|
-
|
|
251
|
-
|
|
262
|
+
// Close the workspace
|
|
263
|
+
if (closeWorkspaceWithSavedChanges) {
|
|
264
|
+
closeWorkspaceWithSavedChanges();
|
|
265
|
+
} else {
|
|
266
|
+
closeWorkspace();
|
|
252
267
|
}
|
|
253
|
-
handleNavigateToServiceDashboard();
|
|
254
268
|
} catch (error) {
|
|
255
269
|
showSnackbar({
|
|
256
270
|
title: t('billPaymentError', 'Bill payment error'),
|
|
257
271
|
kind: 'error',
|
|
258
272
|
subtitle: error instanceof Error ? error.message : String(error),
|
|
259
273
|
});
|
|
274
|
+
} finally {
|
|
275
|
+
setIsSubmitting(false);
|
|
260
276
|
}
|
|
261
277
|
};
|
|
262
278
|
|
|
@@ -279,14 +295,13 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
279
295
|
}
|
|
280
296
|
|
|
281
297
|
return (
|
|
282
|
-
<Form
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
<section>
|
|
298
|
+
<Form
|
|
299
|
+
aria-label={t('billableServiceForm', 'Billable service form')}
|
|
300
|
+
className={styles.form}
|
|
301
|
+
id="billable-service-form"
|
|
302
|
+
onSubmit={handleSubmit(onSubmit)}>
|
|
303
|
+
<Stack className={styles.stack} gap={5}>
|
|
304
|
+
<FormGroup className={styles.formGroup}>
|
|
290
305
|
{serviceToEdit ? (
|
|
291
306
|
<FormLabel className={styles.serviceNameLabel}>{serviceToEdit.name}</FormLabel>
|
|
292
307
|
) : (
|
|
@@ -310,8 +325,8 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
310
325
|
)}
|
|
311
326
|
/>
|
|
312
327
|
)}
|
|
313
|
-
</
|
|
314
|
-
<
|
|
328
|
+
</FormGroup>
|
|
329
|
+
<FormGroup>
|
|
315
330
|
<Controller
|
|
316
331
|
name="shortName"
|
|
317
332
|
control={control}
|
|
@@ -332,8 +347,8 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
332
347
|
</Layer>
|
|
333
348
|
)}
|
|
334
349
|
/>
|
|
335
|
-
</
|
|
336
|
-
<
|
|
350
|
+
</FormGroup>
|
|
351
|
+
<FormGroup>
|
|
337
352
|
<FormLabel className={styles.conceptLabel}>{t('associatedConcept', 'Associated concept')}</FormLabel>
|
|
338
353
|
<ResponsiveWrapper>
|
|
339
354
|
<Search
|
|
@@ -386,8 +401,8 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
386
401
|
</Layer>
|
|
387
402
|
);
|
|
388
403
|
})()}
|
|
389
|
-
</
|
|
390
|
-
<
|
|
404
|
+
</FormGroup>
|
|
405
|
+
<FormGroup>
|
|
391
406
|
<Controller
|
|
392
407
|
name="serviceType"
|
|
393
408
|
control={control}
|
|
@@ -409,7 +424,7 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
409
424
|
</Layer>
|
|
410
425
|
)}
|
|
411
426
|
/>
|
|
412
|
-
</
|
|
427
|
+
</FormGroup>
|
|
413
428
|
<section>
|
|
414
429
|
<div>
|
|
415
430
|
{fields.map((field, index) => (
|
|
@@ -440,6 +455,7 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
440
455
|
<Layer>
|
|
441
456
|
<NumberInput
|
|
442
457
|
allowEmpty
|
|
458
|
+
disableWheel
|
|
443
459
|
id={`price-${index}`}
|
|
444
460
|
invalid={!!errors?.payment?.[index]?.price}
|
|
445
461
|
invalidText={errors?.payment?.[index]?.price?.message}
|
|
@@ -473,16 +489,16 @@ const AddBillableService: React.FC<AddBillableServiceProps> = ({
|
|
|
473
489
|
</div>
|
|
474
490
|
</section>
|
|
475
491
|
</Stack>
|
|
476
|
-
{
|
|
477
|
-
<
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
<
|
|
482
|
-
</
|
|
483
|
-
|
|
492
|
+
<ButtonSet className={isTablet ? styles.tablet : styles.desktop}>
|
|
493
|
+
<Button className={styles.button} kind="secondary" disabled={isSubmitting} onClick={closeWorkspace}>
|
|
494
|
+
{getCoreTranslation('cancel')}
|
|
495
|
+
</Button>
|
|
496
|
+
<Button className={styles.button} kind="primary" disabled={isSubmitting} type="submit">
|
|
497
|
+
{isSubmitting ? <InlineLoading description={t('saving', 'Saving') + '...'} /> : getCoreTranslation('save')}
|
|
498
|
+
</Button>
|
|
499
|
+
</ButtonSet>
|
|
484
500
|
</Form>
|
|
485
501
|
);
|
|
486
502
|
};
|
|
487
503
|
|
|
488
|
-
export default
|
|
504
|
+
export default BillableServiceFormWorkspace;
|
|
@@ -2,8 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { useLeftNav,
|
|
6
|
-
import AddBillableService from './create-edit/add-billable-service.component';
|
|
5
|
+
import { useLeftNav, WorkspaceContainer, useLayoutType, isDesktop } from '@openmrs/esm-framework';
|
|
7
6
|
import BillWaiver from './bill-waiver/bill-waiver.component';
|
|
8
7
|
import BillableServicesDashboard from './dashboard/dashboard.component';
|
|
9
8
|
import BillingHeader from '../billing-header/billing-header.component';
|
|
@@ -18,10 +17,6 @@ const BillableServiceHome: React.FC = () => {
|
|
|
18
17
|
|
|
19
18
|
useLeftNav({ name: 'billable-services-left-panel-slot', basePath });
|
|
20
19
|
|
|
21
|
-
const handleCloseAddService = () => {
|
|
22
|
-
navigate({ to: `${basePath}` });
|
|
23
|
-
};
|
|
24
|
-
|
|
25
20
|
return (
|
|
26
21
|
<BrowserRouter basename={basePath}>
|
|
27
22
|
<div className={styles.pageWrapper}>
|
|
@@ -29,10 +24,9 @@ const BillableServiceHome: React.FC = () => {
|
|
|
29
24
|
<BillingHeader title={t('billableServicesManagement', 'Billable services management')} />
|
|
30
25
|
<Routes>
|
|
31
26
|
<Route path="/" element={<BillableServicesDashboard />} />
|
|
32
|
-
<Route path="/add-service" element={<AddBillableService onClose={handleCloseAddService} />} />
|
|
33
|
-
<Route path="/waive-bill" element={<BillWaiver />} />
|
|
34
27
|
<Route path="/cash-point-config" element={<CashPointConfiguration />} />
|
|
35
28
|
<Route path="/payment-modes-config" element={<PaymentModesConfig />} />
|
|
29
|
+
<Route path="/waive-bill" element={<BillWaiver />} />
|
|
36
30
|
</Routes>
|
|
37
31
|
</main>
|
|
38
32
|
</div>
|
|
@@ -23,7 +23,7 @@ function BillableServicesMenuExtension({ config }: { config: BillableServicesMen
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const menu = (
|
|
26
|
-
<SideNavMenu title={title} renderIcon={Icon}>
|
|
26
|
+
<SideNavMenu defaultExpanded title={title} renderIcon={Icon}>
|
|
27
27
|
{items.map((item) => (
|
|
28
28
|
<SideNavMenuItem key={item.name} onClick={() => handleNavigation(item.path)}>
|
|
29
29
|
{item.title}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { ClickableTile } from '@carbon/react';
|
|
2
1
|
import React from 'react';
|
|
3
|
-
import
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { ClickableTile } from '@carbon/react';
|
|
4
4
|
import { Receipt } from '@carbon/react/icons';
|
|
5
|
+
import styles from './item.scss';
|
|
5
6
|
|
|
6
7
|
const Item = () => {
|
|
7
|
-
|
|
8
|
+
const { t } = useTranslation();
|
|
8
9
|
const openmrsSpaBase = window['getOpenmrsSpaBase']();
|
|
9
10
|
|
|
10
11
|
return (
|
|
11
12
|
<ClickableTile className={styles.customTile} id="menu-item" href={`${openmrsSpaBase}billable-services`}>
|
|
12
13
|
<div className="customTileTitle">{<Receipt size={24} />}</div>
|
|
13
|
-
<div>Billable
|
|
14
|
+
<div>{t('billableServices', 'Billable services')}</div>
|
|
14
15
|
</ClickableTile>
|
|
15
16
|
);
|
|
16
17
|
};
|
|
@@ -24,17 +24,16 @@ import {
|
|
|
24
24
|
ErrorState,
|
|
25
25
|
getCoreTranslation,
|
|
26
26
|
isDesktop,
|
|
27
|
-
|
|
28
|
-
showModal,
|
|
27
|
+
launchWorkspace,
|
|
29
28
|
useConfig,
|
|
30
29
|
useLayoutType,
|
|
31
30
|
usePagination,
|
|
32
31
|
type LayoutType,
|
|
33
32
|
} from '@openmrs/esm-framework';
|
|
34
33
|
import { EmptyState } from '@openmrs/esm-patient-common-lib';
|
|
35
|
-
import { type BillableService } from '../types
|
|
34
|
+
import { type BillableService } from '../types';
|
|
35
|
+
import { type BillingConfig } from '../config-schema';
|
|
36
36
|
import { useBillableServices } from './billable-service.resource';
|
|
37
|
-
import type { BillingConfig } from '../config-schema';
|
|
38
37
|
import styles from './billable-services.scss';
|
|
39
38
|
|
|
40
39
|
interface FilterableTableHeaderProps {
|
|
@@ -79,8 +78,10 @@ const BillableServices = () => {
|
|
|
79
78
|
];
|
|
80
79
|
|
|
81
80
|
const launchBillableServiceForm = useCallback(() => {
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
launchWorkspace('billable-service-form', {
|
|
82
|
+
workspaceTitle: t('addBillableService', 'Add billable service'),
|
|
83
|
+
});
|
|
84
|
+
}, [t]);
|
|
84
85
|
|
|
85
86
|
const searchResults: BillableService[] = useMemo(() => {
|
|
86
87
|
const flatBillableServices = Array.isArray(billableServices) ? billableServices.flat() : billableServices;
|
|
@@ -127,13 +128,13 @@ const BillableServices = () => {
|
|
|
127
128
|
|
|
128
129
|
const handleEditService = useCallback(
|
|
129
130
|
(service: BillableService) => {
|
|
130
|
-
|
|
131
|
+
launchWorkspace('billable-service-form', {
|
|
132
|
+
workspaceTitle: t('editBillableService', 'Edit billable service'),
|
|
131
133
|
serviceToEdit: service,
|
|
132
|
-
|
|
133
|
-
closeModal: () => dispose(),
|
|
134
|
+
onWorkspaceClose: mutate,
|
|
134
135
|
});
|
|
135
136
|
},
|
|
136
|
-
[mutate],
|
|
137
|
+
[mutate, t],
|
|
137
138
|
);
|
|
138
139
|
|
|
139
140
|
if (isLoading) {
|
|
@@ -282,7 +283,9 @@ function FilterableTableHeader({ layout, handleSearch, isValidating, responsiveS
|
|
|
282
283
|
kind="primary"
|
|
283
284
|
renderIcon={(props) => <ArrowRight size={16} {...props} />}
|
|
284
285
|
onClick={() => {
|
|
285
|
-
|
|
286
|
+
launchWorkspace('billable-service-form', {
|
|
287
|
+
workspaceTitle: t('addBillableService', 'Add billable service'),
|
|
288
|
+
});
|
|
286
289
|
}}
|
|
287
290
|
iconDescription={t('addNewBillableService', 'Add new billable service')}>
|
|
288
291
|
{t('addNewService', 'Add new service')}
|
|
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
3
3
|
import { useForm, Controller } from 'react-hook-form';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
6
|
-
import { Button, Dropdown, Form, ModalBody, ModalFooter, ModalHeader, TextInput } from '@carbon/react';
|
|
6
|
+
import { Button, Dropdown, Form, ModalBody, ModalFooter, ModalHeader, Stack, TextInput } from '@carbon/react';
|
|
7
7
|
import { showSnackbar, openmrsFetch, restBaseUrl, getCoreTranslation } from '@openmrs/esm-framework';
|
|
8
8
|
|
|
9
9
|
type CashPointFormValues = {
|
|
@@ -107,50 +107,52 @@ const AddCashPointModal: React.FC<AddCashPointModalProps> = ({ closeModal, onCas
|
|
|
107
107
|
<ModalHeader closeModal={closeModal} title={t('addCashPoint', 'Add Cash Point')} />
|
|
108
108
|
<Form onSubmit={handleSubmit(onSubmit)}>
|
|
109
109
|
<ModalBody>
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
110
|
+
<Stack gap={5}>
|
|
111
|
+
<Controller
|
|
112
|
+
name="name"
|
|
113
|
+
control={control}
|
|
114
|
+
render={({ field }) => (
|
|
115
|
+
<TextInput
|
|
116
|
+
id="cash-point-name"
|
|
117
|
+
labelText={t('cashPointName', 'Cash Point Name')}
|
|
118
|
+
placeholder={t('cashPointNamePlaceholder', 'For example, Pharmacy Cash Point')}
|
|
119
|
+
invalid={!!errors.name}
|
|
120
|
+
invalidText={errors.name?.message}
|
|
121
|
+
{...field}
|
|
122
|
+
/>
|
|
123
|
+
)}
|
|
124
|
+
/>
|
|
125
|
+
<Controller
|
|
126
|
+
name="uuid"
|
|
127
|
+
control={control}
|
|
128
|
+
render={({ field }) => (
|
|
129
|
+
<TextInput
|
|
130
|
+
id="cash-point-uuid"
|
|
131
|
+
labelText={t('cashPointUuid', 'Cash Point UUID')}
|
|
132
|
+
placeholder={t('cashPointUuidPlaceholder', 'Enter UUID')}
|
|
133
|
+
invalid={!!errors.uuid}
|
|
134
|
+
invalidText={errors.uuid?.message}
|
|
135
|
+
{...field}
|
|
136
|
+
/>
|
|
137
|
+
)}
|
|
138
|
+
/>
|
|
139
|
+
<Controller
|
|
140
|
+
name="location"
|
|
141
|
+
control={control}
|
|
142
|
+
render={({ field }) => (
|
|
143
|
+
<Dropdown
|
|
144
|
+
id="cash-point-location"
|
|
145
|
+
label={t('selectLocation', 'Select Location')}
|
|
146
|
+
titleText={t('cashPointLocation', 'Cash Point Location')}
|
|
147
|
+
items={locations}
|
|
148
|
+
selectedItem={locations.find((loc) => loc.id === field.value)}
|
|
149
|
+
onChange={({ selectedItem }) => field.onChange(selectedItem?.id)}
|
|
150
|
+
invalid={!!errors.location}
|
|
151
|
+
invalidText={errors.location?.message}
|
|
152
|
+
/>
|
|
153
|
+
)}
|
|
154
|
+
/>
|
|
155
|
+
</Stack>
|
|
154
156
|
</ModalBody>
|
|
155
157
|
<ModalFooter>
|
|
156
158
|
<Button kind="secondary" onClick={closeModal}>
|
|
@@ -8,10 +8,10 @@ describe('BillableServicesCardLink', () => {
|
|
|
8
8
|
const manageBillableServicesText = screen.getByText('Manage billable services');
|
|
9
9
|
expect(manageBillableServicesText).toHaveClass('heading');
|
|
10
10
|
|
|
11
|
-
const billiableText = screen.getByText('Billable
|
|
11
|
+
const billiableText = screen.getByText('Billable services', { exact: true });
|
|
12
12
|
expect(billiableText).toHaveClass('content');
|
|
13
13
|
|
|
14
|
-
const billiableServiceLink = screen.getByRole('link', { name: /
|
|
14
|
+
const billiableServiceLink = screen.getByRole('link', { name: /Manage billable services/i });
|
|
15
15
|
expect(billiableServiceLink).toHaveAttribute('href', '/spa/billable-services');
|
|
16
16
|
});
|
|
17
17
|
});
|
|
@@ -12,7 +12,7 @@ const BillableServicesCardLink: React.FC = () => {
|
|
|
12
12
|
<ClickableTile href={`${window.spaBase}/billable-services`} target="_blank" rel="noopener noreferrer">
|
|
13
13
|
<div>
|
|
14
14
|
<div className="heading">{header}</div>
|
|
15
|
-
<div className="content">{t('billableServices', 'Billable
|
|
15
|
+
<div className="content">{t('billableServices', 'Billable services')}</div>
|
|
16
16
|
</div>
|
|
17
17
|
<div className="iconWrapper">
|
|
18
18
|
<ArrowRight size={16} />
|
package/src/index.ts
CHANGED
|
@@ -14,7 +14,6 @@ import BillableServicesCardLink from './billable-services-admin-card-link.compon
|
|
|
14
14
|
import BillHistory from './bill-history/bill-history.component';
|
|
15
15
|
import BillingCheckInForm from './billing-form/billing-checkin-form.component';
|
|
16
16
|
import DeletePaymentModeModal from './billable-services/payment-modes/delete-payment-mode.modal';
|
|
17
|
-
import EditBillableServiceModal from './billable-services/create-edit/edit-billable-service.modal';
|
|
18
17
|
import EditBillLineItemModal from './bill-item-actions/edit-bill-item.modal';
|
|
19
18
|
import RequirePaymentModal from './modal/require-payment.modal';
|
|
20
19
|
import RootComponent from './root.component';
|
|
@@ -48,6 +47,7 @@ export const billingSummaryDashboardLink = getSyncLifecycle(
|
|
|
48
47
|
options,
|
|
49
48
|
);
|
|
50
49
|
|
|
50
|
+
// t('billableServices', 'Billable services')
|
|
51
51
|
export const billableServicesAppMenuItem = getSyncLifecycle(appMenu, options);
|
|
52
52
|
|
|
53
53
|
export const billableServicesCardLink = getSyncLifecycle(BillableServicesCardLink, options);
|
|
@@ -66,8 +66,6 @@ export const deletePaymentModeModal = getSyncLifecycle(DeletePaymentModeModal, o
|
|
|
66
66
|
|
|
67
67
|
export const addCashPointModal = getSyncLifecycle(AddCashPointModal, options);
|
|
68
68
|
|
|
69
|
-
export const editBillableServiceModal = getSyncLifecycle(EditBillableServiceModal, options);
|
|
70
|
-
|
|
71
69
|
export const editBillLineItemModal = getSyncLifecycle(EditBillLineItemModal, options);
|
|
72
70
|
|
|
73
71
|
export const root = getSyncLifecycle(RootComponent, options);
|
|
@@ -77,7 +75,13 @@ export const visitAttributeTags = getSyncLifecycle(VisitAttributeTags, options);
|
|
|
77
75
|
// t('billingForm', 'Billing form')
|
|
78
76
|
export const billingFormWorkspace = getAsyncLifecycle(() => import('./billing-form/billing-form.component'), options);
|
|
79
77
|
|
|
80
|
-
// t('
|
|
78
|
+
// t('billableServiceForm', 'Billable service form')
|
|
79
|
+
export const billableServiceFormWorkspace = getAsyncLifecycle(
|
|
80
|
+
() => import('./billable-services/billable-service-form/billable-service-form.workspace'),
|
|
81
|
+
options,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// t('billableServices', 'Billable services')
|
|
81
85
|
export const billableServicesLeftPanelLink = getSyncLifecycle(
|
|
82
86
|
createBillableServicesLeftPanelLink({
|
|
83
87
|
name: 'billable-services',
|
package/src/routes.json
CHANGED
|
@@ -114,10 +114,6 @@
|
|
|
114
114
|
"name": "edit-bill-line-item-modal",
|
|
115
115
|
"component": "editBillLineItemModal"
|
|
116
116
|
},
|
|
117
|
-
{
|
|
118
|
-
"name": "edit-billable-service-modal",
|
|
119
|
-
"component": "editBillableServiceModal"
|
|
120
|
-
},
|
|
121
117
|
{
|
|
122
118
|
"name": "require-billing-modal",
|
|
123
119
|
"component": "requirePaymentModal"
|
|
@@ -129,6 +125,13 @@
|
|
|
129
125
|
"title": "billingForm",
|
|
130
126
|
"component": "billingFormWorkspace",
|
|
131
127
|
"type": "form"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "billable-service-form",
|
|
131
|
+
"title": "billableServiceForm",
|
|
132
|
+
"component": "billableServiceFormWorkspace",
|
|
133
|
+
"type": "form",
|
|
134
|
+
"width": "wider"
|
|
132
135
|
}
|
|
133
136
|
],
|
|
134
137
|
"featureFlags": [
|
package/translations/en.json
CHANGED
|
@@ -20,9 +20,14 @@
|
|
|
20
20
|
"amountToWaiveLabel": "Amount to waive",
|
|
21
21
|
"associatedConcept": "Associated concept",
|
|
22
22
|
"billableService": "Billable service",
|
|
23
|
+
"billableServiceCreated": "Billable service created",
|
|
24
|
+
"billableServiceCreatedSuccessfully": "Billable service created successfully",
|
|
25
|
+
"billableServiceForm": "Billable service form",
|
|
23
26
|
"billableServices": "Billable services",
|
|
24
27
|
"billableServices__lower": "billable services",
|
|
25
28
|
"billableServicesManagement": "Billable services management",
|
|
29
|
+
"billableServiceUpdated": "Billable service updated",
|
|
30
|
+
"billableServiceUpdatedSuccessfully": "Billable service updated successfully",
|
|
26
31
|
"billAmount": "Bill amount",
|
|
27
32
|
"billCode": "Bill code",
|
|
28
33
|
"billCreatedSuccessfully": "Bill created successfully",
|
|
@@ -197,14 +202,14 @@
|
|
|
197
202
|
"sellingPrice": "Selling price",
|
|
198
203
|
"serviceList": "Service list",
|
|
199
204
|
"serviceName": "Service name",
|
|
200
|
-
"serviceNameExceedsLimit": "Service name
|
|
205
|
+
"serviceNameExceedsLimit": "Service name cannot exceed {{MAX_NAME_LENGTH}} characters",
|
|
201
206
|
"serviceNameRequired": "Service name is required",
|
|
202
207
|
"servicesList": "Services list",
|
|
203
208
|
"serviceStatus": "Service status",
|
|
204
209
|
"serviceType": "Service type",
|
|
205
210
|
"serviceTypeRequired": "Service type is required",
|
|
206
211
|
"shortName": "Short name",
|
|
207
|
-
"shortNameExceedsLimit": "Short name
|
|
212
|
+
"shortNameExceedsLimit": "Short name cannot exceed {{MAX_NAME_LENGTH}} characters",
|
|
208
213
|
"status": "Service status",
|
|
209
214
|
"submitting": "Submitting",
|
|
210
215
|
"success": "Success",
|