@openmrs/esm-ward-app 9.2.1-pre.7254 → 9.2.1-pre.7261

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 (111) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/dist/1741.js +1 -1
  3. package/dist/1741.js.map +1 -1
  4. package/dist/1987.js +1 -0
  5. package/dist/1987.js.map +1 -0
  6. package/dist/2216.js +1 -0
  7. package/dist/2216.js.map +1 -0
  8. package/dist/2728.js +1 -1
  9. package/dist/2728.js.map +1 -1
  10. package/dist/283.js +1 -1
  11. package/dist/283.js.map +1 -1
  12. package/dist/2948.js +1 -1
  13. package/dist/2948.js.map +1 -1
  14. package/dist/3365.js +1 -1
  15. package/dist/3365.js.map +1 -1
  16. package/dist/3413.js +1 -1
  17. package/dist/3413.js.map +1 -1
  18. package/dist/3673.js +1 -0
  19. package/dist/3673.js.map +1 -0
  20. package/dist/3982.js +1 -1
  21. package/dist/3982.js.map +1 -1
  22. package/dist/4189.js +1 -0
  23. package/dist/4189.js.map +1 -0
  24. package/dist/4300.js +1 -1
  25. package/dist/5603.js +1 -0
  26. package/dist/5603.js.map +1 -0
  27. package/dist/581.js +1 -1
  28. package/dist/581.js.map +1 -1
  29. package/dist/7179.js +1 -1
  30. package/dist/7179.js.map +1 -1
  31. package/dist/7512.js +1 -1
  32. package/dist/7512.js.map +1 -1
  33. package/dist/7661.js +1 -1
  34. package/dist/7661.js.map +1 -1
  35. package/dist/8501.js +1 -1
  36. package/dist/8501.js.map +1 -1
  37. package/dist/8522.js +1 -1
  38. package/dist/8522.js.map +1 -1
  39. package/dist/8610.js +1 -1
  40. package/dist/8610.js.map +1 -1
  41. package/dist/89.js +2 -1
  42. package/dist/89.js.map +1 -1
  43. package/dist/9117.js +1 -1
  44. package/dist/9117.js.map +1 -1
  45. package/dist/917.js +1 -0
  46. package/dist/917.js.map +1 -0
  47. package/dist/9756.js +1 -0
  48. package/dist/9756.js.map +1 -0
  49. package/dist/main.js +1 -1
  50. package/dist/main.js.map +1 -1
  51. package/dist/openmrs-esm-ward-app.js +1 -1
  52. package/dist/openmrs-esm-ward-app.js.buildmanifest.json +226 -177
  53. package/dist/openmrs-esm-ward-app.js.map +1 -1
  54. package/dist/routes.json +1 -1
  55. package/package.json +1 -1
  56. package/src/action-menu-buttons/clinical-forms-workspace-siderail.component.tsx +16 -24
  57. package/src/action-menu-buttons/discharge-workspace-siderail.component.tsx +6 -6
  58. package/src/action-menu-buttons/order-basket-action-button.component.tsx +31 -0
  59. package/src/action-menu-buttons/transfer-workspace-siderail.component.tsx +7 -18
  60. package/src/hooks/useEmrConfiguration.ts +19 -19
  61. package/src/index.ts +14 -16
  62. package/src/routes.json +127 -80
  63. package/src/types/index.ts +7 -3
  64. package/src/ward-patient-card/row-elements/ward-patient-pending-transfer.component.tsx +9 -4
  65. package/src/ward-patient-card/ward-patient-card.component.tsx +3 -11
  66. package/src/ward-view-header/admission-requests-bar.component.tsx +10 -6
  67. package/src/ward-view-header/admission-requests-bar.test.tsx +3 -3
  68. package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +8 -6
  69. package/src/ward-workspace/admission-request-workspace/admission-requests-action-button.extension.tsx +6 -7
  70. package/src/ward-workspace/admission-request-workspace/admission-requests-empty-state.component.tsx +16 -29
  71. package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +23 -8
  72. package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +28 -28
  73. package/src/ward-workspace/admit-patient-button.component.tsx +3 -2
  74. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +17 -16
  75. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +72 -69
  76. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.component.tsx +176 -0
  77. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.test.tsx +11 -9
  78. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.workspace.tsx +17 -167
  79. package/src/ward-workspace/cancel-admission-request-workspace/ward-patient-cancel-admission-request.workspace.tsx +16 -0
  80. package/src/ward-workspace/create-admission-encounter/create-admission-encounter-action-button.extension.tsx +23 -34
  81. package/src/ward-workspace/create-admission-encounter/create-admission-encounter.test.tsx +9 -4
  82. package/src/ward-workspace/create-admission-encounter/create-admission-encounter.workspace.tsx +39 -19
  83. package/src/ward-workspace/patient-details/ward-patient-action-button.component.tsx +17 -0
  84. package/src/ward-workspace/patient-details/ward-patient.workspace.tsx +27 -7
  85. package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +46 -40
  86. package/src/ward-workspace/patient-transfer-bed-swap/patient-admit-or-transfer-request-form.component.tsx +21 -13
  87. package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +10 -14
  88. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +42 -24
  89. package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.workspace.tsx +22 -8
  90. package/src/ward-workspace/ward-patient-notes/notes-action-button.component.tsx +17 -0
  91. package/src/ward-workspace/ward-patient-notes/{form/notes-form.scss → notes.scss} +0 -1
  92. package/src/ward-workspace/ward-patient-notes/notes.test.tsx +134 -0
  93. package/src/ward-workspace/ward-patient-notes/notes.workspace.tsx +174 -13
  94. package/translations/en.json +3 -1
  95. package/dist/1663.js +0 -1
  96. package/dist/1663.js.map +0 -1
  97. package/dist/2557.js +0 -1
  98. package/dist/2557.js.map +0 -1
  99. package/dist/7232.js +0 -2
  100. package/dist/7232.js.map +0 -1
  101. package/dist/7886.js +0 -1
  102. package/dist/7886.js.map +0 -1
  103. package/dist/9045.js +0 -1
  104. package/dist/9045.js.map +0 -1
  105. package/src/ward-workspace/admission-request-workspace/admission-requests-context.ts +0 -20
  106. package/src/ward-workspace/patient-clinical-forms-workspace/patient-clinical-forms.workspace.tsx +0 -29
  107. package/src/ward-workspace/patient-details/ward-patient-action-button.extension.tsx +0 -18
  108. package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +0 -186
  109. package/src/ward-workspace/ward-patient-notes/form/notes-form.test.tsx +0 -116
  110. package/src/ward-workspace/ward-patient-notes/notes-action-button.extension.tsx +0 -18
  111. /package/dist/{7232.js.LICENSE.txt → 89.js.LICENSE.txt} +0 -0
@@ -1,20 +0,0 @@
1
- import { createContext, useContext } from 'react';
2
- import { type DefaultWorkspaceProps } from '@openmrs/esm-framework';
3
-
4
- export interface AdmissionRequestsWorkspaceContextProps extends DefaultWorkspaceProps {
5
- wardPendingPatients: React.ReactNode;
6
- }
7
-
8
- export const AdmissionRequestsWorkspaceContext = createContext<AdmissionRequestsWorkspaceContextProps>(null);
9
-
10
- export const AdmissionRequestsWorkspaceContextProvider = AdmissionRequestsWorkspaceContext.Provider;
11
-
12
- export const useAdmissionRequestsWorkspaceContext = () => {
13
- const context = useContext(AdmissionRequestsWorkspaceContext);
14
- if (!context) {
15
- throw new Error(
16
- 'useAdmissionRequestsWorkspaceContext must be used within a AdmissionRequestsWorkspaceContextProvider',
17
- );
18
- }
19
- return context;
20
- };
@@ -1,29 +0,0 @@
1
- import { ExtensionSlot } from '@openmrs/esm-framework';
2
- import React, { useMemo } from 'react';
3
- import type { WardPatientWorkspaceProps } from '../../types';
4
- import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
5
-
6
- const WardPatientClinicalFormsWorkspace: React.FC<WardPatientWorkspaceProps> = (props) => {
7
- const { wardPatient, ...restWorkspaceProps } = props;
8
- const patientUuid = wardPatient?.patient?.uuid;
9
-
10
- const clinicalFormsExtensionState = useMemo(
11
- () => ({
12
- patientUuid,
13
- clinicalFormsWorkspaceName: 'ward-patient-clinical-forms-workspace',
14
- formEntryWorkspaceName: 'ward-patient-form-entry-workspace',
15
- htmlFormEntryWorkspaceName: 'ward-patient-html-form-entry-workspace',
16
- ...restWorkspaceProps,
17
- }),
18
- [patientUuid, restWorkspaceProps],
19
- );
20
-
21
- return (
22
- <div>
23
- <WardPatientWorkspaceBanner {...{ wardPatient }} />
24
- <ExtensionSlot name="ward-patient-clinical-forms-workspace-slot" state={clinicalFormsExtensionState} />
25
- </div>
26
- );
27
- };
28
-
29
- export default WardPatientClinicalFormsWorkspace;
@@ -1,18 +0,0 @@
1
- import React from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { ActionMenuButton, launchWorkspace, UserAvatarIcon } from '@openmrs/esm-framework';
4
- import type { WardPatientWorkspaceProps } from '../../types';
5
-
6
- export default function WardPatientActionButton() {
7
- const { t } = useTranslation();
8
-
9
- return (
10
- <ActionMenuButton
11
- getIcon={(props) => <UserAvatarIcon {...props} />}
12
- label={t('Patient', 'patient')}
13
- iconDescription={t('Patient', 'patient')}
14
- handler={() => launchWorkspace<WardPatientWorkspaceProps>('ward-patient-workspace')}
15
- type={'ward'}
16
- />
17
- );
18
- }
@@ -1,186 +0,0 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { z } from 'zod';
4
- import { zodResolver } from '@hookform/resolvers/zod';
5
- import { Controller, useForm } from 'react-hook-form';
6
- import { Button, Column, Form, InlineLoading, InlineNotification, Row, Stack, TextArea } from '@carbon/react';
7
- import {
8
- type DefaultWorkspaceProps,
9
- type PatientUuid,
10
- ResponsiveWrapper,
11
- showSnackbar,
12
- translateFrom,
13
- useSession,
14
- } from '@openmrs/esm-framework';
15
- import { moduleName } from '../../../constant';
16
- import { savePatientNote } from '../notes.resource';
17
- import useEmrConfiguration from '../../../hooks/useEmrConfiguration';
18
- import styles from './notes-form.scss';
19
- import { type EncounterPayload } from '../../../types';
20
-
21
- type NotesFormData = z.infer<typeof noteFormSchema>;
22
-
23
- interface PatientNotesFormProps extends DefaultWorkspaceProps {
24
- patientUuid: PatientUuid;
25
- }
26
-
27
- const noteFormSchema = z.object({
28
- wardClinicalNote: z.string().refine((val) => val.trim().length > 0, {
29
- //t('clinicalNoteErrorMessage','Clinical note is required')
30
- message: translateFrom(moduleName, 'clinicalNoteErrorMessage', 'Clinical note is required'),
31
- }),
32
- });
33
-
34
- const PatientNotesForm: React.FC<PatientNotesFormProps> = ({
35
- closeWorkspaceWithSavedChanges,
36
- patientUuid,
37
- promptBeforeClosing,
38
- }) => {
39
- const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
40
- const { t } = useTranslation();
41
- const session = useSession();
42
-
43
- const [isSubmitting, setIsSubmitting] = useState(false);
44
- const [rows, setRows] = useState(0);
45
-
46
- const {
47
- control,
48
- handleSubmit,
49
- formState: { errors, isDirty },
50
- } = useForm<NotesFormData>({
51
- mode: 'onSubmit',
52
- resolver: zodResolver(noteFormSchema),
53
- defaultValues: {
54
- wardClinicalNote: '',
55
- },
56
- });
57
-
58
- useEffect(() => {
59
- promptBeforeClosing(() => isDirty);
60
- }, [isDirty, promptBeforeClosing]);
61
-
62
- const locationUuid = session?.sessionLocation?.uuid;
63
- const providerUuid = session?.currentProvider?.uuid;
64
-
65
- const onSubmit = useCallback(
66
- (data: NotesFormData) => {
67
- const { wardClinicalNote } = data;
68
- setIsSubmitting(true);
69
-
70
- const notePayload: EncounterPayload = {
71
- patient: patientUuid,
72
- location: locationUuid,
73
- encounterType: emrConfiguration?.inpatientNoteEncounterType?.uuid,
74
- encounterProviders: [
75
- {
76
- encounterRole: emrConfiguration?.clinicianEncounterRole?.uuid,
77
- provider: providerUuid,
78
- },
79
- ],
80
- obs: wardClinicalNote
81
- ? [
82
- {
83
- concept: { uuid: emrConfiguration?.consultFreeTextCommentsConcept.uuid, display: '' },
84
- value: wardClinicalNote,
85
- },
86
- ]
87
- : [],
88
- };
89
-
90
- const abortController = new AbortController();
91
-
92
- savePatientNote(notePayload, abortController)
93
- .then(() => {
94
- closeWorkspaceWithSavedChanges();
95
- showSnackbar({
96
- isLowContrast: true,
97
- kind: 'success',
98
- subtitle: t('patientNoteNowVisible', 'It should be now visible in the notes history'),
99
- title: t('visitNoteSaved', 'Patient note saved'),
100
- });
101
- })
102
- .catch((err) => {
103
- showSnackbar({
104
- isLowContrast: false,
105
- kind: 'error',
106
- subtitle: err?.message,
107
- title: t('patientNoteSaveError', 'Error saving patient note'),
108
- });
109
- })
110
- .finally(() => setIsSubmitting(false));
111
- },
112
- [
113
- closeWorkspaceWithSavedChanges,
114
- emrConfiguration?.clinicianEncounterRole?.uuid,
115
- emrConfiguration?.consultFreeTextCommentsConcept?.uuid,
116
- emrConfiguration?.inpatientNoteEncounterType?.uuid,
117
- locationUuid,
118
- patientUuid,
119
- providerUuid,
120
- t,
121
- ],
122
- );
123
-
124
- const onError = (errors) => console.error(errors);
125
-
126
- return (
127
- <Form className={styles.form} onSubmit={handleSubmit(onSubmit, onError)}>
128
- {errorFetchingEmrConfiguration && (
129
- <div className={styles.formError}>
130
- <InlineNotification
131
- kind="error"
132
- title={t('somePartsOfTheFormDidntLoad', "Some parts of the form didn't load")}
133
- subtitle={t(
134
- 'fetchingEmrConfigurationFailed',
135
- 'Fetching EMR configuration failed. Try refreshing the page or contact your system administrator.',
136
- )}
137
- lowContrast
138
- hideCloseButton
139
- />
140
- </div>
141
- )}
142
- <Stack className={styles.formContainer} gap={2}>
143
- <Row className={styles.row}>
144
- <Column sm={1}>
145
- <span className={styles.columnLabel}>{t('note', 'Note')}</span>
146
- </Column>
147
- <Column sm={3}>
148
- <Controller
149
- name="wardClinicalNote"
150
- control={control}
151
- render={({ field: { onChange, onBlur, value } }) => (
152
- <ResponsiveWrapper>
153
- <TextArea
154
- id="additionalNote"
155
- invalid={!!errors.wardClinicalNote}
156
- invalidText={errors.wardClinicalNote?.message}
157
- labelText={t('clinicalNoteLabel', 'Write your notes')}
158
- onBlur={onBlur}
159
- onChange={(event) => {
160
- onChange(event);
161
- const textAreaLineHeight = 24; // This is the default line height for Carbon's TextArea component
162
- const newRows = Math.ceil(event.target.scrollHeight / textAreaLineHeight);
163
- setRows(newRows);
164
- }}
165
- placeholder={t('wardClinicalNotePlaceholder', 'Write any notes here')}
166
- rows={rows}
167
- value={value}
168
- />
169
- </ResponsiveWrapper>
170
- )}
171
- />
172
- </Column>
173
- </Row>
174
- </Stack>
175
- <Button
176
- className={styles.saveButton}
177
- disabled={isSubmitting || isLoadingEmrConfiguration || errorFetchingEmrConfiguration}
178
- kind="primary"
179
- type="submit">
180
- {isSubmitting ? <InlineLoading description={t('saving', 'Saving...')} /> : <span>{t('save', 'Save')}</span>}
181
- </Button>
182
- </Form>
183
- );
184
- };
185
-
186
- export default PatientNotesForm;
@@ -1,116 +0,0 @@
1
- import React from 'react';
2
- import userEvent from '@testing-library/user-event';
3
- import { render, screen } from '@testing-library/react';
4
- import { createErrorHandler, ResponsiveWrapper, showSnackbar, translateFrom, useSession } from '@openmrs/esm-framework';
5
- import { savePatientNote } from '../notes.resource';
6
- import PatientNotesForm from './notes-form.component';
7
- import { emrConfigurationMock, mockPatient, mockSession } from '__mocks__';
8
- import useEmrConfiguration from '../../../hooks/useEmrConfiguration';
9
-
10
- const testProps = {
11
- patientUuid: mockPatient.uuid,
12
- closeWorkspace: jest.fn(),
13
- closeWorkspaceWithSavedChanges: jest.fn(),
14
- promptBeforeClosing: jest.fn(),
15
- setTitle: jest.fn(),
16
- onWorkspaceClose: jest.fn(),
17
- setOnCloseCallback: jest.fn(),
18
- };
19
-
20
- const mockSavePatientNote = savePatientNote as jest.Mock;
21
- const mockedShowSnackbar = jest.mocked(showSnackbar);
22
- const mockedCreateErrorHandler = jest.mocked(createErrorHandler);
23
- const mockedTranslateFrom = jest.mocked(translateFrom);
24
- const mockedResponsiveWrapper = jest.mocked(ResponsiveWrapper);
25
- const mockedUseSession = jest.mocked(useSession);
26
-
27
- jest.mock('../notes.resource', () => ({
28
- savePatientNote: jest.fn(),
29
- }));
30
-
31
- jest.mock('../../../hooks/useEmrConfiguration', () => jest.fn());
32
-
33
- const mockedUseEmrConfiguration = jest.mocked(useEmrConfiguration);
34
-
35
- mockedUseEmrConfiguration.mockReturnValue({
36
- emrConfiguration: emrConfigurationMock,
37
- mutateEmrConfiguration: jest.fn(),
38
- isLoadingEmrConfiguration: false,
39
- errorFetchingEmrConfiguration: null,
40
- });
41
-
42
- test('renders the visit notes form with all the relevant fields and values', () => {
43
- renderWardPatientNotesForm();
44
-
45
- expect(screen.getByRole('textbox', { name: /Write your notes/i })).toBeInTheDocument();
46
- expect(screen.getByRole('button', { name: /Save/i })).toBeInTheDocument();
47
- });
48
-
49
- test('renders a success snackbar upon successfully recording a visit note', async () => {
50
- const successPayload = {
51
- encounterProviders: expect.arrayContaining([
52
- {
53
- encounterRole: emrConfigurationMock?.clinicianEncounterRole?.uuid,
54
- provider: undefined,
55
- },
56
- ]),
57
- encounterType: emrConfigurationMock?.inpatientNoteEncounterType?.uuid,
58
- location: undefined,
59
- obs: expect.arrayContaining([
60
- {
61
- concept: { display: '', uuid: '162169AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' },
62
- value: 'Sample clinical note',
63
- },
64
- ]),
65
- patient: mockPatient.uuid,
66
- };
67
-
68
- mockSavePatientNote.mockResolvedValue({ status: 201, body: 'Condition created' });
69
-
70
- renderWardPatientNotesForm();
71
-
72
- const note = screen.getByRole('textbox', { name: /Write your notes/i });
73
- await userEvent.clear(note);
74
- await userEvent.type(note, 'Sample clinical note');
75
- expect(note).toHaveValue('Sample clinical note');
76
-
77
- const submitButton = screen.getByRole('button', { name: /Save/i });
78
- await userEvent.click(submitButton);
79
-
80
- expect(mockSavePatientNote).toHaveBeenCalledTimes(1);
81
- expect(mockSavePatientNote).toHaveBeenCalledWith(expect.objectContaining(successPayload), new AbortController());
82
- });
83
-
84
- test('renders an error snackbar if there was a problem recording a visit note', async () => {
85
- const error = {
86
- message: 'Internal Server Error',
87
- response: {
88
- status: 500,
89
- statusText: 'Internal Server Error',
90
- },
91
- };
92
-
93
- mockSavePatientNote.mockRejectedValueOnce(error);
94
- renderWardPatientNotesForm();
95
-
96
- const note = screen.getByRole('textbox', { name: /Write your notes/i });
97
- await userEvent.clear(note);
98
- await userEvent.type(note, 'Sample clinical note');
99
- expect(note).toHaveValue('Sample clinical note');
100
-
101
- const submitButton = screen.getByRole('button', { name: /Save/i });
102
-
103
- await userEvent.click(submitButton);
104
-
105
- expect(mockedShowSnackbar).toHaveBeenCalledWith({
106
- isLowContrast: false,
107
- kind: 'error',
108
- subtitle: 'Internal Server Error',
109
- title: 'Error saving patient note',
110
- });
111
- });
112
-
113
- function renderWardPatientNotesForm() {
114
- mockedUseSession.mockReturnValue(mockSession);
115
- render(<PatientNotesForm {...testProps} />);
116
- }
@@ -1,18 +0,0 @@
1
- import { ActionMenuButton, launchWorkspace, StickyNoteAddIcon } from '@openmrs/esm-framework';
2
- import React from 'react';
3
- import { useTranslation } from 'react-i18next';
4
- import { type WardPatientWorkspaceProps } from '../../types';
5
-
6
- export default function WardPatientNotesActionButton() {
7
- const { t } = useTranslation();
8
-
9
- return (
10
- <ActionMenuButton
11
- getIcon={(props) => <StickyNoteAddIcon {...props} size={16} />}
12
- label={t('PatientNote', 'Patient Note')}
13
- iconDescription={t('PatientNote', 'Patient Note')}
14
- handler={() => launchWorkspace<WardPatientWorkspaceProps>('ward-patient-notes-workspace')}
15
- type={'ward-patient-notes'}
16
- />
17
- );
18
- }
File without changes