import { useEffect, useRef } from 'react'; import { useWebSocketServiceContext } from '../services'; import { useCapabilityServiceContext } from '../services/CapabilityService.tsx'; import { useFormSubmissionNotificationContext } from '../services/FormSubmissionNotificationService.tsx'; import { useFirstSignInGateStatus } from '../components/FirstSignInGate/firstSignInGateStatus.tsx'; import { isStaffExperience } from '../utils/mountContext.ts'; // Re-reads rather than bumping the count, so the rail's rows and count stay one snapshot. // Nothing is read behind an unanswered agreement; a broadcast that arrives then is read once it clears. const mayReadForms = (mayCall: (method: string, path: string) => boolean | undefined) => isStaffExperience() && mayCall('GET', '/form-submissions') !== false; export const useFhirFormSubmissionBroadcast = () => { const { subscribe, unsubscribe } = useWebSocketServiceContext(); const { refresh } = useFormSubmissionNotificationContext(); const { mayCall } = useCapabilityServiceContext(); const gate = useFirstSignInGateStatus(); const held = useRef(false); useEffect(() => { const handler = () => { if (!mayReadForms(mayCall)) return; if (gate !== 'clear') { held.current = true; return; } void refresh(); }; subscribe('com.akashichealthrecords.fhir.formsubmission.created', handler); return () => unsubscribe('com.akashichealthrecords.fhir.formsubmission.created', handler); }, [subscribe, unsubscribe, refresh, mayCall, gate]); useEffect(() => { if (gate !== 'clear' || !held.current) return; held.current = false; // Asked again: what this person may read can have changed while the event waited. if (mayReadForms(mayCall)) void refresh(); }, [gate, refresh, mayCall]); };