@kenyaemr/esm-shr-app 5.4.2-pre.2358 → 5.4.2-pre.2368

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.
@@ -1,202 +1,468 @@
1
- import React, { useState } from 'react';
1
+ import React, { useState, useEffect, useMemo } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
- import { Column, Form, Stack, Search, ButtonSet, ComboBox, Button, Tile, TextArea } from '@carbon/react';
4
- import { ExtensionSlot, showSnackbar, useSession } from '@openmrs/esm-framework';
3
+ import {
4
+ Column,
5
+ Form,
6
+ Stack,
7
+ Search,
8
+ ButtonSet,
9
+ ComboBox,
10
+ Button,
11
+ Tile,
12
+ TextArea,
13
+ InlineLoading,
14
+ Tag,
15
+ } from '@carbon/react';
16
+ import { ExtensionSlot, showSnackbar, useSession, useConfig, formatDate, formatDatetime } from '@openmrs/esm-framework';
17
+ import { z } from 'zod';
5
18
  import PatientInfo from './referral-patient-info.component';
6
19
  import styles from './referral.workspace.scss';
7
- import { useReason, useFacility, Concept, Facility } from './referral-workspace.resource';
20
+ import { Hospital, Close } from '@carbon/react/icons';
21
+ import {
22
+ useFacilities,
23
+ useReasons,
24
+ useSendReferralToArtDirectory,
25
+ useSystemSetting,
26
+ } from './referral-workspace.resource';
27
+ import usePatient from '../hooks/usePatient';
28
+ import { type Concept, type Facility, type ReferralPayload } from '../types';
29
+ import { FacilityReferralFormData, facilityReferralSchema, ValidationErrors } from '../schema';
30
+ import {
31
+ getPatientName,
32
+ getPatientGender,
33
+ getPatientIdentifiers,
34
+ formatBirthDate,
35
+ getPatientAddress,
36
+ getPatientDeathInfo,
37
+ getPhoneNumber,
38
+ } from '../utils/function';
8
39
 
9
- type FacilityReferralProp = {
40
+ interface FacilityReferralProps {
10
41
  closeWorkspace: () => void;
11
- };
42
+ patientUuid?: string;
43
+ }
12
44
 
13
- const FacilityReferralForm: React.FC<FacilityReferralProp> = ({ closeWorkspace }) => {
45
+ const FacilityReferralForm: React.FC<FacilityReferralProps> = ({ closeWorkspace, patientUuid: initialPatientUuid }) => {
14
46
  const { t } = useTranslation();
15
- const { user } = useSession();
16
- const [patientUuid, setPatientUuid] = useState('');
17
- const [patientSelected, setPatientSelected] = useState(false);
47
+ const { mflCodeValue } = useSystemSetting('facility.mflcode');
48
+ const { mutate: sendReferral } = useSendReferralToArtDirectory();
49
+
50
+ const sendingFacilityMflCode = mflCodeValue;
51
+
52
+ const [patientUuid, setPatientUuid] = useState(initialPatientUuid || '');
53
+ const [patientSelected, setPatientSelected] = useState(!!initialPatientUuid);
18
54
  const [reasonSearchTerm, setReasonSearchTerm] = useState('');
19
55
  const [facilitySearchTerm, setFacilitySearchTerm] = useState('');
20
56
  const [selectedReasons, setSelectedReasons] = useState<Concept[]>([]);
21
57
  const [selectedFacility, setSelectedFacility] = useState<Facility | null>(null);
22
58
  const [referralType, setReferralType] = useState('');
23
- const { data: reasons, error: reasonsError } = useReason(reasonSearchTerm);
24
- const { data: facilities, error: facilitiesError } = useFacility(facilitySearchTerm);
59
+ const [clinicalNotes, setClinicalNotes] = useState('');
60
+ const [isSubmitting, setIsSubmitting] = useState(false);
61
+ const [validationErrors, setValidationErrors] = useState<ValidationErrors>({});
62
+
63
+ const { data: reasons } = useReasons(reasonSearchTerm);
64
+ const { data: facilities } = useFacilities(facilitySearchTerm);
65
+ const { patient, isLoading: isLoadingPatient, error: patientError } = usePatient(patientUuid);
66
+
67
+ const getPatientIdentifier = (type: string) => {
68
+ if (!patient?.identifiers?.length) {
69
+ return '';
70
+ }
71
+
72
+ const identifier = patient.identifiers?.find((id) =>
73
+ id.identifierType?.name?.toLowerCase().includes(type.toLowerCase()),
74
+ );
25
75
 
26
- const onSubmit = async (data) => {
76
+ return identifier?.identifier || '';
77
+ };
78
+
79
+ const validateForm = (): boolean => {
27
80
  try {
81
+ const formData: FacilityReferralFormData = {
82
+ referralType,
83
+ patientUuid,
84
+ selectedFacility,
85
+ selectedReasons,
86
+ clinicalNotes,
87
+ };
88
+
89
+ facilityReferralSchema.parse(formData);
90
+ setValidationErrors({});
91
+ return true;
92
+ } catch (error) {
93
+ if (error instanceof z.ZodError) {
94
+ const errors: ValidationErrors = {};
95
+ error.errors.forEach((err) => {
96
+ const path = err.path[0] as keyof FacilityReferralFormData;
97
+ errors[path] = err.message;
98
+ });
99
+ setValidationErrors(errors);
100
+ }
101
+ return false;
102
+ }
103
+ };
104
+
105
+ const buildReferralPayload = (formData: FacilityReferralFormData): ReferralPayload => {
106
+ const receivingFacilityMflCode = selectedFacility.attributes?.[0]?.value || '';
107
+ const deathInfo = getPatientDeathInfo(patient);
108
+
109
+ return {
110
+ MESSAGE_HEADER: {
111
+ SENDING_APPLICATION: 'KENYAEMR',
112
+ SENDING_FACILITY: sendingFacilityMflCode || '18080',
113
+ RECEIVING_APPLICATION: 'IL',
114
+ RECEIVING_FACILITY: receivingFacilityMflCode || '11161',
115
+ MESSAGE_DATETIME: formatDatetime(new Date(), { mode: 'standard' }),
116
+ SECURITY: null,
117
+ MESSAGE_TYPE: 'SIU^S20',
118
+ PROCESSING_ID: 'P',
119
+ },
120
+ PATIENT_IDENTIFICATION: {
121
+ EXTERNAL_PATIENT_ID: {
122
+ ID: null,
123
+ IDENTIFIER_TYPE: 'GODS_NUMBER',
124
+ ASSIGNING_AUTHORITY: 'MPI',
125
+ },
126
+ INTERNAL_PATIENT_ID: getPatientIdentifiers(patient),
127
+ PATIENT_NAME: getPatientName(patient),
128
+ MOTHER_NAME: {
129
+ FIRST_NAME: null,
130
+ MIDDLE_NAME: null,
131
+ LAST_NAME: null,
132
+ },
133
+ DATE_OF_BIRTH: formatBirthDate(patient),
134
+ SEX: getPatientGender(patient),
135
+ PATIENT_ADDRESS: {
136
+ PHYSICAL_ADDRESS: getPatientAddress(patient),
137
+ POSTAL_ADDRESS: null,
138
+ },
139
+ PHONE_NUMBER: getPhoneNumber(patient),
140
+ MARITAL_STATUS: null,
141
+ DEATH_DATE: deathInfo.DEATH_DATE,
142
+ DEATH_INDICATOR: deathInfo.DEATH_INDICATOR,
143
+ DATE_OF_BIRTH_PRECISION: 'EXACT',
144
+ },
145
+ DISCONTINUATION_MESSAGE: {
146
+ DISCONTINUATION_REASON: 'TRANSFER OUT',
147
+ EFFECTIVE_DISCONTINUATION_DATE: formatDate(new Date(), { mode: 'standard' }),
148
+ TARGET_PROGRAM: 'HIV',
149
+ SERVICE_REQUEST: {
150
+ TRANSFER_STATUS: 'ACTIVE',
151
+ TRANSFER_INTENT: 'ORDER',
152
+ TRANSFER_PRIORITY: 'ASAP',
153
+ TRANSFER_OUT_DATE: formatDate(new Date(), { mode: 'standard' }),
154
+ TO_ACCEPTANCE_DATE: null,
155
+ SENDING_FACILITY_MFLCODE: sendingFacilityMflCode || '18080',
156
+ RECEIVING_FACILITY_MFLCODE: receivingFacilityMflCode || '11161',
157
+ SUPPORTING_INFO: formData.clinicalNotes || null,
158
+ },
159
+ },
160
+ };
161
+ };
162
+
163
+ const onSubmit = async (event: React.FormEvent) => {
164
+ event.preventDefault();
165
+
166
+ if (!validateForm()) {
167
+ showSnackbar({
168
+ kind: 'error',
169
+ title: t('validationError', 'Validation Error'),
170
+ subtitle: t('fixValidationErrors', 'Please fix the validation errors and try again'),
171
+ timeoutInMs: 4000,
172
+ });
173
+ return;
174
+ }
175
+
176
+ if (isLoadingPatient) {
177
+ showSnackbar({
178
+ kind: 'warning',
179
+ title: t('patientLoading', 'Patient Loading'),
180
+ subtitle: t('waitForPatientData', 'Please wait for patient data to load'),
181
+ timeoutInMs: 4000,
182
+ });
183
+ return;
184
+ }
185
+
186
+ if (!selectedFacility) {
187
+ showSnackbar({
188
+ kind: 'error',
189
+ title: t('facilityMissing', 'Facility Missing'),
190
+ subtitle: t('selectDestinationFacility', 'Please select a destination facility.'),
191
+ timeoutInMs: 4000,
192
+ });
193
+ return;
194
+ }
195
+
196
+ const hasMinimumPatientData = patientSelected && !!patientUuid;
197
+
198
+ if (!hasMinimumPatientData) {
199
+ showSnackbar({
200
+ kind: 'error',
201
+ title: t('patientDataMissing', 'Patient Data Missing'),
202
+ subtitle: t(
203
+ 'patientDataNotLoaded',
204
+ 'Patient data could not be loaded. Please try selecting the patient again.',
205
+ ),
206
+ timeoutInMs: 4000,
207
+ });
208
+ return;
209
+ }
210
+
211
+ setIsSubmitting(true);
212
+
213
+ try {
214
+ const formData: FacilityReferralFormData = {
215
+ referralType,
216
+ patientUuid,
217
+ selectedFacility,
218
+ selectedReasons,
219
+ clinicalNotes,
220
+ };
221
+
222
+ const payload = buildReferralPayload(formData);
223
+ await sendReferral(payload);
224
+
28
225
  showSnackbar({
29
226
  kind: 'success',
30
- title: t('referSuccess', 'Facility Referral'),
31
- subtitle: t('facilityRefer', 'Patient referred successfully'),
32
- timeoutInMs: 3000,
33
- isLowContrast: true,
227
+ title: t('referSuccess', 'Referral Successful'),
228
+ subtitle: t('facilityReferSuccess', `Patient successfully referred to ${selectedFacility?.name}`),
229
+ timeoutInMs: 5000,
34
230
  });
231
+
35
232
  closeWorkspace();
36
- } catch (err) {
37
- console.error(err);
233
+ } catch (error) {
38
234
  showSnackbar({
39
235
  kind: 'error',
40
- title: t('referError', 'Facility Referral Error'),
41
- subtitle: t('RlshipError', 'Referral request Failed.......'),
42
- timeoutInMs: 2500,
43
- isLowContrast: true,
236
+ title: t('referError', 'Referral Failed'),
237
+ subtitle: t('referErrorDetails', error.message || 'An unexpected error occurred'),
238
+ timeoutInMs: 6000,
44
239
  });
240
+ } finally {
241
+ setIsSubmitting(false);
45
242
  }
46
243
  };
47
244
 
48
- const selectPatient = (patientUuid) => {
49
- setPatientUuid(patientUuid);
245
+ const selectPatient = (selectedPatientUuid: string) => {
246
+ setPatientUuid(selectedPatientUuid);
50
247
  setPatientSelected(true);
51
- };
52
248
 
53
- const handleReasonSearchChange = (e) => {
54
- setReasonSearchTerm(e.target.value);
249
+ if (validationErrors.patientUuid) {
250
+ setValidationErrors((prev) => ({ ...prev, patientUuid: undefined }));
251
+ }
55
252
  };
56
253
 
57
- const handleFacilitySearchChange = (e) => {
58
- setFacilitySearchTerm(e.target.value);
59
- };
254
+ const handleReasonSelect = (reason: Concept) => {
255
+ if (!selectedReasons.some((r) => r.uuid === reason.uuid)) {
256
+ const newReasons = [...selectedReasons, reason];
257
+ setSelectedReasons(newReasons);
258
+ setReasonSearchTerm('');
60
259
 
61
- const handleReasonSelect = (reason) => {
62
- if (!selectedReasons.find((r) => r.uuid === reason.uuid)) {
63
- setSelectedReasons([...selectedReasons, reason]);
260
+ if (validationErrors.selectedReasons) {
261
+ setValidationErrors((prev) => ({ ...prev, selectedReasons: undefined }));
262
+ }
64
263
  }
65
264
  };
66
265
 
67
- const handleFacilitySelect = (facility) => {
266
+ const handleFacilitySelect = (facility: Facility) => {
68
267
  setSelectedFacility(facility);
69
268
  setFacilitySearchTerm('');
269
+
270
+ if (validationErrors.selectedFacility) {
271
+ setValidationErrors((prev) => ({ ...prev, selectedFacility: undefined }));
272
+ }
70
273
  };
71
274
 
72
- const handleRemoveReason = (uuid) => {
275
+ const handleRemoveReason = (uuid: string) => {
73
276
  setSelectedReasons(selectedReasons.filter((reason) => reason.uuid !== uuid));
74
277
  };
75
278
 
76
- const handleRemoveFacility = () => {
77
- setSelectedFacility(null);
78
- };
279
+ const isFormValid = useMemo(() => {
280
+ const checks = {
281
+ hasReferralType: !!referralType,
282
+ hasPatientUuid: !!patientUuid,
283
+ hasFacility: !!selectedFacility,
284
+ hasReasons: selectedReasons.length > 0,
285
+ hasNotes: clinicalNotes.length >= 10,
286
+ patientSelectedCorrectly: patientSelected && !!patientUuid,
287
+ notLoadingPatient: !isLoadingPatient,
288
+ noPatientError: !patientError,
289
+ };
79
290
 
80
- const handleReferralTypeChange = (e) => {
81
- setReferralType(e.selectedItem);
82
- };
291
+ return Object.values(checks).every(Boolean);
292
+ }, [
293
+ referralType,
294
+ patientUuid,
295
+ selectedFacility,
296
+ selectedReasons,
297
+ clinicalNotes,
298
+ patientSelected,
299
+ isLoadingPatient,
300
+ patientError,
301
+ ]);
83
302
 
84
303
  return (
85
304
  <Form className={styles.form} onSubmit={onSubmit}>
86
- <span className={styles.formTitle}>{t('formTitle', 'Fill in the form details')}</span>
87
305
  <Stack gap={4} className={styles.grid}>
88
- <span className={styles.sectionHeader}>Select referral type</span>
306
+ <h3 className={styles.formTitle}>{t('facilityReferral', 'Facility Referral')}</h3>
307
+
89
308
  <Column>
90
309
  <ComboBox
91
- id="select-referral-type"
92
- placeholder="Select referral type"
310
+ id="referral-type"
311
+ titleText={t('referralType', 'Referral Type')}
93
312
  items={['Facility to Facility']}
94
- onChange={handleReferralTypeChange}
313
+ onChange={({ selectedItem }) => {
314
+ setReferralType(selectedItem);
315
+ }}
316
+ placeholder={t('selectReferralType', 'Select referral type')}
317
+ selectedItem={referralType}
318
+ invalid={!!validationErrors.referralType}
319
+ invalidText={validationErrors.referralType}
95
320
  />
96
321
  </Column>
97
322
 
98
- {referralType === 'Facility to Facility' && (
323
+ {referralType && (
99
324
  <>
100
- <span className={styles.sectionHeader}>Search for facility to refer to</span>
101
325
  <Column>
102
- {!selectedFacility && (
103
- <Search
104
- size="lg"
105
- placeholder="Facility to refer patient to"
106
- labelText="Search"
107
- closeButtonLabelText="Clear"
108
- id="facility-search"
109
- value={facilitySearchTerm}
110
- onChange={handleFacilitySearchChange}
326
+ <h4 className={styles.sectionHeader}>{t('destinationFacility', 'Destination Facility')}</h4>
327
+ {!selectedFacility ? (
328
+ <>
329
+ <Search
330
+ size="lg"
331
+ placeholder={t('searchFacility', 'Search for facility')}
332
+ labelText={t('search', 'Search')}
333
+ value={facilitySearchTerm}
334
+ onChange={(e) => {
335
+ const value = e.target.value;
336
+ setFacilitySearchTerm(value);
337
+ }}
338
+ />
339
+ {facilitySearchTerm && facilities?.length > 0 && (
340
+ <div className={styles.searchResults}>
341
+ {facilities.map((facility) => (
342
+ <Tile
343
+ key={facility.uuid}
344
+ className={styles.resultTile}
345
+ onClick={() => handleFacilitySelect(facility)}>
346
+ <div className={styles.tileContent}>
347
+ <Hospital size={20} className={styles.illustrationPictogram} />
348
+ <div className={styles.facilityInfo}>
349
+ <strong>{facility.name}</strong>
350
+ <div>MFL: {facility.attributes?.[0]?.value || 'N/A'}</div>
351
+ </div>
352
+ </div>
353
+ </Tile>
354
+ ))}
355
+ </div>
356
+ )}
357
+ </>
358
+ ) : (
359
+ <Tile className={styles.selectedItem}>
360
+ <div className={styles.tileContent}>
361
+ <Hospital size={20} className={styles.illustrationPictogram} />
362
+ <div className={styles.facilityInfo}>
363
+ <strong>{selectedFacility.name}</strong>
364
+ <div>MFL: {selectedFacility.attributes?.[0]?.value || 'N/A'}</div>
365
+ </div>
366
+ <Button
367
+ hasIconOnly
368
+ renderIcon={Close}
369
+ iconDescription={t('remove', 'Remove')}
370
+ kind="ghost"
371
+ onClick={() => {
372
+ setSelectedFacility(null);
373
+ }}
374
+ />
375
+ </div>
376
+ </Tile>
377
+ )}
378
+ {validationErrors.selectedFacility && (
379
+ <div className={styles.errorMessage}>{validationErrors.selectedFacility}</div>
380
+ )}
381
+ </Column>
382
+
383
+ <Column>
384
+ <h4 className={styles.sectionHeader}>{t('patient', 'Patient')}</h4>
385
+ {patientSelected && patientUuid ? (
386
+ <PatientInfo patientUuid={patientUuid} />
387
+ ) : (
388
+ <ExtensionSlot
389
+ name="patient-search-bar-slot"
390
+ state={{
391
+ selectPatientAction: selectPatient,
392
+ buttonProps: { kind: 'primary' },
393
+ }}
111
394
  />
112
395
  )}
113
- {facilitySearchTerm && facilities && (
114
- <div className={styles.facilityList}>
115
- {facilities.map((facility) => (
116
- <Tile
117
- key={facility.uuid}
118
- className={styles.facilityTile}
119
- onClick={() => handleFacilitySelect(facility)}
120
- role="button"
121
- tabIndex={0}>
122
- {facility.name} - {facility.attributes[0]?.value}
396
+ {validationErrors.patientUuid && (
397
+ <div className={styles.errorMessage}>{validationErrors.patientUuid}</div>
398
+ )}
399
+ </Column>
400
+
401
+ <Column>
402
+ <h4 className={styles.sectionHeader}>{t('referralReasons', 'Referral Reasons')}</h4>
403
+ <Search
404
+ size="lg"
405
+ placeholder={t('searchReasons', 'Search for referral reasons')}
406
+ labelText={t('search', 'Search')}
407
+ value={reasonSearchTerm}
408
+ onChange={(e) => {
409
+ const value = e.target.value;
410
+ setReasonSearchTerm(value);
411
+ }}
412
+ />
413
+ {reasonSearchTerm && reasons?.length > 0 && (
414
+ <div className={styles.searchResults}>
415
+ {reasons.map((reason) => (
416
+ <Tile key={reason.uuid} className={styles.resultTile} onClick={() => handleReasonSelect(reason)}>
417
+ {reason.name.name}
123
418
  </Tile>
124
419
  ))}
125
420
  </div>
126
421
  )}
127
- {selectedFacility && (
128
- <Tile key={selectedFacility.uuid} className={styles.facilityTile} onClick={handleRemoveFacility}>
129
- {selectedFacility.name} - {selectedFacility.attributes[0].value}
130
- </Tile>
422
+ {selectedReasons.length > 0 && (
423
+ <div className={styles.selectedItems}>
424
+ {selectedReasons.map((reason) => (
425
+ <Tag key={reason.uuid} size="lg" type="gray" filter onClose={() => handleRemoveReason(reason.uuid)}>
426
+ {reason.name.name}
427
+ </Tag>
428
+ ))}
429
+ </div>
131
430
  )}
431
+ {validationErrors.selectedReasons && (
432
+ <div className={styles.errorMessage}>{validationErrors.selectedReasons}</div>
433
+ )}
434
+ </Column>
435
+ <Column>
436
+ <h4 className={styles.sectionHeader}>{t('clinicalNotes', 'Clinical Notes')}</h4>
437
+ <TextArea
438
+ labelText={t('clinicalNotes', 'Clinical Notes')}
439
+ rows={4}
440
+ value={clinicalNotes}
441
+ onChange={(e) => {
442
+ const value = e.target.value;
443
+ setClinicalNotes(value);
444
+
445
+ if (validationErrors.clinicalNotes) {
446
+ setValidationErrors((prev) => ({ ...prev, clinicalNotes: undefined }));
447
+ }
448
+ }}
449
+ invalid={!!validationErrors.clinicalNotes}
450
+ invalidText={validationErrors.clinicalNotes}
451
+ />
132
452
  </Column>
133
453
  </>
134
454
  )}
135
- <span className={styles.sectionHeader}>Search for patient</span>
136
- {patientSelected && <PatientInfo patientUuid={patientUuid} />}
137
- {!patientSelected && (
138
- <Column>
139
- <ExtensionSlot
140
- name="patient-search-bar-slot"
141
- state={{
142
- selectPatientAction: selectPatient,
143
- buttonProps: {
144
- kind: 'primary',
145
- },
146
- }}
147
- />
148
- </Column>
149
- )}
150
- <span className={styles.sectionHeader}>Search for referral reasons</span>
151
- <Column>
152
- <Search
153
- size="lg"
154
- placeholder="Search for reasons for referral"
155
- labelText="Search"
156
- closeButtonLabelText="Clear reason"
157
- id="reason-for-referral"
158
- value={reasonSearchTerm}
159
- onChange={handleReasonSearchChange}
160
- />
161
- {reasonSearchTerm && reasons && (
162
- <div className={styles.reasonList}>
163
- {reasons.map((reason) => (
164
- <Tile
165
- key={reason.uuid}
166
- className={styles.reasonTile}
167
- onClick={() => handleReasonSelect(reason)}
168
- role="button"
169
- tabIndex={0}>
170
- {reason.name.name}
171
- </Tile>
172
- ))}
173
- </div>
174
- )}
175
- </Column>
176
- {selectedReasons.length > 0 && (
177
- <Column className={styles.textbox}>
178
- <span className={styles.sectionHeader}>Selected Reasons</span>
179
- <div className={styles.selectedReasons}>
180
- {selectedReasons.map((reason) => (
181
- <Tile key={reason.uuid} className={styles.reasonTile} onClick={() => handleRemoveReason(reason.uuid)}>
182
- {reason.name.name}
183
- </Tile>
184
- ))}
185
- </div>
186
- </Column>
187
- )}
188
- <span className={styles.sectionHeader}>Clinical Notes</span>
189
- <Column>
190
- <TextArea labelText={t('reason', 'Reason')} rows={4} id="text-area-1" className={styles.reasonTextbox} />
191
- </Column>
192
455
  </Stack>
193
-
194
456
  <ButtonSet className={styles.buttonSet}>
195
- <Button className={styles.button} kind="secondary" onClick={closeWorkspace}>
196
- {t('discard', 'Discard')}
457
+ <Button kind="secondary" onClick={closeWorkspace} disabled={isSubmitting}>
458
+ {t('cancel', 'Cancel')}
197
459
  </Button>
198
- <Button className={styles.button} kind="primary" type="submit" disabled={!patientSelected}>
199
- {t('refer', 'Refer Patient')}
460
+ <Button kind="primary" type="submit" disabled={isSubmitting || !isFormValid || isLoadingPatient}>
461
+ {isSubmitting ? (
462
+ <InlineLoading description={t('submitting', 'Submitting...')} />
463
+ ) : (
464
+ t('submitReferral', 'Submit Referral')
465
+ )}
200
466
  </Button>
201
467
  </ButtonSet>
202
468
  </Form>