import { useEffect } from 'react'; import { Observation } from 'fhir/r4'; import { useObservationServiceContext, usePatientServiceContext, useWebSocketServiceContext } from '../services'; import { useNoticeFence } from './useNoticeFence'; interface UseObservationWebSocketOptions { observation?: Observation; observationId?: string; isOpen?: boolean; onUpdate: (observation: Observation) => void; onDelete: () => void; } export const useFhirObservationTargetedBroadcast = ({ observation, observationId, isOpen = true, onUpdate, onDelete }: UseObservationWebSocketOptions) => { const { subscribe, unsubscribe } = useWebSocketServiceContext(); const { patientState } = usePatientServiceContext(); const { fetchObservation } = useObservationServiceContext(); // Closing, opening another result or another patient ends this opening: a reread begun before answers nobody. const fence = useNoticeFence(`${patientState?.id}|${observationId || observation?.id}|${isOpen}`); useEffect(() => { if (!patientState || !observation || !isOpen) { return; } const handleObservationEvent = (cloudEvent: any) => { const observationPayload: Observation = cloudEvent.data; const eventType = cloudEvent.type; const targetId = observationId || observation.id; // A notice names the result and nothing of it: the gated GET says what it is now, or that it is not shown. const stands = observationPayload.id === targetId ? fence.claim(targetId as string) : () => false; if (observationPayload.id === targetId && cloudEvent.data?.invalidated === true) { if (eventType === 'com.akashichealthrecords.fhir.observation.deleted') { onDelete(); return; } if (eventType === 'com.akashichealthrecords.fhir.observation.updated') { fetchObservation(targetId as string, true) .then((fresh) => { if (stands()) onUpdate(fresh); }) .catch(() => { if (stands()) onDelete(); }); } return; } if (observationPayload.id === targetId) { switch (eventType) { case 'com.akashichealthrecords.fhir.observation.updated': onUpdate(observationPayload); break; case 'com.akashichealthrecords.fhir.observation.deleted': onDelete(); break; } } }; subscribe('com.akashichealthrecords.fhir.observation.updated', handleObservationEvent); subscribe('com.akashichealthrecords.fhir.observation.deleted', handleObservationEvent); return () => { unsubscribe('com.akashichealthrecords.fhir.observation.updated', handleObservationEvent); unsubscribe('com.akashichealthrecords.fhir.observation.deleted', handleObservationEvent); }; }, [patientState, observation, observationId, isOpen, onUpdate, onDelete, subscribe, unsubscribe, fetchObservation, fence]); };