// One original view per workspace instance, reached on the same host as the Encounter it starts, so the view, its // receipts and the Start all name one datastore. The instance id lives only in memory: a reload opens a new view. import { useEffect, useMemo, useState } from 'react'; import { environment } from '../../environments/environment.ts'; import { useHttpService } from '../../services/HttpService.tsx'; import { createAnchorView, type AnchorView, type ViewScope } from './anchorView'; const API_URL = environment.fhirBaseApi; const newInstanceId = (): string => `ws-${crypto.randomUUID()}`; /** The view for this patient and visit, and its id once it opened; the id is undefined while none is collecting. */ export function useAnchorView(patientId: string | undefined, scope: ViewScope | undefined): { view: AnchorView | undefined; viewId: string | undefined } { const { post, put } = useHttpService(); const scopeKey = scope ? ('encounterId' in scope ? `e:${scope.encounterId}` : `o:${scope.operationId}`) : undefined; const view = useMemo(() => { if (!patientId || !scopeKey) return undefined; const patient = encodeURIComponent(patientId); return createAnchorView({ open: (body) => post(`${API_URL}/anchor-views?patient=${patient}`, body), submit: (viewId, body, signal) => put(`${API_URL}/anchor-views/${viewId}/manifest?patient=${patient}`, body, signal ? { signal } : {}), }, patientId, newInstanceId()); // The transport is rebuilt only for another patient or visit; post and put are stable callbacks. // eslint-disable-next-line react-hooks/exhaustive-deps }, [patientId, scopeKey]); const [opened, setOpened] = useState<{ view: AnchorView; viewId: string } | undefined>(); useEffect(() => { if (!view || !scope) return; let current = true; void view.open(scope).then((viewId) => { if (current && viewId) setOpened({ view, viewId }); }); return () => { current = false; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [view]); return { view, viewId: opened && opened.view === view ? opened.viewId : undefined }; }