@kenyaemr/esm-morgue-app 5.4.2-pre.2283 → 5.4.2-pre.2291

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 (193) hide show
  1. package/.turbo/turbo-build.log +19 -19
  2. package/dist/109.js +2 -0
  3. package/dist/109.js.map +1 -0
  4. package/dist/201.js +1 -0
  5. package/dist/201.js.map +1 -0
  6. package/dist/293.js +1 -0
  7. package/dist/293.js.map +1 -0
  8. package/dist/300.js +1 -1
  9. package/dist/347.js +1 -2
  10. package/dist/347.js.map +1 -1
  11. package/dist/373.js +2 -0
  12. package/dist/373.js.map +1 -0
  13. package/dist/38.js +1 -0
  14. package/dist/38.js.map +1 -0
  15. package/dist/389.js +1 -0
  16. package/dist/389.js.map +1 -0
  17. package/dist/398.js +1 -0
  18. package/dist/398.js.map +1 -0
  19. package/dist/4.js +2 -0
  20. package/dist/4.js.map +1 -0
  21. package/dist/410.js +1 -0
  22. package/dist/410.js.map +1 -0
  23. package/dist/420.js +2 -0
  24. package/dist/420.js.map +1 -0
  25. package/dist/467.js +1 -0
  26. package/dist/467.js.map +1 -0
  27. package/dist/632.js +1 -0
  28. package/dist/632.js.map +1 -0
  29. package/dist/798.js +1 -0
  30. package/dist/798.js.map +1 -0
  31. package/dist/811.js +1 -0
  32. package/dist/811.js.map +1 -0
  33. package/dist/824.js +1 -0
  34. package/dist/824.js.map +1 -0
  35. package/dist/827.js +1 -0
  36. package/dist/827.js.map +1 -0
  37. package/dist/842.js +2 -0
  38. package/dist/842.js.LICENSE.txt +5 -0
  39. package/dist/842.js.map +1 -0
  40. package/dist/918.js +1 -1
  41. package/dist/918.js.map +1 -1
  42. package/dist/kenyaemr-esm-morgue-app.js +1 -1
  43. package/dist/kenyaemr-esm-morgue-app.js.buildmanifest.json +218 -291
  44. package/dist/kenyaemr-esm-morgue-app.js.map +1 -1
  45. package/dist/main.js +2 -1
  46. package/dist/main.js.LICENSE.txt +15 -0
  47. package/dist/main.js.map +1 -1
  48. package/dist/routes.json +1 -1
  49. package/package.json +1 -1
  50. package/src/bed/bed.component.tsx +164 -0
  51. package/src/bed/bed.scss +192 -0
  52. package/src/bed/divider/divider.component.tsx +18 -0
  53. package/src/bed/empty-bed.component.tsx +47 -0
  54. package/src/bed-layout/admitted/admitted-bed-layout.component.tsx +189 -0
  55. package/src/bed-layout/awaiting/awaiting-bed-layout.component.tsx +86 -0
  56. package/src/bed-layout/bed-layout.resource.ts +72 -0
  57. package/src/bed-layout/bed-layout.scss +55 -0
  58. package/src/bed-layout/discharged/discharged-bed-layout.component.tsx +109 -0
  59. package/src/bed-layout/discharged/discharged-bed-layout.resource.ts +99 -0
  60. package/src/bed-linelist-view/admitted/admitted-bed-linelist-view.component.tsx +420 -0
  61. package/src/bed-linelist-view/awaiting/awaiting-bed-linelist-view.component.tsx +224 -0
  62. package/src/bed-linelist-view/bed-linelist-view.scss +5 -0
  63. package/src/bed-linelist-view/discharged/discharged-bed-line-view.component.tsx +256 -0
  64. package/src/config-schema.ts +41 -9
  65. package/src/constants.ts +57 -0
  66. package/src/deceased-patient-header/deceased-patient-header.component.tsx +31 -0
  67. package/src/deceased-patient-header/deceased-patient-header.scss +50 -0
  68. package/src/{component → deceased-patient-header}/deceasedInfo/deceased-info.component.tsx +1 -1
  69. package/src/deceased-patient-header/deceasedInfo/deceased-info.resource.ts +11 -0
  70. package/src/extension/actionButton.component.tsx +5 -59
  71. package/src/extension/deceasedInfoBanner.component.tsx +5 -9
  72. package/src/{hook/useAdmitPatient.ts → forms/admit-deceased-person-workspace/admit-deceased-person.resource.ts} +177 -46
  73. package/src/forms/admit-deceased-person-workspace/admit-deceased-person.scss +143 -0
  74. package/src/forms/admit-deceased-person-workspace/admit-deceased-person.workspace.tsx +648 -0
  75. package/src/{hook/usePersonAttributes.ts → forms/discharge-deceased-person-workspace/discharge-body.resource.ts} +1 -1
  76. package/src/forms/discharge-deceased-person-workspace/discharge-body.scss +56 -0
  77. package/src/forms/discharge-deceased-person-workspace/discharge-body.workspace.tsx +362 -0
  78. package/src/forms/dispose-deceased-person-workspace/dispose-deceased-person.resource.ts +18 -0
  79. package/src/{workspaces/patientAdditionalInfoForm.scss → forms/dispose-deceased-person-workspace/dispose-deceased-person.scss} +46 -66
  80. package/src/forms/dispose-deceased-person-workspace/dispose-deceased-person.workspace.tsx +401 -0
  81. package/src/forms/form-entry-workspace/form-entry-workspace.workspace.tsx +62 -0
  82. package/src/forms/swap-compartment-workspace/swap-unit.scss +144 -0
  83. package/src/forms/swap-compartment-workspace/swap-unit.workspace.tsx +280 -0
  84. package/src/header/header.component.tsx +41 -0
  85. package/src/header/header.scss +58 -0
  86. package/src/home/home.component.tsx +87 -0
  87. package/src/home/home.resource.ts +261 -0
  88. package/src/home/home.scss +5 -0
  89. package/src/index.ts +18 -12
  90. package/src/metrics/metrics-card.component.tsx +31 -0
  91. package/src/metrics/metrics-card.scss +51 -0
  92. package/src/root.component.tsx +7 -3
  93. package/src/routes.json +25 -14
  94. package/src/schemas/index.ts +66 -0
  95. package/src/summary/summary.component.tsx +42 -0
  96. package/src/summary/summary.scss +10 -0
  97. package/src/switcher/content-switcher.component.tsx +220 -0
  98. package/src/switcher/content-switcher.scss +30 -0
  99. package/src/types/index.ts +336 -359
  100. package/src/utils/utils.ts +20 -2
  101. package/src/view-details/main/main.component.tsx +34 -0
  102. package/src/view-details/main/main.scss +45 -0
  103. package/src/view-details/panels/attachement.component.tsx +21 -0
  104. package/src/view-details/panels/autopsy.component.tsx +215 -0
  105. package/src/view-details/panels/billing-history.component.tsx +13 -0
  106. package/src/view-details/panels/observations/observation.component.tsx +57 -0
  107. package/src/view-details/panels/observations/observation.scss +24 -0
  108. package/src/view-details/panels/panels.scss +46 -0
  109. package/src/view-details/view-details.component.tsx +65 -0
  110. package/src/view-details/view-details.resource.ts +65 -0
  111. package/src/view-details/views-details.scss +82 -0
  112. package/translations/en.json +74 -21
  113. package/tsconfig.json +1 -1
  114. package/dist/113.js +0 -1
  115. package/dist/113.js.map +0 -1
  116. package/dist/160.js +0 -1
  117. package/dist/160.js.map +0 -1
  118. package/dist/299.js +0 -1
  119. package/dist/299.js.map +0 -1
  120. package/dist/433.js +0 -2
  121. package/dist/433.js.map +0 -1
  122. package/dist/441.js +0 -1
  123. package/dist/441.js.map +0 -1
  124. package/dist/496.js +0 -1
  125. package/dist/496.js.map +0 -1
  126. package/dist/511.js +0 -1
  127. package/dist/511.js.map +0 -1
  128. package/dist/603.js +0 -1
  129. package/dist/603.js.map +0 -1
  130. package/dist/610.js +0 -1
  131. package/dist/610.js.map +0 -1
  132. package/dist/612.js +0 -1
  133. package/dist/612.js.map +0 -1
  134. package/dist/656.js +0 -2
  135. package/dist/656.js.map +0 -1
  136. package/dist/752.js +0 -1
  137. package/dist/752.js.map +0 -1
  138. package/dist/754.js +0 -1
  139. package/dist/754.js.map +0 -1
  140. package/dist/781.js +0 -1
  141. package/dist/781.js.map +0 -1
  142. package/dist/801.js +0 -2
  143. package/dist/801.js.map +0 -1
  144. package/dist/817.js +0 -1
  145. package/dist/817.js.map +0 -1
  146. package/dist/877.js +0 -1
  147. package/dist/877.js.map +0 -1
  148. package/dist/924.js +0 -1
  149. package/dist/924.js.map +0 -1
  150. package/src/autosuggest/autosuggest.component.tsx +0 -162
  151. package/src/autosuggest/autosuggest.scss +0 -61
  152. package/src/autosuggest/patient-search-info.component.tsx +0 -75
  153. package/src/autosuggest/patient-search-info.scss +0 -62
  154. package/src/autosuggest/search-empty-state.component.tsx +0 -21
  155. package/src/autosuggest/search-empty-state.scss +0 -18
  156. package/src/card/avail-compartment.compartment.tsx +0 -94
  157. package/src/card/compartment-view.compartment.tsx +0 -62
  158. package/src/card/compartment.scss +0 -128
  159. package/src/card/compartmentSharing.component.tsx +0 -21
  160. package/src/card/compartmentSharing.scss +0 -24
  161. package/src/card/empty-compartment.component.tsx +0 -28
  162. package/src/card/empty-compartment.scss +0 -61
  163. package/src/component/main.component.tsx +0 -17
  164. package/src/component/next-of-kin-details/nextOfKinDetails.component.tsx +0 -50
  165. package/src/component/next-of-kin-details/nextOfKinDetails.scss +0 -37
  166. package/src/header/admitted-queue-header.component.tsx +0 -30
  167. package/src/header/admitted-queue-header.scss +0 -32
  168. package/src/header/morgue-header.component.tsx +0 -38
  169. package/src/header/morgue-header.scss +0 -95
  170. package/src/header/morgue-illustration.component.tsx +0 -13
  171. package/src/hook/useDeceasedPatients.ts +0 -12
  172. package/src/hook/useDischargedPatient.ts +0 -55
  173. package/src/hook/useMorgue.resource.ts +0 -163
  174. package/src/hook/useMortuaryAdmissionLocation.ts +0 -64
  175. package/src/tables/admitted-queue.component.tsx +0 -54
  176. package/src/tables/admitted-queue.scss +0 -62
  177. package/src/tables/discharge-queue.component.tsx +0 -87
  178. package/src/tables/generic-table.component.tsx +0 -140
  179. package/src/tables/generic-table.scss +0 -37
  180. package/src/tabs/tabs.component.tsx +0 -82
  181. package/src/tabs/tabs.scss +0 -15
  182. package/src/workspaces/admit-body.scss +0 -46
  183. package/src/workspaces/admit-body.workspace.tsx +0 -79
  184. package/src/workspaces/discharge-body.scss +0 -67
  185. package/src/workspaces/discharge-body.workspace.tsx +0 -329
  186. package/src/workspaces/patientAdditionalInfoForm.workspace.tsx +0 -562
  187. package/src/workspaces/swap-unit.scss +0 -46
  188. package/src/workspaces/swap-unit.workspace.tsx +0 -168
  189. /package/dist/{347.js.LICENSE.txt → 109.js.LICENSE.txt} +0 -0
  190. /package/dist/{656.js.LICENSE.txt → 373.js.LICENSE.txt} +0 -0
  191. /package/dist/{801.js.LICENSE.txt → 4.js.LICENSE.txt} +0 -0
  192. /package/dist/{433.js.LICENSE.txt → 420.js.LICENSE.txt} +0 -0
  193. /package/src/{component → deceased-patient-header}/deceasedInfo/deceased-info.scss +0 -0
@@ -0,0 +1,56 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+
5
+ .form {
6
+ display: flex;
7
+ flex-direction: column;
8
+ justify-content: space-between;
9
+ height: 100%;
10
+ }
11
+
12
+ .formContainer {
13
+ margin: layout.$spacing-05;
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: layout.$spacing-05;
17
+ }
18
+
19
+ .tablet {
20
+ padding: layout.$spacing-06 layout.$spacing-05;
21
+ background-color: colors.$white;
22
+ }
23
+
24
+ .desktop {
25
+ padding: 0;
26
+ padding: layout.$spacing-01 layout.$spacing-04;
27
+ }
28
+ .buttonContainer {
29
+ max-width: 50%;
30
+ }
31
+ .inlineLoading {
32
+ display: flex;
33
+ align-items: center;
34
+ gap: layout.$spacing-03;
35
+ }
36
+ .formDeathTimepickerSelector {
37
+ min-width: layout.$spacing-05;
38
+ margin-top: layout.$spacing-06;
39
+ }
40
+ .formAdmissionTimepicker input {
41
+ min-width: 11rem;
42
+ }
43
+ .formAdmissionDatepicker input {
44
+ min-width: 23rem;
45
+ }
46
+ .dateTimeSection {
47
+ display: flex;
48
+ flex-direction: row;
49
+ gap: layout.$spacing-02;
50
+ align-items: center;
51
+ padding-top: layout.$spacing-03;
52
+ }
53
+
54
+ .sectionField {
55
+ padding-top: layout.$spacing-03;
56
+ }
@@ -0,0 +1,362 @@
1
+ import {
2
+ Button,
3
+ ButtonSet,
4
+ Column,
5
+ DatePicker,
6
+ DatePickerInput,
7
+ Form,
8
+ InlineLoading,
9
+ SelectItem,
10
+ Stack,
11
+ TextInput,
12
+ TimePicker,
13
+ TimePickerSelect,
14
+ } from '@carbon/react';
15
+ import { zodResolver } from '@hookform/resolvers/zod';
16
+ import {
17
+ ExtensionSlot,
18
+ fhirBaseUrl,
19
+ ResponsiveWrapper,
20
+ restBaseUrl,
21
+ setCurrentVisit,
22
+ showSnackbar,
23
+ useConfig,
24
+ useLayoutType,
25
+ useVisit,
26
+ } from '@openmrs/esm-framework';
27
+ import React, { useCallback, useEffect } from 'react';
28
+ import { Controller, useForm } from 'react-hook-form';
29
+ import { useTranslation } from 'react-i18next';
30
+ import { mutate as mutateSWR } from 'swr';
31
+ import { z } from 'zod';
32
+ import styles from './discharge-body.scss';
33
+ import DeceasedInfo from '../../deceased-patient-header/deceasedInfo/deceased-info.component';
34
+ import { PatientInfo } from '../../types';
35
+ import { usePersonAttributes } from './discharge-body.resource';
36
+ import { ConfigObject } from '../../config-schema';
37
+ import { getCurrentTime } from '../../utils/utils';
38
+ import { dischargeSchema } from '../../schemas';
39
+ import { useVisitQueueEntry } from '../../home/home.resource';
40
+ import classNames from 'classnames';
41
+ import { useMortuaryOperation } from '../admit-deceased-person-workspace/admit-deceased-person.resource';
42
+
43
+ interface DischargeFormProps {
44
+ closeWorkspace: () => void;
45
+ patientUuid: string;
46
+ personUuid: string;
47
+ bedId: number;
48
+ mutate: () => void;
49
+ }
50
+
51
+ type DischargeFormValues = z.infer<typeof dischargeSchema>;
52
+
53
+ const DischargeForm: React.FC<DischargeFormProps> = ({ closeWorkspace, patientUuid, bedId, personUuid, mutate }) => {
54
+ const { t } = useTranslation();
55
+ const isTablet = useLayoutType() === 'tablet';
56
+ const { activeVisit, currentVisitIsRetrospective } = useVisit(patientUuid);
57
+ const { queueEntry } = useVisitQueueEntry(patientUuid, activeVisit?.uuid);
58
+ const { dischargeBody, isLoadingEmrConfiguration } = useMortuaryOperation();
59
+ const { createOrUpdatePersonAttribute, personAttributes } = usePersonAttributes(personUuid);
60
+
61
+ const { time: defaultTime, period: defaultPeriod } = getCurrentTime();
62
+
63
+ const { nextOfKinAddressUuid, nextOfKinNameUuid, nextOfKinPhoneUuid, nextOfKinRelationshipUuid } =
64
+ useConfig<ConfigObject>();
65
+
66
+ const getAttributeValue = useCallback(
67
+ (attributeTypeUuid: string) => {
68
+ if (!personAttributes) {
69
+ return '';
70
+ }
71
+ const attributes = Array.isArray(personAttributes) ? personAttributes : [];
72
+ const attribute = attributes.find((attr) => attr.attributeType.uuid === attributeTypeUuid);
73
+ return attribute ? attribute.value : '';
74
+ },
75
+ [personAttributes],
76
+ );
77
+
78
+ const {
79
+ watch,
80
+ control,
81
+ setValue,
82
+ handleSubmit,
83
+ formState: { errors, isDirty, isSubmitting },
84
+ } = useForm<DischargeFormValues>({
85
+ resolver: zodResolver(dischargeSchema),
86
+ defaultValues: {
87
+ dateOfDischarge: new Date(),
88
+ timeOfDischarge: defaultTime,
89
+ period: defaultPeriod,
90
+ burialPermitNumber: '',
91
+ },
92
+ });
93
+ useEffect(() => {
94
+ if (Array.isArray(personAttributes) && personAttributes.length > 0) {
95
+ setValue('nextOfKinNames', getAttributeValue(nextOfKinNameUuid));
96
+ setValue('relationshipType', getAttributeValue(nextOfKinRelationshipUuid));
97
+ setValue('nextOfKinContact', getAttributeValue(nextOfKinPhoneUuid));
98
+ setValue('nextOfKinAddress', getAttributeValue(nextOfKinAddressUuid));
99
+ }
100
+ }, [
101
+ personAttributes,
102
+ getAttributeValue,
103
+ nextOfKinNameUuid,
104
+ nextOfKinRelationshipUuid,
105
+ nextOfKinPhoneUuid,
106
+ nextOfKinAddressUuid,
107
+ setValue,
108
+ ]);
109
+ const onSubmit = async (data: DischargeFormValues) => {
110
+ if (currentVisitIsRetrospective) {
111
+ setCurrentVisit(null, null);
112
+ closeWorkspace();
113
+ } else {
114
+ try {
115
+ const nextOfKinAttributes = [
116
+ { attributeType: nextOfKinNameUuid, value: data.nextOfKinNames },
117
+ { attributeType: nextOfKinRelationshipUuid, value: data.relationshipType },
118
+ { attributeType: nextOfKinPhoneUuid, value: data.nextOfKinContact },
119
+ { attributeType: nextOfKinAddressUuid, value: data.nextOfKinAddress },
120
+ ];
121
+ const patientInfo: PatientInfo = {
122
+ uuid: activeVisit.patient.uuid,
123
+ attributes: (activeVisit?.patient?.person?.attributes || []).map((attr) => ({
124
+ uuid: attr.uuid,
125
+ display: attr.display || '',
126
+ })),
127
+ };
128
+
129
+ for (const attribute of nextOfKinAttributes) {
130
+ await createOrUpdatePersonAttribute(patientUuid, attribute, patientInfo);
131
+ }
132
+
133
+ await dischargeBody(activeVisit, queueEntry, bedId, data);
134
+
135
+ showSnackbar({
136
+ title: t('dischargeDeceasedPatient', 'Deceased patient'),
137
+ subtitle: t('deceasedPatientDischargedSuccessfully', 'Deceased patient has been discharged successfully'),
138
+ kind: 'success',
139
+ isLowContrast: true,
140
+ });
141
+ mutateSWR((key) => typeof key === 'string' && key.startsWith(`${restBaseUrl}/visit`));
142
+ mutateSWR((key) => typeof key === 'string' && key.startsWith(`${restBaseUrl}/patient`));
143
+ mutateSWR((key) => typeof key === 'string' && key.startsWith(`${fhirBaseUrl}/Encounter`));
144
+
145
+ mutate();
146
+ closeWorkspace();
147
+ } catch (error) {
148
+ console.error(error);
149
+ const errorMessage = JSON.stringify(error?.responseBody?.error?.message?.replace(/\[/g, '').replace(/\]/g, ''));
150
+ showSnackbar({
151
+ title: t('visitError', 'Visit Error'),
152
+ subtitle: t(
153
+ 'visitErrorMessage',
154
+ `An error has occurred while ending visit, Contact system administrator quoting this error ${errorMessage}`,
155
+ ),
156
+ kind: 'error',
157
+ isLowContrast: true,
158
+ });
159
+ }
160
+ }
161
+ };
162
+
163
+ if (isLoadingEmrConfiguration || !personAttributes) {
164
+ return <InlineLoading status="active" iconDescription="Loading" description="Loading ..." />;
165
+ }
166
+
167
+ return (
168
+ <Form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
169
+ <div className={styles.formContainer}>
170
+ <Stack gap={3}>
171
+ <DeceasedInfo patientUuid={patientUuid} />
172
+ <ResponsiveWrapper>
173
+ <div className={styles.dateTimePickerContainer}>
174
+ <Column>
175
+ <Controller
176
+ name="dateOfDischarge"
177
+ control={control}
178
+ render={({ field }) => (
179
+ <DatePicker
180
+ datePickerType="single"
181
+ className={styles.formAdmissionDatepicker}
182
+ onChange={(event) => {
183
+ if (event.length) {
184
+ field.onChange(event[0]);
185
+ }
186
+ }}
187
+ value={field.value ? new Date(field.value) : null}>
188
+ <DatePickerInput
189
+ {...field}
190
+ id="date-of-admission"
191
+ placeholder="yyyy-mm-dd"
192
+ labelText={t('dateOfAdmission', 'Date of discharge*')}
193
+ invalid={!!errors.dateOfDischarge}
194
+ invalidText={errors.dateOfDischarge?.message}
195
+ />
196
+ </DatePicker>
197
+ )}
198
+ />
199
+ </Column>
200
+
201
+ <Column>
202
+ <div className={styles.dateTimeSection}>
203
+ <ResponsiveWrapper>
204
+ <Controller
205
+ name="timeOfDischarge"
206
+ control={control}
207
+ render={({ field }) => (
208
+ <TimePicker
209
+ {...field}
210
+ id="time-of-discharge-picker"
211
+ labelText={t('timeOfDischarge', 'Time of discharge*')}
212
+ className={styles.formAdmissionTimepicker}
213
+ invalid={!!errors.timeOfDischarge}
214
+ invalidText={errors.timeOfDischarge?.message}
215
+ />
216
+ )}
217
+ />
218
+ <Controller
219
+ name="period"
220
+ control={control}
221
+ render={({ field }) => (
222
+ <TimePickerSelect
223
+ {...field}
224
+ className={styles.formDeathTimepickerSelector}
225
+ id="time-picker-select">
226
+ <SelectItem value="AM" text="AM" />
227
+ <SelectItem value="PM" text="PM" />
228
+ </TimePickerSelect>
229
+ )}
230
+ />
231
+ </ResponsiveWrapper>
232
+ </div>
233
+ </Column>
234
+ </div>
235
+ <Column className={styles.fieldColumn}>
236
+ <Controller
237
+ name="burialPermitNumber"
238
+ control={control}
239
+ render={({ field }) => (
240
+ <TextInput
241
+ {...field}
242
+ id="burialPermitNumber"
243
+ type="text"
244
+ className={styles.sectionField}
245
+ placeholder={t('burialPermitNumber', 'Burial permit number')}
246
+ labelText={t('burialPermitNumber', 'Burial permit number')}
247
+ invalid={!!errors.burialPermitNumber}
248
+ invalidText={errors.burialPermitNumber?.message}
249
+ />
250
+ )}
251
+ />
252
+ </Column>
253
+ <Column className={styles.fieldColumn}>
254
+ <Controller
255
+ name="nextOfKinNames"
256
+ control={control}
257
+ render={({ field }) => (
258
+ <TextInput
259
+ {...field}
260
+ id="nextOfKinNames"
261
+ type="text"
262
+ className={styles.sectionField}
263
+ placeholder={t('nextOfKinNames', 'Next of kin names')}
264
+ labelText={t('nextOfKinNames', 'Next of kin names')}
265
+ invalid={!!errors.nextOfKinNames}
266
+ invalidText={errors.nextOfKinNames?.message}
267
+ />
268
+ )}
269
+ />
270
+ </Column>
271
+ <Column className={styles.fieldColumn}>
272
+ <Controller
273
+ name="relationshipType"
274
+ control={control}
275
+ render={({ field }) => (
276
+ <TextInput
277
+ {...field}
278
+ id="relationship"
279
+ type="text"
280
+ className={styles.sectionField}
281
+ placeholder={t('relationship', 'Relationship')}
282
+ labelText={t('relationship', 'Relationship')}
283
+ invalid={!!errors.relationshipType}
284
+ invalidText={errors.relationshipType?.message}
285
+ />
286
+ )}
287
+ />
288
+ </Column>
289
+ <Column className={styles.fieldColumn}>
290
+ <Controller
291
+ name="nextOfKinContact"
292
+ control={control}
293
+ render={({ field }) => (
294
+ <TextInput
295
+ {...field}
296
+ id="telephone"
297
+ type="text"
298
+ className={styles.fieldSection}
299
+ placeholder={t('telephone', 'Telephone number')}
300
+ labelText={t('telephone', 'Telephone number')}
301
+ invalid={!!errors.nextOfKinContact}
302
+ invalidText={errors.nextOfKinContact?.message}
303
+ />
304
+ )}
305
+ />
306
+ </Column>
307
+ <Column className={styles.fieldColumn}>
308
+ <Controller
309
+ name="nextOfKinAddress"
310
+ control={control}
311
+ render={({ field }) => (
312
+ <TextInput
313
+ {...field}
314
+ id="nextOfKinAddress"
315
+ type="text"
316
+ className={styles.sectionField}
317
+ placeholder={t('nextOfKinAddress', 'Next of kin address')}
318
+ labelText={t('nextOfKinAddress', 'Next of kin address')}
319
+ invalid={!!errors.nextOfKinAddress}
320
+ invalidText={errors.nextOfKinAddress?.message}
321
+ />
322
+ )}
323
+ />
324
+ </Column>
325
+ </ResponsiveWrapper>
326
+ <ResponsiveWrapper>
327
+ <Column>
328
+ <ExtensionSlot
329
+ name="patient-chart-attachments-dashboard-slot"
330
+ className={styles.sectionField}
331
+ state={{
332
+ patientUuid,
333
+ }}
334
+ />
335
+ </Column>
336
+ </ResponsiveWrapper>
337
+ </Stack>
338
+ </div>
339
+ <ButtonSet
340
+ className={classNames({
341
+ [styles.tablet]: isTablet,
342
+ [styles.desktop]: !isTablet,
343
+ })}>
344
+ <Button className={styles.buttonContainer} kind="secondary" onClick={() => closeWorkspace()}>
345
+ {t('cancel', 'Cancel')}
346
+ </Button>
347
+ <Button className={styles.buttonContainer} disabled={isSubmitting || !isDirty} kind="primary" type="submit">
348
+ {isSubmitting ? (
349
+ <span className={styles.inlineLoading}>
350
+ {t('submitting', 'Submitting' + '...')}
351
+ <InlineLoading status="active" iconDescription="Loading" />
352
+ </span>
353
+ ) : (
354
+ t('saveAndClose', 'Save & close')
355
+ )}
356
+ </Button>
357
+ </ButtonSet>
358
+ </Form>
359
+ );
360
+ };
361
+
362
+ export default DischargeForm;
@@ -0,0 +1,18 @@
1
+ import useSWR from 'swr';
2
+ import { type ConceptResponse } from '../../types';
3
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
4
+
5
+ export const useConcept = (conceptUuid: string) => {
6
+ const apiUrl = `${restBaseUrl}/concept/${conceptUuid}`;
7
+
8
+ const { data, error, isLoading } = useSWR<{ data: ConceptResponse }, Error>(
9
+ conceptUuid ? apiUrl : null,
10
+ openmrsFetch,
11
+ );
12
+
13
+ return {
14
+ concept: data?.data || null,
15
+ error: error,
16
+ isLoading: isLoading,
17
+ };
18
+ };
@@ -1,75 +1,54 @@
1
+ @use '@carbon/colors';
1
2
  @use '@carbon/layout';
2
3
  @use '@carbon/type';
3
- @use '@carbon/colors';
4
4
 
5
- .formContainer {
6
- width: 100%;
7
- max-height: 100vh;
5
+ .form {
8
6
  display: flex;
9
7
  flex-direction: column;
10
- overflow-y: auto;
8
+ justify-content: space-between;
9
+ height: 100%;
11
10
  }
12
11
 
13
- .visitTypeHeader {
14
- color: colors.$gray-70;
15
- display: inline-block;
16
- font-size: layout.$spacing-04;
17
- line-height: layout.$spacing-05;
18
- margin-bottom: layout.$spacing-01;
19
- vertical-align: baseline;
20
- }
21
-
22
- .formButton {
23
- height: layout.$spacing-09;
24
- display: flex;
25
- align-content: flex-start;
26
- align-items: baseline;
27
- min-width: layout.$spacing-11;
28
- margin-bottom: layout.$spacing-05;
29
- }
30
-
31
- .buttonSet {
32
- width: 80%;
33
- padding-top: layout.$spacing-10;
12
+ .formContainer {
13
+ margin: layout.$spacing-05;
34
14
  display: flex;
35
- align-items: center;
36
- margin-bottom: layout.$spacing-03;
37
- position: relative;
38
- & > button {
39
- max-width: 50%;
40
- width: 50%;
41
- }
15
+ flex-direction: column;
16
+ gap: layout.$spacing-05;
42
17
  }
43
18
 
44
- .formSubHeader {
45
- @include type.type-style('heading-02');
46
- margin-top: layout.$spacing-05;
19
+ .tablet {
20
+ padding: layout.$spacing-06 layout.$spacing-05;
21
+ background-color: colors.$white;
47
22
  }
48
23
 
49
- .formGrid {
50
- margin: 0 layout.$spacing-05;
24
+ .desktop {
51
25
  padding: 0;
52
- flex-grow: 1;
26
+ padding: layout.$spacing-01 layout.$spacing-04;
53
27
  }
54
-
55
- .formAdmissionDatepicker input {
56
- min-width: 23rem;
28
+ .buttonContainer {
29
+ max-width: 50%;
30
+ }
31
+ .inlineLoading {
32
+ display: flex;
33
+ align-items: center;
34
+ gap: layout.$spacing-03;
35
+ }
36
+ .formDeathTimepickerSelector {
37
+ min-width: layout.$spacing-05;
38
+ margin-top: layout.$spacing-06;
57
39
  }
58
40
  .formAdmissionTimepicker input {
59
41
  min-width: 11rem;
60
42
  }
61
-
62
- .visitTypeOverviewWrapper {
63
- margin: layout.$spacing-05 0;
64
- border: 0.0625rem solid colors.$gray-30;
65
- }
66
-
67
- .visitTypeOverviewWrapper div:nth-child(3) > div:nth-child(2) {
68
- position: relative;
43
+ .formAdmissionDatepicker input {
44
+ min-width: 24rem;
69
45
  }
70
-
71
- .visitTypeOverviewWrapper div:nth-child(3) span * {
72
- display: none;
46
+ .dateTimeSection {
47
+ display: flex;
48
+ flex-direction: row;
49
+ gap: layout.$spacing-02;
50
+ align-items: center;
51
+ margin-top: layout.$spacing-02;
73
52
  }
74
53
 
75
54
  .radioButtonGroup {
@@ -86,19 +65,20 @@
86
65
  padding: layout.$spacing-02 layout.$spacing-05;
87
66
  margin: layout.$spacing-03 0;
88
67
  }
89
- .dateTimeSection {
90
- display: flex;
91
- flex-direction: row;
92
- gap: layout.$spacing-02;
93
- align-items: center;
68
+
69
+ .visitTypeOverviewWrapper {
70
+ margin: layout.$spacing-05 0;
71
+ border: 0.0625rem solid colors.$gray-30;
94
72
  }
95
- .formDeathTimepickerSelector {
96
- min-width: layout.$spacing-05;
97
- margin-top: layout.$spacing-06;
73
+
74
+ .visitTypeOverviewWrapper div:nth-child(3) > div:nth-child(2) {
75
+ position: relative;
98
76
  }
99
- .content {
100
- @include type.type-style('heading-compact-01');
101
- color: colors.$gray-30;
102
- margin-top: layout.$spacing-05;
103
- margin-bottom: layout.$spacing-03;
77
+
78
+ .visitTypeOverviewWrapper div:nth-child(3) span * {
79
+ display: none;
80
+ }
81
+
82
+ .sectionField {
83
+ padding-top: layout.$spacing-03;
104
84
  }