From 012557959f4b0c7e62cae25f43ede31eb1b91545 Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Fri, 2 Feb 2024 09:22:13 -0500 Subject: [PATCH 1/4] O3-2812: Appointments: Refactoring and Code Cleanup --- .../calendar-patient-list.component.tsx | 2 +- .../src/appointments.component.tsx | 4 +- .../appointments-table.resource.ts | 43 ----------- .../appointments/appointments.resources.ts | 74 ------------------- .../src/hooks/useAppointments.ts | 25 +++++++ .../visit-form/visit-form.component.tsx | 2 +- .../src/root.component.tsx | 4 +- 7 files changed, 31 insertions(+), 123 deletions(-) delete mode 100644 packages/esm-appointments-app/src/appointments/appointments-table.resource.ts delete mode 100644 packages/esm-appointments-app/src/appointments/appointments.resources.ts diff --git a/packages/esm-appointments-app/src/appointments-calendar/patient-list/calendar-patient-list.component.tsx b/packages/esm-appointments-app/src/appointments-calendar/patient-list/calendar-patient-list.component.tsx index 17c522b97..ab077ddc7 100644 --- a/packages/esm-appointments-app/src/appointments-calendar/patient-list/calendar-patient-list.component.tsx +++ b/packages/esm-appointments-app/src/appointments-calendar/patient-list/calendar-patient-list.component.tsx @@ -21,7 +21,7 @@ import { ExtensionSlot, formatDate, formatDatetime } from '@openmrs/esm-framewor import { downloadAppointmentsAsExcel } from '../../helpers/excel'; import { Download } from '@carbon/react/icons'; import styles from './calenar-patient-list.scss'; -import { useAppointments } from '../../appointments/appointments-table.resource'; +import { useAppointments } from '../../hooks/useAppointments'; interface CalendarPatientListProps {} diff --git a/packages/esm-appointments-app/src/appointments.component.tsx b/packages/esm-appointments-app/src/appointments.component.tsx index b32573ff2..3f9127ede 100644 --- a/packages/esm-appointments-app/src/appointments.component.tsx +++ b/packages/esm-appointments-app/src/appointments.component.tsx @@ -5,7 +5,7 @@ import AppointmentsHeader from './appointments-header/appointments-header.compon import AppointmentMetrics from './appointments-metrics/appointments-metrics.component'; import Overlay from './overlay.component'; -const ClinicalAppointments: React.FC = () => { +const Appointments: React.FC = () => { const { t } = useTranslation(); const [appointmentServiceType, setAppointmentServiceType] = useState(''); @@ -19,4 +19,4 @@ const ClinicalAppointments: React.FC = () => { ); }; -export default ClinicalAppointments; +export default Appointments; diff --git a/packages/esm-appointments-app/src/appointments/appointments-table.resource.ts b/packages/esm-appointments-app/src/appointments/appointments-table.resource.ts deleted file mode 100644 index cd940f582..000000000 --- a/packages/esm-appointments-app/src/appointments/appointments-table.resource.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { useMemo } from 'react'; -import useSWR from 'swr'; -import { openmrsFetch } from '@openmrs/esm-framework'; -import { AppointmentService, Appointment } from '../types'; -import { getAppointment, useAppointmentDate } from '../helpers'; -import isEmpty from 'lodash-es/isEmpty'; - -export function useAppointments(status?: string, forDate?: string) { - const { currentAppointmentDate } = useAppointmentDate(); - const startDate = forDate ? forDate : currentAppointmentDate; - const apiUrl = `/ws/rest/v1/appointment/appointmentStatus?forDate=${startDate}&status=${status}`; - const allAppointmentsUrl = `/ws/rest/v1/appointment/all?forDate=${startDate}`; - - const { data, error, isLoading, isValidating, mutate } = useSWR<{ data: Array }, Error>( - isEmpty(status) ? allAppointmentsUrl : apiUrl, - openmrsFetch, - ); - - const appointments = useMemo(() => data?.data?.map((appointment) => getAppointment(appointment)) ?? [], [data?.data]); - - return { - appointments, - isLoading, - isError: error, - isValidating, - mutate, - }; -} - -export function useServices() { - const apiUrl = `/ws/rest/v1/appointmentService/all/default`; - const { data, error, isLoading, isValidating } = useSWR<{ data: Array }, Error>( - apiUrl, - openmrsFetch, - ); - - return { - services: data ? data.data : [], - isLoading, - isError: error, - isValidating, - }; -} diff --git a/packages/esm-appointments-app/src/appointments/appointments.resources.ts b/packages/esm-appointments-app/src/appointments/appointments.resources.ts deleted file mode 100644 index 5afcf8883..000000000 --- a/packages/esm-appointments-app/src/appointments/appointments.resources.ts +++ /dev/null @@ -1,74 +0,0 @@ -import useSWR from 'swr'; -import { openmrsFetch } from '@openmrs/esm-framework'; -import { AppointmentService, AppointmentsFetchResponse, Provider } from '../types'; - -export const appointmentsSearchUrl = `/ws/rest/v1/appointments/search`; - -export function useAppointments(patientUuid: string, startDate: string) { - const abortController = new AbortController(); - /* - SWR isn't meant to make POST requests for data fetching. This is a consequence of the API only exposing this resource via POST. - This works but likely isn't recommended. - */ - const fetcher = () => - openmrsFetch(appointmentsSearchUrl, { - method: 'POST', - signal: abortController.signal, - headers: { - 'Content-Type': 'application/json', - }, - body: { - patientUuid: patientUuid, - startDate: startDate, - }, - }); - - const { data, error, isLoading, isValidating } = useSWR( - appointmentsSearchUrl, - fetcher, - ); - - const appointments = data?.data?.length - ? data.data.sort((a, b) => (b.startDateTime > a.startDateTime ? 1 : -1)) - : null; - - return { - data: data ? appointments : null, - isError: error, - isLoading, - isValidating, - }; -} - -export function useAppointmentService() { - const { data, error, isLoading } = useSWR<{ data: Array }, Error>( - `/ws/rest/v1/appointmentService/all/full`, - openmrsFetch, - ); - - return { - data: data ? data.data : null, - isError: error, - isLoading, - }; -} - -export function getAppointmentsByUuid(appointmentUuid: string) { - const abortController = new AbortController(); - - return openmrsFetch(`/ws/rest/v1/appointments/${appointmentUuid}`, { - signal: abortController.signal, - }); -} - -export function getAppointmentService(uuid) { - const abortController = new AbortController(); - - return openmrsFetch(`/ws/rest/v1/appointmentService?uuid=` + uuid, { - signal: abortController.signal, - }); -} - -export function getTimeSlots() { - //https://openmrs-spa.org/openmrs/ws/rest/v1/appointment/all?forDate=2020-03-02T21:00:00.000Z -} diff --git a/packages/esm-appointments-app/src/hooks/useAppointments.ts b/packages/esm-appointments-app/src/hooks/useAppointments.ts index 183d969ef..f95efd154 100644 --- a/packages/esm-appointments-app/src/hooks/useAppointments.ts +++ b/packages/esm-appointments-app/src/hooks/useAppointments.ts @@ -3,6 +3,9 @@ import dayjs from 'dayjs'; import useSWR from 'swr'; import { omrsDateFormat } from '../constants'; import { type Appointment, DurationPeriod } from '../types'; +import { getAppointment, useAppointmentDate } from '../helpers'; +import isEmpty from 'lodash-es/isEmpty'; +import { useMemo } from 'react'; interface AppointmentsReturnType { isLoading: boolean; @@ -10,6 +13,28 @@ interface AppointmentsReturnType { error: Error; } +export function useAppointments(status?: string, forDate?: string) { + const { currentAppointmentDate } = useAppointmentDate(); + const startDate = forDate ? forDate : currentAppointmentDate; + const apiUrl = `/ws/rest/v1/appointment/appointmentStatus?forDate=${startDate}&status=${status}`; + const allAppointmentsUrl = `/ws/rest/v1/appointment/all?forDate=${startDate}`; + + const { data, error, isLoading, isValidating, mutate } = useSWR<{ data: Array }, Error>( + isEmpty(status) ? allAppointmentsUrl : apiUrl, + openmrsFetch, + ); + + const appointments = useMemo(() => data?.data?.map((appointment) => getAppointment(appointment)) ?? [], [data?.data]); + + return { + appointments, + isLoading, + isError: error, + isValidating, + mutate, + }; +} + export const useDailyAppointments = (startDateTime: string, durationPeriod: DurationPeriod) => { const url = `/ws/rest/v1/appointment/all?forDate=${startDateTime}`; const { data, error, isLoading } = useSWR<{ data: Array }>(startDateTime ? url : null, openmrsFetch); diff --git a/packages/esm-appointments-app/src/patient-queue/visit-form/visit-form.component.tsx b/packages/esm-appointments-app/src/patient-queue/visit-form/visit-form.component.tsx index 5246cede6..912c059b8 100644 --- a/packages/esm-appointments-app/src/patient-queue/visit-form/visit-form.component.tsx +++ b/packages/esm-appointments-app/src/patient-queue/visit-form/visit-form.component.tsx @@ -38,7 +38,7 @@ import { type amPm, convertTime12to24, useAppointmentDate } from '../../helpers' import { closeOverlay } from '../../hooks/useOverlay'; import { saveQueueEntry } from './queue.resource'; import { type MappedAppointment } from '../../types'; -import { useAppointments } from '../../appointments/appointments-table.resource'; +import { useAppointments } from '../../hooks/useAppointments'; import { useDefaultLoginLocation } from '../../hooks/useDefaultLocation'; import { useVisits } from '../../hooks/useVisits'; import styles from './visit-form.scss'; diff --git a/packages/esm-appointments-app/src/root.component.tsx b/packages/esm-appointments-app/src/root.component.tsx index 2a80fc614..0983c75bd 100644 --- a/packages/esm-appointments-app/src/root.component.tsx +++ b/packages/esm-appointments-app/src/root.component.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { SWRConfig } from 'swr'; import { BrowserRouter, Route, Routes } from 'react-router-dom'; import AppointmentsCalendarView from './appointments-calendar/appointments-calendar-view.component'; -import ClinicalAppointments from './appointments.component'; +import Appointments from './appointments.component'; import CalendarPatientList from './appointments-calendar/patient-list/calendar-patient-list.component'; const swrConfiguration = { @@ -17,7 +17,7 @@ const RootComponent: React.FC = () => { - } /> + } /> } /> } /> From f8d30acca0c351143aa29287c330b1c2aecc51c3 Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Fri, 2 Feb 2024 10:00:16 -0500 Subject: [PATCH 2/4] O3-2812: Appointments: Refactoring and Code Cleanup --- .../src/appointments/forms/forms.resource.ts | 12 +++--------- .../appointments-list.component.tsx | 2 +- .../src/home-appointments/appointments-list.test.tsx | 2 +- .../check-in-modal/check-in-modal.component.tsx | 2 +- .../check-in-modal/check-in-modal.test.tsx | 2 +- .../src/home-appointments/common.ts | 2 +- ...ble.resource.ts => home-appointments.resource.ts} | 0 7 files changed, 8 insertions(+), 14 deletions(-) rename packages/esm-appointments-app/src/home-appointments/{appointments-table.resource.ts => home-appointments.resource.ts} (100%) diff --git a/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts b/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts index 5084a109b..e1bf2d9dc 100644 --- a/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts +++ b/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts @@ -22,15 +22,6 @@ export function useServices() { isValidating, }; } - -export function getAppointmentService(uuid: string) { - const abortController = new AbortController(); - - return openmrsFetch(`/ws/rest/v1/appointmentService?uuid=` + uuid, { - signal: abortController.signal, - }); -} - export function useProviders() { const { data, error, isLoading } = useSWR<{ data: { results: Array } }, Error>( `/ws/rest/v1/provider`, @@ -86,6 +77,9 @@ export const useAppointmentSummary = (fromDate: Date, serviceUuid: string): Arra })) .sort((dateA, dateB) => new Date(dateA.date).getTime() - new Date(dateB.date).getTime()); }; + + +// NOTE: I don't think this is used anywhere? export const checkAppointmentConflict = async (appointmentPayload: AppointmentPayload) => { return await openmrsFetch('/ws/rest/v1/appointments/conflicts', { method: 'POST', diff --git a/packages/esm-appointments-app/src/home-appointments/appointments-list.component.tsx b/packages/esm-appointments-app/src/home-appointments/appointments-list.component.tsx index 572d1e439..21b28b783 100644 --- a/packages/esm-appointments-app/src/home-appointments/appointments-list.component.tsx +++ b/packages/esm-appointments-app/src/home-appointments/appointments-list.component.tsx @@ -32,7 +32,7 @@ import { EmptyDataIllustration } from './empty-data-illustration.component'; import { launchCheckInAppointmentModal, handleComplete } from './common'; import { SeeAllAppointmentsLink, AddAppointmentLink, ViewCalendarLink } from './links.component'; import { type Appointment, type MappedHomeAppointment } from '../types'; -import { useTodaysAppointments } from './appointments-table.resource'; +import { useTodaysAppointments } from './home-appointments.resource'; import styles from './appointments-list.scss'; import { type ConfigObject } from '../config-schema'; diff --git a/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx b/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx index 1f7d69769..cce07cb94 100644 --- a/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx +++ b/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { mockSession } from '__mocks__'; import { usePagination } from '@openmrs/esm-framework'; -import { useTodaysAppointments } from './appointments-table.resource'; +import { useTodaysAppointments } from './home-appointments.resource'; import AppointmentsBaseTable from './appointments-list.component'; const useTodaysAppointmentsMock = useTodaysAppointments as jest.Mock; diff --git a/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.component.tsx b/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.component.tsx index 0ab5546b8..597e25548 100644 --- a/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.component.tsx +++ b/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.component.tsx @@ -4,7 +4,7 @@ import { Button, Layer, ModalBody, ModalFooter, ModalHeader, TimePicker } from ' import { useSWRConfig } from 'swr'; import { useTranslation } from 'react-i18next'; import { showNotification, showActionableNotification } from '@openmrs/esm-framework'; -import { updateAppointmentStatus } from '../appointments-table.resource'; +import { updateAppointmentStatus } from '../home-appointments.resource'; import { handleUndoAction } from '../common'; import styles from './check-in-modal.scss'; diff --git a/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx b/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx index e56353a27..48dbe8b8d 100644 --- a/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx +++ b/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import { render, screen } from '@testing-library/react'; -import { updateAppointmentStatus } from '../appointments-table.resource'; +import { updateAppointmentStatus } from '../home-appointments.resource'; import { showActionableNotification, showNotification } from '@openmrs/esm-framework'; import CheckInAppointmentModal from './check-in-modal.component'; diff --git a/packages/esm-appointments-app/src/home-appointments/common.ts b/packages/esm-appointments-app/src/home-appointments/common.ts index c02edfecb..6d020d8fd 100644 --- a/packages/esm-appointments-app/src/home-appointments/common.ts +++ b/packages/esm-appointments-app/src/home-appointments/common.ts @@ -1,5 +1,5 @@ import { showModal, showNotification, showActionableNotification } from '@openmrs/esm-framework'; -import { updateAppointmentStatus, undoAppointmentStatus } from './appointments-table.resource'; +import { updateAppointmentStatus, undoAppointmentStatus } from './home-appointments.resource'; export const launchCheckInAppointmentModal = (appointmentUuid: string) => { const dispose = showModal('check-in-appointment-modal', { diff --git a/packages/esm-appointments-app/src/home-appointments/appointments-table.resource.ts b/packages/esm-appointments-app/src/home-appointments/home-appointments.resource.ts similarity index 100% rename from packages/esm-appointments-app/src/home-appointments/appointments-table.resource.ts rename to packages/esm-appointments-app/src/home-appointments/home-appointments.resource.ts From 89d1cc7659d8c50500b2ee274457c9e73d4d6d28 Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Fri, 2 Feb 2024 10:06:23 -0500 Subject: [PATCH 3/4] O3-2812: Appointments: Refactoring and Code Cleanup --- .../src/appointments/forms/forms.resource.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts b/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts index e1bf2d9dc..5f3172e65 100644 --- a/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts +++ b/packages/esm-appointments-app/src/appointments/forms/forms.resource.ts @@ -78,7 +78,6 @@ export const useAppointmentSummary = (fromDate: Date, serviceUuid: string): Arra .sort((dateA, dateB) => new Date(dateA.date).getTime() - new Date(dateB.date).getTime()); }; - // NOTE: I don't think this is used anywhere? export const checkAppointmentConflict = async (appointmentPayload: AppointmentPayload) => { return await openmrsFetch('/ws/rest/v1/appointments/conflicts', { From 3db2c574dc84f42d89e0b5bebb57601ed1031ad6 Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Fri, 2 Feb 2024 10:08:48 -0500 Subject: [PATCH 4/4] O3-2812: Appointments: Refactoring and Code Cleanup --- .../src/home-appointments/appointments-list.test.tsx | 2 +- .../home-appointments/check-in-modal/check-in-modal.test.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx b/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx index cce07cb94..c751e3edc 100644 --- a/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx +++ b/packages/esm-appointments-app/src/home-appointments/appointments-list.test.tsx @@ -8,7 +8,7 @@ import AppointmentsBaseTable from './appointments-list.component'; const useTodaysAppointmentsMock = useTodaysAppointments as jest.Mock; const usePaginationMock = usePagination as jest.Mock; -jest.mock('./appointments-table.resource'); +jest.mock('./home-appointments.resource'); jest.mock('@openmrs/esm-framework', () => ({ ...jest.requireActual('@openmrs/esm-framework'), diff --git a/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx b/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx index 48dbe8b8d..901045b12 100644 --- a/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx +++ b/packages/esm-appointments-app/src/home-appointments/check-in-modal/check-in-modal.test.tsx @@ -9,7 +9,7 @@ const mockUpdateAppointmentStatus = updateAppointmentStatus as jest.Mock; const appointmentUuid = '7cd38a6d-377e-491b-8284-b04cf8b8c6d8'; jest.mock('@openmrs/esm-framework'); -jest.mock('../appointments-table.resource'); +jest.mock('../home-appointments.resource'); describe('CheckInAppointmentModal', () => { afterEach(() => {