import { useState } from "react"; import type { Organization } from "fhir/r4"; import { environment } from "../../../environments/environment"; import { sandboxOffered } from "../../../components/SandboxMode/useSandboxEntry"; import SandboxEntryDialog from "../../../components/SandboxMode/SandboxEntryDialog"; import { getOnboardingStatus, setOnboardingTaskStatus, type OrgOnboardingTaskState } from "../../../utils/orgOnboardingStatus"; import { useAuthServiceContext } from "../../../services/AuthService"; import { useOrganizationServiceContext } from "../../../services/OrganizationService"; import type { SaveTransport } from "../../../utils/saveOperation"; export const SANDBOX_STEP_ID = "explore-sandbox"; // Settled for the practice once somebody entered or skipped, so no later visitor is offered it again. export const sandboxStepSettled = (organization?: Organization | null) => getOnboardingStatus(organization)[SANDBOX_STEP_ID] !== undefined; // Offered only to someone who can record the outcome, on a stack with a sandbox, outside it already. export const showsSandboxStep = (organization: Organization | null | undefined, canManage: boolean) => Boolean(organization) && canManage && sandboxOffered() && !environment.inSandboxMode && !sandboxStepSettled(organization); // Once the step is settled its row is gone, and the only way back is the practice menu, so the guide says so. export const showsSandboxWayBack = (organization: Organization | null | undefined, canManage: boolean) => Boolean(organization) && canManage && sandboxOffered() && !environment.inSandboxMode && sandboxStepSettled(organization); export const SandboxWayBack = () => (
i Sandbox Mode Open it any time from the practice menu at the top left, under Workspace mode.
); type PracticeSandboxStepProps = { organization: Organization }; // admin-v2 first-run "Explore Sandbox Mode": optional, after the required steps, never counted in them. const PracticeSandboxStep = ({ organization }: PracticeSandboxStepProps) => { const { setWpOrganization } = useAuthServiceContext(); const { updateOrganization } = useOrganizationServiceContext(); const [explaining, setExplaining] = useState(false); const [skipping, setSkipping] = useState(false); const [skipFailed, setSkipFailed] = useState(false); // Both gates again at the row itself, so no caller can place it in front of a patient. if (!sandboxOffered() || environment.inSandboxMode) return null; const save = (state: OrgOnboardingTaskState, transport?: SaveTransport) => updateOrganization(setOnboardingTaskStatus(organization, SANDBOX_STEP_ID, state), transport); const record = async (state: OrgOnboardingTaskState) => { setWpOrganization(await save(state)); }; // Entering reloads into the sandbox. Publishing the settled step first would hide this row, // unmount the entry sheet mid-entry and cancel it. Sent only while the entry that asked for it is still owned. const recordEntered = async (transport: SaveTransport) => { await save("done", transport); }; const skip = async () => { setSkipping(true); setSkipFailed(false); try { await record("skipped"); } catch { setSkipFailed(true); } finally { setSkipping(false); } }; return (
i Explore Sandbox Mode Optional Practice with sample patients and activity. {/* Skip settles the step for the whole practice, so no other admin is offered it again. */} Skip hides this for everyone here. Sandbox stays in the practice menu. {skipFailed && ( This step could not be skipped. Nothing has changed; try again. )} {explaining && setExplaining(false)} beforeEnter={recordEntered} />}
); }; export default PracticeSandboxStep;