Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(refactor) Switch visit requests to use promises instead of observables #2073

Merged
merged 3 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/esm-patient-chart-app/src/offline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function setupOfflineVisitsSync() {
stopDatetime: new Date(),
};

const res = await saveVisit(visitPayload, options.abort).toPromise();
const res = await saveVisit(visitPayload, options.abort);
if (!res.ok) {
throw new Error(
`Failed to synchronize offline visit with the UUID: ${visit.uuid}. Error: ${JSON.stringify(res.data)}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,122 +474,120 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
? updateVisit(visitToEdit?.uuid, payload, abortController)
: saveVisit(payload, abortController)
)
.pipe(first())
.subscribe({
next: (response) => {
if (config.showServiceQueueFields && queueLocation && service && priority) {
// retrieve values from the queue extension
setVisitUuid(response.data.uuid);

saveQueueEntry(
response.data.uuid,
service,
patientUuid,
priority,
status,
sortWeight,
queueLocation,
visitQueueNumberAttributeUuid,
abortController,
).then(
({ status }) => {
.then((response) => {
if (config.showServiceQueueFields && queueLocation && service && priority) {
// retrieve values from the queue extension
setVisitUuid(response.data.uuid);

saveQueueEntry(
response.data.uuid,
service,
patientUuid,
priority,
status,
sortWeight,
queueLocation,
visitQueueNumberAttributeUuid,
abortController,
).then(
() => {
mutateCurrentVisit();
mutateVisits();
mutateInfiniteVisits();
mutateQueueEntry();
showSnackbar({
kind: 'success',
title: t('visitStarted', 'Visit started'),
subtitle: t('queueAddedSuccessfully', `Patient added to the queue successfully.`),
});
},
(error) => {
showSnackbar({
title: t('queueEntryError', 'Error adding patient to the queue'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
},
);

if (config.showUpcomingAppointments && upcomingAppointment) {
updateAppointmentStatus('CheckedIn', upcomingAppointment.uuid, abortController).then(
() => {
mutateCurrentVisit();
mutateVisits();
mutateInfiniteVisits();
Comment on lines 517 to 519
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make these 3 mutates outside of the if conditions since they are related to the core visit form itself?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vasharma05 Let's move that to it's own ticket.

mutateQueueEntry();
mutateAppointments();
showSnackbar({
isLowContrast: true,
kind: 'success',
title: t('visitStarted', 'Visit started'),
subtitle: t('queueAddedSuccessfully', `Patient added to the queue successfully.`),
subtitle: t('appointmentMarkedChecked', 'Appointment marked as Checked In'),
title: t('appointmentCheckedIn', 'Appointment Checked In'),
});
},
(error) => {
showSnackbar({
title: t('queueEntryError', 'Error adding patient to the queue'),
title: t('updateError', 'Error updating upcoming appointment'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
},
);

if (config.showUpcomingAppointments && upcomingAppointment) {
updateAppointmentStatus('CheckedIn', upcomingAppointment.uuid, abortController).then(
() => {
mutateCurrentVisit();
mutateVisits();
mutateInfiniteVisits();
mutateAppointments();
showSnackbar({
isLowContrast: true,
kind: 'success',
subtitle: t('appointmentMarkedChecked', 'Appointment marked as Checked In'),
title: t('appointmentCheckedIn', 'Appointment Checked In'),
});
},
(error) => {
showSnackbar({
title: t('updateError', 'Error updating upcoming appointment'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
},
);
}
}
}

from(handleVisitAttributes(visitAttributes, response.data.uuid))
.pipe(first())
.subscribe({
next: (attributesResponses) => {
setIsSubmitting(false);
// Check for no undefined,
// that if there was no failed requests on either creating, updating or deleting an attribute
// then continue and close workspace
if (!attributesResponses.includes(undefined)) {
mutateCurrentVisit();
mutateVisits();
mutateInfiniteVisits();
closeWorkspace({ ignoreChanges: true });
showSnackbar({
isLowContrast: true,
kind: 'success',
subtitle: !visitToEdit
? t('visitStartedSuccessfully', '{{visit}} started successfully', {
visit: response?.data?.visitType?.display ?? t('visit', 'Visit'),
})
: t('visitDetailsUpdatedSuccessfully', '{{visit}} updated successfully', {
visit: response?.data?.visitType?.display ?? t('pastVisit', 'Past visit'),
}),
title: !visitToEdit
? t('visitStarted', 'Visit started')
: t('visitDetailsUpdated', 'Visit details updated'),
});
}
},
error: (error) => {
// TODO: Refactor this to use Promises
from(handleVisitAttributes(visitAttributes, response.data.uuid))
.pipe(first())
.subscribe({
next: (attributesResponses) => {
setIsSubmitting(false);
// Check for no undefined,
// that if there was no failed requests on either creating, updating or deleting an attribute
// then continue and close workspace
if (!attributesResponses.includes(undefined)) {
mutateCurrentVisit();
mutateVisits();
mutateInfiniteVisits();
closeWorkspace({ ignoreChanges: true });
showSnackbar({
isLowContrast: true,
kind: 'success',
subtitle: !visitToEdit
? t('visitStartedSuccessfully', '{{visit}} started successfully', {
visit: response?.data?.visitType?.display ?? t('visit', 'Visit'),
})
: t('visitDetailsUpdatedSuccessfully', '{{visit}} updated successfully', {
visit: response?.data?.visitType?.display ?? t('pastVisit', 'Past visit'),
}),
title: !visitToEdit
? t('startVisitError', 'Error starting visit')
: t('errorUpdatingVisitDetails', 'Error updating visit details'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
? t('visitStarted', 'Visit started')
: t('visitDetailsUpdated', 'Visit details updated'),
});
},
});
},
error: (error) => {
showSnackbar({
title: !visitToEdit
? t('startVisitError', 'Error starting visit')
: t('errorUpdatingVisitDetails', 'Error updating visit details'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
}
},
error: (error) => {
showSnackbar({
title: !visitToEdit
? t('startVisitError', 'Error starting visit')
: t('errorUpdatingVisitDetails', 'Error updating visit details'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
},
});
},
})
.catch((error) => {
showSnackbar({
title: !visitToEdit
? t('startVisitError', 'Error starting visit')
: t('errorUpdatingVisitDetails', 'Error updating visit details'),
kind: 'error',
isLowContrast: false,
subtitle: error?.message,
});
});
} else {
createOfflineVisitForPatient(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import dayjs from 'dayjs';
import { of, throwError } from 'rxjs';
import { render, screen } from '@testing-library/react';
import { esmPatientChartSchema, type ChartConfig } from '../../config-schema';
import userEvent from '@testing-library/user-event';
Expand Down Expand Up @@ -256,16 +255,14 @@ describe('Visit form', () => {
it('starts a new visit upon successful submission of the form', async () => {
const user = userEvent.setup();

mockSaveVisit.mockReturnValue(
of({
status: 201,
data: {
visitType: {
display: 'Facility Visit',
},
mockSaveVisit.mockResolvedValue({
status: 201,
data: {
visitType: {
display: 'Facility Visit',
},
} as FetchResponse<{ visitType: { display: string } }>),
);
},
} as unknown as FetchResponse<Visit>);

renderVisitForm();

Expand Down Expand Up @@ -324,17 +321,15 @@ describe('Visit form', () => {
await user.clear(insuranceNumberInput);
await user.type(insuranceNumberInput, '183299');

mockSaveVisit.mockReturnValue(
of({
status: 201,
data: {
uuid: visitUuid,
visitType: {
display: 'Facility Visit',
},
mockSaveVisit.mockResolvedValue({
status: 201,
data: {
uuid: visitUuid,
visitType: {
display: 'Facility Visit',
},
} as FetchResponse<{ uuid: string; visitType: { display: string } }>),
);
},
} as unknown as FetchResponse<Visit>);

await user.click(saveButton);

Expand Down Expand Up @@ -394,17 +389,15 @@ describe('Visit form', () => {
await user.clear(insuranceNumberInput);
await user.type(insuranceNumberInput, '1873290');

mockUpdateVisit.mockReturnValue(
of({
status: 201,
data: {
uuid: visitUuid,
visitType: {
display: 'Facility Visit',
},
mockUpdateVisit.mockResolvedValue({
status: 201,
data: {
uuid: visitUuid,
visitType: {
display: 'Facility Visit',
},
}),
);
},
} as unknown as FetchResponse<Visit>);

await user.click(saveButton);

Expand Down Expand Up @@ -467,17 +460,15 @@ describe('Visit form', () => {
const insuranceNumberInput = screen.getByRole('textbox', { name: 'Insurance Policy Number (optional)' });
await user.clear(insuranceNumberInput);

mockUpdateVisit.mockReturnValue(
of({
status: 201,
data: {
uuid: visitUuid,
visitType: {
display: 'Facility Visit',
},
mockUpdateVisit.mockResolvedValue({
status: 201,
data: {
uuid: visitUuid,
visitType: {
display: 'Facility Visit',
},
}),
);
},
} as unknown as FetchResponse<Visit>);

await user.click(saveButton);

Expand Down Expand Up @@ -512,7 +503,8 @@ describe('Visit form', () => {

it('renders an error message if there was a problem starting a new visit', async () => {
const user = userEvent.setup();
mockSaveVisit.mockReturnValue(throwError(() => ({ status: 500, statusText: 'Internal server error' })));

mockSaveVisit.mockRejectedValue({ status: 500, statusText: 'Internal server error' });

renderVisitForm();

Expand Down Expand Up @@ -576,16 +568,14 @@ describe('Visit form', () => {
],
});

mockSaveVisit.mockReturnValue(
of({
status: 201,
data: {
visitType: {
display: 'Facility Visit',
},
mockSaveVisit.mockResolvedValue({
status: 201,
data: {
visitType: {
display: 'Facility Visit',
},
} as FetchResponse<{ visitType: { display: string } }>),
);
},
} as unknown as FetchResponse<Visit>);

renderVisitForm();

Expand Down
Loading