Skip to content

Commit

Permalink
Merge branch 'main' into overflow-menu
Browse files Browse the repository at this point in the history
  • Loading branch information
ayush-AI committed Sep 21, 2023
2 parents a7d0e08 + 12b02ef commit ba239f2
Show file tree
Hide file tree
Showing 214 changed files with 1,752 additions and 342 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -8,7 +8,7 @@ This repository contains frontend modules for the OpenMRS SPA. These modules rel

- [Active visits app](packages/esm-active-visits-app/)
- [Appointments app](packages/esm-appointments-app/)
- [Outpatient app](packages/esm-outpatient-app/README.md)
- [Service queues](packages/esm-service-queues-app/README.md)
- [Patient search](packages/esm-patient-search-app)
- [Patient registration](packages/esm-patient-registration-app)
- [Patient list](packages/esm-patient-list-app)
Expand Down
Expand Up @@ -247,15 +247,21 @@ const ActiveVisitsTable = () => {
{rows.map((row, index) => {
const visit = activeVisits.find((visit) => visit.id === row.id);

if (!visit) {
return null;
}

const patientLink = `$\{openmrsSpaBase}/patient/${visit.patientUuid}/chart/Patient%20Summary`;

return (
<React.Fragment key={index}>
<TableExpandRow {...getRowProps({ row })} data-testid={`activeVisitRow${visit.patientUuid}`}>
<TableExpandRow
{...getRowProps({ row })}
data-testid={`activeVisitRow${visit.patientUuid || 'unknown'}`}>
{row.cells.map((cell) => (
<TableCell key={cell.id} data-testid={cell.id}>
{cell.info.header === 'name' ? (
<PatientNameLink
from={fromPage}
to={`\${openmrsSpaBase}/patient/${visit.patientUuid}/chart/Patient%20Summary`}>
{cell.info.header === 'name' && visit.patientUuid ? (
<PatientNameLink from={fromPage} to={patientLink}>
{cell.value}
</PatientNameLink>
) : (
Expand Down
Expand Up @@ -6,12 +6,13 @@ import type { CalendarType } from '../types';
import AppointmentsHeader from '../appointments-header/appointments-header.component';
import CalendarHeader from './header/calendar-header.component';
import CalendarView from './calendar-view.component';
import { useAppointmentDate } from '../helpers';

const AppointmentsCalendarView: React.FC = () => {
const { t } = useTranslation();
const [calendarView, setCalendarView] = useState<CalendarType>('monthly');
const [currentDate, setCurrentDate] = useState(dayjs());
const { calendarEvents } = useAppointmentsCalendar(currentDate.toISOString(), calendarView);
const { currentAppointmentDate, setCurrentAppointmentDate } = useAppointmentDate();
const { calendarEvents } = useAppointmentsCalendar(dayjs(currentAppointmentDate).toISOString(), calendarView);

return (
<div data-testid="appointments-calendar">
Expand All @@ -20,8 +21,8 @@ const AppointmentsCalendarView: React.FC = () => {
<CalendarView
calendarView={calendarView}
events={calendarEvents}
currentDate={currentDate}
setCurrentDate={setCurrentDate}
currentDate={dayjs(currentAppointmentDate)}
setCurrentDate={setCurrentAppointmentDate}
/>
</div>
);
Expand Down
@@ -1,5 +1,5 @@
import React from 'react';
import { Dayjs } from 'dayjs';
import dayjs, { Dayjs } from 'dayjs';
import styles from './monthly-header.module.scss';
import { Button } from '@carbon/react';
import { useTranslation } from 'react-i18next';
Expand All @@ -24,6 +24,7 @@ function MonthlyHeader({
setCurrentDate: (date: Dayjs) => void;
}) {
const { t } = useTranslation();

return (
<>
<div className={styles.container}>
Expand Down
Expand Up @@ -6,7 +6,7 @@ import AppointmentsIllustration from './appointments-illustration.component';
import styles from './appointments-header.scss';
import { DatePicker, DatePickerInput, Dropdown, Layer } from '@carbon/react';
import dayjs from 'dayjs';
import { changeStartDate } from '../helpers';
import { changeStartDate, useAppointmentDate } from '../helpers';
import { useAppointmentServices } from '../hooks/useAppointmentService';

interface AppointmentHeaderProps {
Expand All @@ -18,7 +18,7 @@ const AppointmentsHeader: React.FC<AppointmentHeaderProps> = ({ title, onChange
const { t } = useTranslation();
const session = useSession();
const datePickerRef = useRef(null);
const [appointmentDate, setDateTime] = useState(new Date());
const { currentAppointmentDate } = useAppointmentDate();
const location = session?.sessionLocation?.display;
const { serviceTypes } = useAppointmentServices();
return (
Expand Down Expand Up @@ -46,7 +46,7 @@ const AppointmentsHeader: React.FC<AppointmentHeaderProps> = ({ title, onChange
placeholder="DD-MMM-YYYY"
labelText=""
type="text"
value={dayjs(appointmentDate).format('DD MMM YYYY')}
value={dayjs(currentAppointmentDate).format('DD MMM YYYY')}
/>
</DatePicker>
</div>
Expand Down
Expand Up @@ -15,8 +15,8 @@ const AppointmentsMetrics: React.FC<{ serviceUuid: string }> = ({ serviceUuid })
const { totalProviders, isLoading: allAppointmentsLoading } = useAllAppointmentsByDate();
const { totalScheduledAppointments } = useScheduledAppointment(serviceUuid);

const startDate = useAppointmentDate();
const formattedStartDate = formatDate(parseDate(startDate), { mode: 'standard', time: false });
const { currentAppointmentDate } = useAppointmentDate();
const formattedStartDate = formatDate(parseDate(currentAppointmentDate), { mode: 'standard', time: false });

const { appointmentList: arrivedAppointments } = useAppointmentList('Honoured');
const { appointmentList: pendingAppointments } = useAppointmentList('Pending');
Expand All @@ -43,7 +43,7 @@ const AppointmentsMetrics: React.FC<{ serviceUuid: string }> = ({ serviceUuid })
value={totalScheduledAppointments}
headerLabel={t('scheduledAppointments', 'Scheduled appointments')}
count={{ pendingAppointments: filteredPendingAppointments, arrivedAppointments: filteredArrivedAppointments }}
appointmentDate={startDate}
appointmentDate={currentAppointmentDate}
/>
<MetricsCard
label={
Expand Down
Expand Up @@ -6,8 +6,8 @@ import { getAppointment, useAppointmentDate } from '../helpers';
import isEmpty from 'lodash-es/isEmpty';

export function useAppointments(status?: string, forDate?: string) {
const appointmentDate = useAppointmentDate();
const startDate = forDate ? forDate : appointmentDate;
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}`;

Expand Down
@@ -0,0 +1,48 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { SelectItem } from '@carbon/react';

interface SelectLocationProps {
selectedLocation: string;
defaultFacility: {
uuid: string;
display: string;
};
locations?: Array<LocationOptions>;
}

interface LocationOptions {
uuid?: string;
display?: string;
}

const LocationSelectOption: React.FC<SelectLocationProps> = ({ selectedLocation, defaultFacility, locations }) => {
const { t } = useTranslation();
if (!selectedLocation) {
return <SelectItem text={t('selectOption', 'Select an option')} value="" />;
}

if (defaultFacility && Object.keys(defaultFacility).length !== 0) {
return (
<SelectItem key={defaultFacility?.uuid} text={defaultFacility?.display} value={defaultFacility?.uuid}>
{defaultFacility?.display}
</SelectItem>
);
}

if (locations && locations.length > 0) {
return (
<>
{locations.map((location) => (
<SelectItem key={location.uuid} text={location.display} value={location.uuid}>
{location.display}
</SelectItem>
))}
</>
);
}

return null;
};

export default LocationSelectOption;
Expand Up @@ -19,7 +19,7 @@ const CancelAppointment: React.FC<CancelAppointmentProps> = ({ appointment }) =>
const session = useSession();
const [selectedLocation, setSelectedLocation] = useState(appointment.location);
const [reason, setReason] = useState('');
const startDate = useAppointmentDate();
const { currentAppointmentDate } = useAppointmentDate();
const [isSubmitting, setIsSubmitting] = useState(false);

useEffect(() => {
Expand All @@ -38,8 +38,8 @@ const CancelAppointment: React.FC<CancelAppointmentProps> = ({ appointment }) =>
description: t('appointmentNowVisible', 'It has been cancelled successfully'),
title: t('appointmentCancelled', 'Appointment cancelled'),
});
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${startDate}&status=Scheduled`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${startDate}&status=Cancelled`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${currentAppointmentDate}&status=Scheduled`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${currentAppointmentDate}&status=Cancelled`);
closeOverlay();
} else {
showNotification({
Expand Down
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';
import {
Expand Down Expand Up @@ -32,6 +32,7 @@ import {
showNotification,
showToast,
ConfigObject,
useSession,
} from '@openmrs/esm-framework';

import first from 'lodash-es/first';
Expand All @@ -50,6 +51,8 @@ import {
import { useInitialAppointmentFormValue, PatientAppointment } from '../useInitialFormValues';
import { useCalendarDistribution } from '../workload-helper';
import WorkloadCard from '../workload.component';
import { useDefaultLoginLocation } from '../../../hooks/useDefaultLocation';
import LocationSelectOption from '../../common-components/location-select-option.component';

interface AppointmentFormProps {
appointment?: MappedAppointment;
Expand All @@ -63,6 +66,7 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
const [patientAppointment, setPatientAppointment] = useState<PatientAppointment>(initialAppointmentFormValues);
const { patient, isLoading } = usePatient(patientUuid ?? patientAppointment.patientUuid);
const locations = useLocations();
const sessionUser = useSession();
const { providers } = useProviders();
const { services } = useServices();
const [isSubmitting, setIsSubmitting] = useState(false);
Expand All @@ -71,11 +75,22 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
const calendarWorkload = useCalendarDistribution(
patientAppointment.serviceUuid,
selectedTab === 0 ? 'week' : 'month',
patientAppointment.visitDate,
);
const appointmentStartDate = useAppointmentDate();
const { currentAppointmentDate } = useAppointmentDate();
const [selectedLocation, setSelectedLocation] = useState('');
const { defaultFacility, isLoading: loadingDefaultFacility } = useDefaultLoginLocation();

const appointmentService = services?.find(({ uuid }) => uuid === patientAppointment.serviceUuid);

useEffect(() => {
if (locations?.length && sessionUser) {
setSelectedLocation(sessionUser?.sessionLocation?.uuid);
} else if (!loadingDefaultFacility && defaultFacility) {
setSelectedLocation(defaultFacility?.uuid);
}
}, [locations, sessionUser, loadingDefaultFacility]);

const handleSubmit = async () => {
const [hours, minutes] = convertTime12to24(patientAppointment.startDateTime, patientAppointment.timeFormat);
const startDatetime = toAppointmentDateTime(patientAppointment.visitDate, hours, minutes);
Expand Down Expand Up @@ -107,11 +122,11 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
title: t('appointmentScheduled', 'Appointment scheduled'),
});
setIsSubmitting(false);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${appointmentStartDate}&status=Scheduled`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${appointmentStartDate}&status=CheckedIn`);
mutate(`/ws/rest/v1/appointment/all?forDate=${appointmentStartDate}`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?status=Scheduled&forDate=${appointmentStartDate}`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?status=Pending&forDate=${appointmentStartDate}`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${currentAppointmentDate}&status=Scheduled`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?forDate=${currentAppointmentDate}&status=CheckedIn`);
mutate(`/ws/rest/v1/appointment/all?forDate=${currentAppointmentDate}`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?status=Scheduled&forDate=${currentAppointmentDate}`);
mutate(`/ws/rest/v1/appointment/appointmentStatus?status=Pending&forDate=${currentAppointmentDate}`);
closeOverlay();
}
},
Expand Down Expand Up @@ -159,15 +174,14 @@ const AppointmentForm: React.FC<AppointmentFormProps> = ({ appointment, patientU
labelText={t('selectLocation', 'Select a location')}
id="location"
invalidText="Required"
value={patientAppointment.locationUuid}
className={styles.inputContainer}
onChange={(event) => setPatientAppointment({ ...patientAppointment, locationUuid: event.target.value })}>
{locations?.length > 0 &&
locations.map((location) => (
<SelectItem key={location.uuid} text={location.display} value={location.uuid}>
{location.display}
</SelectItem>
))}
value={selectedLocation}
defaultSelected={selectedLocation}
onChange={(event) => setSelectedLocation(event.target.value)}>
<LocationSelectOption
selectedLocation={selectedLocation}
defaultFacility={defaultFacility}
locations={locations}
/>
</Select>

<Select
Expand Down
@@ -1,6 +1,5 @@
import dayjs from 'dayjs';
import { useAppointmentSummary } from './forms.resource';
import { useAppointmentDate } from '../../helpers';
interface AppointmentCount {
date: string;
count: number;
Expand All @@ -20,9 +19,12 @@ export const getMonthlyCalendarDistribution = (startDate: Date, appointmentCount
return Array.from(distributionHashTable).flatMap(([date, value]) => ({ date: date, count: value }));
};

export const useCalendarDistribution = (servieUuid: string, distributionType: 'month' | 'week') => {
const appointmentStartDate = useAppointmentDate();
const appointmentSummary = useAppointmentSummary(new Date(appointmentStartDate), servieUuid);
const monthlyData = getMonthlyCalendarDistribution(new Date(appointmentStartDate), appointmentSummary) ?? [];
export const useCalendarDistribution = (
servieUuid: string,
distributionType: 'month' | 'week',
appointmentDate: Date,
) => {
const appointmentSummary = useAppointmentSummary(new Date(appointmentDate), servieUuid);
const monthlyData = getMonthlyCalendarDistribution(new Date(appointmentDate), appointmentSummary) ?? [];
return distributionType === 'month' ? monthlyData : monthlyData.slice(0, 7);
};
Expand Up @@ -25,18 +25,25 @@ type scheduleType = 'CameEarly' | 'Rescheduled' | 'Honoured' | 'Pending' | 'Sche
const ScheduledAppointments: React.FC<ScheduledAppointmentsProps> = ({ visits, appointmentServiceType }) => {
const { t } = useTranslation();
const { patientIdentifierType } = useConfig<ConfigObject>();
const appointmentDate = useAppointmentDate();
const { currentAppointmentDate } = useAppointmentDate();
const [scheduleType, setScheduleType] = useState<scheduleType>('Scheduled');
const { appointmentList, isLoading } = useAppointmentList(scheduleType, appointmentDate, patientIdentifierType);
const { earlyAppointmentList, isLoading: loading } = useEarlyAppointmentList(appointmentDate, patientIdentifierType);
const { completedAppointments } = useCompletedAppointmentList(appointmentDate, patientIdentifierType);
const isDateInPast = dayjs(appointmentDate).isBefore(dayjs(), 'date');
const isDateInFuture = dayjs(appointmentDate).isAfter(dayjs(), 'date');
const isToday = dayjs(appointmentDate).isSame(dayjs(), 'date');
const { appointmentList, isLoading } = useAppointmentList(
scheduleType,
currentAppointmentDate,
patientIdentifierType,
);
const { earlyAppointmentList, isLoading: loading } = useEarlyAppointmentList(
currentAppointmentDate,
patientIdentifierType,
);
const { completedAppointments } = useCompletedAppointmentList(currentAppointmentDate, patientIdentifierType);
const isDateInPast = dayjs(currentAppointmentDate).isBefore(dayjs(), 'date');
const isDateInFuture = dayjs(currentAppointmentDate).isAfter(dayjs(), 'date');
const isToday = dayjs(currentAppointmentDate).isSame(dayjs(), 'date');

useEffect(() => {
setScheduleType('Scheduled');
}, [appointmentDate]);
}, [currentAppointmentDate]);

const filteredAppointments = appointmentServiceType
? appointmentList.filter(({ serviceTypeUuid }) => serviceTypeUuid === appointmentServiceType)
Expand Down
2 changes: 1 addition & 1 deletion packages/esm-appointments-app/src/helpers/time.tsx
Expand Up @@ -37,5 +37,5 @@ export const useAppointmentDate = () => {
getStartDate().subscribe(({ appointmentDate }) => setCurrentAppointmentDate(appointmentDate.toString()));
}, []);

return currentAppointmentDate;
return { currentAppointmentDate, setCurrentAppointmentDate };
};

0 comments on commit ba239f2

Please sign in to comment.