import dayjs from 'dayjs'; import useSWR from 'swr'; import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; import { type AppointmentsFetchResponse, BackendAppointmentStates } from '../types'; import { useSelectedDateContext } from './selected-date-context'; export function usePatientAppointmentHistory(patientUuid: string) { const abortController = new AbortController(); const appointmentsSearchUrl = `${restBaseUrl}/appointments/search`; const { selectedDate } = useSelectedDateContext(); const fetcher = () => openmrsFetch(appointmentsSearchUrl, { method: 'POST', signal: abortController.signal, headers: { 'Content-Type': 'application/json', }, body: { patientUuid: patientUuid, startDate: selectedDate, }, }); const { data, error, isLoading, isValidating } = useSWR( patientUuid ? appointmentsSearchUrl : null, fetcher, ); // Helper function to extract appointment state value const getAppointmentStateValue = (appointment: any) => { if (appointment.appointmentState && typeof appointment.appointmentState === 'object') { return ( (appointment.appointmentState as any).description || (appointment.appointmentState as any).name || (appointment.appointmentState as any).value ); } return appointment.appointmentState || appointment.status; }; // Helper function to categorize appointments by their state const categorizeAppointment = (appointment: any) => { const stateValue = getAppointmentStateValue(appointment); if (stateValue === BackendAppointmentStates.ATTENDED || stateValue === 'Completed') { return 'completed'; } if (stateValue === BackendAppointmentStates.EXPIRED || stateValue === 'Missed') { return 'missed'; } if (stateValue === BackendAppointmentStates.RETIRED || stateValue === 'Cancelled') { return 'cancelled'; } if ( stateValue === BackendAppointmentStates.UPCOMING || (stateValue === BackendAppointmentStates.CONFIRMED && dayjs(appointment.startDateTime || appointment.appointmentDate).isAfter(dayjs())) ) { return 'upcoming'; } if (dayjs(appointment.startDateTime || appointment.appointmentDate).isAfter(dayjs())) { return 'upcoming'; } return 'other'; }; const appointmentsByCategory = data?.data?.reduce((acc: any, appointment: any) => { const category = categorizeAppointment(appointment); acc[category] = (acc[category] || 0) + 1; return acc; }, {}) || {}; const missedAppointments = appointmentsByCategory.missed || 0; const completedAppointments = appointmentsByCategory.completed || 0; const cancelledAppointments = appointmentsByCategory.cancelled || 0; const upcomingAppointments = appointmentsByCategory.upcoming || 0; return { appointmentsCount: { missedAppointments, completedAppointments, cancelledAppointments, upcomingAppointments, }, error, isLoading, isValidating, }; }