import { useEffect } from 'react'; import { HealthcareService } from 'fhir/r4'; import { useHealthcareServiceServiceContext, useFhirServiceContext, useWebSocketServiceContext } from '../services'; import { environment } from '../environments/environment.ts'; import { evidenceScope, observe, type ServiceObservation } from '../utils/booking/serviceCatalogueEvidence'; // A change seen as it happened is what the service is now, until a later whole search agrees; it never ends an attempt. const recordEvidence = (service: HealthcareService, observation: ServiceObservation) => { const practice = service?.providedBy?.reference?.split('/')[1]; if (!service?.id || !practice) return; try { observe(evidenceScope(practice, environment.fhirBaseApi), service.id, observation); } catch (error) { console.error('Service change could not be kept:', error); } }; export const useFhirHealthcareServiceBroadcast = () => { const { subscribe, unsubscribe } = useWebSocketServiceContext(); const { healthcareServicesList, setHealthcareServicesList } = useHealthcareServiceServiceContext(); const { extractReferenceId } = useFhirServiceContext(); useEffect(() => { const handleHealthcareServiceEvent = (cloudEvent: any) => { const healthcareService: HealthcareService = cloudEvent.data; const eventType = cloudEvent.type; if (eventType === 'com.akashichealthrecords.fhir.healthcareservice.deleted') recordEvidence(healthcareService, { kind: 'deleted' }); else if (eventType === 'com.akashichealthrecords.fhir.healthcareservice.created' || eventType === 'com.akashichealthrecords.fhir.healthcareservice.updated') { recordEvidence(healthcareService, { kind: 'version', versionId: healthcareService?.meta?.versionId, active: healthcareService?.active !== false }); } switch (eventType) { case 'com.akashichealthrecords.fhir.healthcareservice.created': // The list has two writers: this broadcast, and the service's own refetch after a write // (several of which POLL until the new id appears). Refetch first and the list already holds // the record, so an unconditional append put a SECOND copy of it on screen - observed on a // patient's questionnaire answers, where one submission rendered as two completed forms. // Keeping the broadcast's copy rather than skipping: its body is at least as fresh. setHealthcareServicesList(prev => prev.some(p => p.id === healthcareService.id) ? prev.map(p => p.id === healthcareService.id ? healthcareService : p) : [...prev, healthcareService] ); break; case 'com.akashichealthrecords.fhir.healthcareservice.updated': setHealthcareServicesList(prev => prev.map(p => p.id === healthcareService.id ? healthcareService : p)); break; case 'com.akashichealthrecords.fhir.healthcareservice.deleted': setHealthcareServicesList(prev => prev.filter(p => p.id !== healthcareService.id)); break; } }; subscribe('com.akashichealthrecords.fhir.healthcareservice.created', handleHealthcareServiceEvent); subscribe('com.akashichealthrecords.fhir.healthcareservice.updated', handleHealthcareServiceEvent); subscribe('com.akashichealthrecords.fhir.healthcareservice.deleted', handleHealthcareServiceEvent); return () => { unsubscribe('com.akashichealthrecords.fhir.healthcareservice.created', handleHealthcareServiceEvent); unsubscribe('com.akashichealthrecords.fhir.healthcareservice.updated', handleHealthcareServiceEvent); unsubscribe('com.akashichealthrecords.fhir.healthcareservice.deleted', handleHealthcareServiceEvent); }; }, [subscribe, unsubscribe, extractReferenceId, healthcareServicesList]); };