import { useEffect, useState, useCallback } from 'react'; import { usePatientServiceContext, useCarePlanServiceContext } from '../services'; import { describeFetchFailure, isRefusedRead } from '../utils/fetchFailureMessage'; interface UseFhirCarePlansOptions { autoLoad?: boolean; errorMessage?: string; forceReload?: boolean; } interface UseFhirCarePlansReturn { loading: boolean; error: string | undefined; /** The last load was answered with a 403: refused, not lost. */ refused: boolean; /** This patient's read has answered, one way or the other. Until then an empty list is unknown. */ answered: boolean; loadCarePlans: () => Promise; clearError: () => void; carePlansBundle: ReturnType['carePlansBundle']; carePlansList: ReturnType['carePlansList']; } export const useFhirCarePlans = (options: UseFhirCarePlansOptions = {}): UseFhirCarePlansReturn => { const { autoLoad = true, errorMessage = "Failed to load care plans", forceReload = false } = options; const { patientState } = usePatientServiceContext(); const { cachedForPatientId, fetchCarePlansWithPolling, carePlansBundle, carePlansList } = useCarePlanServiceContext(); const [loading, setLoading] = useState(false); const [error, setError] = useState(); const [refused, setRefused] = useState(false); const loadCarePlans = useCallback(async () => { if (!patientState) { return; } setLoading(true); setError(undefined); setRefused(false); try { await fetchCarePlansWithPolling(patientState); } catch (err) { console.error('Failed to load care plans:', err); setError(describeFetchFailure(err, errorMessage)); setRefused(isRefusedRead(err)); } finally { setLoading(false); } }, [patientState, fetchCarePlansWithPolling, errorMessage]); const clearError = useCallback(() => { setError(undefined); }, []); useEffect(() => { if (!autoLoad) return; if (!patientState) return; // A bundle belonging to SOMEBODY ELSE is not a reason not to ask. This used to fire only when // there was no bundle at all, so moving between two charts left the previous patient's list in // place, with no request and nothing on screen to say it was not theirs. // NOT a refetch on every navigation: same patient, bundle loaded, no request. if (!carePlansBundle || cachedForPatientId !== patientState.id || forceReload) { loadCarePlans(); } }, [autoLoad, patientState, carePlansBundle, cachedForPatientId, forceReload, loadCarePlans]); return { loading, error, refused, answered: Boolean(error) || (Boolean(carePlansBundle) && cachedForPatientId === patientState?.id), loadCarePlans, clearError, carePlansBundle, carePlansList }; };