import { useEffect, useRef } from 'react'; import type { ConsentInstrumentId } from '../config/consentInstruments'; import { useOptionalWebSocketServiceContext } from '../services/WebSocketService'; import { AUTHORIZATION_ANSWER_EVENT, isRecordAnswerFor, onRecordAuthorizationAnswer, type AuthorizationAnswerNotice } from '../utils/recordAuthorizationAnswers'; import { useRereadOnReturn } from './useRereadOnReturn'; /** * Tells one agreement row that its answer may have changed: an answer returned in this client, or the server's notice * of one accepted elsewhere for this patient, this document and the session's practice. The notice never carries the * answer, so it only invalidates; the row confirms by reading its own status. Coming back to the window reads quietly, * unless the row's surface already rereads it when the page is seen again (no `onReturn`). */ export const useAgreementAnswerNotice = ( { patientId, instrument, practiceId, enabled = true }: { patientId?: string; instrument: ConsentInstrumentId; practiceId: () => string | undefined; enabled?: boolean; }, onNotice: () => void, onReturn?: () => void, ): void => { const socket = useOptionalWebSocketServiceContext(); const subscribe = socket?.subscribe; const unsubscribe = socket?.unsubscribe; const latest = useRef({ onNotice, practiceId }); latest.current = { onNotice, practiceId }; const listening = enabled && Boolean(patientId); useEffect(() => (listening ? onRecordAuthorizationAnswer(() => latest.current.onNotice()) : undefined), [listening]); useEffect(() => { if (!listening || !patientId || !subscribe || !unsubscribe) return undefined; const heard = (notice: AuthorizationAnswerNotice) => { if (isRecordAnswerFor(notice, patientId, latest.current.practiceId(), instrument)) latest.current.onNotice(); }; subscribe(AUTHORIZATION_ANSWER_EVENT, heard); return () => unsubscribe(AUTHORIZATION_ANSWER_EVENT, heard); }, [listening, patientId, instrument, subscribe, unsubscribe]); useRereadOnReturn(() => onReturn?.(), listening && Boolean(onReturn)); };