import { useCallback } from 'react'; import dayjs from 'dayjs'; import isToday from 'dayjs/plugin/isToday'; import useSWR, { useSWRConfig } from 'swr'; import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; import { type AppointmentPayload, type AppointmentService, type AppointmentsFetchResponse, type RecurringAppointmentsPayload, } from '../types'; dayjs.extend(isToday); // FIXED: Use your actual mohappointment endpoints const mohAppointmentUrl = `${restBaseUrl}/mohappointment/appointment`; const mohAppointmentServicesUrl = `${restBaseUrl}/mohappointment/services`; // Legacy endpoint (keep for compatibility if needed) const appointmentUrlMatcher = `${restBaseUrl}/appointment`; export function useMutateAppointments() { const { mutate } = useSWRConfig(); // FIXED: Target the correct mohappointment endpoint for mutations const mutateAppointments = useCallback( () => mutate((key) => { return ( (typeof key === 'string' && (key.startsWith(mohAppointmentUrl) || key.startsWith(appointmentUrlMatcher))) || (Array.isArray(key) && (key[0].startsWith(mohAppointmentUrl) || key[0].startsWith(appointmentUrlMatcher))) ); }), [mutate], ); return { mutateAppointments, }; } export function useAppointments(patientUuid: string, startDate: string, abortController: AbortController) { const fetcher = () => openmrsFetch(`${mohAppointmentUrl}?patient=${patientUuid}&appointmentDate=${startDate}`, { method: 'GET', signal: abortController.signal, }); const { data, error, isLoading, isValidating, mutate } = useSWR([mohAppointmentUrl, patientUuid, startDate], fetcher); const appointments = data && (data as any).results?.length ? (data as any).results : null; const pastAppointments = appointments ?.sort((a, b) => (b.startDateTime > a.startDateTime ? 1 : -1)) ?.filter(({ status }) => status !== 'Cancelled') ?.filter(({ startDateTime }) => dayjs(new Date(startDateTime).toISOString()).isBefore(new Date().setHours(0, 0, 0, 0)), ); const upcomingAppointments = appointments ?.sort((a, b) => (a.startDateTime > b.startDateTime ? 1 : -1)) ?.filter(({ status }) => status !== 'Cancelled') ?.filter(({ startDateTime }) => dayjs(new Date(startDateTime).toISOString()).isAfter(new Date())); const todaysAppointments = appointments ?.sort((a, b) => (a.startDateTime > b.startDateTime ? 1 : -1)) ?.filter(({ status }) => status !== 'Cancelled') ?.filter(({ startDateTime }) => dayjs(new Date(startDateTime).toISOString()).isToday()); return { data: data ? { pastAppointments, upcomingAppointments, todaysAppointments } : null, error, isLoading, isValidating, mutate, }; } export function useAppointmentService() { const { data, error, isLoading } = useSWR<{ results: Array }, Error>( mohAppointmentServicesUrl, (url) => openmrsFetch(url).then((res) => res.data), ); return { data: data ? data.results : null, error, isLoading, }; } export function saveAppointment( appointment: { appointmentDate: string; reason: { person: string; concept: string; value: string; obsDatetime: string; }; nextVisitDate?: string; note?: string; encounter?: string | null; location: string; provider: string; service: { serviceId: number }; patient: string; }, abortController: AbortController, ) { return openmrsFetch(mohAppointmentUrl, { method: 'POST', signal: abortController.signal, headers: { 'Content-Type': 'application/json', }, body: appointment, }); } export function editAppointment( uuid: string, appointment: { appointmentDate: string; reason: { person: string; concept: string; value: string; obsDatetime: string; }; nextVisitDate?: string; note?: string; encounter?: string | null; location: string; provider: string; service: { serviceId: number }; patient: string; }, abortController: AbortController, ) { return openmrsFetch(`${mohAppointmentUrl}/${uuid}`, { method: 'POST', signal: abortController.signal, headers: { 'Content-Type': 'application/json', }, body: appointment, }); } export function saveRecurringAppointments( recurringAppointments: RecurringAppointmentsPayload, abortController: AbortController, ) { return openmrsFetch(`${restBaseUrl}/recurring-appointments`, { method: 'POST', signal: abortController.signal, headers: { 'Content-Type': 'application/json', }, body: recurringAppointments, }); } // TODO refactor to use SWR? export function getAppointmentsByUuid(appointmentId: number, abortController: AbortController) { return openmrsFetch(`${restBaseUrl}/mohappointment/${appointmentId}`, { signal: abortController.signal, }); } // TODO refactor to use SWR? export function getAppointmentService(abortController: AbortController, uuid) { return openmrsFetch(`${restBaseUrl}/appointmentService?uuid=` + uuid, { signal: abortController.signal, }); } export const cancelAppointment = async (toStatus: string, appointmentUuid: string) => { const omrsDateFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZZ'; const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; const statusChangeTime = dayjs(new Date()).format(omrsDateFormat); const url = `${restBaseUrl}/mohappointment/${appointmentUuid}/status-change`; return await openmrsFetch(url, { body: { toStatus, onDate: statusChangeTime, timeZone: timeZone }, method: 'POST', headers: { 'Content-Type': 'application/json' }, }); }; export const checkAppointmentConflict = async (appointmentPayload: any) => { return await openmrsFetch(`${restBaseUrl}/mohappointment/appointments/conflicts`, { method: 'POST', body: appointmentPayload, headers: { 'Content-Type': 'application/json' }, }); };