import { useCallback, useEffect, useRef, useState } from "react"; import type { Organization } from "fhir/r4"; import { Button } from "../../../components/ui/button"; import { Input } from "../../../components/ui/input"; import { Label } from "../../../components/ui/label"; import { RadioControl } from "../../../components/ui/radio-control"; import { useOrganizationServiceContext } from "../../../services/OrganizationService"; import { environment } from "../../../environments/environment"; import { relayServerFailure } from "../../../utils/fetchFailureMessage"; import { formatDayMonthYear } from "../../../utils/dateUtils"; import { isSaveRetired, outcomeUnknown, TIMED_OUT_MAY_HAVE_SAVED, useSaveScope, type SaveOperation } from "../../../utils/saveOperation"; import { expectedVersionOf, isDeclarationChanged, onFileVersion, PART2_STATUS_LABELS, readPart2OnFile, type Part2OnFile, type Part2Status, } from "../../../utils/part2Declaration"; const DATE = /^\d{4}-\d{2}-\d{2}$/; const STATUS_OPTIONS = [ { value: "part2", label: "A Part 2 program: this practice runs a federally assisted substance use disorder program" }, { value: "not-part2", label: "Not a Part 2 program" }, { value: "mixed", label: "Mixed: some of this practice's programs are Part 2 programs and some are not" }, ]; const COVERAGE_OPTIONS = [ { value: "yes", label: "Yes, every program this practice runs" }, { value: "no", label: "No, only some of them" }, ]; // What is on file for one practice, read by one viewer. A read for another practice or viewer is never shown here. type Read = | { owner: string; state: "reading" } | { owner: string; state: "read"; onFile: Part2OnFile } | { owner: string; state: "unavailable" }; type Outcome = | { kind: "saved"; version: string } | { kind: "saved-unread"; version: string } | { kind: "saved-unconfirmed"; version: string } | { kind: "superseded"; version: string; currentVersion: string } | { kind: "moved" } | { kind: "refused"; message: string } | { kind: "unconfirmed" }; interface Answer { status?: Part2Status; covers?: "yes" | "no"; effectiveFrom: string; } const NO_ANSWER: Answer = { effectiveFrom: "" }; type WriteReceipt = { owner: string; version: string; answer: Answer }; const reconcileRead = (onFile: Part2OnFile, receipt: WriteReceipt): "current" | "superseded" | "unconfirmed" => { if (onFile.kind !== "declared") return "unconfirmed"; const current = onFile.declaration; if (current.version === receipt.version) { const effective = Date.parse(current.effectiveFrom ?? ""); return current.status === receipt.answer.status && current.coversAllPrograms === (receipt.answer.covers === "yes") && Number.isFinite(effective) && effective === Date.parse(receipt.answer.effectiveFrom) ? "current" : "unconfirmed"; } const currentNumber = Number(current.version); const savedNumber = Number(receipt.version); return Number.isSafeInteger(currentNumber) && Number.isSafeInteger(savedNumber) && currentNumber > savedNumber ? "superseded" : "unconfirmed"; }; const describe = (onFile: Part2OnFile): string => { if (onFile.kind === "none") return "No declaration is on file. Until one is, no record is released as this practice's own."; if (onFile.kind === "unusable") return "A declaration is on file but cannot be read, so it is not used. Save a new one."; const { declaration } = onFile; return [ `${PART2_STATUS_LABELS[declaration.status]}.`, declaration.coversAllPrograms ? "Covers every program." : "Does not cover every program.", declaration.effectiveFrom ? `Effective ${formatDayMonthYear(declaration.effectiveFrom)}.` : undefined, `Version ${declaration.version}${declaration.attestedAt ? `, declared ${formatDayMonthYear(declaration.attestedAt)}` : ""}.`, ].filter(Boolean).join(" "); }; /** * The practice administrator says whether this practice's programs are 42 CFR Part 2 programs. Nothing is chosen for * them. The opening, its read and its save belong to this practice and this viewer: a change of either retires them. * The save re-reads first and refuses if the declaration changed since it was shown, then reads back what was stored. */ const Part2DeclarationSection = ({ organizationId }: { organizationId: string }) => { const { fetchOrganizationAsCaller, declarePart2Program } = useOrganizationServiceContext(); const [stored, setStored] = useState({ owner: "", state: "reading" }); const [answer, setAnswer] = useState(NO_ANSWER); const [saving, setSaving] = useState(false); const [outcome, setOutcome] = useState(); const [generation, setGeneration] = useState(0); const confirmedWrite = useRef(); const scope = useSaveScope(organizationId, () => { confirmedWrite.current = undefined; setStored({ owner: "", state: "reading" }); setAnswer(NO_ANSWER); setSaving(false); setOutcome(undefined); setGeneration((g) => g + 1); }); const read: Read = stored.owner === organizationId ? stored : { owner: organizationId, state: "reading" }; const publishRead = useCallback((owner: string, onFile: Part2OnFile, preserveOutcome = false) => { const receipt = confirmedWrite.current?.owner === owner ? confirmedWrite.current : undefined; const settled = receipt ? reconcileRead(onFile, receipt) : undefined; if (receipt && settled === "unconfirmed") { setStored({ owner, state: "unavailable" }); setOutcome({ kind: "saved-unconfirmed", version: receipt.version }); return; } setStored({ owner, state: "read", onFile }); if (receipt && !preserveOutcome) { setOutcome(settled === "superseded" && onFile.kind === "declared" ? { kind: "superseded", version: receipt.version, currentVersion: onFile.declaration.version } : { kind: "saved", version: receipt.version }); } }, []); const readOrganization = useCallback( (operation: SaveOperation) => operation.step(() => fetchOrganizationAsCaller(organizationId, environment.wpData?.installationId, organizationId, operation.transport)), [fetchOrganizationAsCaller, organizationId], ); // Every opening reads what is on file now, never a copy held from earlier. A change of practice or viewer retires // the scope, which bumps the generation: that is the one trigger, so each change reads once. const readNow = useRef(readOrganization); readNow.current = readOrganization; const ownerNow = useRef(organizationId); ownerNow.current = organizationId; useEffect(() => { const operation = scope.start(); const owner = ownerNow.current; readNow.current(operation).then( (organization: Organization) => { if (operation.belongs()) publishRead(owner, readPart2OnFile(organization)); }, (error: unknown) => { if (!isSaveRetired(error) && operation.belongs()) setStored({ owner, state: "unavailable" }); }, ); return () => operation.retire(); }, [scope, generation, publishRead]); const reread = () => { setOutcome(undefined); setAnswer(NO_ANSWER); setStored({ owner: organizationId, state: "reading" }); setGeneration((g) => g + 1); }; const ended = outcome?.kind === "unconfirmed"; const complete = !!answer.status && !!answer.covers && DATE.test(answer.effectiveFrom); const canSave = read.state === "read" && complete && !saving && !ended; const save = async () => { if (!canSave || read.state !== "read" || !answer.status || !answer.covers) return; const shown = onFileVersion(read.onFile); const operation = scope.start(); setSaving(true); setOutcome(undefined); try { // The declaration this answer was given against must still be the one on file. const current = readPart2OnFile(await readOrganization(operation)); if (onFileVersion(current) !== shown) { setStored({ owner: organizationId, state: "read", onFile: current }); setAnswer(NO_ANSWER); setOutcome({ kind: "moved" }); return; } const result = await operation.step(() => declarePart2Program({ status: answer.status as Part2Status, coversAllPrograms: answer.covers === "yes", effectiveFrom: answer.effectiveFrom, expectedVersion: expectedVersionOf(current), }, operation.transport), true); setAnswer(NO_ANSWER); if (!result || typeof result.version !== "string" || !result.version) { setStored({ owner: organizationId, state: "unavailable" }); setOutcome({ kind: "unconfirmed" }); return; } // A later reload cannot present a version older than this confirmed write as current. confirmedWrite.current = { owner: organizationId, version: result.version, answer: { ...answer } }; // What is stored now, read back rather than assumed from the answer. try { const committed = readPart2OnFile(await readOrganization(operation)); publishRead(organizationId, committed); } catch (error) { if (isSaveRetired(error) || !operation.belongs()) return; setStored({ owner: organizationId, state: "unavailable" }); setOutcome({ kind: "saved-unread", version: result.version }); } } catch (error) { if (isSaveRetired(error) || !operation.belongs()) return; // Another declaration was stored after the one these answers were given against: nothing was written. if (isDeclarationChanged(error)) { setAnswer(NO_ANSWER); setOutcome({ kind: "moved" }); setStored({ owner: organizationId, state: "reading" }); try { publishRead(organizationId, readPart2OnFile(await readOrganization(operation)), true); } catch (readError) { if (!isSaveRetired(readError) && operation.belongs()) setStored({ owner: organizationId, state: "unavailable" }); } return; } if (outcomeUnknown(error)) setOutcome({ kind: "unconfirmed" }); else setOutcome({ kind: "refused", message: relayServerFailure(error, "The declaration could not be saved. Nothing was changed.") }); } finally { if (operation.belongs()) setSaving(false); operation.retire(); } }; return (

This declares whether this practice runs a program covered by 42 CFR Part 2. It is a statement about the practice's programs, not permission to release any record: a record from a Part 2 or mixed program, of unknown origin, or with its own restriction stays withheld. It does not change records already on file.

On file

{read.state === "reading" &&

Reading…

} {read.state === "read" &&

{describe(read.onFile)}

} {read.state === "unavailable" && ( <>

What is on file could not be read, so a new declaration cannot be saved against it.

)}
setAnswer((a) => ({ ...a, status: value as Part2Status }))} /> setAnswer((a) => ({ ...a, covers: value as "yes" | "no" }))} />
setAnswer((a) => ({ ...a, effectiveFrom: e.target.value }))} aria-describedby="part2-effective-from-help" />

{read.state === "read" && read.onFile.kind === "declared" && read.onFile.declaration.effectiveFrom ? `The declaration on file starts ${formatDayMonthYear(read.onFile.declaration.effectiveFrom)}. ` : ""} A start date later than the one on file holds back the records this practice entered before it, until the declaration is restated from the earlier date.

{outcome?.kind === "saved" && (
Saved. Version {outcome.version} is on file, as shown above.
)} {outcome?.kind === "saved-unread" && (
Saved as version {outcome.version}, but it could not be read back. Try again to check what is on file.
)} {outcome?.kind === "saved-unconfirmed" && (
Saved as version {outcome.version}, but the current declaration could not be confirmed. Try again to check what is on file.
)} {outcome?.kind === "superseded" && (
Version {outcome.version} was saved. A newer declaration, version {outcome.currentVersion}, is now on file.
)} {outcome?.kind === "moved" && (
The declaration changed since this was opened, so nothing was saved. It now reads as shown above. Answer again.
)} {outcome?.kind === "refused" && (
{outcome.message}
)} {outcome?.kind === "unconfirmed" && (
{TIMED_OUT_MAY_HAVE_SAVED}
)}
); }; export default Part2DeclarationSection;