Skip to content

Commit

Permalink
(refactor) Switch visit requests to use promises instead of observabl…
Browse files Browse the repository at this point in the history
…es (#1353)
  • Loading branch information
denniskigen authored Oct 24, 2024
1 parent bd30184 commit c79b31f
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 284 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useVisit, updateVisit, parseDate, showSnackbar } from '@openmrs/esm-framework';
import { showSnackbar, updateVisit, useVisit } from '@openmrs/esm-framework';
import { Button, ModalBody, ModalFooter, ModalHeader } from '@carbon/react';
import { changeAppointmentStatus } from '../../patient-appointments/patient-appointments.resource';
import { useMutateAppointments } from '../../form/appointments-form.resource';
Expand All @@ -12,48 +12,43 @@ interface EndAppointmentModalProps {
}

const EndAppointmentModal: React.FC<EndAppointmentModalProps> = ({ patientUuid, appointmentUuid, closeModal }) => {
const { activeVisit, mutate } = useVisit(patientUuid);
const { t } = useTranslation();
const { activeVisit, mutate } = useVisit(patientUuid);
const { mutateAppointments } = useMutateAppointments();

const endAppointment = () => {
return changeAppointmentStatus('Completed', appointmentUuid)
const handleEndAppointment = useCallback(() => {
changeAppointmentStatus('Completed', appointmentUuid)
.then(() => {
mutateAppointments();
if (activeVisit) {
const abortController = new AbortController();
const endVisitPayload = {
location: activeVisit.location.uuid,
startDatetime: parseDate(activeVisit.startDatetime),
visitType: activeVisit.visitType.uuid,
stopDatetime: new Date(),
};
updateVisit(activeVisit.uuid, endVisitPayload, abortController)
.toPromise()
const endVisitPayload = { stopDatetime: new Date() };

return updateVisit(activeVisit.uuid, endVisitPayload, abortController)
.then(() => {
mutate();
showSnackbar({
title: t('appointmentEnded', 'Appointment ended'),
subtitle: t(
'appointmentEndedAndVisitClosedSuccessfully',
'Appointment successfully ended and visit successfully closed.',
'Appointment successfully ended and visit successfully closed',
),
isLowContrast: true,
kind: 'success',
});
closeModal();
mutate();
})
.catch((err) => {
closeModal();
.catch((error) => {
showSnackbar({
title: t('appointmentEndedButVisitNotClosedError', 'Appointment ended, but error closing visit'),
subtitle: err?.message,
title: t(
'appointmentEndedButVisitNotClosedError',
'Appointment ended successfully, but there was an error closing the visit.',
),
subtitle: error?.message,
kind: 'error',
isLowContrast: true,
});
});
} else {
closeModal();
showSnackbar({
title: t('appointmentEnded', 'Appointment ended'),
subtitle: t('appointmentEndedSuccessfully', 'Appointment successfully ended.'),
Expand All @@ -62,16 +57,18 @@ const EndAppointmentModal: React.FC<EndAppointmentModalProps> = ({ patientUuid,
});
}
})
.catch((err) => {
closeModal();
.catch((error) => {
showSnackbar({
title: t('appointmentEndError', 'Error ending appointment'),
subtitle: err?.message,
subtitle: error?.message,
kind: 'error',
isLowContrast: true,
});
})
.finally(() => {
closeModal();
});
};
}, [activeVisit, mutate, mutateAppointments, closeModal, patientUuid, appointmentUuid]);

return (
<div>
Expand All @@ -84,7 +81,7 @@ const EndAppointmentModal: React.FC<EndAppointmentModalProps> = ({ patientUuid,
{activeVisit
? t(
'endAppointmentAndVisitConfirmationMessage',
'Checking the patient out will mark the appointment as complete, and close out the active visit for this patient.',
'Checking the patient out will mark the appointment as complete and close out the active visit for this patient.',
)
: t('endAppointmentConfirmationMessage', 'Checking the patient out will mark the appointment as complete.')}
</p>
Expand All @@ -93,7 +90,7 @@ const EndAppointmentModal: React.FC<EndAppointmentModalProps> = ({ patientUuid,
<Button kind="secondary" onClick={closeModal}>
{t('cancel', 'Cancel')}
</Button>
<Button kind="danger" onClick={endAppointment}>
<Button kind="danger" onClick={handleEndAppointment}>
{t('checkOut', 'Check out')}
</Button>
</ModalFooter>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from 'react';
import { of } from 'rxjs';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { updateVisit, showSnackbar, useVisit, type VisitReturnType } from '@openmrs/esm-framework';
import {
updateVisit,
showSnackbar,
useVisit,
type VisitReturnType,
type FetchResponse,
type Visit,
} from '@openmrs/esm-framework';
import { changeAppointmentStatus } from '../../patient-appointments/patient-appointments.resource';
import EndAppointmentModal from './end-appointment.modal';

Expand All @@ -20,7 +26,7 @@ jest.mock('../../form/appointments-form.resource', () => ({

describe('EndAppointmentModal', () => {
beforeEach(() => {
mockUpdateVisit.mockImplementation(() => of({}));
mockUpdateVisit.mockResolvedValue({} as FetchResponse<Visit>);
});

it('has a cancel button that closes the modal', async () => {
Expand Down Expand Up @@ -73,7 +79,7 @@ describe('EndAppointmentModal', () => {
expect(closeModal).toHaveBeenCalled();
expect(showSnackbar).toHaveBeenCalledWith({
title: 'Appointment ended',
subtitle: 'Appointment successfully ended and visit successfully closed.',
subtitle: 'Appointment successfully ended and visit successfully closed',
isLowContrast: true,
kind: 'success',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ const AppointmentsForm: React.FC<AppointmentsFormProps> = ({
datePickerType="single"
dateFormat={datePickerFormat}
value={value}
maxDate={new Date()}
maxDate={new Date().toISOString()}
onChange={([date]) => onChange(date)}
invalid={!!fieldState?.error?.message}
invalidText={fieldState?.error?.message}>
Expand Down
2 changes: 1 addition & 1 deletion packages/esm-appointments-app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"appointmentEdited": "Appointment edited",
"appointmentEditError": "Error editing appointment",
"appointmentEnded": "Appointment ended",
"appointmentEndedAndVisitClosedSuccessfully": "Appointment successfully ended and visit successfully closed.",
"appointmentEndedAndVisitClosedSuccessfully": "Appointment successfully ended and visit successfully closed",
"appointmentEndedButVisitNotClosedError": "Appointment ended, but error closing visit",
"appointmentEndedSuccessfully": "Appointment successfully ended.",
"appointmentEndError": "Error ending appointment",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useCallback, useEffect, useState } from 'react';
import dayjs from 'dayjs';
import head from 'lodash-es/head';
import { first } from 'rxjs/operators';
import { useTranslation } from 'react-i18next';
import {
Button,
Expand Down Expand Up @@ -113,58 +112,50 @@ const ScheduledVisitsForVisitType: React.FC<{
const abortController = new AbortController();

saveVisit(payload, abortController)
.pipe(first())
.subscribe(
(response) => {
if (response.status === 201) {
postQueueEntry(
response.data.uuid,
patientId,
priority,
defaultStatus,
service,
appointment,
selectedQueueLocation,
visitQueueNumberAttributeUuid,
).then(
({ status }) => {
if (status === 201) {
showSnackbar({
kind: 'success',
title: t('startAVisit', 'Start a visit'),
subtitle: t(
'startVisitQueueSuccessfully',
'Patient has been added to active visits list and queue.',
`${hours} : ${minutes}`,
),
});
closeWorkspace();
setIsSubmitting(false);
mutateQueueEntries();
}
},
(error) => {
showSnackbar({
title: t('queueEntryError', 'Error adding patient to the queue'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
setIsSubmitting(false);
},
);
}
},
(error) => {
showSnackbar({
title: t('startVisitError', 'Error starting visit'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
.then((response) => {
postQueueEntry(
response.data.uuid,
patientId,
priority,
defaultStatus,
service,
appointment,
selectedQueueLocation,
visitQueueNumberAttributeUuid,
)
.then(() => {
showSnackbar({
kind: 'success',
title: t('startAVisit', 'Start a visit'),
subtitle: t(
'startVisitQueueSuccessfully',
'Patient has been added to active visits list and queue.',
`${hours} : ${minutes}`,
),
});
closeWorkspace();
setIsSubmitting(false);
mutateQueueEntries();
})
.catch((error) => {
showSnackbar({
title: t('queueEntryError', 'Error adding patient to the queue'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
setIsSubmitting(false);
});
setIsSubmitting(false);
},
);
})
.catch((error) => {
showSnackbar({
title: t('startVisitError', 'Error starting visit'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
setIsSubmitting(false);
});
}
},
[
Expand Down
Loading

0 comments on commit c79b31f

Please sign in to comment.