import { useCallback, useRef, useState } from 'react'; import type { Appointment } from 'fhir/r4'; const versionOf = (appointment: Appointment | undefined): number => { const version = Number(appointment?.meta?.versionId); return appointment?.meta?.versionId && Number.isFinite(version) ? version : -1; }; /** `candidate` while it is at least as new as `fallback` and the same appointment; otherwise `fallback`. */ export const newerAppointment = (candidate: Appointment | undefined, fallback: Appointment | undefined): Appointment | undefined => candidate && candidate.id === fallback?.id && versionOf(candidate) >= versionOf(fallback) ? candidate : fallback; /** What a list or selection shows for one appointment: the incoming copy unless the one it holds is newer. */ export const latestKnown = (known: T, incoming: T): T => incoming.id === known.id && versionOf(incoming) < versionOf(known) ? known : incoming; /** * The Appointment an edit was opened on: the version its save names. A refresh of the shown appointment while the * form is open never moves it or refills the form; a newer one only marks this opening as changed elsewhere, and the * edit must be reloaded before it can be saved. */ export function useAppointmentEditBasis(shown: Appointment | undefined) { const basisRef = useRef(); const [basis, setBasis] = useState(); const open = useCallback((opened: Appointment | undefined) => { basisRef.current = opened; setBasis(opened); }, []); const newer = shown && basis && shown.id === basis.id && versionOf(shown) > versionOf(basis) ? shown : undefined; return { /** The version the next save names, read at the moment of saving. */ current: () => basisRef.current, open, /** A version saved elsewhere since this edit opened. */ newer, }; }