@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,44 +1,44 @@
1
- import React from 'react';
1
+ import React, { type ReactNode } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { InlineNotification } from '@carbon/react';
4
- import { useAppContext } from '@openmrs/esm-framework';
4
+ import { useAppContext, Workspace2, type Workspace2DefinitionProps } from '@openmrs/esm-framework';
5
5
  import { type WardViewContext } from '../../types';
6
- import {
7
- AdmissionRequestsWorkspaceContextProvider,
8
- type AdmissionRequestsWorkspaceContextProps,
9
- } from './admission-requests-context';
10
6
  import AdmissionRequestsEmptyState from './admission-requests-empty-state.component';
11
7
  import useEmrConfiguration from '../../hooks/useEmrConfiguration';
12
8
  import styles from './admission-requests-workspace.scss';
9
+ export interface AdmissionRequestsWorkspaceProps {
10
+ wardPendingPatients: ReactNode;
11
+ }
13
12
 
14
- const AdmissionRequestsWorkspace: React.FC<AdmissionRequestsWorkspaceContextProps> = ({ wardPendingPatients }) => {
13
+ const AdmissionRequestsWorkspace: React.FC<Workspace2DefinitionProps<AdmissionRequestsWorkspaceProps>> = ({
14
+ workspaceProps: { wardPendingPatients },
15
+ }) => {
15
16
  const { t } = useTranslation();
16
17
  const { errorFetchingEmrConfiguration } = useEmrConfiguration();
17
18
  const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
18
- const { inpatientRequests, isLoading, error } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
19
+ const { inpatientRequests, isLoading } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
19
20
 
20
21
  return (
21
- <div className={styles.admissionRequestsWorkspaceContainer}>
22
- {errorFetchingEmrConfiguration && (
23
- <div className={styles.formError}>
24
- <InlineNotification
25
- kind="error"
26
- title={t('somePartsOfTheFormDidntLoad', "Some parts of the form didn't load")}
27
- subtitle={t(
28
- 'fetchingEmrConfigurationFailed',
29
- 'Fetching EMR configuration failed. Try refreshing the page or contact your system administrator.',
30
- )}
31
- lowContrast
32
- hideCloseButton
33
- />
34
- </div>
35
- )}
36
- {inpatientRequests?.length === 0 && !isLoading && <AdmissionRequestsEmptyState />}
37
- <AdmissionRequestsWorkspaceContextProvider
38
- value={{ wardPendingPatients } as unknown as AdmissionRequestsWorkspaceContextProps}>
22
+ <Workspace2 title={t('admissionRequests', 'Admission requests')}>
23
+ <div className={styles.admissionRequestsWorkspaceContainer}>
24
+ {errorFetchingEmrConfiguration && (
25
+ <div className={styles.formError}>
26
+ <InlineNotification
27
+ kind="error"
28
+ title={t('somePartsOfTheFormDidntLoad', "Some parts of the form didn't load")}
29
+ subtitle={t(
30
+ 'fetchingEmrConfigurationFailed',
31
+ 'Fetching EMR configuration failed. Try refreshing the page or contact your system administrator.',
32
+ )}
33
+ lowContrast
34
+ hideCloseButton
35
+ />
36
+ </div>
37
+ )}
38
+ {inpatientRequests?.length === 0 && !isLoading && <AdmissionRequestsEmptyState />}
39
39
  <div className={styles.content}>{wardPendingPatients}</div>
40
- </AdmissionRequestsWorkspaceContextProvider>
41
- </div>
40
+ </div>
41
+ </Workspace2>
42
42
  );
43
43
  };
44
44
 
@@ -3,11 +3,12 @@ import { useTranslation } from 'react-i18next';
3
3
  import { Button } from '@carbon/react';
4
4
  import {
5
5
  ArrowRightIcon,
6
- launchWorkspace,
6
+ launchWorkspace2,
7
7
  showSnackbar,
8
8
  useAppContext,
9
9
  useFeatureFlag,
10
10
  useLayoutType,
11
+ Workspace2DefinitionProps,
11
12
  } from '@openmrs/esm-framework';
12
13
  import useWardLocation from '../hooks/useWardLocation';
13
14
  import type { DispositionType, WardPatient, WardPatientWorkspaceProps, WardViewContext } from '../types';
@@ -39,7 +40,7 @@ const AdmitPatientButton: React.FC<AdmitPatientButtonProps> = ({
39
40
  const [isAdmitting, setIsAdmitting] = useState(false);
40
41
 
41
42
  const launchPatientAdmissionForm = () =>
42
- launchWorkspace<WardPatientWorkspaceProps>('admit-patient-form-workspace', { wardPatient });
43
+ launchWorkspace2<WardPatientWorkspaceProps, {}, {}>('admit-patient-form-workspace', { wardPatient });
43
44
 
44
45
  const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');
45
46
 
@@ -7,12 +7,13 @@ import {
7
7
  useAppContext,
8
8
  useFeatureFlag,
9
9
  useSession,
10
+ type Workspace2DefinitionProps,
10
11
  } from '@openmrs/esm-framework';
11
12
  import { mockInpatientRequestAlice, mockLocationInpatientWard, mockPatientAlice } from '__mocks__';
12
13
  import { renderWithSwr } from 'tools';
13
14
  import { mockWardPatientGroupDetails, mockWardViewContext } from '../../../mock';
14
15
  import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
15
- import type { WardPatient, WardViewContext } from '../../types';
16
+ import type { WardPatient, WardPatientWorkspaceProps, WardViewContext } from '../../types';
16
17
  import { assignPatientToBed, removePatientFromBed, useAdmitPatient } from '../../ward.resource';
17
18
  import AdmitPatientFormWorkspace from './admit-patient-form.workspace';
18
19
  import useWardLocation from '../../hooks/useWardLocation';
@@ -64,13 +65,6 @@ const mockUseAdmitPatientObj: ReturnType<typeof useAdmitPatient> = {
64
65
  };
65
66
  jest.mocked(useAdmitPatient).mockReturnValue(mockUseAdmitPatientObj);
66
67
 
67
- const mockWorkspaceProps: DefaultWorkspaceProps = {
68
- closeWorkspaceWithSavedChanges: jest.fn(),
69
- promptBeforeClosing: jest.fn(),
70
- setTitle: jest.fn(),
71
- closeWorkspace: jest.fn(),
72
- };
73
-
74
68
  const mockWardPatientAliceProps: WardPatient = {
75
69
  visit: mockInpatientRequestAlice.visit,
76
70
  patient: mockPatientAlice,
@@ -79,12 +73,21 @@ const mockWardPatientAliceProps: WardPatient = {
79
73
  inpatientRequest: mockInpatientRequestAlice,
80
74
  };
81
75
 
76
+ const mockWorkspaceProps: Workspace2DefinitionProps<WardPatientWorkspaceProps, {}, {}> = {
77
+ closeWorkspace: jest.fn(),
78
+ launchChildWorkspace: jest.fn(),
79
+ workspaceProps: {
80
+ wardPatient: mockWardPatientAliceProps,
81
+ },
82
+ windowProps: {},
83
+ groupProps: {},
84
+ workspaceName: '',
85
+ windowName: '',
86
+ isRootWorkspace: false,
87
+ };
88
+
82
89
  function renderAdmissionForm() {
83
- renderWithSwr(
84
- <AdmitPatientFormWorkspace
85
- {...{ ...mockWorkspaceProps, wardPatient: mockWardPatientAliceProps, WardPatientHeader: jest.fn() }}
86
- />,
87
- );
90
+ renderWithSwr(<AdmitPatientFormWorkspace {...mockWorkspaceProps} />);
88
91
  }
89
92
 
90
93
  describe('Testing AdmitPatientForm', () => {
@@ -151,9 +154,7 @@ describe('Testing AdmitPatientForm', () => {
151
154
  renderAdmissionForm();
152
155
  const cancelButton = screen.getByRole('button', { name: 'Cancel' });
153
156
  await user.click(cancelButton);
154
- expect(mockWorkspaceProps.closeWorkspace).toHaveBeenCalledWith({
155
- ignoreChanges: true,
156
- });
157
+ expect(mockWorkspaceProps.closeWorkspace).toHaveBeenCalledWith();
157
158
  screen.getByText('Admit');
158
159
  expect(screen.getByText('Select a bed')).toBeInTheDocument();
159
160
 
@@ -4,7 +4,13 @@ import { zodResolver } from '@hookform/resolvers/zod';
4
4
  import { Controller, useForm } from 'react-hook-form';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { z } from 'zod';
7
- import { showSnackbar, useAppContext } from '@openmrs/esm-framework';
7
+ import {
8
+ closeWorkspaceGroup2,
9
+ showSnackbar,
10
+ useAppContext,
11
+ Workspace2,
12
+ type Workspace2DefinitionProps,
13
+ } from '@openmrs/esm-framework';
8
14
  import type { WardPatientWorkspaceProps, WardViewContext } from '../../types';
9
15
  import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
10
16
  import { assignPatientToBed, removePatientFromBed, useAdmitPatient } from '../../ward.resource';
@@ -19,11 +25,9 @@ import styles from './admit-patient-form.scss';
19
25
  * the bed management module is installed. It asks to (optionally) select
20
26
  * a bed to assign to patient
21
27
  */
22
- const AdmitPatientFormWorkspace: React.FC<WardPatientWorkspaceProps> = ({
23
- wardPatient,
28
+ const AdmitPatientFormWorkspace: React.FC<Workspace2DefinitionProps<WardPatientWorkspaceProps, {}, {}>> = ({
29
+ workspaceProps: { wardPatient },
24
30
  closeWorkspace,
25
- closeWorkspaceWithSavedChanges,
26
- promptBeforeClosing,
27
31
  }) => {
28
32
  const { patient, inpatientRequest, visit } = wardPatient ?? {};
29
33
  const dispositionType = inpatientRequest?.dispositionType ?? 'ADMIT';
@@ -59,10 +63,6 @@ const AdmitPatientFormWorkspace: React.FC<WardPatientWorkspaceProps> = ({
59
63
  resolver: zodResolver(zodSchema),
60
64
  });
61
65
 
62
- useEffect(() => {
63
- promptBeforeClosing(() => isDirty);
64
- }, [isDirty, promptBeforeClosing]);
65
-
66
66
  const onSubmit = (values: FormValues) => {
67
67
  setShowErrorNotifications(false);
68
68
  setIsSubmitting(true);
@@ -115,6 +115,8 @@ const AdmitPatientFormWorkspace: React.FC<WardPatientWorkspaceProps> = ({
115
115
  }),
116
116
  });
117
117
  }
118
+ closeWorkspace({ discardUnsavedChanges: true });
119
+ closeWorkspaceGroup2();
118
120
  }
119
121
  },
120
122
  () => {
@@ -131,7 +133,6 @@ const AdmitPatientFormWorkspace: React.FC<WardPatientWorkspaceProps> = ({
131
133
  .finally(async () => {
132
134
  await wardPatientGroupDetails?.mutate?.();
133
135
  setIsSubmitting(false);
134
- closeWorkspaceWithSavedChanges();
135
136
  });
136
137
  };
137
138
 
@@ -143,66 +144,68 @@ const AdmitPatientFormWorkspace: React.FC<WardPatientWorkspaceProps> = ({
143
144
  if (!wardPatientGroupDetails) return <></>;
144
145
 
145
146
  return (
146
- <div className={styles.flexWrapper}>
147
- <WardPatientWorkspaceBanner {...{ wardPatient }} />
148
- <Form control={control} className={styles.form} onSubmit={handleSubmit(onSubmit, onError)}>
149
- <div className={styles.formContent}>
150
- <Row>
151
- <Column>
152
- <h2 className={styles.productiveHeading02}>{t('selectABed', 'Select a bed')}</h2>
153
- <div className={styles.bedSelectionDropdown}>
154
- <Controller
155
- control={control}
156
- name="bedId"
157
- render={({ field: { onChange, value }, fieldState: { error } }) => {
158
- return (
159
- <BedSelector
160
- beds={beds}
161
- isLoadingBeds={isLoading}
162
- currentPatient={patient}
163
- selectedBedId={value}
164
- error={error}
165
- control={control}
166
- onChange={onChange}
167
- />
168
- );
169
- }}
170
- />
171
- </div>
172
- </Column>
173
- </Row>
174
- <div className={styles.errorNotifications}>
175
- {showErrorNotifications &&
176
- Object.entries(errors).map(([key, value]) => {
177
- return (
178
- <Row key={key}>
179
- <Column>
180
- <InlineNotification kind="error" subtitle={value.message} lowContrast />
181
- </Column>
182
- </Row>
183
- );
184
- })}
147
+ <Workspace2 title={t('admitPatient', 'Admit patient')} hasUnsavedChanges={isDirty}>
148
+ <div className={styles.flexWrapper}>
149
+ <WardPatientWorkspaceBanner {...{ wardPatient }} />
150
+ <Form control={control} className={styles.form} onSubmit={handleSubmit(onSubmit, onError)}>
151
+ <div className={styles.formContent}>
152
+ <Row>
153
+ <Column>
154
+ <h2 className={styles.productiveHeading02}>{t('selectABed', 'Select a bed')}</h2>
155
+ <div className={styles.bedSelectionDropdown}>
156
+ <Controller
157
+ control={control}
158
+ name="bedId"
159
+ render={({ field: { onChange, value }, fieldState: { error } }) => {
160
+ return (
161
+ <BedSelector
162
+ beds={beds}
163
+ isLoadingBeds={isLoading}
164
+ currentPatient={patient}
165
+ selectedBedId={value}
166
+ error={error}
167
+ control={control}
168
+ onChange={onChange}
169
+ />
170
+ );
171
+ }}
172
+ />
173
+ </div>
174
+ </Column>
175
+ </Row>
176
+ <div className={styles.errorNotifications}>
177
+ {showErrorNotifications &&
178
+ Object.entries(errors).map(([key, value]) => {
179
+ return (
180
+ <Row key={key}>
181
+ <Column>
182
+ <InlineNotification kind="error" subtitle={value.message} lowContrast />
183
+ </Column>
184
+ </Row>
185
+ );
186
+ })}
187
+ </div>
185
188
  </div>
186
- </div>
187
- <ButtonSet className={styles.buttonSet}>
188
- <Button size="xl" kind="secondary" onClick={() => closeWorkspace({ ignoreChanges: true })}>
189
- {t('cancel', 'Cancel')}
190
- </Button>
191
- <Button
192
- type="submit"
193
- size="xl"
194
- disabled={
195
- isSubmitting ||
196
- isLoadingEmrConfiguration ||
197
- errorFetchingEmrConfiguration ||
198
- isLoading ||
199
- isLoadingBedsAssignedToPatient
200
- }>
201
- {!isSubmitting ? t('admit', 'Admit') : t('admitting', 'Admitting...')}
202
- </Button>
203
- </ButtonSet>
204
- </Form>
205
- </div>
189
+ <ButtonSet className={styles.buttonSet}>
190
+ <Button size="xl" kind="secondary" onClick={() => closeWorkspace()}>
191
+ {t('cancel', 'Cancel')}
192
+ </Button>
193
+ <Button
194
+ type="submit"
195
+ size="xl"
196
+ disabled={
197
+ isSubmitting ||
198
+ isLoadingEmrConfiguration ||
199
+ errorFetchingEmrConfiguration ||
200
+ isLoading ||
201
+ isLoadingBedsAssignedToPatient
202
+ }>
203
+ {!isSubmitting ? t('admit', 'Admit') : t('admitting', 'Admitting...')}
204
+ </Button>
205
+ </ButtonSet>
206
+ </Form>
207
+ </div>
208
+ </Workspace2>
206
209
  );
207
210
  };
208
211
 
@@ -0,0 +1,176 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import { Button, ButtonSet, Form, InlineNotification, TextArea } from '@carbon/react';
3
+ import classNames from 'classnames';
4
+ import { zodResolver } from '@hookform/resolvers/zod';
5
+ import { Controller, useForm } from 'react-hook-form';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { z } from 'zod';
8
+ import {
9
+ closeWorkspaceGroup2,
10
+ getCoreTranslation,
11
+ ResponsiveWrapper,
12
+ showSnackbar,
13
+ useAppContext,
14
+ Workspace2,
15
+ type Workspace2DefinitionProps,
16
+ } from '@openmrs/esm-framework';
17
+ import type { ObsPayload, WardPatient, WardViewContext } from '../../types';
18
+ import { useCreateEncounter } from '../../ward.resource';
19
+ import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
20
+ import styles from './cancel-admission-request.scss';
21
+
22
+ interface CancelAdmissionRequestProps {
23
+ wardPatient: WardPatient;
24
+ closeWorkspace: Workspace2DefinitionProps['closeWorkspace'];
25
+ }
26
+
27
+ const CancelAdmissionRequest: React.FC<CancelAdmissionRequestProps> = ({ closeWorkspace, wardPatient }) => {
28
+ const { patient, visit } = wardPatient ?? {};
29
+ const { t } = useTranslation();
30
+ const [isSubmitting, setIsSubmitting] = useState(false);
31
+ const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
32
+ useCreateEncounter();
33
+ const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
34
+
35
+ const zodSchema = useMemo(
36
+ () =>
37
+ z.object({
38
+ note: z
39
+ .string()
40
+ .trim()
41
+ .min(1, {
42
+ message: t(
43
+ 'notesRequiredForCancellingRequest',
44
+ 'Notes required for cancelling admission or transfer request',
45
+ ),
46
+ }),
47
+ }),
48
+ [t],
49
+ );
50
+
51
+ type FormValues = z.infer<typeof zodSchema>;
52
+
53
+ const {
54
+ formState: { errors, isDirty },
55
+ control,
56
+ handleSubmit,
57
+ } = useForm<FormValues>({
58
+ resolver: zodResolver(zodSchema),
59
+ defaultValues: { note: '' },
60
+ });
61
+
62
+ const onSubmit = useCallback(
63
+ (values: FormValues) => {
64
+ setIsSubmitting(true);
65
+ const obs: Array<ObsPayload> = [
66
+ {
67
+ concept: emrConfiguration?.consultFreeTextCommentsConcept?.uuid,
68
+ value: values.note,
69
+ },
70
+ {
71
+ concept: emrConfiguration?.admissionDecisionConcept?.uuid,
72
+ value: {
73
+ uuid: emrConfiguration?.denyAdmissionConcept?.uuid,
74
+ },
75
+ },
76
+ ];
77
+
78
+ createEncounter(patient, emrConfiguration?.cancelADTRequestEncounterType, visit?.uuid, obs)
79
+ .then(() => {
80
+ showSnackbar({
81
+ title: t('admissionRequestCancelled', 'Admission request cancelled.'),
82
+ kind: 'success',
83
+ });
84
+ closeWorkspace({ discardUnsavedChanges: true });
85
+ closeWorkspaceGroup2();
86
+ })
87
+ .catch((err: Error) => {
88
+ showSnackbar({
89
+ title: t('errorCancellingAdmissionRequest', 'Error cancelling admission request'),
90
+ subtitle: err.message,
91
+ kind: 'error',
92
+ });
93
+ })
94
+ .finally(() => {
95
+ setIsSubmitting(false);
96
+ wardPatientGroupDetails.mutate();
97
+ });
98
+ },
99
+ [
100
+ emrConfiguration?.consultFreeTextCommentsConcept?.uuid,
101
+ emrConfiguration?.admissionDecisionConcept?.uuid,
102
+ emrConfiguration?.denyAdmissionConcept?.uuid,
103
+ emrConfiguration?.cancelADTRequestEncounterType,
104
+ createEncounter,
105
+ patient,
106
+ t,
107
+ wardPatientGroupDetails,
108
+ visit?.uuid,
109
+ closeWorkspace,
110
+ ],
111
+ );
112
+
113
+ const onError = useCallback(() => {
114
+ setIsSubmitting(false);
115
+ }, []);
116
+
117
+ if (!wardPatientGroupDetails) return null;
118
+
119
+ return (
120
+ <Workspace2 title={t('cancelAdmissionRequest', 'Cancel admission request')} hasUnsavedChanges={isDirty}>
121
+ <div className={styles.flexWrapper}>
122
+ <WardPatientWorkspaceBanner wardPatient={wardPatient} />
123
+ <Form
124
+ onSubmit={handleSubmit(onSubmit, onError)}
125
+ className={classNames(styles.formContainer, styles.workspaceContent)}>
126
+ <div>
127
+ {errorFetchingEmrConfiguration && (
128
+ <div className={styles.formError}>
129
+ <InlineNotification
130
+ kind="error"
131
+ title={t('somePartsOfTheFormDidntLoad', "Some parts of the form didn't load")}
132
+ subtitle={t(
133
+ 'fetchingEmrConfigurationFailed',
134
+ 'Fetching EMR configuration failed. Try refreshing the page or contact your system administrator.',
135
+ )}
136
+ lowContrast
137
+ hideCloseButton
138
+ />
139
+ </div>
140
+ )}
141
+ <div className={styles.field}>
142
+ <Controller
143
+ name="note"
144
+ control={control}
145
+ render={({ field, fieldState: { error } }) => (
146
+ <ResponsiveWrapper>
147
+ <TextArea
148
+ {...field}
149
+ id="clinical-notes"
150
+ labelText={t('clinicalNotes', 'Clinical notes')}
151
+ invalid={!!error}
152
+ invalidText={error?.message}
153
+ />
154
+ </ResponsiveWrapper>
155
+ )}
156
+ />
157
+ </div>
158
+ </div>
159
+ <ButtonSet className={styles.buttonSet}>
160
+ <Button size="xl" kind="secondary" onClick={() => closeWorkspace()}>
161
+ {getCoreTranslation('cancel')}
162
+ </Button>
163
+ <Button
164
+ type="submit"
165
+ size="xl"
166
+ disabled={isLoadingEmrConfiguration || isSubmitting || errorFetchingEmrConfiguration || !patient}>
167
+ {getCoreTranslation('save')}
168
+ </Button>
169
+ </ButtonSet>
170
+ </Form>
171
+ </div>
172
+ </Workspace2>
173
+ );
174
+ };
175
+
176
+ export default CancelAdmissionRequest;
@@ -50,14 +50,7 @@ mockedUseWardLocation.mockReturnValue({
50
50
  errorFetchingLocation: null,
51
51
  });
52
52
 
53
- const mockWorkspaceProps: DefaultWorkspaceProps = {
54
- closeWorkspaceWithSavedChanges: jest.fn(),
55
- promptBeforeClosing: jest.fn(),
56
- setTitle: jest.fn(),
57
- closeWorkspace: jest.fn(),
58
- };
59
-
60
- const mockWardPatientAliceProps: WardPatient = {
53
+ const mockWardPatientAlice: WardPatient = {
61
54
  visit: mockInpatientRequestAlice.visit,
62
55
  patient: mockPatientAlice,
63
56
  bed: null,
@@ -70,7 +63,16 @@ jest.mocked(useAppContext<WardViewContext>).mockReturnValue(mockWardViewContext)
70
63
  function renderCancelAdmissionRequestWorkspace() {
71
64
  renderWithSwr(
72
65
  <CancelAdmissionRequestWorkspace
73
- {...{ ...mockWorkspaceProps, wardPatient: mockWardPatientAliceProps, WardPatientHeader: jest.fn() }}
66
+ launchChildWorkspace={jest.fn()}
67
+ closeWorkspace={jest.fn()}
68
+ workspaceProps={{
69
+ wardPatient: mockWardPatientAlice,
70
+ }}
71
+ windowProps={undefined}
72
+ groupProps={undefined}
73
+ workspaceName={''}
74
+ windowName={''}
75
+ isRootWorkspace={false}
74
76
  />,
75
77
  );
76
78
  }