@patientos/website-kit 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,6 @@ import {
17
17
  FlowLoading,
18
18
  FlowRailContext,
19
19
  FlowShell,
20
- PORTAL_REQUEST_INIT,
21
20
  PatientOSApiError,
22
21
  PortalLinkSentNotice,
23
22
  PortalRescheduleInline,
@@ -25,8 +24,7 @@ import {
25
24
  SlotPicker,
26
25
  SummarisedFieldErrors,
27
26
  adoptClaimToken,
28
- configurePortalApiOrigin,
29
- currentPagePath,
27
+ createPortalClient,
30
28
  describedBy,
31
29
  effectiveFee,
32
30
  errorCode,
@@ -55,24 +53,23 @@ import {
55
53
  patientos,
56
54
  persistClaimToken,
57
55
  pickDeliveryOption,
58
- portalApiUrl,
59
56
  portalDelete,
57
+ portalFetchForClient,
60
58
  portalGet,
61
59
  portalSend,
62
60
  readPortalSignedInHint,
63
- requestPortalSignInLink,
64
61
  resetSession,
65
62
  saveFlowRecord,
66
63
  signOutOfPortal,
67
64
  writePortalSignedInHint,
68
65
  zoneAbbr
69
- } from "./chunk-BW7YKCKH.js";
66
+ } from "./chunk-BHVDY6SC.js";
70
67
  import {
71
68
  __export
72
69
  } from "./chunk-MLKGABMK.js";
73
70
 
74
71
  // src/booking-block.client.tsx
75
- import * as React3 from "react";
72
+ import * as React4 from "react";
76
73
 
77
74
  // src/booking-block-machine.ts
78
75
  var BOOKING_STEPS = [
@@ -203,7 +200,7 @@ function bookingStepTitle(step, clinicName) {
203
200
  }
204
201
 
205
202
  // src/identity.tsx
206
- import * as React from "react";
203
+ import * as React2 from "react";
207
204
 
208
205
  // src/address-picker.tsx
209
206
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -419,69 +416,73 @@ function formatAuPhone(input) {
419
416
  return national.startsWith("04") ? `${national.slice(0, 4)} ${national.slice(4, 7)} ${national.slice(7)}` : `(${national.slice(0, 2)}) ${national.slice(2, 6)} ${national.slice(6)}`;
420
417
  }
421
418
 
422
- // src/portal-bridge.ts
423
- function portalBridgeAvailable(portal) {
424
- if (typeof window === "undefined") return false;
425
- const origin = portal?.portalOrigin?.trim();
426
- if (!origin) return false;
427
- return window.location.origin === origin.replace(/\/+$/, "");
428
- }
429
- var BRIDGE_TIMEOUT_MS = 15e3;
430
- var BRIDGE_PROBE_TIMEOUT_MS = 8e3;
431
- async function bridgeFetch(path, init) {
432
- const ctl = new AbortController();
433
- const timer = setTimeout(() => ctl.abort(), init?.timeoutMs ?? BRIDGE_TIMEOUT_MS);
434
- try {
435
- const res = await fetch(path, {
436
- signal: ctl.signal,
437
- method: init?.method ?? "GET",
438
- // The whole point: the portal session cookie must ride along.
439
- credentials: "include",
440
- // PHI in flight — never let a bfcache/CDN keep it.
441
- cache: "no-store",
442
- headers: {
443
- accept: "application/json",
444
- ...init?.body !== void 0 ? { "content-type": "application/json" } : {}
445
- },
446
- ...init?.body !== void 0 ? { body: JSON.stringify(init.body) } : {}
447
- });
448
- if (!res.ok) return null;
449
- return await res.json();
450
- } catch {
451
- return null;
452
- } finally {
453
- clearTimeout(timer);
454
- }
455
- }
456
- async function fetchWhoAmI(portal) {
457
- if (!portalBridgeAvailable(portal)) return { signedIn: false };
458
- const out = await bridgeFetch("/portal/api/whoami", {
459
- timeoutMs: BRIDGE_PROBE_TIMEOUT_MS
460
- });
461
- return out && out.signedIn === true ? out : { signedIn: false };
462
- }
463
- async function requestMagicLink(portal, email, redirect) {
464
- if (!portalBridgeAvailable(portal)) return false;
465
- const out = await bridgeFetch("/portal/api/magic-link", {
466
- method: "POST",
467
- body: { email, ...redirect ? { redirect } : {} }
468
- });
469
- return out?.ok === true;
470
- }
471
- async function fetchPrefill(portal) {
472
- if (!portalBridgeAvailable(portal)) return null;
473
- return bridgeFetch("/portal/api/prefill");
474
- }
475
- async function mintPublicClaim(portal) {
476
- if (!portalBridgeAvailable(portal)) return null;
477
- return bridgeFetch("/portal/api/public-claim", { method: "POST", body: {} });
478
- }
479
- function portalHref(portal) {
480
- return portal?.portalUrl?.trim() ?? "";
419
+ // src/portal-context.tsx
420
+ import * as React from "react";
421
+ import { jsx as jsx2 } from "react/jsx-runtime";
422
+ var PortalContext = React.createContext(void 0);
423
+ function PortalProvider({ client, children }) {
424
+ return /* @__PURE__ */ jsx2(PortalContext.Provider, { value: client, children });
425
+ }
426
+ function usePortalClient() {
427
+ const client = React.useContext(PortalContext);
428
+ if (!client) {
429
+ throw new Error("usePortalClient must be used inside a <PortalProvider>.");
430
+ }
431
+ return client;
432
+ }
433
+ function usePortalSession() {
434
+ const client = usePortalClient();
435
+ const [state, setState] = React.useState({ status: "loading", who: null });
436
+ const mounted = React.useRef(false);
437
+ const requestNumber = React.useRef(0);
438
+ const refresh = React.useCallback(async () => {
439
+ const currentRequest = ++requestNumber.current;
440
+ setState({ status: "loading", who: null });
441
+ let who = { signedIn: false };
442
+ try {
443
+ who = await client.whoAmI();
444
+ } catch {
445
+ }
446
+ if (!mounted.current || currentRequest !== requestNumber.current) return;
447
+ setState({ status: who.signedIn ? "signedIn" : "anonymous", who });
448
+ }, [client]);
449
+ React.useEffect(() => {
450
+ mounted.current = true;
451
+ void refresh();
452
+ return () => {
453
+ mounted.current = false;
454
+ requestNumber.current += 1;
455
+ };
456
+ }, [refresh]);
457
+ const requestSignInLink = React.useCallback(
458
+ async (email, redirect) => {
459
+ try {
460
+ return await client.requestMagicLink(email, redirect);
461
+ } catch {
462
+ return false;
463
+ }
464
+ },
465
+ [client]
466
+ );
467
+ const prefill = React.useCallback(async () => {
468
+ try {
469
+ return await client.prefill();
470
+ } catch {
471
+ return null;
472
+ }
473
+ }, [client]);
474
+ const mintClaim = React.useCallback(async () => {
475
+ try {
476
+ return await client.mintPublicClaim();
477
+ } catch {
478
+ return null;
479
+ }
480
+ }, [client]);
481
+ return { ...state, refresh, requestSignInLink, prefill, mintClaim };
481
482
  }
482
483
 
483
484
  // src/identity.tsx
484
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
485
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
485
486
  var MAGIC_LINK_UNIFORM_MESSAGE = "If that email is known to this clinic, a sign-in link is on its way.";
486
487
  var EMPTY_IDENTITY = {
487
488
  givenName: "",
@@ -523,33 +524,49 @@ function toSessionInput(v) {
523
524
  dateOfBirth: v.dateOfBirth
524
525
  };
525
526
  }
526
- function SignInRamp({ portal, redirect }) {
527
- const [open, setOpen] = React.useState(false);
528
- const [email, setEmail] = React.useState("");
529
- const [sent, setSent] = React.useState(false);
530
- const [busy, setBusy] = React.useState(false);
531
- const available = portalBridgeAvailable(portal);
532
- const href = portalHref(portal);
527
+ function SignInRamp({ redirect }) {
528
+ const portal = usePortalClient();
529
+ const [open, setOpen] = React2.useState(false);
530
+ const [email, setEmail] = React2.useState("");
531
+ const [outcome, setOutcome] = React2.useState("idle");
532
+ const [busy, setBusy] = React2.useState(false);
533
+ const available = portal.available;
534
+ const href = portal.portalHref;
533
535
  if (!available) {
534
536
  if (!href) return null;
535
537
  return /* @__PURE__ */ jsxs2("p", { className: "sk-identity__ramp", children: [
536
538
  "Been here before?",
537
539
  " ",
538
- /* @__PURE__ */ jsx2("a", { href, className: "sk-identity__ramp-link", children: "Sign in to the patient portal" })
540
+ /* @__PURE__ */ jsx3("a", { href, className: "sk-identity__ramp-link", children: "Sign in to the patient portal" })
539
541
  ] });
540
542
  }
541
- if (sent) {
542
- return /* @__PURE__ */ jsx2("p", { className: "sk-identity__ramp sk-identity__ramp--sent", role: "status", "aria-live": "polite", children: MAGIC_LINK_UNIFORM_MESSAGE });
543
+ if (outcome === "sent") {
544
+ return /* @__PURE__ */ jsx3("p", { className: "sk-identity__ramp sk-identity__ramp--sent", role: "status", "aria-live": "polite", children: MAGIC_LINK_UNIFORM_MESSAGE });
545
+ }
546
+ if (outcome === "failed") {
547
+ return /* @__PURE__ */ jsxs2(
548
+ "p",
549
+ {
550
+ className: "sk-identity__ramp sk-identity__ramp--failed",
551
+ role: "status",
552
+ "aria-live": "polite",
553
+ children: [
554
+ "We couldn\u2019t reach the clinic.",
555
+ " ",
556
+ href ? /* @__PURE__ */ jsx3("a", { href, className: "sk-identity__ramp-link", children: "Try the patient portal directly" }) : "Please try the patient portal directly."
557
+ ]
558
+ }
559
+ );
543
560
  }
544
561
  if (!open) {
545
- return /* @__PURE__ */ jsx2("p", { className: "sk-identity__ramp", children: /* @__PURE__ */ jsx2("button", { type: "button", className: "sk-identity__ramp-link", onClick: () => setOpen(true), children: "Been here before? Get a sign-in link" }) });
562
+ return /* @__PURE__ */ jsx3("p", { className: "sk-identity__ramp", children: /* @__PURE__ */ jsx3("button", { type: "button", className: "sk-identity__ramp-link", onClick: () => setOpen(true), children: "Been here before? Get a sign-in link" }) });
546
563
  }
547
564
  return (
548
565
  // A nested <form> is illegal HTML, and the identity form is usually a form already —
549
566
  // so this is a div with an explicit click handler, not a form element.
550
567
  /* @__PURE__ */ jsxs2("div", { className: "sk-identity__ramp sk-identity__ramp--open", children: [
551
- /* @__PURE__ */ jsx2("label", { className: "sk-identity__label", htmlFor: "sk-ramp-email", children: "Your email" }),
552
- /* @__PURE__ */ jsx2(
568
+ /* @__PURE__ */ jsx3("label", { className: "sk-identity__label", htmlFor: "sk-ramp-email", children: "Your email" }),
569
+ /* @__PURE__ */ jsx3(
553
570
  "input",
554
571
  {
555
572
  id: "sk-ramp-email",
@@ -560,7 +577,7 @@ function SignInRamp({ portal, redirect }) {
560
577
  onChange: (e) => setEmail(e.target.value)
561
578
  }
562
579
  ),
563
- /* @__PURE__ */ jsx2(
580
+ /* @__PURE__ */ jsx3(
564
581
  FlowButton,
565
582
  {
566
583
  type: "button",
@@ -569,9 +586,8 @@ function SignInRamp({ portal, redirect }) {
569
586
  onClick: () => {
570
587
  if (busy) return;
571
588
  setBusy(true);
572
- void requestMagicLink(portal, email.trim(), redirect).finally(() => {
589
+ void portal.requestMagicLink(email.trim(), redirect ?? portal.returnPath()).then((reached) => setOutcome(reached ? "sent" : "failed")).catch(() => setOutcome("failed")).finally(() => {
573
590
  setBusy(false);
574
- setSent(true);
575
591
  });
576
592
  },
577
593
  children: busy ? "Sending\u2026" : "Send me a link"
@@ -589,16 +605,16 @@ function ConfirmIdentityCard({
589
605
  const given = prefill.givenName?.trim() || "";
590
606
  const name = [given, prefill.familyName?.trim() || ""].filter(Boolean).join(" ");
591
607
  return /* @__PURE__ */ jsxs2("div", { className: "sk-identity__confirm", children: [
592
- /* @__PURE__ */ jsx2("p", { className: "sk-identity__confirm-title", children: "Is this you?" }),
608
+ /* @__PURE__ */ jsx3("p", { className: "sk-identity__confirm-title", children: "Is this you?" }),
593
609
  /* @__PURE__ */ jsxs2("dl", { className: "sk-identity__confirm-list", children: [
594
- name && /* @__PURE__ */ jsx2(Row, { label: "Name", value: name }),
595
- prefill.dateOfBirth && /* @__PURE__ */ jsx2(Row, { label: "Date of birth", value: formatDobAu(prefill.dateOfBirth) }),
596
- prefill.email && /* @__PURE__ */ jsx2(Row, { label: "Email", value: prefill.email }),
597
- prefill.phone && /* @__PURE__ */ jsx2(Row, { label: "Phone", value: prefill.phone })
610
+ name && /* @__PURE__ */ jsx3(Row, { label: "Name", value: name }),
611
+ prefill.dateOfBirth && /* @__PURE__ */ jsx3(Row, { label: "Date of birth", value: formatDobAu(prefill.dateOfBirth) }),
612
+ prefill.email && /* @__PURE__ */ jsx3(Row, { label: "Email", value: prefill.email }),
613
+ prefill.phone && /* @__PURE__ */ jsx3(Row, { label: "Phone", value: prefill.phone })
598
614
  ] }),
599
615
  /* @__PURE__ */ jsxs2("div", { className: "sk-identity__confirm-actions", children: [
600
- /* @__PURE__ */ jsx2(FlowButton, { type: "button", variant: "primary", busy, onClick: onConfirm, children: given ? `Yes, continue as ${given}` : "Yes, that\u2019s me" }),
601
- /* @__PURE__ */ jsx2(FlowButton, { type: "button", variant: "quiet", disabled: busy, onClick: onReject, children: "Not you? Start fresh" })
616
+ /* @__PURE__ */ jsx3(FlowButton, { type: "button", variant: "primary", busy, onClick: onConfirm, children: given ? `Yes, continue as ${given}` : "Yes, that\u2019s me" }),
617
+ /* @__PURE__ */ jsx3(FlowButton, { type: "button", variant: "quiet", disabled: busy, onClick: onReject, children: "Not you? Start fresh" })
602
618
  ] })
603
619
  ] });
604
620
  }
@@ -625,8 +641,8 @@ function formatDobAu(iso) {
625
641
  }
626
642
  function Row({ label, value }) {
627
643
  return /* @__PURE__ */ jsxs2("div", { className: "sk-identity__confirm-row", children: [
628
- /* @__PURE__ */ jsx2("dt", { children: label }),
629
- /* @__PURE__ */ jsx2("dd", { children: value })
644
+ /* @__PURE__ */ jsx3("dt", { children: label }),
645
+ /* @__PURE__ */ jsx3("dd", { children: value })
630
646
  ] });
631
647
  }
632
648
  function IdentityForm({
@@ -641,7 +657,7 @@ function IdentityForm({
641
657
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
642
658
  return /* @__PURE__ */ jsxs2("div", { className: "sk-identity", children: [
643
659
  /* @__PURE__ */ jsxs2("div", { className: "sk-identity__grid", children: [
644
- /* @__PURE__ */ jsx2(Field, { id: `${idPrefix}-given`, label: "First name", error: errors2.givenName, children: /* @__PURE__ */ jsx2(
660
+ /* @__PURE__ */ jsx3(Field, { id: `${idPrefix}-given`, label: "First name", error: errors2.givenName, children: /* @__PURE__ */ jsx3(
645
661
  "input",
646
662
  {
647
663
  id: `${idPrefix}-given`,
@@ -654,7 +670,7 @@ function IdentityForm({
654
670
  onChange: (e) => set2("givenName", e.target.value)
655
671
  }
656
672
  ) }),
657
- /* @__PURE__ */ jsx2(Field, { id: `${idPrefix}-family`, label: "Last name", error: errors2.familyName, children: /* @__PURE__ */ jsx2(
673
+ /* @__PURE__ */ jsx3(Field, { id: `${idPrefix}-family`, label: "Last name", error: errors2.familyName, children: /* @__PURE__ */ jsx3(
658
674
  "input",
659
675
  {
660
676
  id: `${idPrefix}-family`,
@@ -667,7 +683,7 @@ function IdentityForm({
667
683
  onChange: (e) => set2("familyName", e.target.value)
668
684
  }
669
685
  ) }),
670
- /* @__PURE__ */ jsx2(Field, { id: `${idPrefix}-email`, label: "Email", error: errors2.email, wide: true, children: /* @__PURE__ */ jsx2(
686
+ /* @__PURE__ */ jsx3(Field, { id: `${idPrefix}-email`, label: "Email", error: errors2.email, wide: true, children: /* @__PURE__ */ jsx3(
671
687
  "input",
672
688
  {
673
689
  id: `${idPrefix}-email`,
@@ -680,7 +696,7 @@ function IdentityForm({
680
696
  onChange: (e) => set2("email", e.target.value)
681
697
  }
682
698
  ) }),
683
- /* @__PURE__ */ jsx2(Field, { id: `${idPrefix}-phone`, label: "Phone", error: errors2.phone, children: /* @__PURE__ */ jsx2(
699
+ /* @__PURE__ */ jsx3(Field, { id: `${idPrefix}-phone`, label: "Phone", error: errors2.phone, children: /* @__PURE__ */ jsx3(
684
700
  "input",
685
701
  {
686
702
  id: `${idPrefix}-phone`,
@@ -694,14 +710,14 @@ function IdentityForm({
694
710
  onChange: (e) => set2("phone", e.target.value)
695
711
  }
696
712
  ) }),
697
- /* @__PURE__ */ jsx2(
713
+ /* @__PURE__ */ jsx3(
698
714
  Field,
699
715
  {
700
716
  id: `${idPrefix}-dob`,
701
717
  label: "Date of birth",
702
718
  error: errors2.dateOfBirth,
703
719
  help: "We ask so we match you to the right record.",
704
- children: /* @__PURE__ */ jsx2(
720
+ children: /* @__PURE__ */ jsx3(
705
721
  "input",
706
722
  {
707
723
  id: `${idPrefix}-dob`,
@@ -721,16 +737,16 @@ function IdentityForm({
721
737
  )
722
738
  ] }),
723
739
  address && /* @__PURE__ */ jsxs2(Fragment, { children: [
724
- /* @__PURE__ */ jsx2("p", { className: "sk-identity__section", id: `${idPrefix}-address-heading`, children: "Residential address" }),
725
- /* @__PURE__ */ jsx2("p", { className: "sk-identity__section-note", id: `${idPrefix}-address-note`, children: "A practitioner can only issue to a patient they have identified, so your address goes on your patient record." }),
726
- /* @__PURE__ */ jsx2(
740
+ /* @__PURE__ */ jsx3("p", { className: "sk-identity__section", id: `${idPrefix}-address-heading`, children: "Residential address" }),
741
+ /* @__PURE__ */ jsx3("p", { className: "sk-identity__section-note", id: `${idPrefix}-address-note`, children: "A practitioner can only issue to a patient they have identified, so your address goes on your patient record." }),
742
+ /* @__PURE__ */ jsx3(
727
743
  "div",
728
744
  {
729
745
  className: "sk-identity__grid",
730
746
  role: "group",
731
747
  "aria-labelledby": `${idPrefix}-address-heading`,
732
748
  "aria-describedby": `${idPrefix}-address-note`,
733
- children: /* @__PURE__ */ jsx2(
749
+ children: /* @__PURE__ */ jsx3(
734
750
  AddressPicker,
735
751
  {
736
752
  idPrefix,
@@ -758,28 +774,28 @@ function Field({
758
774
  }) {
759
775
  const helpId = help ? `${id}-help` : void 0;
760
776
  const errorId = error2 ? `${id}-error` : void 0;
761
- const control = React.isValidElement(children) ? React.cloneElement(children, {
777
+ const control = React2.isValidElement(children) ? React2.cloneElement(children, {
762
778
  "aria-describedby": describedBy(helpId, errorId),
763
779
  "aria-invalid": error2 ? true : void 0
764
780
  }) : children;
765
781
  return /* @__PURE__ */ jsxs2("div", { className: ["sk-identity__field", wide ? "sk-identity__field--wide" : ""].filter(Boolean).join(" "), children: [
766
- /* @__PURE__ */ jsx2("label", { className: "sk-identity__label", htmlFor: id, children: label }),
782
+ /* @__PURE__ */ jsx3("label", { className: "sk-identity__label", htmlFor: id, children: label }),
767
783
  control,
768
- help && /* @__PURE__ */ jsx2("p", { className: "sk-identity__help", id: helpId, children: help }),
769
- /* @__PURE__ */ jsx2(FlowError, { id: errorId, children: error2 })
784
+ help && /* @__PURE__ */ jsx3("p", { className: "sk-identity__help", id: helpId, children: help }),
785
+ /* @__PURE__ */ jsx3(FlowError, { id: errorId, children: error2 })
770
786
  ] });
771
787
  }
772
788
  async function probeIdentity(portal) {
773
- const who = await fetchWhoAmI(portal);
789
+ const who = await portal.whoAmI();
774
790
  if (!who.signedIn) return { state: "anonymous" };
775
- const prefill = await fetchPrefill(portal);
791
+ const prefill = await portal.prefill();
776
792
  if (!prefill) return { state: "anonymous" };
777
793
  return { state: "signed-in", prefill };
778
794
  }
779
795
 
780
796
  // src/turnstile.tsx
781
- import * as React2 from "react";
782
- import { jsx as jsx3 } from "react/jsx-runtime";
797
+ import * as React3 from "react";
798
+ import { jsx as jsx4 } from "react/jsx-runtime";
783
799
  function loadTurnstileScript() {
784
800
  if (typeof window === "undefined") return Promise.resolve();
785
801
  if (window.turnstile) return Promise.resolve();
@@ -800,14 +816,14 @@ function TurnstileWidget({
800
816
  onToken,
801
817
  onError
802
818
  }) {
803
- const containerRef = React2.useRef(null);
804
- const widgetIdRef = React2.useRef(null);
805
- const onTokenRef = React2.useRef(onToken);
806
- const onErrorRef = React2.useRef(onError);
819
+ const containerRef = React3.useRef(null);
820
+ const widgetIdRef = React3.useRef(null);
821
+ const onTokenRef = React3.useRef(onToken);
822
+ const onErrorRef = React3.useRef(onError);
807
823
  onTokenRef.current = onToken;
808
824
  onErrorRef.current = onError;
809
825
  const key = siteKey?.trim() ?? "";
810
- React2.useEffect(() => {
826
+ React3.useEffect(() => {
811
827
  if (!key) return;
812
828
  let cancelled = false;
813
829
  const container = containerRef.current;
@@ -833,25 +849,37 @@ function TurnstileWidget({
833
849
  };
834
850
  }, [key]);
835
851
  if (!key) return null;
836
- return /* @__PURE__ */ jsx3("div", { ref: containerRef, className: "sk-turnstile" });
852
+ return /* @__PURE__ */ jsx4("div", { ref: containerRef, className: "sk-turnstile" });
837
853
  }
838
854
  function turnstileRequired(siteKey) {
839
855
  return (siteKey?.trim().length ?? 0) > 0;
840
856
  }
841
857
 
842
858
  // src/booking-block.client.tsx
843
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
859
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
844
860
  function BookingBlockClient(props) {
861
+ const portalClient = React4.useMemo(
862
+ () => createPortalClient({
863
+ apiOrigin: props.publicApi?.portalApiOrigin,
864
+ portalOrigin: props.publicApi?.portalOrigin,
865
+ portalUrl: props.publicApi?.portalUrl
866
+ }),
867
+ [
868
+ props.publicApi?.portalApiOrigin,
869
+ props.publicApi?.portalOrigin,
870
+ props.publicApi?.portalUrl
871
+ ]
872
+ );
845
873
  if (!props.publicApi?.publishableKey) {
846
874
  return /* @__PURE__ */ jsxs3("div", { className: "sk-booking__unconfigured", children: [
847
- /* @__PURE__ */ jsx4("h2", { className: "sk-booking__heading", children: props.heading ?? "Book an appointment" }),
875
+ /* @__PURE__ */ jsx5("h2", { className: "sk-booking__heading", children: props.heading ?? "Book an appointment" }),
848
876
  /* @__PURE__ */ jsxs3("p", { className: "sk-booking__placeholder", children: [
849
877
  "Online booking isn\u2019t available right now.",
850
878
  props.clinicPhone ? ` Please call the clinic on ${props.clinicPhone}.` : " Please call the clinic."
851
879
  ] })
852
880
  ] });
853
881
  }
854
- return /* @__PURE__ */ jsx4(Booking, { ...props });
882
+ return /* @__PURE__ */ jsx5(PortalProvider, { client: portalClient, children: /* @__PURE__ */ jsx5(Booking, { ...props }) });
855
883
  }
856
884
  function Booking({
857
885
  publicApi,
@@ -862,27 +890,24 @@ function Booking({
862
890
  clinicPhone
863
891
  }) {
864
892
  const api = publicApi;
865
- const client = React3.useMemo(
893
+ const portal = usePortalClient();
894
+ const client = React4.useMemo(
866
895
  () => patientos({ publishableKey: api.publishableKey, apiBase: api.apiBase }),
867
896
  [api.publishableKey, api.apiBase]
868
897
  );
869
- const portal = React3.useMemo(
870
- () => ({ portalUrl: api.portalUrl, portalOrigin: api.portalOrigin }),
871
- [api.portalUrl, api.portalOrigin]
872
- );
873
- const pinned = React3.useMemo(() => ({ pinnedType: !!pinnedType }), [pinnedType]);
874
- const [state, setState] = React3.useState(null);
875
- const [identity, setIdentity] = React3.useState(EMPTY_IDENTITY);
876
- const [identityErrors, setIdentityErrors] = React3.useState({});
877
- const [prefill, setPrefill] = React3.useState(null);
878
- const [turnstileToken, setTurnstileToken] = React3.useState(null);
879
- const [contactId, setContactId] = React3.useState(null);
880
- const [busy, setBusy] = React3.useState(false);
881
- const [error2, setError] = React3.useState(null);
882
- const [tz, setTz] = React3.useState("Australia/Sydney");
883
- const [availabilityNonce, setAvailabilityNonce] = React3.useState(0);
884
- const holdRef = React3.useRef(null);
885
- const dispatch = React3.useCallback(
898
+ const pinned = React4.useMemo(() => ({ pinnedType: !!pinnedType }), [pinnedType]);
899
+ const [state, setState] = React4.useState(null);
900
+ const [identity, setIdentity] = React4.useState(EMPTY_IDENTITY);
901
+ const [identityErrors, setIdentityErrors] = React4.useState({});
902
+ const [prefill, setPrefill] = React4.useState(null);
903
+ const [turnstileToken, setTurnstileToken] = React4.useState(null);
904
+ const [contactId, setContactId] = React4.useState(null);
905
+ const [busy, setBusy] = React4.useState(false);
906
+ const [error2, setError] = React4.useState(null);
907
+ const [tz, setTz] = React4.useState("Australia/Sydney");
908
+ const [availabilityNonce, setAvailabilityNonce] = React4.useState(0);
909
+ const holdRef = React4.useRef(null);
910
+ const dispatch = React4.useCallback(
886
911
  (event) => {
887
912
  setState((prev) => {
888
913
  const current = prev ?? initialBookingState(pinnedType);
@@ -904,14 +929,14 @@ function Booking({
904
929
  },
905
930
  [pinnedType, pinned]
906
931
  );
907
- React3.useEffect(() => {
932
+ React4.useEffect(() => {
908
933
  dispatch({ type: "RESTORE", state: bookingStepFromUrl(window.location.search, pinnedType) });
909
934
  const onPop = () => dispatch({ type: "RESTORE", state: bookingStepFromUrl(window.location.search, pinnedType) });
910
935
  window.addEventListener("popstate", onPop);
911
936
  return () => window.removeEventListener("popstate", onPop);
912
937
  }, [dispatch, pinnedType]);
913
938
  const step = state?.step;
914
- React3.useEffect(() => {
939
+ React4.useEffect(() => {
915
940
  if (step !== "identity") return;
916
941
  let alive = true;
917
942
  void probeIdentity(portal).then((probe) => {
@@ -923,7 +948,7 @@ function Booking({
923
948
  alive = false;
924
949
  };
925
950
  }, [step, portal, dispatch]);
926
- const placeHold = React3.useCallback(
951
+ const placeHold = React4.useCallback(
927
952
  async (slot, appointmentTypeId) => {
928
953
  try {
929
954
  const hold = await client.createHold({
@@ -937,7 +962,7 @@ function Booking({
937
962
  },
938
963
  [client]
939
964
  );
940
- const commit = React3.useCallback(
965
+ const commit = React4.useCallback(
941
966
  async (resolvedContactId) => {
942
967
  if (!state?.slot || !state.appointmentTypeId) return;
943
968
  try {
@@ -1003,7 +1028,7 @@ function Booking({
1003
1028
  if (busy) return;
1004
1029
  setBusy(true);
1005
1030
  setError(null);
1006
- const claim = await mintPublicClaim(portal);
1031
+ const claim = await portal.mintPublicClaim();
1007
1032
  if (!claim) {
1008
1033
  setBusy(false);
1009
1034
  setError("Your sign-in has expired. Please enter your details below.");
@@ -1015,24 +1040,24 @@ function Booking({
1015
1040
  if (state?.slot && state.appointmentTypeId) void placeHold(state.slot, state.appointmentTypeId);
1016
1041
  await commit(claim.contactId);
1017
1042
  }
1018
- const back2 = React3.useCallback(() => dispatch({ type: "BACK" }), [dispatch]);
1019
- if (!state) return /* @__PURE__ */ jsx4(FlowLoading, {});
1043
+ const back2 = React4.useCallback(() => dispatch({ type: "BACK" }), [dispatch]);
1044
+ if (!state) return /* @__PURE__ */ jsx5(FlowLoading, {});
1020
1045
  const title = bookingStepTitle(state.step, clinicName);
1021
1046
  const showBack = canBookingGoBack(state, pinned);
1022
1047
  const chosenType = appointmentTypes.find((t) => t.id === state.appointmentTypeId) ?? null;
1023
1048
  switch (state.step) {
1024
1049
  case "type":
1025
- return /* @__PURE__ */ jsx4(FlowShell, { stepKey: "type", eyebrow: "Step 1 of 3", heading: heading2, stepNumber: 1, totalSteps: 3, documentTitle: title, children: appointmentTypes.length === 0 ? /* @__PURE__ */ jsxs3("p", { className: "sk-booking__empty", children: [
1050
+ return /* @__PURE__ */ jsx5(FlowShell, { stepKey: "type", eyebrow: "Step 1 of 3", heading: heading2, stepNumber: 1, totalSteps: 3, documentTitle: title, children: appointmentTypes.length === 0 ? /* @__PURE__ */ jsxs3("p", { className: "sk-booking__empty", children: [
1026
1051
  "Online booking isn\u2019t available right now.",
1027
1052
  clinicPhone ? ` Please call the clinic on ${clinicPhone}.` : " Please call the clinic."
1028
- ] }) : /* @__PURE__ */ jsx4("ul", { className: "sk-booking__list", children: appointmentTypes.map((t) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs3(
1053
+ ] }) : /* @__PURE__ */ jsx5("ul", { className: "sk-booking__list", children: appointmentTypes.map((t) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs3(
1029
1054
  "button",
1030
1055
  {
1031
1056
  type: "button",
1032
1057
  className: "sk-booking__option",
1033
1058
  onClick: () => dispatch({ type: "SELECT_TYPE", appointmentTypeId: t.id }),
1034
1059
  children: [
1035
- /* @__PURE__ */ jsx4("span", { className: "sk-booking__option-label", children: t.label }),
1060
+ /* @__PURE__ */ jsx5("span", { className: "sk-booking__option-label", children: t.label }),
1036
1061
  /* @__PURE__ */ jsxs3("span", { className: "sk-booking__option-meta", children: [
1037
1062
  t.durationMinutes ? `${t.durationMinutes} min` : "",
1038
1063
  t.modality === "telehealth" ? " \xB7 Telehealth" : ""
@@ -1053,8 +1078,8 @@ function Booking({
1053
1078
  documentTitle: title,
1054
1079
  onBack: showBack ? back2 : void 0,
1055
1080
  children: [
1056
- /* @__PURE__ */ jsx4(FlowError, { children: error2 }),
1057
- /* @__PURE__ */ jsx4(
1081
+ /* @__PURE__ */ jsx5(FlowError, { children: error2 }),
1082
+ /* @__PURE__ */ jsx5(
1058
1083
  SlotPicker,
1059
1084
  {
1060
1085
  client,
@@ -1087,17 +1112,11 @@ function Booking({
1087
1112
  totalSteps: 3,
1088
1113
  documentTitle: title,
1089
1114
  onBack: showBack ? back2 : void 0,
1090
- footer: /* @__PURE__ */ jsx4(FlowButton, { type: "submit", form: "sk-bk-identity", variant: "primary", busy, children: busy ? "Confirming\u2026" : "Confirm booking" }),
1115
+ footer: /* @__PURE__ */ jsx5(FlowButton, { type: "submit", form: "sk-bk-identity", variant: "primary", busy, children: busy ? "Confirming\u2026" : "Confirm booking" }),
1091
1116
  children: [
1092
- /* @__PURE__ */ jsx4(
1093
- SignInRamp,
1094
- {
1095
- portal,
1096
- redirect: typeof window === "undefined" ? void 0 : window.location.href
1097
- }
1098
- ),
1117
+ /* @__PURE__ */ jsx5(SignInRamp, {}),
1099
1118
  /* @__PURE__ */ jsxs3("form", { id: "sk-bk-identity", onSubmit: (e) => void handleAnonymousSubmit(e), noValidate: true, children: [
1100
- /* @__PURE__ */ jsx4(
1119
+ /* @__PURE__ */ jsx5(
1101
1120
  IdentityForm,
1102
1121
  {
1103
1122
  values: identity,
@@ -1107,7 +1126,7 @@ function Booking({
1107
1126
  idPrefix: "sk-bk"
1108
1127
  }
1109
1128
  ),
1110
- /* @__PURE__ */ jsx4(
1129
+ /* @__PURE__ */ jsx5(
1111
1130
  TurnstileWidget,
1112
1131
  {
1113
1132
  siteKey: api.turnstileSiteKey,
@@ -1116,7 +1135,7 @@ function Booking({
1116
1135
  }
1117
1136
  )
1118
1137
  ] }),
1119
- /* @__PURE__ */ jsx4(FlowError, { children: error2 })
1138
+ /* @__PURE__ */ jsx5(FlowError, { children: error2 })
1120
1139
  ]
1121
1140
  }
1122
1141
  );
@@ -1133,7 +1152,7 @@ function Booking({
1133
1152
  documentTitle: title,
1134
1153
  onBack: showBack ? back2 : void 0,
1135
1154
  children: [
1136
- prefill ? /* @__PURE__ */ jsx4(
1155
+ prefill ? /* @__PURE__ */ jsx5(
1137
1156
  ConfirmIdentityCard,
1138
1157
  {
1139
1158
  prefill,
@@ -1141,8 +1160,8 @@ function Booking({
1141
1160
  onConfirm: () => void handleSignedInConfirm(),
1142
1161
  onReject: () => dispatch({ type: "IDENTITY_REJECTED" })
1143
1162
  }
1144
- ) : /* @__PURE__ */ jsx4(FlowLoading, { message: "Checking your details\u2026" }),
1145
- /* @__PURE__ */ jsx4(FlowError, { children: error2 })
1163
+ ) : /* @__PURE__ */ jsx5(FlowLoading, { message: "Checking your details\u2026" }),
1164
+ /* @__PURE__ */ jsx5(FlowError, { children: error2 })
1146
1165
  ]
1147
1166
  }
1148
1167
  );
@@ -1153,14 +1172,14 @@ function Booking({
1153
1172
  " ",
1154
1173
  "We\u2019ve sent you a confirmation."
1155
1174
  ] }),
1156
- api.portalUrl && /* @__PURE__ */ jsx4("p", { className: "sk-booking__aside", children: /* @__PURE__ */ jsx4("a", { className: "sk-booking__link", href: api.portalUrl, children: "Manage this in the patient portal" }) }),
1157
- /* @__PURE__ */ jsx4("span", { hidden: true, "data-sk-contact-bound": contactId ? "1" : "0" })
1175
+ api.portalUrl && /* @__PURE__ */ jsx5("p", { className: "sk-booking__aside", children: /* @__PURE__ */ jsx5("a", { className: "sk-booking__link", href: api.portalUrl, children: "Manage this in the patient portal" }) }),
1176
+ /* @__PURE__ */ jsx5("span", { hidden: true, "data-sk-contact-bound": contactId ? "1" : "0" })
1158
1177
  ] });
1159
1178
  }
1160
1179
  }
1161
1180
 
1162
1181
  // src/certificate-funnel.client.tsx
1163
- import * as React15 from "react";
1182
+ import * as React16 from "react";
1164
1183
 
1165
1184
  // src/certificate-funnel-machine.ts
1166
1185
  var FUNNEL_STEPS = [
@@ -1472,14 +1491,14 @@ var STEP_TITLES = {
1472
1491
  };
1473
1492
 
1474
1493
  // src/flow-progress.ts
1475
- import * as React4 from "react";
1476
- var FlowShapeContext = React4.createContext(DEFAULT_SHAPE);
1494
+ import * as React5 from "react";
1495
+ var FlowShapeContext = React5.createContext(DEFAULT_SHAPE);
1477
1496
  function useStepProgress(step, questionIndex = 0) {
1478
- return stepProgress(step, React4.useContext(FlowShapeContext), questionIndex);
1497
+ return stepProgress(step, React5.useContext(FlowShapeContext), questionIndex);
1479
1498
  }
1480
1499
 
1481
1500
  // src/portal-panel.tsx
1482
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1501
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1483
1502
  var PORTAL_SURFACE_LABEL = {
1484
1503
  appointments: "Your appointments",
1485
1504
  documents: "Your documents",
@@ -1504,15 +1523,15 @@ function PortalPanel({
1504
1523
  props: { surface, portalUrl, portalApiOrigin },
1505
1524
  className: ["sk-portal-panel", className].filter(Boolean).join(" "),
1506
1525
  children: [
1507
- /* @__PURE__ */ jsx5("h2", { className: "sk-portal-panel__heading", children: PORTAL_SURFACE_LABEL[surface] ?? "Your portal" }),
1508
- /* @__PURE__ */ jsx5("p", { className: "sk-portal-panel__placeholder", children: /* @__PURE__ */ jsx5("a", { className: "sk-portal-panel__link", href: portalUrl ?? "/portal", children: "Sign in to your patient portal" }) })
1526
+ /* @__PURE__ */ jsx6("h2", { className: "sk-portal-panel__heading", children: PORTAL_SURFACE_LABEL[surface] ?? "Your portal" }),
1527
+ /* @__PURE__ */ jsx6("p", { className: "sk-portal-panel__placeholder", children: /* @__PURE__ */ jsx6("a", { className: "sk-portal-panel__link", href: portalUrl ?? "/portal", children: "Sign in to your patient portal" }) })
1509
1528
  ]
1510
1529
  }
1511
1530
  );
1512
1531
  }
1513
1532
 
1514
1533
  // src/payment.tsx
1515
- import * as React5 from "react";
1534
+ import * as React6 from "react";
1516
1535
 
1517
1536
  // src/bpoint-client.ts
1518
1537
  function bpoint() {
@@ -1587,7 +1606,7 @@ async function attachCardToAuthKey(authKey, card) {
1587
1606
  }
1588
1607
 
1589
1608
  // src/payment.tsx
1590
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1609
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1591
1610
  var PHASE_MICROCOPY = {
1592
1611
  init: "Preparing secure form\u2026",
1593
1612
  // Deliberately blank: the `FlowError` already carries the reason, and a second live
@@ -1647,19 +1666,19 @@ function PaymentStep({
1647
1666
  clinicPhone,
1648
1667
  onOutcome
1649
1668
  }) {
1650
- const [phase, setPhase] = React5.useState("init");
1651
- const [providerKey, setProviderKey] = React5.useState(null);
1652
- const [authKey, setAuthKey] = React5.useState(null);
1653
- const [amount, setAmount] = React5.useState(feeAmount);
1654
- const [artifacts, setArtifacts] = React5.useState(null);
1655
- const [error2, setError] = React5.useState(null);
1656
- const [card, setCard] = React5.useState({ number: "", expiry: "", cvn: "", name: "" });
1657
- const [cardErrors, setCardErrors] = React5.useState({});
1658
- const [initAttempt, setInitAttempt] = React5.useState(0);
1659
- const iframeRef = React5.useRef(null);
1669
+ const [phase, setPhase] = React6.useState("init");
1670
+ const [providerKey, setProviderKey] = React6.useState(null);
1671
+ const [authKey, setAuthKey] = React6.useState(null);
1672
+ const [amount, setAmount] = React6.useState(feeAmount);
1673
+ const [artifacts, setArtifacts] = React6.useState(null);
1674
+ const [error2, setError] = React6.useState(null);
1675
+ const [card, setCard] = React6.useState({ number: "", expiry: "", cvn: "", name: "" });
1676
+ const [cardErrors, setCardErrors] = React6.useState({});
1677
+ const [initAttempt, setInitAttempt] = React6.useState(0);
1678
+ const iframeRef = React6.useRef(null);
1660
1679
  const isMock = providerKey === "mock";
1661
1680
  const feeText = formatFee(amount);
1662
- const runConfirm = React5.useCallback(async () => {
1681
+ const runConfirm = React6.useCallback(async () => {
1663
1682
  setPhase("processing");
1664
1683
  try {
1665
1684
  const res = await client.payConfirm(requestId);
@@ -1690,7 +1709,7 @@ function PaymentStep({
1690
1709
  setPhase("ready");
1691
1710
  }
1692
1711
  }, [client, requestId, onOutcome]);
1693
- const runAuthenticate = React5.useCallback(async () => {
1712
+ const runAuthenticate = React6.useCallback(async () => {
1694
1713
  setError(null);
1695
1714
  setPhase("authenticating");
1696
1715
  try {
@@ -1707,7 +1726,7 @@ function PaymentStep({
1707
1726
  setPhase("ready");
1708
1727
  }
1709
1728
  }, [client, requestId, runConfirm]);
1710
- React5.useEffect(() => {
1729
+ React6.useEffect(() => {
1711
1730
  let alive = true;
1712
1731
  void (async () => {
1713
1732
  setPhase("init");
@@ -1742,7 +1761,7 @@ function PaymentStep({
1742
1761
  alive = false;
1743
1762
  };
1744
1763
  }, [client, requestId, initAttempt]);
1745
- React5.useEffect(() => {
1764
+ React6.useEffect(() => {
1746
1765
  const origin = artifacts?.iframeOrigin;
1747
1766
  if (phase !== "authenticating" || !origin) return;
1748
1767
  function onMessage(event) {
@@ -1815,14 +1834,14 @@ function PaymentStep({
1815
1834
  const microcopy = PHASE_MICROCOPY[phase];
1816
1835
  const holdLabel = feeText ? `Place ${feeText} hold` : "Place hold";
1817
1836
  return /* @__PURE__ */ jsxs5("div", { className: "sk-pay", children: [
1818
- isMock ? /* @__PURE__ */ jsx6("p", { className: "sk-pay__mock", children: "Mock payments mode \u2014 card entry is skipped. Continue to simulate an approved pre-authorisation." }) : phase === "init" ? /* @__PURE__ */ jsx6("p", { className: "sk-pay__loading", role: "status", "aria-live": "polite", children: "Preparing the secure card form\u2026" }) : phase === "init_failed" ? (
1837
+ isMock ? /* @__PURE__ */ jsx7("p", { className: "sk-pay__mock", children: "Mock payments mode \u2014 card entry is skipped. Continue to simulate an approved pre-authorisation." }) : phase === "init" ? /* @__PURE__ */ jsx7("p", { className: "sk-pay__loading", role: "status", "aria-live": "polite", children: "Preparing the secure card form\u2026" }) : phase === "init_failed" ? (
1819
1838
  // Nothing. There is no AuthKey, so four PAN fields and a promise about BPOINT
1820
1839
  // would be asking for a card we have no way to tokenise. The `FlowError` below
1821
1840
  // says what went wrong; the actions block says what to do about it.
1822
1841
  null
1823
1842
  ) : /* @__PURE__ */ jsxs5("form", { id: "sk-pay-form", className: "sk-pay__form", onSubmit: handleCardSubmit, noValidate: true, children: [
1824
- /* @__PURE__ */ jsx6(PaymentOrderSummary, { serviceLabel, feeText }),
1825
- /* @__PURE__ */ jsx6(CardField, { id: "sk-cc-number", label: "Card number", error: cardErrors.number, children: /* @__PURE__ */ jsx6(
1843
+ /* @__PURE__ */ jsx7(PaymentOrderSummary, { serviceLabel, feeText }),
1844
+ /* @__PURE__ */ jsx7(CardField, { id: "sk-cc-number", label: "Card number", error: cardErrors.number, children: /* @__PURE__ */ jsx7(
1826
1845
  "input",
1827
1846
  {
1828
1847
  id: "sk-cc-number",
@@ -1837,7 +1856,7 @@ function PaymentStep({
1837
1856
  }
1838
1857
  ) }),
1839
1858
  /* @__PURE__ */ jsxs5("div", { className: "sk-pay__row", children: [
1840
- /* @__PURE__ */ jsx6(CardField, { id: "sk-cc-expiry", label: "Expiry (MM/YY)", error: cardErrors.expiry, children: /* @__PURE__ */ jsx6(
1859
+ /* @__PURE__ */ jsx7(CardField, { id: "sk-cc-expiry", label: "Expiry (MM/YY)", error: cardErrors.expiry, children: /* @__PURE__ */ jsx7(
1841
1860
  "input",
1842
1861
  {
1843
1862
  id: "sk-cc-expiry",
@@ -1851,7 +1870,7 @@ function PaymentStep({
1851
1870
  onChange: (e) => setCard({ ...card, expiry: formatExpiry(e.target.value) })
1852
1871
  }
1853
1872
  ) }),
1854
- /* @__PURE__ */ jsx6(CardField, { id: "sk-cc-cvn", label: "Security code", error: cardErrors.cvn, children: /* @__PURE__ */ jsx6(
1873
+ /* @__PURE__ */ jsx7(CardField, { id: "sk-cc-cvn", label: "Security code", error: cardErrors.cvn, children: /* @__PURE__ */ jsx7(
1855
1874
  "input",
1856
1875
  {
1857
1876
  id: "sk-cc-cvn",
@@ -1866,7 +1885,7 @@ function PaymentStep({
1866
1885
  }
1867
1886
  ) })
1868
1887
  ] }),
1869
- /* @__PURE__ */ jsx6(CardField, { id: "sk-cc-name", label: "Name on card", error: cardErrors.name, children: /* @__PURE__ */ jsx6(
1888
+ /* @__PURE__ */ jsx7(CardField, { id: "sk-cc-name", label: "Name on card", error: cardErrors.name, children: /* @__PURE__ */ jsx7(
1870
1889
  "input",
1871
1890
  {
1872
1891
  id: "sk-cc-name",
@@ -1879,7 +1898,7 @@ function PaymentStep({
1879
1898
  }
1880
1899
  ) }),
1881
1900
  /* @__PURE__ */ jsxs5("p", { className: "sk-pay__secure", children: [
1882
- /* @__PURE__ */ jsx6(
1901
+ /* @__PURE__ */ jsx7(
1883
1902
  "svg",
1884
1903
  {
1885
1904
  className: "sk-pay__secure-icon",
@@ -1888,7 +1907,7 @@ function PaymentStep({
1888
1907
  height: "14",
1889
1908
  "aria-hidden": "true",
1890
1909
  focusable: "false",
1891
- children: /* @__PURE__ */ jsx6(
1910
+ children: /* @__PURE__ */ jsx7(
1892
1911
  "path",
1893
1912
  {
1894
1913
  d: "M4.5 7V5a3.5 3.5 0 0 1 7 0v2M3.75 7h8.5a.75.75 0 0 1 .75.75v5.5a.75.75 0 0 1-.75.75h-8.5a.75.75 0 0 1-.75-.75v-5.5A.75.75 0 0 1 3.75 7Z",
@@ -1904,7 +1923,7 @@ function PaymentStep({
1904
1923
  "Your card details go straight to BPOINT, our Australian payment gateway, and are never sent to or stored on this clinic\u2019s systems."
1905
1924
  ] })
1906
1925
  ] }),
1907
- phase === "authenticating" && artifacts?.iframeUrl && /* @__PURE__ */ jsx6(
1926
+ phase === "authenticating" && artifacts?.iframeUrl && /* @__PURE__ */ jsx7(
1908
1927
  "iframe",
1909
1928
  {
1910
1929
  ref: iframeRef,
@@ -1914,8 +1933,8 @@ function PaymentStep({
1914
1933
  style: { width: "100%", height: "1px", visibility: "hidden", border: "none" }
1915
1934
  }
1916
1935
  ),
1917
- /* @__PURE__ */ jsx6(FlowError, { children: error2 }),
1918
- microcopy && /* @__PURE__ */ jsx6("p", { className: "sk-pay__status", role: "status", "aria-live": "polite", children: microcopy }),
1936
+ /* @__PURE__ */ jsx7(FlowError, { children: error2 }),
1937
+ microcopy && /* @__PURE__ */ jsx7("p", { className: "sk-pay__status", role: "status", "aria-live": "polite", children: microcopy }),
1919
1938
  phase === "init_failed" && clinicPhone && /* @__PURE__ */ jsxs5("p", { className: "sk-cf__body", children: [
1920
1939
  "Still not working?",
1921
1940
  " ",
@@ -1924,12 +1943,12 @@ function PaymentStep({
1924
1943
  clinicPhone
1925
1944
  ] })
1926
1945
  ] }),
1927
- /* @__PURE__ */ jsx6("div", { className: "sk-pay__actions", children: phase === "init_failed" ? (
1946
+ /* @__PURE__ */ jsx7("div", { className: "sk-pay__actions", children: phase === "init_failed" ? (
1928
1947
  // NOT `busy` — `busy` is `phase !== 'ready'`, which would render the one control
1929
1948
  // on this screen disabled and reinstate the defect this branch exists to fix.
1930
1949
  // NOT `holdLabel` either: no hold exists yet, so naming the amount here would
1931
1950
  // promise something this press does not do.
1932
- /* @__PURE__ */ jsx6(
1951
+ /* @__PURE__ */ jsx7(
1933
1952
  FlowButton,
1934
1953
  {
1935
1954
  type: "button",
@@ -1938,7 +1957,7 @@ function PaymentStep({
1938
1957
  children: "Try again"
1939
1958
  }
1940
1959
  )
1941
- ) : isMock ? /* @__PURE__ */ jsx6(FlowButton, { type: "button", variant: "primary", busy, onClick: () => void runConfirm(), children: busy ? "Securing\u2026" : `${holdLabel} & continue` }) : /* @__PURE__ */ jsx6(FlowButton, { type: "submit", form: "sk-pay-form", variant: "primary", busy, children: busy ? "Securing\u2026" : holdLabel }) })
1960
+ ) : isMock ? /* @__PURE__ */ jsx7(FlowButton, { type: "button", variant: "primary", busy, onClick: () => void runConfirm(), children: busy ? "Securing\u2026" : `${holdLabel} & continue` }) : /* @__PURE__ */ jsx7(FlowButton, { type: "submit", form: "sk-pay-form", variant: "primary", busy, children: busy ? "Securing\u2026" : holdLabel }) })
1942
1961
  ] });
1943
1962
  }
1944
1963
  function PaymentOrderSummary({
@@ -1946,8 +1965,8 @@ function PaymentOrderSummary({
1946
1965
  feeText
1947
1966
  }) {
1948
1967
  return /* @__PURE__ */ jsxs5("dl", { className: "sk-pay__summary", children: [
1949
- /* @__PURE__ */ jsx6("dt", { children: serviceLabel }),
1950
- feeText && /* @__PURE__ */ jsx6("dd", { children: feeText })
1968
+ /* @__PURE__ */ jsx7("dt", { children: serviceLabel }),
1969
+ feeText && /* @__PURE__ */ jsx7("dd", { children: feeText })
1951
1970
  ] });
1952
1971
  }
1953
1972
  function CardField({
@@ -1957,14 +1976,14 @@ function CardField({
1957
1976
  children
1958
1977
  }) {
1959
1978
  return /* @__PURE__ */ jsxs5("div", { className: "sk-pay__field", children: [
1960
- /* @__PURE__ */ jsx6("label", { className: "sk-pay__label", htmlFor: id, children: label }),
1979
+ /* @__PURE__ */ jsx7("label", { className: "sk-pay__label", htmlFor: id, children: label }),
1961
1980
  children,
1962
- /* @__PURE__ */ jsx6(FlowError, { children: error2 })
1981
+ /* @__PURE__ */ jsx7(FlowError, { children: error2 })
1963
1982
  ] });
1964
1983
  }
1965
1984
 
1966
1985
  // src/certificate-funnel-steps/service-step.tsx
1967
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1986
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1968
1987
  var printsPrice = (fee) => !!fee?.requiresPayment && formatFee(fee.amount) !== "";
1969
1988
  var HOLD_NOTE = "Where a price is shown, that amount is held on your card at the payment step and charged only if what you asked for is issued.";
1970
1989
  var DELIVERY_NOTE = {
@@ -1998,10 +2017,10 @@ function ServiceStep({
1998
2017
  "Online certificate requests aren\u2019t available right now.",
1999
2018
  clinicPhone ? ` Please call the clinic on ${clinicPhone}.` : " Please call the clinic."
2000
2019
  ] })
2001
- ) : /* @__PURE__ */ jsx7("ul", { className: "sk-cf__services", "aria-busy": deliveryPending || void 0, children: services.map((s) => {
2020
+ ) : /* @__PURE__ */ jsx8("ul", { className: "sk-cf__services", "aria-busy": deliveryPending || void 0, children: services.map((s) => {
2002
2021
  const note = feeRowNote(fees?.[s.key]);
2003
2022
  const deliveryNote = deliveryModes?.[s.key] ? DELIVERY_NOTE[deliveryModes[s.key]] : "";
2004
- return /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsxs6(
2023
+ return /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsxs6(
2005
2024
  "button",
2006
2025
  {
2007
2026
  type: "button",
@@ -2011,27 +2030,27 @@ function ServiceStep({
2011
2030
  "data-sk-service": s.key,
2012
2031
  children: [
2013
2032
  /* @__PURE__ */ jsxs6("span", { className: "sk-cf__service-body", children: [
2014
- /* @__PURE__ */ jsx7("span", { className: "sk-cf__service-label", children: s.label }),
2015
- deliveryNote && /* @__PURE__ */ jsx7("span", { className: "sk-cf__service-delivery", children: deliveryNote }),
2016
- note && /* @__PURE__ */ jsx7("span", { className: "sk-cf__service-fee", children: note })
2033
+ /* @__PURE__ */ jsx8("span", { className: "sk-cf__service-label", children: s.label }),
2034
+ deliveryNote && /* @__PURE__ */ jsx8("span", { className: "sk-cf__service-delivery", children: deliveryNote }),
2035
+ note && /* @__PURE__ */ jsx8("span", { className: "sk-cf__service-fee", children: note })
2017
2036
  ] }),
2018
- /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", className: "sk-cf__service-chevron", children: "\u2192" })
2037
+ /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "sk-cf__service-chevron", children: "\u2192" })
2019
2038
  ]
2020
2039
  }
2021
2040
  ) }, s.key);
2022
2041
  }) }),
2023
- deliveryPending && /* @__PURE__ */ jsx7("p", { className: "sk-cf__services-note", role: "status", "aria-live": "polite", children: "Loading what happens next\u2026" }),
2024
- services.some((s) => printsPrice(fees?.[s.key])) && /* @__PURE__ */ jsx7("p", { className: "sk-cf__services-note", children: HOLD_NOTE }),
2025
- !deliveryPending && services.some((s) => !!deliveryModes?.[s.key]) && /* @__PURE__ */ jsx7("p", { className: "sk-cf__services-note", children: "We\u2019ll email you about what happens next. If a document is issued, we\u2019ll email you a secure download link." }),
2026
- /* @__PURE__ */ jsx7("div", { className: "sk-cf__after", children: /* @__PURE__ */ jsx7(FlowButton, { type: "button", variant: "quiet", onClick: onNeedDifferent, children: "I need a different type of certificate" }) })
2042
+ deliveryPending && /* @__PURE__ */ jsx8("p", { className: "sk-cf__services-note", role: "status", "aria-live": "polite", children: "Loading what happens next\u2026" }),
2043
+ services.some((s) => printsPrice(fees?.[s.key])) && /* @__PURE__ */ jsx8("p", { className: "sk-cf__services-note", children: HOLD_NOTE }),
2044
+ !deliveryPending && services.some((s) => !!deliveryModes?.[s.key]) && /* @__PURE__ */ jsx8("p", { className: "sk-cf__services-note", children: "We\u2019ll email you about what happens next. If a document is issued, we\u2019ll email you a secure download link." }),
2045
+ /* @__PURE__ */ jsx8("div", { className: "sk-cf__after", children: /* @__PURE__ */ jsx8(FlowButton, { type: "button", variant: "quiet", onClick: onNeedDifferent, children: "I need a different type of certificate" }) })
2027
2046
  ]
2028
2047
  }
2029
2048
  );
2030
2049
  }
2031
2050
 
2032
2051
  // src/certificate-funnel-steps/preflight-step.tsx
2033
- import * as React6 from "react";
2034
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2052
+ import * as React7 from "react";
2053
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2035
2054
  var EMERGENCY = "000";
2036
2055
  var POLICY_LINKS = { terms: "/terms", privacy: "/privacy" };
2037
2056
  var PREFLIGHT_STATEMENTS = [
@@ -2094,7 +2113,7 @@ function PreflightStep({
2094
2113
  onBack,
2095
2114
  documentTitle
2096
2115
  }) {
2097
- const [declining, setDeclining] = React6.useState(false);
2116
+ const [declining, setDeclining] = React7.useState(false);
2098
2117
  return /* @__PURE__ */ jsxs7(
2099
2118
  FlowShell,
2100
2119
  {
@@ -2124,7 +2143,7 @@ function PreflightStep({
2124
2143
  // visible subheading ("Please read all five…") and the primary button ("Yes —
2125
2144
  // all five are true"), so what AT speaks matches what the screen says.
2126
2145
  /* @__PURE__ */ jsxs7("div", { className: "sk-cf__actions", role: "group", "aria-label": "Are all five statements true?", children: [
2127
- /* @__PURE__ */ jsx8(
2146
+ /* @__PURE__ */ jsx9(
2128
2147
  FlowButton,
2129
2148
  {
2130
2149
  type: "button",
@@ -2134,7 +2153,7 @@ function PreflightStep({
2134
2153
  children: "Yes \u2014 all five are true"
2135
2154
  }
2136
2155
  ),
2137
- /* @__PURE__ */ jsx8(
2156
+ /* @__PURE__ */ jsx9(
2138
2157
  FlowButton,
2139
2158
  {
2140
2159
  type: "button",
@@ -2153,7 +2172,7 @@ function PreflightStep({
2153
2172
  // the list gets the question as its accessible name. `aria-label` on the `<ul>`
2154
2173
  // rather than `role="group"`: naming it keeps `role="list"`, so AT still says how
2155
2174
  // many options there are — a count the patient wants and a group would swallow.
2156
- /* @__PURE__ */ jsx8("ul", { className: "sk-pf__declines", "aria-label": "Which one doesn\u2019t apply?", children: PREFLIGHT_DISPLAY_STATEMENTS.map((s) => /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsxs7(
2175
+ /* @__PURE__ */ jsx9("ul", { className: "sk-pf__declines", "aria-label": "Which one doesn\u2019t apply?", children: PREFLIGHT_DISPLAY_STATEMENTS.map((s) => /* @__PURE__ */ jsx9("li", { children: /* @__PURE__ */ jsxs7(
2157
2176
  "button",
2158
2177
  {
2159
2178
  type: "button",
@@ -2161,24 +2180,24 @@ function PreflightStep({
2161
2180
  onClick: () => s.exit.kind === "out-of-scope" ? onOutOfScope() : onExit(s.exit),
2162
2181
  "data-sk-preflight-decline": s.id,
2163
2182
  children: [
2164
- /* @__PURE__ */ jsx8("span", { className: "sk-pf__decline-label", children: s.decline }),
2165
- /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "sk-cf__service-chevron", children: "\u2192" })
2183
+ /* @__PURE__ */ jsx9("span", { className: "sk-pf__decline-label", children: s.decline }),
2184
+ /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", className: "sk-cf__service-chevron", children: "\u2192" })
2166
2185
  ]
2167
2186
  }
2168
2187
  ) }, s.id)) })
2169
- ) : /* @__PURE__ */ jsx8("ol", { className: "sk-pf__statements", children: PREFLIGHT_DISPLAY_STATEMENTS.map((s, i) => /* @__PURE__ */ jsxs7("li", { className: "sk-pf__statement", children: [
2170
- /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "sk-pf__num", children: i + 1 }),
2188
+ ) : /* @__PURE__ */ jsx9("ol", { className: "sk-pf__statements", children: PREFLIGHT_DISPLAY_STATEMENTS.map((s, i) => /* @__PURE__ */ jsxs7("li", { className: "sk-pf__statement", children: [
2189
+ /* @__PURE__ */ jsx9("span", { "aria-hidden": "true", className: "sk-pf__num", children: i + 1 }),
2171
2190
  /* @__PURE__ */ jsxs7("div", { className: "sk-pf__statement-body", children: [
2172
- /* @__PURE__ */ jsx8("p", { className: "sk-pf__statement-title", children: s.title }),
2191
+ /* @__PURE__ */ jsx9("p", { className: "sk-pf__statement-title", children: s.title }),
2173
2192
  /* @__PURE__ */ jsxs7("p", { className: "sk-pf__statement-detail", children: [
2174
2193
  s.detail,
2175
2194
  s.id === "terms" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
2176
2195
  " ",
2177
- /* @__PURE__ */ jsx8("a", { className: "sk-cf__link", href: POLICY_LINKS.terms, children: "Read the terms" }),
2196
+ /* @__PURE__ */ jsx9("a", { className: "sk-cf__link", href: POLICY_LINKS.terms, children: "Read the terms" }),
2178
2197
  " ",
2179
2198
  "and the",
2180
2199
  " ",
2181
- /* @__PURE__ */ jsx8("a", { className: "sk-cf__link", href: POLICY_LINKS.privacy, children: "privacy policy" }),
2200
+ /* @__PURE__ */ jsx9("a", { className: "sk-cf__link", href: POLICY_LINKS.privacy, children: "privacy policy" }),
2182
2201
  "."
2183
2202
  ] })
2184
2203
  ] })
@@ -2194,8 +2213,8 @@ function PreflightStep({
2194
2213
  }
2195
2214
 
2196
2215
  // src/certificate-funnel-steps/identity-step.tsx
2197
- import * as React7 from "react";
2198
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2216
+ import * as React8 from "react";
2217
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2199
2218
  var IDENTITY_ID_PREFIX = "sk-id";
2200
2219
  var IDENTITY_FIELDS = [
2201
2220
  { key: "givenName", id: `${IDENTITY_ID_PREFIX}-given`, label: "First name" },
@@ -2211,20 +2230,21 @@ function midSentence(label) {
2211
2230
  }
2212
2231
  var detailsSubheading = (serviceLabel) => `We\u2019ll use these to identify you and contact you about your ${midSentence(serviceLabel)}.`;
2213
2232
  function IdentityStep(props) {
2214
- const { client, portal, mode, onSignedIn, onRejected, onStarted, onBack, documentTitle } = props;
2233
+ const { client, mode, onSignedIn, onRejected, onStarted, onBack, documentTitle } = props;
2234
+ const portal = usePortalClient();
2215
2235
  const progress = useStepProgress(mode);
2216
- const [identity, setIdentity] = React7.useState(
2236
+ const [identity, setIdentity] = React8.useState(
2217
2237
  props.draft?.identity ?? EMPTY_IDENTITY
2218
2238
  );
2219
- const [address, setAddress] = React7.useState(props.draft?.address ?? EMPTY_ADDRESS);
2220
- const [identityErrors, setIdentityErrors] = React7.useState({});
2221
- const [addressErrors, setAddressErrors] = React7.useState({});
2222
- const [turnstileToken, setTurnstileToken] = React7.useState(null);
2223
- const [busy, setBusy] = React7.useState(false);
2224
- const [error2, setError] = React7.useState(null);
2225
- const [prefill, setPrefill] = React7.useState(null);
2226
- const [probing, setProbing] = React7.useState(mode === "identity" && !props.draft);
2227
- React7.useEffect(() => {
2239
+ const [address, setAddress] = React8.useState(props.draft?.address ?? EMPTY_ADDRESS);
2240
+ const [identityErrors, setIdentityErrors] = React8.useState({});
2241
+ const [addressErrors, setAddressErrors] = React8.useState({});
2242
+ const [turnstileToken, setTurnstileToken] = React8.useState(null);
2243
+ const [busy, setBusy] = React8.useState(false);
2244
+ const [error2, setError] = React8.useState(null);
2245
+ const [prefill, setPrefill] = React8.useState(null);
2246
+ const [probing, setProbing] = React8.useState(mode === "identity" && !props.draft);
2247
+ React8.useEffect(() => {
2228
2248
  if (mode !== "identity" || props.draft) return;
2229
2249
  let alive = true;
2230
2250
  void probeIdentity(portal).then((probe) => {
@@ -2239,7 +2259,7 @@ function IdentityStep(props) {
2239
2259
  alive = false;
2240
2260
  };
2241
2261
  }, []);
2242
- React7.useEffect(() => {
2262
+ React8.useEffect(() => {
2243
2263
  if (mode !== "confirm-identity" || prefill) return;
2244
2264
  let alive = true;
2245
2265
  void probeIdentity(portal).then((probe) => {
@@ -2252,17 +2272,17 @@ function IdentityStep(props) {
2252
2272
  };
2253
2273
  }, [mode, prefill, portal, onRejected]);
2254
2274
  const { onDraftChange } = props;
2255
- React7.useEffect(() => {
2275
+ React8.useEffect(() => {
2256
2276
  onDraftChange?.({ identity, address });
2257
2277
  }, [identity, address, onDraftChange]);
2258
- const addressSearch = React7.useCallback(
2278
+ const addressSearch = React8.useCallback(
2259
2279
  async (q) => {
2260
2280
  const res = await client.suggestAddress(q);
2261
2281
  return res.disabled ? [] : res.suggestions ?? [];
2262
2282
  },
2263
2283
  [client]
2264
2284
  );
2265
- const addressValidate = React7.useCallback(
2285
+ const addressValidate = React8.useCallback(
2266
2286
  async (a) => {
2267
2287
  const res = await client.resolveAddress(a);
2268
2288
  const confirmed = res.disabled ? null : res.address?.formattedAddress ?? null;
@@ -2270,7 +2290,7 @@ function IdentityStep(props) {
2270
2290
  },
2271
2291
  [client]
2272
2292
  );
2273
- const startRequest = React7.useCallback(
2293
+ const startRequest = React8.useCallback(
2274
2294
  async (capturedIdentity) => {
2275
2295
  const { requestId } = await client.startRequest({ serviceKey: props.serviceKey });
2276
2296
  onStarted(requestId, capturedIdentity);
@@ -2282,7 +2302,7 @@ function IdentityStep(props) {
2282
2302
  setBusy(true);
2283
2303
  setError(null);
2284
2304
  try {
2285
- const claim = await mintPublicClaim(portal);
2305
+ const claim = await portal.mintPublicClaim();
2286
2306
  if (!claim) {
2287
2307
  setError("Your sign-in has expired. Please enter your details below.");
2288
2308
  setBusy(false);
@@ -2366,7 +2386,7 @@ function IdentityStep(props) {
2366
2386
  onBack,
2367
2387
  documentTitle,
2368
2388
  children: [
2369
- prefill ? /* @__PURE__ */ jsx9(
2389
+ prefill ? /* @__PURE__ */ jsx10(
2370
2390
  ConfirmIdentityCard,
2371
2391
  {
2372
2392
  prefill,
@@ -2374,14 +2394,14 @@ function IdentityStep(props) {
2374
2394
  onConfirm: () => void handleConfirmSignedIn(),
2375
2395
  onReject: onRejected
2376
2396
  }
2377
- ) : /* @__PURE__ */ jsx9(FlowLoading, { message: "Checking your details\u2026" }),
2378
- /* @__PURE__ */ jsx9(FlowError, { children: error2 })
2397
+ ) : /* @__PURE__ */ jsx10(FlowLoading, { message: "Checking your details\u2026" }),
2398
+ /* @__PURE__ */ jsx10(FlowError, { children: error2 })
2379
2399
  ]
2380
2400
  }
2381
2401
  );
2382
2402
  }
2383
2403
  const invalid = invalidFields(IDENTITY_FIELDS, { ...identityErrors, ...addressErrors });
2384
- return /* @__PURE__ */ jsx9(
2404
+ return /* @__PURE__ */ jsx10(
2385
2405
  FlowShell,
2386
2406
  {
2387
2407
  ...progress,
@@ -2390,12 +2410,12 @@ function IdentityStep(props) {
2390
2410
  subheading: detailsSubheading(props.serviceLabel),
2391
2411
  onBack,
2392
2412
  documentTitle,
2393
- footer: probing ? void 0 : /* @__PURE__ */ jsx9(FlowButton, { type: "submit", form: "sk-cf-identity", variant: "primary", busy, children: busy ? "Starting\u2026" : "Continue" }),
2394
- children: probing ? /* @__PURE__ */ jsx9(FlowLoading, { message: "Checking if you\u2019re signed in\u2026" }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
2395
- /* @__PURE__ */ jsx9(SignInRamp, { portal, redirect: props.returnUrl }),
2396
- /* @__PURE__ */ jsx9(FlowErrorSummary, { fields: invalid }),
2413
+ footer: probing ? void 0 : /* @__PURE__ */ jsx10(FlowButton, { type: "submit", form: "sk-cf-identity", variant: "primary", busy, children: busy ? "Starting\u2026" : "Continue" }),
2414
+ children: probing ? /* @__PURE__ */ jsx10(FlowLoading, { message: "Checking if you\u2019re signed in\u2026" }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
2415
+ /* @__PURE__ */ jsx10(SignInRamp, { redirect: props.returnUrl }),
2416
+ /* @__PURE__ */ jsx10(FlowErrorSummary, { fields: invalid }),
2397
2417
  /* @__PURE__ */ jsxs8("form", { id: "sk-cf-identity", onSubmit: (e) => void handleSubmitAnonymous(e), noValidate: true, children: [
2398
- /* @__PURE__ */ jsx9(SummarisedFieldErrors, { children: /* @__PURE__ */ jsx9(
2418
+ /* @__PURE__ */ jsx10(SummarisedFieldErrors, { children: /* @__PURE__ */ jsx10(
2399
2419
  IdentityForm,
2400
2420
  {
2401
2421
  idPrefix: IDENTITY_ID_PREFIX,
@@ -2412,7 +2432,7 @@ function IdentityStep(props) {
2412
2432
  disabled: busy
2413
2433
  }
2414
2434
  ) }),
2415
- /* @__PURE__ */ jsx9(
2435
+ /* @__PURE__ */ jsx10(
2416
2436
  TurnstileWidget,
2417
2437
  {
2418
2438
  siteKey: props.turnstileSiteKey,
@@ -2421,18 +2441,18 @@ function IdentityStep(props) {
2421
2441
  }
2422
2442
  )
2423
2443
  ] }),
2424
- /* @__PURE__ */ jsx9(FlowError, { children: error2 })
2444
+ /* @__PURE__ */ jsx10(FlowError, { children: error2 })
2425
2445
  ] })
2426
2446
  }
2427
2447
  );
2428
2448
  }
2429
2449
 
2430
2450
  // src/certificate-funnel-steps/intake-step.tsx
2431
- import * as React9 from "react";
2451
+ import * as React10 from "react";
2432
2452
 
2433
2453
  // src/question-render.tsx
2434
- import * as React8 from "react";
2435
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2454
+ import * as React9 from "react";
2455
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2436
2456
  var RENDERABLE_KINDS = [
2437
2457
  "text",
2438
2458
  "boolean",
@@ -2484,8 +2504,8 @@ function QuestionField({
2484
2504
  const helpId = question.helpText ? `${id}-help` : void 0;
2485
2505
  const errorId = error2 ? `${id}-error` : void 0;
2486
2506
  const description = describedBy(helpId, errorId);
2487
- const help = question.helpText ? /* @__PURE__ */ jsx10("p", { className: "sk-q__help", id: helpId, children: question.helpText }) : null;
2488
- const errorNode = error2 ? /* @__PURE__ */ jsx10("p", { className: "sk-q__error", id: errorId, children: error2 }) : null;
2507
+ const help = question.helpText ? /* @__PURE__ */ jsx11("p", { className: "sk-q__help", id: helpId, children: question.helpText }) : null;
2508
+ const errorNode = error2 ? /* @__PURE__ */ jsx11("p", { className: "sk-q__error", id: errorId, children: error2 }) : null;
2489
2509
  if (question.kind === "boolean" || question.kind === "single_select") {
2490
2510
  const options = question.kind === "boolean" ? [
2491
2511
  { value: "true", label: "Yes" },
@@ -2501,11 +2521,11 @@ function QuestionField({
2501
2521
  children: [
2502
2522
  /* @__PURE__ */ jsxs9("legend", { className: hideLabel ? "sk-q__legend sk-sr-only" : "sk-q__legend", children: [
2503
2523
  question.label,
2504
- question.required && /* @__PURE__ */ jsx10(RequiredMark, {})
2524
+ question.required && /* @__PURE__ */ jsx11(RequiredMark, {})
2505
2525
  ] }),
2506
2526
  help,
2507
- /* @__PURE__ */ jsx10("div", { className: "sk-q__options", children: options.map((opt) => /* @__PURE__ */ jsxs9("label", { className: "sk-q__option", children: [
2508
- /* @__PURE__ */ jsx10(
2527
+ /* @__PURE__ */ jsx11("div", { className: "sk-q__options", children: options.map((opt) => /* @__PURE__ */ jsxs9("label", { className: "sk-q__option", children: [
2528
+ /* @__PURE__ */ jsx11(
2509
2529
  "input",
2510
2530
  {
2511
2531
  type: "radio",
@@ -2518,7 +2538,7 @@ function QuestionField({
2518
2538
  )
2519
2539
  }
2520
2540
  ),
2521
- /* @__PURE__ */ jsx10("span", { children: opt.label })
2541
+ /* @__PURE__ */ jsx11("span", { children: opt.label })
2522
2542
  ] }, opt.value)) }),
2523
2543
  errorNode
2524
2544
  ]
@@ -2534,7 +2554,7 @@ function QuestionField({
2534
2554
  className: "sk-q__input"
2535
2555
  };
2536
2556
  if (question.kind === "date_recent" || question.kind === "date_range") {
2537
- return /* @__PURE__ */ jsx10(
2557
+ return /* @__PURE__ */ jsx11(
2538
2558
  QuickDateField,
2539
2559
  {
2540
2560
  question,
@@ -2553,10 +2573,10 @@ function QuestionField({
2553
2573
  return /* @__PURE__ */ jsxs9("div", { className: "sk-q", children: [
2554
2574
  /* @__PURE__ */ jsxs9("label", { className: hideLabel ? "sk-q__label sk-sr-only" : "sk-q__label", htmlFor: id, children: [
2555
2575
  question.label,
2556
- question.required && /* @__PURE__ */ jsx10(RequiredMark, {})
2576
+ question.required && /* @__PURE__ */ jsx11(RequiredMark, {})
2557
2577
  ] }),
2558
2578
  help,
2559
- question.kind === "number" ? /* @__PURE__ */ jsx10(
2579
+ question.kind === "number" ? /* @__PURE__ */ jsx11(
2560
2580
  "input",
2561
2581
  {
2562
2582
  ...common,
@@ -2568,7 +2588,7 @@ function QuestionField({
2568
2588
  onChange(raw === "" ? null : Number(raw));
2569
2589
  }
2570
2590
  }
2571
- ) : question.kind === "date" ? /* @__PURE__ */ jsx10(
2591
+ ) : question.kind === "date" ? /* @__PURE__ */ jsx11(
2572
2592
  "input",
2573
2593
  {
2574
2594
  ...common,
@@ -2577,7 +2597,7 @@ function QuestionField({
2577
2597
  value: value == null ? "" : String(value),
2578
2598
  onChange: (e) => onChange(e.target.value || null)
2579
2599
  }
2580
- ) : /* @__PURE__ */ jsx10(
2600
+ ) : /* @__PURE__ */ jsx11(
2581
2601
  "input",
2582
2602
  {
2583
2603
  ...common,
@@ -2602,8 +2622,8 @@ function QuickDateField({
2602
2622
  invalid
2603
2623
  }) {
2604
2624
  const isRange = question.kind === "date_range";
2605
- const [today, setToday] = React8.useState(null);
2606
- React8.useEffect(() => setToday(todayIso()), []);
2625
+ const [today, setToday] = React9.useState(null);
2626
+ React9.useEffect(() => setToday(todayIso()), []);
2607
2627
  const raw = value == null ? "" : String(value);
2608
2628
  const range = isRange ? parseRangeValue(raw) : null;
2609
2629
  const from = isRange ? range?.from ?? "" : raw;
@@ -2628,8 +2648,8 @@ function QuickDateField({
2628
2648
  apply: () => emit(shiftIso(todayIso(), -p.daysAgo), "")
2629
2649
  }));
2630
2650
  const dateInput = (which, inputId, label, val, onPick) => /* @__PURE__ */ jsxs9("div", { className: "sk-qd__field", children: [
2631
- /* @__PURE__ */ jsx10("label", { className: "sk-qd__sublabel", htmlFor: inputId, children: label }),
2632
- /* @__PURE__ */ jsx10(
2651
+ /* @__PURE__ */ jsx11("label", { className: "sk-qd__sublabel", htmlFor: inputId, children: label }),
2652
+ /* @__PURE__ */ jsx11(
2633
2653
  "input",
2634
2654
  {
2635
2655
  id: inputId,
@@ -2646,10 +2666,10 @@ function QuickDateField({
2646
2666
  return /* @__PURE__ */ jsxs9("fieldset", { className: "sk-q sk-qd", "aria-describedby": description, children: [
2647
2667
  /* @__PURE__ */ jsxs9("legend", { className: hideLabel ? "sk-q__label sk-sr-only" : "sk-q__label", children: [
2648
2668
  question.label,
2649
- question.required && /* @__PURE__ */ jsx10(RequiredMark, {})
2669
+ question.required && /* @__PURE__ */ jsx11(RequiredMark, {})
2650
2670
  ] }),
2651
2671
  help,
2652
- /* @__PURE__ */ jsx10("div", { className: "sk-qd__chips", children: chips.map((c) => /* @__PURE__ */ jsx10(
2672
+ /* @__PURE__ */ jsx11("div", { className: "sk-qd__chips", children: chips.map((c) => /* @__PURE__ */ jsx11(
2653
2673
  "button",
2654
2674
  {
2655
2675
  type: "button",
@@ -2661,7 +2681,7 @@ function QuickDateField({
2661
2681
  },
2662
2682
  c.label
2663
2683
  )) }),
2664
- /* @__PURE__ */ jsx10("div", { className: "sk-qd__fields", children: isRange ? [
2684
+ /* @__PURE__ */ jsx11("div", { className: "sk-qd__fields", children: isRange ? [
2665
2685
  dateInput("from", `${id}-from`, "First day", from, (next) => emit(next, to)),
2666
2686
  dateInput("to", `${id}-to`, "Last day", to, (next) => emit(from, next))
2667
2687
  ] : dateInput("single", id, "Or pick a date", from, (next) => emit(next, "")) }),
@@ -2675,13 +2695,13 @@ function parseRangeValue(raw) {
2675
2695
  }
2676
2696
  function RequiredMark() {
2677
2697
  return /* @__PURE__ */ jsxs9("span", { className: "sk-q__required", children: [
2678
- /* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: " *" }),
2679
- /* @__PURE__ */ jsx10("span", { className: "sk-sr-only", children: " (required)" })
2698
+ /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: " *" }),
2699
+ /* @__PURE__ */ jsx11("span", { className: "sk-sr-only", children: " (required)" })
2680
2700
  ] });
2681
2701
  }
2682
2702
 
2683
2703
  // src/certificate-funnel-steps/intake-step.tsx
2684
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2704
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2685
2705
  var INTAKE_UNAVAILABLE = "We can\u2019t show this clinic\u2019s questions on this page. Please contact the clinic to finish your request.";
2686
2706
  function IntakeInterstitial({
2687
2707
  progress,
@@ -2691,7 +2711,7 @@ function IntakeInterstitial({
2691
2711
  onRetry,
2692
2712
  message
2693
2713
  }) {
2694
- return /* @__PURE__ */ jsx11(
2714
+ return /* @__PURE__ */ jsx12(
2695
2715
  FlowShell,
2696
2716
  {
2697
2717
  ...progress,
@@ -2702,9 +2722,9 @@ function IntakeInterstitial({
2702
2722
  footer: error2 && onRetry ? (
2703
2723
  // `primary`, not `secondary`: retry is the only action on this screen, which is
2704
2724
  // exactly what the accent is for.
2705
- /* @__PURE__ */ jsx11(FlowButton, { type: "button", variant: "primary", onClick: onRetry, children: "Try again" })
2725
+ /* @__PURE__ */ jsx12(FlowButton, { type: "button", variant: "primary", onClick: onRetry, children: "Try again" })
2706
2726
  ) : void 0,
2707
- children: error2 ? /* @__PURE__ */ jsx11(FlowError, { children: error2 }) : /* @__PURE__ */ jsx11(FlowLoading, { message })
2727
+ children: error2 ? /* @__PURE__ */ jsx12(FlowError, { children: error2 }) : /* @__PURE__ */ jsx12(FlowLoading, { message })
2708
2728
  }
2709
2729
  );
2710
2730
  }
@@ -2729,15 +2749,15 @@ function IntakeStep({
2729
2749
  onBack,
2730
2750
  documentTitle
2731
2751
  }) {
2732
- const [questions, setQuestions] = React9.useState(null);
2733
- const [answers, setAnswers] = React9.useState({});
2734
- const [index, setIndex] = React9.useState(0);
2735
- const [draft, setDraft] = React9.useState(null);
2736
- const [busy, setBusy] = React9.useState(false);
2737
- const [error2, setError] = React9.useState(null);
2738
- const [reload2, setReload] = React9.useState(0);
2752
+ const [questions, setQuestions] = React10.useState(null);
2753
+ const [answers, setAnswers] = React10.useState({});
2754
+ const [index, setIndex] = React10.useState(0);
2755
+ const [draft, setDraft] = React10.useState(null);
2756
+ const [busy, setBusy] = React10.useState(false);
2757
+ const [error2, setError] = React10.useState(null);
2758
+ const [reload2, setReload] = React10.useState(0);
2739
2759
  const progress = useStepProgress("intake", index);
2740
- React9.useEffect(() => {
2760
+ React10.useEffect(() => {
2741
2761
  let alive = true;
2742
2762
  const action = intakeMountAction(questionSetId);
2743
2763
  if (action === "wait") {
@@ -2762,16 +2782,16 @@ function IntakeStep({
2762
2782
  alive = false;
2763
2783
  };
2764
2784
  }, [client, questionSetId, reload2]);
2765
- React9.useEffect(() => {
2785
+ React10.useEffect(() => {
2766
2786
  if (questions && questions.length === 0 && !busy) onComplete();
2767
2787
  }, [questions, busy, onComplete]);
2768
- const visible = React9.useMemo(
2788
+ const visible = React10.useMemo(
2769
2789
  () => questions ? visibleQuestions(questions, answers) : [],
2770
2790
  [questions, answers]
2771
2791
  );
2772
2792
  const total = questions?.length ?? 0;
2773
2793
  const current = visible[index];
2774
- React9.useEffect(() => {
2794
+ React10.useEffect(() => {
2775
2795
  setDraft(current ? answers[current.key] ?? null : null);
2776
2796
  }, [current?.key]);
2777
2797
  async function record(value) {
@@ -2812,7 +2832,7 @@ function IntakeStep({
2812
2832
  onBack?.();
2813
2833
  }
2814
2834
  if (error2 && !questions) {
2815
- return /* @__PURE__ */ jsx11(
2835
+ return /* @__PURE__ */ jsx12(
2816
2836
  IntakeInterstitial,
2817
2837
  {
2818
2838
  progress,
@@ -2827,7 +2847,7 @@ function IntakeStep({
2827
2847
  );
2828
2848
  }
2829
2849
  if (!questions) {
2830
- return /* @__PURE__ */ jsx11(
2850
+ return /* @__PURE__ */ jsx12(
2831
2851
  IntakeInterstitial,
2832
2852
  {
2833
2853
  progress,
@@ -2839,7 +2859,7 @@ function IntakeStep({
2839
2859
  );
2840
2860
  }
2841
2861
  if (!current) {
2842
- return /* @__PURE__ */ jsx11(
2862
+ return /* @__PURE__ */ jsx12(
2843
2863
  IntakeInterstitial,
2844
2864
  {
2845
2865
  progress,
@@ -2859,7 +2879,7 @@ function IntakeStep({
2859
2879
  heading: current.label,
2860
2880
  onBack: goBack,
2861
2881
  documentTitle,
2862
- footer: isChoice ? void 0 : /* @__PURE__ */ jsx11(
2882
+ footer: isChoice ? void 0 : /* @__PURE__ */ jsx12(
2863
2883
  FlowButton,
2864
2884
  {
2865
2885
  type: "button",
@@ -2871,7 +2891,7 @@ function IntakeStep({
2871
2891
  }
2872
2892
  ),
2873
2893
  children: [
2874
- /* @__PURE__ */ jsx11(
2894
+ /* @__PURE__ */ jsx12(
2875
2895
  QuestionField,
2876
2896
  {
2877
2897
  question: current,
@@ -2885,14 +2905,14 @@ function IntakeStep({
2885
2905
  idPrefix: `sk-cf-${index}`
2886
2906
  }
2887
2907
  ),
2888
- /* @__PURE__ */ jsx11(FlowError, { children: error2 })
2908
+ /* @__PURE__ */ jsx12(FlowError, { children: error2 })
2889
2909
  ]
2890
2910
  }
2891
2911
  );
2892
2912
  }
2893
2913
 
2894
2914
  // src/certificate-funnel-steps/medicare-step.tsx
2895
- import * as React10 from "react";
2915
+ import * as React11 from "react";
2896
2916
 
2897
2917
  // src/medicare.ts
2898
2918
  var WEIGHTS = [1, 3, 7, 9, 1, 3, 7, 9];
@@ -2938,7 +2958,7 @@ function printedExpiry(month, year) {
2938
2958
  }
2939
2959
 
2940
2960
  // src/certificate-funnel-steps/medicare-step.tsx
2941
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2961
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2942
2962
  var MEDICARE_FIELDS = [
2943
2963
  { key: "number", id: "sk-mc-number", label: "Medicare number" },
2944
2964
  { key: "irn", id: "sk-mc-irn", label: "Reference number" },
@@ -2961,16 +2981,16 @@ async function skipMedicare(client, requestId, draft, onSaving, onDone) {
2961
2981
  }
2962
2982
  function MedicareStep(props) {
2963
2983
  const { client, requestId, onDone, onBack, documentTitle } = props;
2964
- const [number, setNumber] = React10.useState(props.draft?.number ?? "");
2965
- const [irn, setIrn] = React10.useState(props.draft?.irn ?? "");
2966
- const [month, setMonth] = React10.useState(props.draft?.month ?? "");
2967
- const [year, setYear] = React10.useState(props.draft?.year ?? "");
2968
- const savedKey = React10.useRef(props.draft?.savedKey ?? null);
2969
- const [errors2, setErrors] = React10.useState({});
2970
- const [error2, setError] = React10.useState(null);
2971
- const [busy, setBusy] = React10.useState(false);
2984
+ const [number, setNumber] = React11.useState(props.draft?.number ?? "");
2985
+ const [irn, setIrn] = React11.useState(props.draft?.irn ?? "");
2986
+ const [month, setMonth] = React11.useState(props.draft?.month ?? "");
2987
+ const [year, setYear] = React11.useState(props.draft?.year ?? "");
2988
+ const savedKey = React11.useRef(props.draft?.savedKey ?? null);
2989
+ const [errors2, setErrors] = React11.useState({});
2990
+ const [error2, setError] = React11.useState(null);
2991
+ const [busy, setBusy] = React11.useState(false);
2972
2992
  const { onDraftChange } = props;
2973
- React10.useEffect(() => {
2993
+ React11.useEffect(() => {
2974
2994
  onDraftChange?.({ number, irn, month, year, savedKey: savedKey.current });
2975
2995
  }, [number, irn, month, year, onDraftChange]);
2976
2996
  function reject(found) {
@@ -3038,8 +3058,8 @@ function MedicareStep(props) {
3038
3058
  onBack,
3039
3059
  documentTitle,
3040
3060
  footer: /* @__PURE__ */ jsxs11("div", { className: "sk-cf__actions", children: [
3041
- /* @__PURE__ */ jsx12(FlowButton, { type: "submit", form: "sk-cf-medicare", variant: "primary", busy, children: busy ? "Saving\u2026" : "Continue" }),
3042
- /* @__PURE__ */ jsx12(
3061
+ /* @__PURE__ */ jsx13(FlowButton, { type: "submit", form: "sk-cf-medicare", variant: "primary", busy, children: busy ? "Saving\u2026" : "Continue" }),
3062
+ /* @__PURE__ */ jsx13(
3043
3063
  FlowButton,
3044
3064
  {
3045
3065
  type: "button",
@@ -3051,11 +3071,11 @@ function MedicareStep(props) {
3051
3071
  )
3052
3072
  ] }),
3053
3073
  children: [
3054
- /* @__PURE__ */ jsx12(FlowErrorSummary, { fields: invalid }),
3074
+ /* @__PURE__ */ jsx13(FlowErrorSummary, { fields: invalid }),
3055
3075
  /* @__PURE__ */ jsxs11("form", { id: "sk-cf-medicare", onSubmit: (e) => void handleSubmit(e), noValidate: true, children: [
3056
3076
  /* @__PURE__ */ jsxs11("div", { className: "sk-cf__field", children: [
3057
- /* @__PURE__ */ jsx12("label", { className: "sk-cf__label", htmlFor: "sk-mc-number", children: "Medicare number" }),
3058
- /* @__PURE__ */ jsx12(
3077
+ /* @__PURE__ */ jsx13("label", { className: "sk-cf__label", htmlFor: "sk-mc-number", children: "Medicare number" }),
3078
+ /* @__PURE__ */ jsx13(
3059
3079
  "input",
3060
3080
  {
3061
3081
  id: "sk-mc-number",
@@ -3069,12 +3089,12 @@ function MedicareStep(props) {
3069
3089
  onChange: (e) => setNumber(formatMedicareNumber(e.target.value))
3070
3090
  }
3071
3091
  ),
3072
- /* @__PURE__ */ jsx12(FlowFieldError, { id: "sk-mc-number-error", children: errors2.number })
3092
+ /* @__PURE__ */ jsx13(FlowFieldError, { id: "sk-mc-number-error", children: errors2.number })
3073
3093
  ] }),
3074
3094
  /* @__PURE__ */ jsxs11("div", { className: "sk-cf__row", children: [
3075
3095
  /* @__PURE__ */ jsxs11("div", { className: "sk-cf__field", children: [
3076
- /* @__PURE__ */ jsx12("label", { className: "sk-cf__label", htmlFor: "sk-mc-irn", children: "Reference number" }),
3077
- /* @__PURE__ */ jsx12(
3096
+ /* @__PURE__ */ jsx13("label", { className: "sk-cf__label", htmlFor: "sk-mc-irn", children: "Reference number" }),
3097
+ /* @__PURE__ */ jsx13(
3078
3098
  "input",
3079
3099
  {
3080
3100
  id: "sk-mc-irn",
@@ -3088,14 +3108,14 @@ function MedicareStep(props) {
3088
3108
  onChange: (e) => setIrn(e.target.value.replace(/\D/g, "").slice(0, 1))
3089
3109
  }
3090
3110
  ),
3091
- /* @__PURE__ */ jsx12("p", { className: "sk-cf__help", id: "sk-mc-irn-help", children: "The digit beside your name on the card." }),
3092
- /* @__PURE__ */ jsx12(FlowFieldError, { id: "sk-mc-irn-error", children: errors2.irn })
3111
+ /* @__PURE__ */ jsx13("p", { className: "sk-cf__help", id: "sk-mc-irn-help", children: "The digit beside your name on the card." }),
3112
+ /* @__PURE__ */ jsx13(FlowFieldError, { id: "sk-mc-irn-error", children: errors2.irn })
3093
3113
  ] }),
3094
3114
  /* @__PURE__ */ jsxs11("div", { className: "sk-cf__field", children: [
3095
3115
  /* @__PURE__ */ jsxs11("fieldset", { className: "sk-cf__expiry", children: [
3096
- /* @__PURE__ */ jsx12("legend", { className: "sk-cf__label", children: "Expiry" }),
3097
- /* @__PURE__ */ jsx12("label", { className: "sk-sr-only", htmlFor: "sk-mc-month", children: "Expiry month" }),
3098
- /* @__PURE__ */ jsx12(
3116
+ /* @__PURE__ */ jsx13("legend", { className: "sk-cf__label", children: "Expiry" }),
3117
+ /* @__PURE__ */ jsx13("label", { className: "sk-sr-only", htmlFor: "sk-mc-month", children: "Expiry month" }),
3118
+ /* @__PURE__ */ jsx13(
3099
3119
  "input",
3100
3120
  {
3101
3121
  id: "sk-mc-month",
@@ -3110,8 +3130,8 @@ function MedicareStep(props) {
3110
3130
  onChange: (e) => setMonth(e.target.value.replace(/\D/g, "").slice(0, 2))
3111
3131
  }
3112
3132
  ),
3113
- /* @__PURE__ */ jsx12("label", { className: "sk-sr-only", htmlFor: "sk-mc-year", children: "Expiry year" }),
3114
- /* @__PURE__ */ jsx12(
3133
+ /* @__PURE__ */ jsx13("label", { className: "sk-sr-only", htmlFor: "sk-mc-year", children: "Expiry year" }),
3134
+ /* @__PURE__ */ jsx13(
3115
3135
  "input",
3116
3136
  {
3117
3137
  id: "sk-mc-year",
@@ -3127,18 +3147,18 @@ function MedicareStep(props) {
3127
3147
  }
3128
3148
  )
3129
3149
  ] }),
3130
- /* @__PURE__ */ jsx12(FlowFieldError, { id: "sk-mc-expiry-error", children: errors2.expiry })
3150
+ /* @__PURE__ */ jsx13(FlowFieldError, { id: "sk-mc-expiry-error", children: errors2.expiry })
3131
3151
  ] })
3132
3152
  ] })
3133
3153
  ] }),
3134
- /* @__PURE__ */ jsx12(FlowError, { children: error2 })
3154
+ /* @__PURE__ */ jsx13(FlowError, { children: error2 })
3135
3155
  ]
3136
3156
  }
3137
3157
  );
3138
3158
  }
3139
3159
 
3140
3160
  // src/certificate-funnel-steps/consent-step.tsx
3141
- import * as React11 from "react";
3161
+ import * as React12 from "react";
3142
3162
 
3143
3163
  // src/certificate-funnel-steps/consent-text.ts
3144
3164
  var CONSENT_TEXT_V5 = [
@@ -3182,7 +3202,7 @@ var CONSENT_SUMMARY_FREE = [
3182
3202
  ];
3183
3203
 
3184
3204
  // src/certificate-funnel-steps/consent-step.tsx
3185
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
3205
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3186
3206
  function confirmDetails(input) {
3187
3207
  const text2 = (v) => typeof v === "string" ? v : "";
3188
3208
  const phone = text2(input.phone);
@@ -3236,22 +3256,22 @@ function ConsentStep({
3236
3256
  onBack,
3237
3257
  documentTitle
3238
3258
  }) {
3239
- const [showFull, setShowFull] = React11.useState(false);
3240
- const [busy, setBusy] = React11.useState(false);
3241
- const [error2, setError] = React11.useState(null);
3259
+ const [showFull, setShowFull] = React12.useState(false);
3260
+ const [busy, setBusy] = React12.useState(false);
3261
+ const [error2, setError] = React12.useState(null);
3242
3262
  const feeText = formatFee(feeAmount);
3243
3263
  const clinic = clinicName || "the clinic";
3244
- const paragraphs = React11.useMemo(
3264
+ const paragraphs = React12.useMemo(
3245
3265
  () => isFree === true ? renderConsentTextFree({ clinic }) : renderConsentText({ clinic, fee: feeText }),
3246
3266
  [clinic, feeText, isFree]
3247
3267
  );
3248
- const summary = React11.useMemo(
3268
+ const summary = React12.useMemo(
3249
3269
  () => isFree === true ? [...CONSENT_SUMMARY_FREE] : CONSENT_SUMMARY(feeText),
3250
3270
  [feeText, isFree]
3251
3271
  );
3252
3272
  const policyHash = isFree === true ? CONSENT_FREE_POLICY_HASH_V4 : CONSENT_POLICY_HASH_V5;
3253
3273
  const feeUnknown = isFree === null || isFree === false && !feeText;
3254
- const details = React11.useMemo(
3274
+ const details = React12.useMemo(
3255
3275
  () => confirmDetails({
3256
3276
  name: patientName,
3257
3277
  dateOfBirth,
@@ -3295,7 +3315,7 @@ function ConsentStep({
3295
3315
  setError(errorMessage(err, "We could not submit your request. Please try again."));
3296
3316
  }
3297
3317
  }
3298
- return /* @__PURE__ */ jsx13(
3318
+ return /* @__PURE__ */ jsx14(
3299
3319
  FlowShell,
3300
3320
  {
3301
3321
  ...useStepProgress("consent"),
@@ -3308,7 +3328,7 @@ function ConsentStep({
3308
3328
  ),
3309
3329
  onBack,
3310
3330
  documentTitle,
3311
- footer: feeUnknown ? void 0 : /* @__PURE__ */ jsx13(
3331
+ footer: feeUnknown ? void 0 : /* @__PURE__ */ jsx14(
3312
3332
  FlowButton,
3313
3333
  {
3314
3334
  type: "submit",
@@ -3321,14 +3341,14 @@ function ConsentStep({
3321
3341
  ),
3322
3342
  children: feeUnknown ? (
3323
3343
  // No consent is offered until the fee is resolved — see `feeUnknown`.
3324
- /* @__PURE__ */ jsx13(FlowLoading, { message: "Confirming the fee\u2026" })
3344
+ /* @__PURE__ */ jsx14(FlowLoading, { message: "Confirming the fee\u2026" })
3325
3345
  ) : /* @__PURE__ */ jsxs12(Fragment4, { children: [
3326
- /* @__PURE__ */ jsx13("dl", { className: "sk-cf__review", children: details.map((d) => /* @__PURE__ */ jsxs12("div", { className: "sk-cf__review-row", children: [
3327
- /* @__PURE__ */ jsx13("dt", { className: "sk-cf__review-label", children: d.label }),
3328
- /* @__PURE__ */ jsx13("dd", { className: "sk-cf__review-value", children: d.value })
3346
+ /* @__PURE__ */ jsx14("dl", { className: "sk-cf__review", children: details.map((d) => /* @__PURE__ */ jsxs12("div", { className: "sk-cf__review-row", children: [
3347
+ /* @__PURE__ */ jsx14("dt", { className: "sk-cf__review-label", children: d.label }),
3348
+ /* @__PURE__ */ jsx14("dd", { className: "sk-cf__review-value", children: d.value })
3329
3349
  ] }, d.label)) }),
3330
- /* @__PURE__ */ jsx13("ul", { className: "sk-cf__consent-summary", children: summary.map((point) => /* @__PURE__ */ jsx13("li", { children: point }, point)) }),
3331
- /* @__PURE__ */ jsx13(
3350
+ /* @__PURE__ */ jsx14("ul", { className: "sk-cf__consent-summary", children: summary.map((point) => /* @__PURE__ */ jsx14("li", { children: point }, point)) }),
3351
+ /* @__PURE__ */ jsx14(
3332
3352
  "button",
3333
3353
  {
3334
3354
  type: "button",
@@ -3339,26 +3359,26 @@ function ConsentStep({
3339
3359
  children: showFull ? "Hide full text" : "Read the full text"
3340
3360
  }
3341
3361
  ),
3342
- /* @__PURE__ */ jsx13("div", { id: "sk-cf-consent-full", className: "sk-cf__consent-full", hidden: !showFull, children: paragraphs.map((p) => /* @__PURE__ */ jsx13("p", { children: p }, p)) }),
3343
- /* @__PURE__ */ jsx13("form", { id: "sk-cf-consent", onSubmit: (e) => void handleSubmit(e), className: "sk-cf__consent-form", children: /* @__PURE__ */ jsxs12("p", { className: "sk-cf__agree-note", children: [
3362
+ /* @__PURE__ */ jsx14("div", { id: "sk-cf-consent-full", className: "sk-cf__consent-full", hidden: !showFull, children: paragraphs.map((p) => /* @__PURE__ */ jsx14("p", { children: p }, p)) }),
3363
+ /* @__PURE__ */ jsx14("form", { id: "sk-cf-consent", onSubmit: (e) => void handleSubmit(e), className: "sk-cf__consent-form", children: /* @__PURE__ */ jsxs12("p", { className: "sk-cf__agree-note", children: [
3344
3364
  "Confirming agrees to the above, the",
3345
3365
  " ",
3346
- /* @__PURE__ */ jsx13("a", { className: "sk-cf__link", href: POLICY_LINKS.terms, children: "terms" }),
3366
+ /* @__PURE__ */ jsx14("a", { className: "sk-cf__link", href: POLICY_LINKS.terms, children: "terms" }),
3347
3367
  " ",
3348
3368
  "and the",
3349
3369
  " ",
3350
- /* @__PURE__ */ jsx13("a", { className: "sk-cf__link", href: POLICY_LINKS.privacy, children: "privacy policy" }),
3370
+ /* @__PURE__ */ jsx14("a", { className: "sk-cf__link", href: POLICY_LINKS.privacy, children: "privacy policy" }),
3351
3371
  "."
3352
3372
  ] }) }),
3353
- /* @__PURE__ */ jsx13(FlowError, { children: error2 })
3373
+ /* @__PURE__ */ jsx14(FlowError, { children: error2 })
3354
3374
  ] })
3355
3375
  }
3356
3376
  );
3357
3377
  }
3358
3378
 
3359
3379
  // src/certificate-funnel-steps/slot-step.tsx
3360
- import * as React12 from "react";
3361
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
3380
+ import * as React13 from "react";
3381
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3362
3382
  function formatBookedFor(iso, tz) {
3363
3383
  const day = new Intl.DateTimeFormat("en-AU", {
3364
3384
  timeZone: tz,
@@ -3384,9 +3404,9 @@ function SlotCancelControl({
3384
3404
  role: confirming ? "group" : void 0,
3385
3405
  "aria-label": confirming ? "Confirm cancellation" : void 0,
3386
3406
  children: [
3387
- confirming && /* @__PURE__ */ jsx14("p", { className: "sk-cf__body", role: "status", "aria-live": "polite", children: "Cancel this request? You\u2019ll need to start again if you change your mind." }),
3388
- /* @__PURE__ */ jsx14(FlowButton, { type: "button", variant: "quiet", onClick: confirming ? onKeep : onAsk, children: confirming ? "Keep my request" : isFree === false ? "Cancel and release the hold" : "Cancel this request" }),
3389
- confirming && /* @__PURE__ */ jsx14(FlowButton, { type: "button", variant: "secondary", busy, onClick: onConfirm, children: busy ? "Cancelling\u2026" : "Yes, cancel this request" })
3407
+ confirming && /* @__PURE__ */ jsx15("p", { className: "sk-cf__body", role: "status", "aria-live": "polite", children: "Cancel this request? You\u2019ll need to start again if you change your mind." }),
3408
+ /* @__PURE__ */ jsx15(FlowButton, { type: "button", variant: "quiet", onClick: confirming ? onKeep : onAsk, children: confirming ? "Keep my request" : isFree === false ? "Cancel and release the hold" : "Cancel this request" }),
3409
+ confirming && /* @__PURE__ */ jsx15(FlowButton, { type: "button", variant: "secondary", busy, onClick: onConfirm, children: busy ? "Cancelling\u2026" : "Yes, cancel this request" })
3390
3410
  ]
3391
3411
  }
3392
3412
  );
@@ -3401,9 +3421,9 @@ function SlotStep({
3401
3421
  onCancelled,
3402
3422
  documentTitle
3403
3423
  }) {
3404
- const [cancelling, setCancelling] = React12.useState(false);
3405
- const [confirmCancel, setConfirmCancel] = React12.useState(false);
3406
- const [cancelError, setCancelError] = React12.useState(null);
3424
+ const [cancelling, setCancelling] = React13.useState(false);
3425
+ const [confirmCancel, setConfirmCancel] = React13.useState(false);
3426
+ const [cancelError, setCancelError] = React13.useState(null);
3407
3427
  const progress = useStepProgress("slot");
3408
3428
  async function releaseAndExit() {
3409
3429
  if (cancelling) return;
@@ -3429,7 +3449,7 @@ function SlotStep({
3429
3449
  subheading: isFree === true ? "A practitioner will call you in the time you choose. This consult is bulk billed \u2014 there\u2019s nothing to pay." : "A practitioner will call you in the time you choose.",
3430
3450
  documentTitle,
3431
3451
  children: [
3432
- /* @__PURE__ */ jsx14(
3452
+ /* @__PURE__ */ jsx15(
3433
3453
  SlotPicker,
3434
3454
  {
3435
3455
  client,
@@ -3470,7 +3490,7 @@ function SlotStep({
3470
3490
  HOLD_RELEASE_NOTE
3471
3491
  ] })
3472
3492
  ] }),
3473
- /* @__PURE__ */ jsx14(
3493
+ /* @__PURE__ */ jsx15(
3474
3494
  SlotCancelControl,
3475
3495
  {
3476
3496
  confirming: confirmCancel,
@@ -3481,15 +3501,15 @@ function SlotStep({
3481
3501
  onConfirm: () => void releaseAndExit()
3482
3502
  }
3483
3503
  ),
3484
- /* @__PURE__ */ jsx14(FlowError, { children: cancelError })
3504
+ /* @__PURE__ */ jsx15(FlowError, { children: cancelError })
3485
3505
  ]
3486
3506
  }
3487
3507
  );
3488
3508
  }
3489
3509
 
3490
3510
  // src/certificate-funnel-steps/submitted-step.tsx
3491
- import * as React13 from "react";
3492
- import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
3511
+ import * as React14 from "react";
3512
+ import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3493
3513
  var CLOSED = /* @__PURE__ */ new Set(["cancelled", "blocked", "payment_failed"]);
3494
3514
  var CANCELLABLE = /* @__PURE__ */ new Set(["draft", "payment_failed", "ready"]);
3495
3515
  function terminalCopy(row, bookedFor, deliveryMode) {
@@ -3586,14 +3606,14 @@ function SubmittedStep({
3586
3606
  onRestart,
3587
3607
  documentTitle
3588
3608
  }) {
3589
- const [row, setRow] = React13.useState(void 0);
3590
- const [noSession, setNoSession] = React13.useState(false);
3591
- const [unreachable, setUnreachable] = React13.useState(false);
3592
- const [cancelling, setCancelling] = React13.useState(false);
3593
- const [confirmCancel, setConfirmCancel] = React13.useState(false);
3594
- const [notice, setNotice] = React13.useState(null);
3595
- const [error2, setError] = React13.useState(null);
3596
- React13.useEffect(() => {
3609
+ const [row, setRow] = React14.useState(void 0);
3610
+ const [noSession, setNoSession] = React14.useState(false);
3611
+ const [unreachable, setUnreachable] = React14.useState(false);
3612
+ const [cancelling, setCancelling] = React14.useState(false);
3613
+ const [confirmCancel, setConfirmCancel] = React14.useState(false);
3614
+ const [notice, setNotice] = React14.useState(null);
3615
+ const [error2, setError] = React14.useState(null);
3616
+ React14.useEffect(() => {
3597
3617
  if (!client.getClaimToken()) {
3598
3618
  setNoSession(true);
3599
3619
  return;
@@ -3657,15 +3677,15 @@ function SubmittedStep({
3657
3677
  "We\u2019ve emailed you about your request.",
3658
3678
  portalUrl ? " You can also manage it in the patient portal." : ""
3659
3679
  ] }),
3660
- /* @__PURE__ */ jsx15(EmailDestination, { promisesEmail: true, email }),
3661
- /* @__PURE__ */ jsx15(PortalLink, { portalUrl }),
3662
- !portalUrl && clinicPhone && /* @__PURE__ */ jsx15(ClinicPhone, { clinicPhone })
3680
+ /* @__PURE__ */ jsx16(EmailDestination, { promisesEmail: true, email }),
3681
+ /* @__PURE__ */ jsx16(PortalLink, { portalUrl }),
3682
+ !portalUrl && clinicPhone && /* @__PURE__ */ jsx16(ClinicPhone, { clinicPhone })
3663
3683
  ]
3664
3684
  }
3665
3685
  );
3666
3686
  }
3667
3687
  if (unreachable) {
3668
- return /* @__PURE__ */ jsx15(
3688
+ return /* @__PURE__ */ jsx16(
3669
3689
  SubmittedUnreachable,
3670
3690
  {
3671
3691
  documentTitle,
@@ -3676,25 +3696,25 @@ function SubmittedStep({
3676
3696
  }
3677
3697
  const status = row?.status;
3678
3698
  const copy = terminalCopy(row, bookedFor, deliveryMode);
3679
- return /* @__PURE__ */ jsx15(
3699
+ return /* @__PURE__ */ jsx16(
3680
3700
  FlowShell,
3681
3701
  {
3682
3702
  stepKey: "submitted-status",
3683
3703
  heading: copy.heading,
3684
3704
  documentTitle,
3685
- footer: portalUrl ? /* @__PURE__ */ jsx15("a", { className: "sk-flow__btn sk-flow__btn--primary", href: portalUrl, children: "Track this in the patient portal" }) : /* @__PURE__ */ jsx15(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Make another request" }),
3686
- children: row === void 0 ? /* @__PURE__ */ jsx15(FlowLoading, { message: "Loading your request\u2026" }) : /* @__PURE__ */ jsxs14(Fragment5, { children: [
3687
- /* @__PURE__ */ jsx15("p", { className: "sk-cf__body", children: copy.body }),
3705
+ footer: portalUrl ? /* @__PURE__ */ jsx16("a", { className: "sk-flow__btn sk-flow__btn--primary", href: portalUrl, children: "Track this in the patient portal" }) : /* @__PURE__ */ jsx16(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Make another request" }),
3706
+ children: row === void 0 ? /* @__PURE__ */ jsx16(FlowLoading, { message: "Loading your request\u2026" }) : /* @__PURE__ */ jsxs14(Fragment5, { children: [
3707
+ /* @__PURE__ */ jsx16("p", { className: "sk-cf__body", children: copy.body }),
3688
3708
  copy.booked && bookedFor && /* @__PURE__ */ jsxs14("p", { className: "sk-cf__booked", children: [
3689
- /* @__PURE__ */ jsx15("span", { className: "sk-cf__booked-label", children: "Your appointment" }),
3690
- /* @__PURE__ */ jsx15("span", { className: "sk-cf__booked-when", children: bookedFor })
3709
+ /* @__PURE__ */ jsx16("span", { className: "sk-cf__booked-label", children: "Your appointment" }),
3710
+ /* @__PURE__ */ jsx16("span", { className: "sk-cf__booked-when", children: bookedFor })
3691
3711
  ] }),
3692
- /* @__PURE__ */ jsx15(CallDestination, { booked: copy.booked, phone: patientPhone }),
3693
- /* @__PURE__ */ jsx15(EmailDestination, { promisesEmail: copy.promisesEmail, email }),
3694
- notice && /* @__PURE__ */ jsx15("p", { className: "sk-cf__notice", role: "status", "aria-live": "polite", children: notice }),
3695
- /* @__PURE__ */ jsx15(FlowError, { children: error2 }),
3696
- portalUrl && /* @__PURE__ */ jsx15("div", { className: "sk-cf__after", children: /* @__PURE__ */ jsx15(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Make another request" }) }),
3697
- status && CANCELLABLE.has(status) && !notice && /* @__PURE__ */ jsx15(
3712
+ /* @__PURE__ */ jsx16(CallDestination, { booked: copy.booked, phone: patientPhone }),
3713
+ /* @__PURE__ */ jsx16(EmailDestination, { promisesEmail: copy.promisesEmail, email }),
3714
+ notice && /* @__PURE__ */ jsx16("p", { className: "sk-cf__notice", role: "status", "aria-live": "polite", children: notice }),
3715
+ /* @__PURE__ */ jsx16(FlowError, { children: error2 }),
3716
+ portalUrl && /* @__PURE__ */ jsx16("div", { className: "sk-cf__after", children: /* @__PURE__ */ jsx16(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Make another request" }) }),
3717
+ status && CANCELLABLE.has(status) && !notice && /* @__PURE__ */ jsx16(
3698
3718
  CancelControl,
3699
3719
  {
3700
3720
  confirming: confirmCancel,
@@ -3727,10 +3747,10 @@ function SubmittedUnreachable({
3727
3747
  stepKey: "submitted-unreachable",
3728
3748
  heading: "We can\u2019t check your request",
3729
3749
  documentTitle,
3730
- footer: portalUrl ? /* @__PURE__ */ jsx15("a", { className: "sk-flow__btn sk-flow__btn--primary", href: portalUrl, children: "Track this in the patient portal" }) : void 0,
3750
+ footer: portalUrl ? /* @__PURE__ */ jsx16("a", { className: "sk-flow__btn sk-flow__btn--primary", href: portalUrl, children: "Track this in the patient portal" }) : void 0,
3731
3751
  children: [
3732
- /* @__PURE__ */ jsx15(FlowError, { children: "We can\u2019t check your request in this browser right now. Your request is still with the clinic." }),
3733
- clinicPhone ? /* @__PURE__ */ jsx15(ClinicPhone, { clinicPhone }) : !portalUrl ? /* @__PURE__ */ jsx15("p", { className: "sk-cf__aside", children: "Please contact the clinic using the details on this website." }) : null
3752
+ /* @__PURE__ */ jsx16(FlowError, { children: "We can\u2019t check your request in this browser right now. Your request is still with the clinic." }),
3753
+ clinicPhone ? /* @__PURE__ */ jsx16(ClinicPhone, { clinicPhone }) : !portalUrl ? /* @__PURE__ */ jsx16("p", { className: "sk-cf__aside", children: "Please contact the clinic using the details on this website." }) : null
3734
3754
  ]
3735
3755
  }
3736
3756
  );
@@ -3741,8 +3761,8 @@ function CallDestination({
3741
3761
  }) {
3742
3762
  if (!booked) return null;
3743
3763
  return /* @__PURE__ */ jsxs14("p", { className: "sk-cf__booked sk-cf__call", children: [
3744
- /* @__PURE__ */ jsx15("span", { className: "sk-cf__booked-label", children: "We\u2019ll call you on" }),
3745
- /* @__PURE__ */ jsx15("span", { className: "sk-cf__booked-when", children: phone ? formatAuPhone(phone) : "the number you gave us" })
3764
+ /* @__PURE__ */ jsx16("span", { className: "sk-cf__booked-label", children: "We\u2019ll call you on" }),
3765
+ /* @__PURE__ */ jsx16("span", { className: "sk-cf__booked-when", children: phone ? formatAuPhone(phone) : "the number you gave us" })
3746
3766
  ] });
3747
3767
  }
3748
3768
  function EmailDestination({
@@ -3752,7 +3772,7 @@ function EmailDestination({
3752
3772
  if (!promisesEmail || !email) return null;
3753
3773
  return /* @__PURE__ */ jsxs14("p", { className: "sk-cf__aside", children: [
3754
3774
  "We\u2019ll email ",
3755
- /* @__PURE__ */ jsx15("strong", { children: email }),
3775
+ /* @__PURE__ */ jsx16("strong", { children: email }),
3756
3776
  " as things progress."
3757
3777
  ] });
3758
3778
  }
@@ -3782,53 +3802,53 @@ function CancelControl({
3782
3802
  booked ? "You\u2019ll give up your appointment time. " : "",
3783
3803
  "You\u2019ll need to start again if you change your mind."
3784
3804
  ] }),
3785
- /* @__PURE__ */ jsx15(FlowButton, { type: "button", variant: "quiet", onClick: confirming ? onKeep : onAsk, children: confirming ? `Keep my ${noun}` : "Cancel this request" }),
3786
- confirming && /* @__PURE__ */ jsx15(FlowButton, { type: "button", variant: "secondary", busy, onClick: onConfirm, children: busy ? "Cancelling\u2026" : `Yes, cancel this ${noun}` })
3805
+ /* @__PURE__ */ jsx16(FlowButton, { type: "button", variant: "quiet", onClick: confirming ? onKeep : onAsk, children: confirming ? `Keep my ${noun}` : "Cancel this request" }),
3806
+ confirming && /* @__PURE__ */ jsx16(FlowButton, { type: "button", variant: "secondary", busy, onClick: onConfirm, children: busy ? "Cancelling\u2026" : `Yes, cancel this ${noun}` })
3787
3807
  ]
3788
3808
  }
3789
3809
  );
3790
3810
  }
3791
3811
  function PortalLink({ portalUrl }) {
3792
3812
  if (!portalUrl) return null;
3793
- return /* @__PURE__ */ jsx15("p", { className: "sk-cf__aside", children: /* @__PURE__ */ jsx15("a", { className: "sk-cf__link", href: portalUrl, children: "Manage this in the patient portal" }) });
3813
+ return /* @__PURE__ */ jsx16("p", { className: "sk-cf__aside", children: /* @__PURE__ */ jsx16("a", { className: "sk-cf__link", href: portalUrl, children: "Manage this in the patient portal" }) });
3794
3814
  }
3795
3815
  function ClinicPhone({ clinicPhone }) {
3796
- return /* @__PURE__ */ jsx15("p", { className: "sk-cf__aside", children: /* @__PURE__ */ jsxs14("a", { className: "sk-cf__link", href: `tel:${normalizeAuPhone(clinicPhone)}`, children: [
3816
+ return /* @__PURE__ */ jsx16("p", { className: "sk-cf__aside", children: /* @__PURE__ */ jsxs14("a", { className: "sk-cf__link", href: `tel:${normalizeAuPhone(clinicPhone)}`, children: [
3797
3817
  "Call the clinic on ",
3798
3818
  formatAuPhone(clinicPhone)
3799
3819
  ] }) });
3800
3820
  }
3801
3821
 
3802
3822
  // src/certificate-funnel-steps/trust-rail.tsx
3803
- import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
3823
+ import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3804
3824
  function TrustRail({ clinicName, fee }) {
3805
3825
  const money = feeNote(fee);
3806
3826
  return /* @__PURE__ */ jsxs15(Fragment6, { children: [
3807
- clinicName && /* @__PURE__ */ jsx16("p", { className: "sk-flow__rail-clinic", children: clinicName }),
3808
- /* @__PURE__ */ jsx16("p", { children: "Every request is reviewed by a practitioner registered with Ahpra, the Australian Health Practitioner Regulation Agency." }),
3809
- money && /* @__PURE__ */ jsx16("p", { children: money }),
3810
- /* @__PURE__ */ jsx16("p", { children: "Your health information is stored in Australia and is only accessible to this clinic\u2019s care team." }),
3827
+ clinicName && /* @__PURE__ */ jsx17("p", { className: "sk-flow__rail-clinic", children: clinicName }),
3828
+ /* @__PURE__ */ jsx17("p", { children: "Every request is reviewed by a practitioner registered with Ahpra, the Australian Health Practitioner Regulation Agency." }),
3829
+ money && /* @__PURE__ */ jsx17("p", { children: money }),
3830
+ /* @__PURE__ */ jsx17("p", { children: "Your health information is stored in Australia and is only accessible to this clinic\u2019s care team." }),
3811
3831
  /* @__PURE__ */ jsxs15("p", { className: "sk-flow__rail-policies", children: [
3812
- /* @__PURE__ */ jsx16("a", { className: "sk-flow__rail-link", href: POLICY_LINKS.terms, children: "Terms" }),
3813
- /* @__PURE__ */ jsx16("a", { className: "sk-flow__rail-link", href: POLICY_LINKS.privacy, children: "Privacy policy" })
3832
+ /* @__PURE__ */ jsx17("a", { className: "sk-flow__rail-link", href: POLICY_LINKS.terms, children: "Terms" }),
3833
+ /* @__PURE__ */ jsx17("a", { className: "sk-flow__rail-link", href: POLICY_LINKS.privacy, children: "Privacy policy" })
3814
3834
  ] })
3815
3835
  ] });
3816
3836
  }
3817
3837
 
3818
3838
  // src/certificate-funnel-steps/exit-steps.tsx
3819
- import * as React14 from "react";
3820
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
3839
+ import * as React15 from "react";
3840
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
3821
3841
  var EMERGENCY2 = "000";
3822
3842
  var EMERGENCY_INTL = "112";
3823
3843
  function EscalateStep({
3824
3844
  gate,
3825
3845
  documentTitle
3826
3846
  }) {
3827
- const headingRef = React14.useRef(null);
3828
- React14.useEffect(() => {
3847
+ const headingRef = React15.useRef(null);
3848
+ React15.useEffect(() => {
3829
3849
  headingRef.current?.focus();
3830
3850
  }, []);
3831
- React14.useEffect(() => {
3851
+ React15.useEffect(() => {
3832
3852
  if (documentTitle && typeof document !== "undefined") document.title = documentTitle;
3833
3853
  }, [documentTitle]);
3834
3854
  return (
@@ -3842,12 +3862,12 @@ function EscalateStep({
3842
3862
  "aria-labelledby": "sk-cf-escalate-heading",
3843
3863
  "data-sk-escalate": "",
3844
3864
  children: [
3845
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__escalate-eyebrow", children: "Emergency" }),
3865
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__escalate-eyebrow", children: "Emergency" }),
3846
3866
  /* @__PURE__ */ jsxs16("h2", { id: "sk-cf-escalate-heading", ref: headingRef, tabIndex: -1, className: "sk-cf__escalate-heading", children: [
3847
3867
  "Call ",
3848
3868
  EMERGENCY2
3849
3869
  ] }),
3850
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__escalate-body", children: gate?.message ?? "Your answers suggest you may need urgent care. Please call 000 or go to your nearest emergency department." }),
3870
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__escalate-body", children: gate?.message ?? "Your answers suggest you may need urgent care. Please call 000 or go to your nearest emergency department." }),
3851
3871
  /* @__PURE__ */ jsxs16("a", { className: "sk-cf__escalate-cta", href: `tel:${EMERGENCY2}`, children: [
3852
3872
  "Call ",
3853
3873
  EMERGENCY2,
@@ -3857,7 +3877,7 @@ function EscalateStep({
3857
3877
  "Outside Australia / international SIM: ",
3858
3878
  EMERGENCY_INTL
3859
3879
  ] }),
3860
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__escalate-note", children: "We\u2019ve stopped your request so you can get to care quickly." })
3880
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__escalate-note", children: "We\u2019ve stopped your request so you can get to care quickly." })
3861
3881
  ]
3862
3882
  }
3863
3883
  )
@@ -3876,22 +3896,22 @@ function BlockedStep({
3876
3896
  eyebrow: "Next step",
3877
3897
  heading: "Let\u2019s get you to the right care",
3878
3898
  documentTitle,
3879
- footer: /* @__PURE__ */ jsx17(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Start again" }),
3899
+ footer: /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Start again" }),
3880
3900
  children: [
3881
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: gate?.message ?? "Based on your answers, we\u2019re not able to issue a certificate online this time." }),
3882
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: "We\u2019d recommend seeing your own GP, who can assess you properly." }),
3883
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: "Nothing has been charged." }),
3901
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: gate?.message ?? "Based on your answers, we\u2019re not able to issue a certificate online this time." }),
3902
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: "We\u2019d recommend seeing your own GP, who can assess you properly." }),
3903
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: "Nothing has been charged." }),
3884
3904
  /* @__PURE__ */ jsxs16("ul", { className: "sk-cf__links", children: [
3885
- /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs16("a", { className: "sk-cf__emergency", href: `tel:${EMERGENCY2}`, children: [
3905
+ /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsxs16("a", { className: "sk-cf__emergency", href: `tel:${EMERGENCY2}`, children: [
3886
3906
  "If your symptoms get worse, call ",
3887
3907
  EMERGENCY2
3888
3908
  ] }) }),
3889
- /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsx17("a", { className: "sk-cf__link", href: "tel:1800022222", children: "Health advice, 24 hours \u2014 healthdirect on 1800 022 222" }) }),
3890
- clinicPhone && /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs16("a", { className: "sk-cf__link", href: `tel:${clinicPhone.replace(/[^\d+]/g, "")}`, children: [
3909
+ /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18("a", { className: "sk-cf__link", href: "tel:1800022222", children: "Health advice, 24 hours \u2014 healthdirect on 1800 022 222" }) }),
3910
+ clinicPhone && /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsxs16("a", { className: "sk-cf__link", href: `tel:${clinicPhone.replace(/[^\d+]/g, "")}`, children: [
3891
3911
  "Call the clinic on ",
3892
3912
  clinicPhone
3893
3913
  ] }) }),
3894
- /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsx17(
3914
+ /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(
3895
3915
  "a",
3896
3916
  {
3897
3917
  className: "sk-cf__link",
@@ -3918,10 +3938,10 @@ function PaymentFailedStep({
3918
3938
  stepKey: "payment-failed",
3919
3939
  heading: "Payment could not be authorised",
3920
3940
  documentTitle,
3921
- footer: /* @__PURE__ */ jsx17(FlowButton, { type: "button", variant: "primary", onClick: onRestart, children: "Start again with a different card" }),
3941
+ footer: /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "primary", onClick: onRestart, children: "Start again with a different card" }),
3922
3942
  children: [
3923
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: message ?? "Your card was declined and the pre-authorisation could not be completed." }),
3924
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: "No hold was placed and no certificate has been created." }),
3943
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: message ?? "Your card was declined and the pre-authorisation could not be completed." }),
3944
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: "No hold was placed and no certificate has been created." }),
3925
3945
  clinicPhone && /* @__PURE__ */ jsxs16("p", { className: "sk-cf__body", children: [
3926
3946
  "Still not working?",
3927
3947
  " ",
@@ -3945,19 +3965,19 @@ function UnavailableStep({
3945
3965
  stepKey: "unavailable",
3946
3966
  heading: "We can\u2019t help with this type of certificate online",
3947
3967
  documentTitle,
3948
- footer: onBack ? /* @__PURE__ */ jsx17(FlowButton, { type: "button", variant: "quiet", onClick: onBack, children: "Choose a different certificate" }) : void 0,
3968
+ footer: onBack ? /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "quiet", onClick: onBack, children: "Choose a different certificate" }) : void 0,
3949
3969
  children: [
3950
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: "Online certificates cover short, common illness absences. These need an in-person assessment:" }),
3970
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: "Online certificates cover short, common illness absences. These need an in-person assessment:" }),
3951
3971
  /* @__PURE__ */ jsxs16("ul", { className: "sk-cf__list", children: [
3952
- /* @__PURE__ */ jsx17("li", { children: "Mental-health-related absences" }),
3953
- /* @__PURE__ */ jsx17("li", { children: "Workers\u2019 compensation certificates" }),
3954
- /* @__PURE__ */ jsx17("li", { children: "Legal or court-related certificates" }),
3955
- /* @__PURE__ */ jsx17("li", { children: "Insurance claim certificates" }),
3956
- /* @__PURE__ */ jsx17("li", { children: "Backdated certificates well after the fact" })
3972
+ /* @__PURE__ */ jsx18("li", { children: "Mental-health-related absences" }),
3973
+ /* @__PURE__ */ jsx18("li", { children: "Workers\u2019 compensation certificates" }),
3974
+ /* @__PURE__ */ jsx18("li", { children: "Legal or court-related certificates" }),
3975
+ /* @__PURE__ */ jsx18("li", { children: "Insurance claim certificates" }),
3976
+ /* @__PURE__ */ jsx18("li", { children: "Backdated certificates well after the fact" })
3957
3977
  ] }),
3958
- /* @__PURE__ */ jsx17("p", { className: "sk-cf__body", children: "For these, please see your regular GP, who can assess you in person and issue the right kind of certificate." }),
3978
+ /* @__PURE__ */ jsx18("p", { className: "sk-cf__body", children: "For these, please see your regular GP, who can assess you in person and issue the right kind of certificate." }),
3959
3979
  /* @__PURE__ */ jsxs16("ul", { className: "sk-cf__links", children: [
3960
- /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsx17(
3980
+ /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(
3961
3981
  "a",
3962
3982
  {
3963
3983
  className: "sk-cf__link",
@@ -3967,11 +3987,11 @@ function UnavailableStep({
3967
3987
  children: "Find a GP near you"
3968
3988
  }
3969
3989
  ) }),
3970
- clinicPhone && /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs16("a", { className: "sk-cf__link", href: `tel:${clinicPhone.replace(/[^\d+]/g, "")}`, children: [
3990
+ clinicPhone && /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsxs16("a", { className: "sk-cf__link", href: `tel:${clinicPhone.replace(/[^\d+]/g, "")}`, children: [
3971
3991
  "Call the clinic on ",
3972
3992
  clinicPhone
3973
3993
  ] }) }),
3974
- /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsx17("a", { className: "sk-cf__link", href: "tel:1800022222", children: "Health advice, 24 hours \u2014 healthdirect on 1800 022 222" }) })
3994
+ /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18("a", { className: "sk-cf__link", href: "tel:1800022222", children: "Health advice, 24 hours \u2014 healthdirect on 1800 022 222" }) })
3975
3995
  ] })
3976
3996
  ]
3977
3997
  }
@@ -3979,7 +3999,7 @@ function UnavailableStep({
3979
3999
  }
3980
4000
 
3981
4001
  // src/certificate-funnel.client.tsx
3982
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
4002
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
3983
4003
  function slotFlowIsLost(flowChecked, flow, capturing) {
3984
4004
  return flowChecked && !flow?.appointmentTypeId && !capturing;
3985
4005
  }
@@ -3991,16 +4011,28 @@ async function cancelRequestThenRestart(client, requestId, restart) {
3991
4011
  restart();
3992
4012
  }
3993
4013
  function CertificateFunnelClient(props) {
4014
+ const portalClient = React16.useMemo(
4015
+ () => createPortalClient({
4016
+ apiOrigin: props.publicApi?.portalApiOrigin,
4017
+ portalOrigin: props.publicApi?.portalOrigin,
4018
+ portalUrl: props.publicApi?.portalUrl
4019
+ }),
4020
+ [
4021
+ props.publicApi?.portalApiOrigin,
4022
+ props.publicApi?.portalOrigin,
4023
+ props.publicApi?.portalUrl
4024
+ ]
4025
+ );
3994
4026
  if (!props.publicApi?.publishableKey) {
3995
4027
  return /* @__PURE__ */ jsxs17("div", { className: "sk-cf sk-cf--unconfigured", children: [
3996
- /* @__PURE__ */ jsx18("h2", { className: "sk-certificate-funnel__heading", children: props.heading ?? "Medical certificates" }),
4028
+ /* @__PURE__ */ jsx19("h2", { className: "sk-certificate-funnel__heading", children: props.heading ?? "Medical certificates" }),
3997
4029
  /* @__PURE__ */ jsxs17("p", { className: "sk-certificate-funnel__placeholder", children: [
3998
4030
  "Online requests aren\u2019t available right now.",
3999
4031
  props.clinicPhone ? ` Please call the clinic on ${props.clinicPhone}.` : " Please call the clinic."
4000
4032
  ] })
4001
4033
  ] });
4002
4034
  }
4003
- return /* @__PURE__ */ jsx18(Funnel, { ...props });
4035
+ return /* @__PURE__ */ jsx19(PortalProvider, { client: portalClient, children: /* @__PURE__ */ jsx19(Funnel, { ...props }) });
4004
4036
  }
4005
4037
  function Funnel({
4006
4038
  publicApi,
@@ -4011,33 +4043,29 @@ function Funnel({
4011
4043
  serviceKey: pinnedService
4012
4044
  }) {
4013
4045
  const api = publicApi;
4014
- const rawClient = React15.useMemo(
4046
+ const rawClient = React16.useMemo(
4015
4047
  () => patientos({ publishableKey: api.publishableKey, apiBase: api.apiBase }),
4016
4048
  [api.publishableKey, api.apiBase]
4017
4049
  );
4018
- const portal = React15.useMemo(
4019
- () => ({ portalUrl: api.portalUrl, portalOrigin: api.portalOrigin }),
4020
- [api.portalUrl, api.portalOrigin]
4021
- );
4022
- const pinned = React15.useMemo(() => ({ pinnedService: !!pinnedService }), [pinnedService]);
4023
- const [state, setState] = React15.useState(null);
4024
- const [flow, setFlow] = React15.useState(null);
4025
- const [flowChecked, setFlowChecked] = React15.useState(false);
4026
- const [capturing, setCapturing] = React15.useState(false);
4027
- const [cancellingLostSlot, setCancellingLostSlot] = React15.useState(false);
4028
- const [lostSlotCancelError, setLostSlotCancelError] = React15.useState(null);
4029
- const [resolveError, setResolveError] = React15.useState(null);
4030
- const [identityDraft, setIdentityDraft] = React15.useState(null);
4031
- const [submittedIdentitySnapshot, setSubmittedIdentitySnapshot] = React15.useState(
4050
+ const pinned = React16.useMemo(() => ({ pinnedService: !!pinnedService }), [pinnedService]);
4051
+ const [state, setState] = React16.useState(null);
4052
+ const [flow, setFlow] = React16.useState(null);
4053
+ const [flowChecked, setFlowChecked] = React16.useState(false);
4054
+ const [capturing, setCapturing] = React16.useState(false);
4055
+ const [cancellingLostSlot, setCancellingLostSlot] = React16.useState(false);
4056
+ const [lostSlotCancelError, setLostSlotCancelError] = React16.useState(null);
4057
+ const [resolveError, setResolveError] = React16.useState(null);
4058
+ const [identityDraft, setIdentityDraft] = React16.useState(null);
4059
+ const [submittedIdentitySnapshot, setSubmittedIdentitySnapshot] = React16.useState(
4032
4060
  null
4033
4061
  );
4034
- const onDraftChange = React15.useCallback((draft) => setIdentityDraft(draft), []);
4035
- const [medicareDraft, setMedicareDraft] = React15.useState(null);
4036
- const onMedicareDraftChange = React15.useCallback(
4062
+ const onDraftChange = React16.useCallback((draft) => setIdentityDraft(draft), []);
4063
+ const [medicareDraft, setMedicareDraft] = React16.useState(null);
4064
+ const onMedicareDraftChange = React16.useCallback(
4037
4065
  (draft) => setMedicareDraft(draft),
4038
4066
  []
4039
4067
  );
4040
- const dispatch = React15.useCallback(
4068
+ const dispatch = React16.useCallback(
4041
4069
  (event) => {
4042
4070
  setState((prev) => {
4043
4071
  const current = prev ?? initialFunnelState(pinnedService);
@@ -4059,16 +4087,16 @@ function Funnel({
4059
4087
  },
4060
4088
  [pinnedService, pinned]
4061
4089
  );
4062
- const client = React15.useMemo(
4090
+ const client = React16.useMemo(
4063
4091
  () => observeSessionExpiry(rawClient, () => dispatch({ type: "SESSION_EXPIRED" })),
4064
4092
  [rawClient, dispatch]
4065
4093
  );
4066
- const [fees, setFees] = React15.useState(null);
4067
- const [deliveryModes, setDeliveryModes] = React15.useState(
4094
+ const [fees, setFees] = React16.useState(null);
4095
+ const [deliveryModes, setDeliveryModes] = React16.useState(
4068
4096
  null
4069
4097
  );
4070
- const [questionCounts, setQuestionCounts] = React15.useState({});
4071
- React15.useEffect(() => {
4098
+ const [questionCounts, setQuestionCounts] = React16.useState({});
4099
+ React16.useEffect(() => {
4072
4100
  let alive = true;
4073
4101
  void (async () => {
4074
4102
  try {
@@ -4100,9 +4128,9 @@ function Funnel({
4100
4128
  alive = false;
4101
4129
  };
4102
4130
  }, [client]);
4103
- const stateRef = React15.useRef(state);
4131
+ const stateRef = React16.useRef(state);
4104
4132
  stateRef.current = state;
4105
- React15.useEffect(() => {
4133
+ React16.useEffect(() => {
4106
4134
  dispatch({ type: "RESTORE", state: stepFromUrl(window.location.search, pinnedService) });
4107
4135
  const onPop = () => {
4108
4136
  const current = stateRef.current;
@@ -4119,7 +4147,7 @@ function Funnel({
4119
4147
  return () => window.removeEventListener("popstate", onPop);
4120
4148
  }, [dispatch, pinnedService, pinned]);
4121
4149
  const requestId = state?.requestId ?? null;
4122
- React15.useEffect(() => {
4150
+ React16.useEffect(() => {
4123
4151
  if (!requestId) {
4124
4152
  setFlow(null);
4125
4153
  setFlowChecked(false);
@@ -4132,7 +4160,7 @@ function Funnel({
4132
4160
  setFlow(loadFlowRecord(requestId));
4133
4161
  setFlowChecked(true);
4134
4162
  }, [requestId, flow]);
4135
- const captureFlow = React15.useCallback(
4163
+ const captureFlow = React16.useCallback(
4136
4164
  async (newRequestId, serviceKey, identity) => {
4137
4165
  const svc = await findServiceByKey(client, serviceKey);
4138
4166
  if (!svc) throw new Error("This certificate type is not currently available.");
@@ -4161,18 +4189,18 @@ function Funnel({
4161
4189
  },
4162
4190
  [client]
4163
4191
  );
4164
- const back2 = React15.useCallback(() => dispatch({ type: "BACK" }), [dispatch]);
4165
- const restart = React15.useCallback(() => {
4192
+ const back2 = React16.useCallback(() => dispatch({ type: "BACK" }), [dispatch]);
4193
+ const restart = React16.useCallback(() => {
4166
4194
  setIdentityDraft(null);
4167
4195
  setSubmittedIdentitySnapshot(null);
4168
4196
  setMedicareDraft(null);
4169
4197
  dispatch({ type: "RESTART" });
4170
4198
  }, [dispatch]);
4171
- const retryPayment = React15.useCallback(() => {
4199
+ const retryPayment = React16.useCallback(() => {
4172
4200
  setSubmittedIdentitySnapshot(null);
4173
4201
  dispatch({ type: "RETRY_PAYMENT" });
4174
4202
  }, [dispatch]);
4175
- const cancelLostSlot = React15.useCallback(async () => {
4203
+ const cancelLostSlot = React16.useCallback(async () => {
4176
4204
  const id = state?.requestId;
4177
4205
  if (!id || cancellingLostSlot) return;
4178
4206
  setCancellingLostSlot(true);
@@ -4189,7 +4217,7 @@ function Funnel({
4189
4217
  }, [cancellingLostSlot, client, restart, state?.requestId]);
4190
4218
  const chosenKey = state?.serviceKey ?? null;
4191
4219
  const step = state?.step;
4192
- const shape = React15.useMemo(() => {
4220
+ const shape = React16.useMemo(() => {
4193
4221
  const free = flowIsFree(flow);
4194
4222
  const feeSaysPaid = chosenKey ? fees?.[chosenKey]?.requiresPayment : void 0;
4195
4223
  return {
@@ -4210,7 +4238,7 @@ function Funnel({
4210
4238
  intakeSteps: intakeStepsFor(questionCounts, chosenKey)
4211
4239
  };
4212
4240
  }, [flow, fees, pinnedService, chosenKey, step, questionCounts]);
4213
- if (!state) return /* @__PURE__ */ jsx18(FlowLoading, {});
4241
+ if (!state) return /* @__PURE__ */ jsx19(FlowLoading, {});
4214
4242
  const title = stepTitle(state.step, clinicName);
4215
4243
  const service = services.find((s) => s.key === state.serviceKey) ?? null;
4216
4244
  const serviceLabel = service?.label ?? "certificate";
@@ -4223,7 +4251,7 @@ function Funnel({
4223
4251
  const showBack = canGoBack(state, pinned);
4224
4252
  const flowLost = slotFlowIsLost(flowChecked, flow, capturing);
4225
4253
  const quietMoney = HOLDLESS_STEPS.has(state.step) || state.step === "consent" || state.step === "payment";
4226
- const rail = /* @__PURE__ */ jsx18(
4254
+ const rail = /* @__PURE__ */ jsx19(
4227
4255
  TrustRail,
4228
4256
  {
4229
4257
  clinicName,
@@ -4233,7 +4261,7 @@ function Funnel({
4233
4261
  const renderStep = () => {
4234
4262
  switch (state.step) {
4235
4263
  case "service":
4236
- return /* @__PURE__ */ jsx18(
4264
+ return /* @__PURE__ */ jsx19(
4237
4265
  ServiceStep,
4238
4266
  {
4239
4267
  services,
@@ -4247,7 +4275,7 @@ function Funnel({
4247
4275
  }
4248
4276
  );
4249
4277
  case "preflight":
4250
- return /* @__PURE__ */ jsx18(
4278
+ return /* @__PURE__ */ jsx19(
4251
4279
  PreflightStep,
4252
4280
  {
4253
4281
  documentTitle: title,
@@ -4270,17 +4298,15 @@ function Funnel({
4270
4298
  dispatch({ type: "REQUEST_STARTED", requestId: resumeRequestId });
4271
4299
  },
4272
4300
  children: [
4273
- /* @__PURE__ */ jsx18(
4301
+ /* @__PURE__ */ jsx19(
4274
4302
  IdentityStep,
4275
4303
  {
4276
4304
  client,
4277
- portal,
4278
4305
  turnstileSiteKey: api.turnstileSiteKey,
4279
4306
  serviceKey: state.serviceKey ?? "",
4280
4307
  serviceLabel,
4281
4308
  mode: state.step,
4282
4309
  documentTitle: title,
4283
- returnUrl: typeof window === "undefined" ? void 0 : window.location.href,
4284
4310
  onSignedIn: () => dispatch({ type: "SIGNED_IN" }),
4285
4311
  onRejected: () => {
4286
4312
  setIdentityDraft(null);
@@ -4302,12 +4328,12 @@ function Funnel({
4302
4328
  }
4303
4329
  }
4304
4330
  ),
4305
- /* @__PURE__ */ jsx18(FlowError, { children: resolveError })
4331
+ /* @__PURE__ */ jsx19(FlowError, { children: resolveError })
4306
4332
  ]
4307
4333
  }
4308
4334
  );
4309
4335
  case "intake":
4310
- return /* @__PURE__ */ jsx18(
4336
+ return /* @__PURE__ */ jsx19(
4311
4337
  IntakeStep,
4312
4338
  {
4313
4339
  client,
@@ -4321,7 +4347,7 @@ function Funnel({
4321
4347
  }
4322
4348
  );
4323
4349
  case "medicare":
4324
- return /* @__PURE__ */ jsx18(
4350
+ return /* @__PURE__ */ jsx19(
4325
4351
  MedicareStep,
4326
4352
  {
4327
4353
  client,
@@ -4334,7 +4360,7 @@ function Funnel({
4334
4360
  }
4335
4361
  );
4336
4362
  case "consent":
4337
- return flowChecked && !flow && !capturing ? /* @__PURE__ */ jsx18(
4363
+ return flowChecked && !flow && !capturing ? /* @__PURE__ */ jsx19(
4338
4364
  FlowShell,
4339
4365
  {
4340
4366
  ...stepProgress("consent", shape),
@@ -4342,9 +4368,9 @@ function Funnel({
4342
4368
  heading: "Confirm & sign",
4343
4369
  onBack: showBack ? back2 : void 0,
4344
4370
  documentTitle: title,
4345
- children: /* @__PURE__ */ jsx18(FlowError, { children: "We can\u2019t pick up this booking in this browser. Please go back and try again." })
4371
+ children: /* @__PURE__ */ jsx19(FlowError, { children: "We can\u2019t pick up this booking in this browser. Please go back and try again." })
4346
4372
  }
4347
- ) : /* @__PURE__ */ jsx18(
4373
+ ) : /* @__PURE__ */ jsx19(
4348
4374
  ConsentStep,
4349
4375
  {
4350
4376
  client,
@@ -4368,7 +4394,7 @@ function Funnel({
4368
4394
  }
4369
4395
  );
4370
4396
  case "payment":
4371
- return /* @__PURE__ */ jsx18(
4397
+ return /* @__PURE__ */ jsx19(
4372
4398
  FlowShell,
4373
4399
  {
4374
4400
  ...stepProgress("payment", shape),
@@ -4377,7 +4403,7 @@ function Funnel({
4377
4403
  subheading: HOLD_RELEASE_NOTE,
4378
4404
  documentTitle: title,
4379
4405
  onBack: showBack ? back2 : void 0,
4380
- children: /* @__PURE__ */ jsx18(
4406
+ children: /* @__PURE__ */ jsx19(
4381
4407
  PaymentStep,
4382
4408
  {
4383
4409
  client,
@@ -4391,7 +4417,7 @@ function Funnel({
4391
4417
  }
4392
4418
  );
4393
4419
  case "slot":
4394
- return flow?.appointmentTypeId ? /* @__PURE__ */ jsx18(
4420
+ return flow?.appointmentTypeId ? /* @__PURE__ */ jsx19(
4395
4421
  SlotStep,
4396
4422
  {
4397
4423
  client,
@@ -4421,7 +4447,7 @@ function Funnel({
4421
4447
  stepKey: "slot",
4422
4448
  heading: "Choose your appointment time",
4423
4449
  documentTitle: title,
4424
- footer: /* @__PURE__ */ jsx18(
4450
+ footer: /* @__PURE__ */ jsx19(
4425
4451
  FlowButton,
4426
4452
  {
4427
4453
  type: "button",
@@ -4432,7 +4458,7 @@ function Funnel({
4432
4458
  }
4433
4459
  ),
4434
4460
  children: [
4435
- /* @__PURE__ */ jsx18(FlowError, { children: "We can\u2019t pick up this booking in this browser. Your request is still with the clinic." }),
4461
+ /* @__PURE__ */ jsx19(FlowError, { children: "We can\u2019t pick up this booking in this browser. Your request is still with the clinic." }),
4436
4462
  clinicPhone && /* @__PURE__ */ jsxs17("p", { className: "sk-slots__empty-note", children: [
4437
4463
  "Can\u2019t find a time that suits?",
4438
4464
  " ",
@@ -4441,22 +4467,22 @@ function Funnel({
4441
4467
  clinicPhone
4442
4468
  ] })
4443
4469
  ] }),
4444
- /* @__PURE__ */ jsx18(FlowError, { children: lostSlotCancelError })
4470
+ /* @__PURE__ */ jsx19(FlowError, { children: lostSlotCancelError })
4445
4471
  ]
4446
4472
  }
4447
4473
  )
4448
- ) : /* @__PURE__ */ jsx18(
4474
+ ) : /* @__PURE__ */ jsx19(
4449
4475
  FlowShell,
4450
4476
  {
4451
4477
  ...stepProgress("slot", shape),
4452
4478
  stepKey: "slot",
4453
4479
  heading: "Choose your appointment time",
4454
4480
  documentTitle: title,
4455
- children: /* @__PURE__ */ jsx18(FlowLoading, { message: "Loading your booking\u2026" })
4481
+ children: /* @__PURE__ */ jsx19(FlowLoading, { message: "Loading your booking\u2026" })
4456
4482
  }
4457
4483
  );
4458
4484
  case "submitted":
4459
- return /* @__PURE__ */ jsx18(
4485
+ return /* @__PURE__ */ jsx19(
4460
4486
  SubmittedStep,
4461
4487
  {
4462
4488
  client,
@@ -4472,7 +4498,7 @@ function Funnel({
4472
4498
  }
4473
4499
  );
4474
4500
  case "blocked":
4475
- return /* @__PURE__ */ jsx18(
4501
+ return /* @__PURE__ */ jsx19(
4476
4502
  BlockedStep,
4477
4503
  {
4478
4504
  gate: state.gate,
@@ -4482,9 +4508,9 @@ function Funnel({
4482
4508
  }
4483
4509
  );
4484
4510
  case "escalate":
4485
- return /* @__PURE__ */ jsx18(EscalateStep, { gate: state.gate, documentTitle: title });
4511
+ return /* @__PURE__ */ jsx19(EscalateStep, { gate: state.gate, documentTitle: title });
4486
4512
  case "payment-failed":
4487
- return /* @__PURE__ */ jsx18(
4513
+ return /* @__PURE__ */ jsx19(
4488
4514
  PaymentFailedStep,
4489
4515
  {
4490
4516
  message: state.failure,
@@ -4494,7 +4520,7 @@ function Funnel({
4494
4520
  }
4495
4521
  );
4496
4522
  case "session-expired":
4497
- return /* @__PURE__ */ jsx18(
4523
+ return /* @__PURE__ */ jsx19(
4498
4524
  SessionExpiredState,
4499
4525
  {
4500
4526
  requestStarted: !!state.requestId,
@@ -4505,7 +4531,7 @@ function Funnel({
4505
4531
  }
4506
4532
  );
4507
4533
  case "unavailable":
4508
- return /* @__PURE__ */ jsx18(
4534
+ return /* @__PURE__ */ jsx19(
4509
4535
  UnavailableStep,
4510
4536
  {
4511
4537
  documentTitle: title,
@@ -4515,7 +4541,7 @@ function Funnel({
4515
4541
  );
4516
4542
  }
4517
4543
  };
4518
- return /* @__PURE__ */ jsx18(FlowShapeContext.Provider, { value: shape, children: /* @__PURE__ */ jsx18(FlowRailContext.Provider, { value: rail, children: renderStep() }) });
4544
+ return /* @__PURE__ */ jsx19(FlowShapeContext.Provider, { value: shape, children: /* @__PURE__ */ jsx19(FlowRailContext.Provider, { value: rail, children: renderStep() }) });
4519
4545
  }
4520
4546
  function SessionExpiredState({
4521
4547
  requestStarted,
@@ -4530,35 +4556,29 @@ function SessionExpiredState({
4530
4556
  stepKey: "session-expired",
4531
4557
  heading: "Your secure session ended",
4532
4558
  documentTitle,
4533
- footer: portalUrl ? /* @__PURE__ */ jsx18("a", { className: "sk-flow__btn sk-flow__btn--primary", href: portalUrl, children: "Continue in the patient portal" }) : !requestStarted ? /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "primary", onClick: onRestart, children: "Start again securely" }) : void 0,
4559
+ footer: portalUrl ? /* @__PURE__ */ jsx19("a", { className: "sk-flow__btn sk-flow__btn--primary", href: portalUrl, children: "Continue in the patient portal" }) : !requestStarted ? /* @__PURE__ */ jsx19(FlowButton, { type: "button", variant: "primary", onClick: onRestart, children: "Start again securely" }) : void 0,
4534
4560
  children: [
4535
4561
  /* @__PURE__ */ jsxs17("p", { className: "sk-cf__body", children: [
4536
4562
  "This secure session is no longer available.",
4537
4563
  " ",
4538
4564
  requestStarted ? "Your request is still with the clinic." : "You can start again securely."
4539
4565
  ] }),
4540
- clinicPhone ? /* @__PURE__ */ jsx18(ClinicPhone, { clinicPhone }) : !portalUrl ? /* @__PURE__ */ jsx18("p", { className: "sk-cf__aside", children: "Please contact the clinic using the details on this website." }) : null
4566
+ clinicPhone ? /* @__PURE__ */ jsx19(ClinicPhone, { clinicPhone }) : !portalUrl ? /* @__PURE__ */ jsx19("p", { className: "sk-cf__aside", children: "Please contact the clinic using the details on this website." }) : null
4541
4567
  ]
4542
4568
  }
4543
4569
  );
4544
4570
  }
4545
4571
 
4546
4572
  // src/portal-panel.client.tsx
4547
- import * as React16 from "react";
4548
- import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
4573
+ import * as React17 from "react";
4574
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4549
4575
  var SUMMARY_URL = "/portal/api/summary";
4550
- async function loadPortalPanel(surface, fetchImpl) {
4551
- let body;
4552
- try {
4553
- const res = await fetchImpl(
4554
- portalApiUrl(`${SUMMARY_URL}?surface=${encodeURIComponent(surface)}`),
4555
- PORTAL_REQUEST_INIT
4556
- );
4557
- body = await res.json();
4558
- if (!res.ok) return { kind: "link-out" };
4559
- } catch {
4560
- return { kind: "link-out" };
4561
- }
4576
+ async function loadPortalPanelWithClient(surface, client) {
4577
+ const res = await client.get(
4578
+ `${SUMMARY_URL}?surface=${encodeURIComponent(surface)}`
4579
+ );
4580
+ if (!res.ok) return { kind: "link-out" };
4581
+ const body = res.data;
4562
4582
  if (typeof body?.signedIn !== "boolean") return { kind: "link-out" };
4563
4583
  if (!body.signedIn) return { kind: "signed-out" };
4564
4584
  return {
@@ -4567,9 +4587,6 @@ async function loadPortalPanel(surface, fetchImpl) {
4567
4587
  items: Array.isArray(body?.items) ? body.items : []
4568
4588
  };
4569
4589
  }
4570
- function requestPortalMagicLink(surface, email, fetchImpl) {
4571
- return requestPortalSignInLink(email, `/portal/${surface}`, fetchImpl);
4572
- }
4573
4590
  function itemMeta(item) {
4574
4591
  const when = item.start ?? item.date ?? item.placedAt ?? null;
4575
4592
  const parts = [];
@@ -4588,51 +4605,68 @@ function PortalPanelClient({
4588
4605
  initialState,
4589
4606
  fetchImpl
4590
4607
  }) {
4591
- configurePortalApiOrigin(portalApiOrigin);
4592
- const [state, setState] = React16.useState(initialState ?? { kind: "loading" });
4593
- React16.useEffect(() => {
4608
+ const client = React17.useMemo(
4609
+ () => createPortalClient({ apiOrigin: portalApiOrigin, portalUrl, fetchImpl }),
4610
+ [portalApiOrigin, portalUrl, fetchImpl]
4611
+ );
4612
+ return /* @__PURE__ */ jsx20(PortalProvider, { client, children: /* @__PURE__ */ jsx20(
4613
+ PortalPanelContent,
4614
+ {
4615
+ surface,
4616
+ portalUrl,
4617
+ initialState
4618
+ }
4619
+ ) });
4620
+ }
4621
+ function PortalPanelContent({
4622
+ surface,
4623
+ portalUrl,
4624
+ initialState
4625
+ }) {
4626
+ const client = usePortalClient();
4627
+ const [state, setState] = React17.useState(initialState ?? { kind: "loading" });
4628
+ React17.useEffect(() => {
4594
4629
  if (initialState) return;
4595
4630
  let live = true;
4596
- const f = fetchImpl ?? ((i, init) => fetch(i, init));
4597
- void loadPortalPanel(surface, f).then((next) => {
4631
+ void loadPortalPanelWithClient(surface, client).then((next) => {
4598
4632
  if (live) setState(next);
4599
4633
  });
4600
4634
  return () => {
4601
4635
  live = false;
4602
4636
  };
4603
- }, [surface, fetchImpl, initialState]);
4637
+ }, [surface, client, initialState]);
4604
4638
  const heading2 = PORTAL_SURFACE_LABEL[surface] ?? "Your portal";
4605
4639
  const href = portalSurfaceHref(surface, portalUrl);
4606
4640
  const signInHref = portalUrl ?? "/portal";
4607
4641
  return /* @__PURE__ */ jsxs18("section", { className: "sk-portal-panel__body", "aria-busy": state.kind === "loading", children: [
4608
- /* @__PURE__ */ jsx19("h2", { className: "sk-portal-panel__heading", children: heading2 }),
4609
- state.kind === "loading" ? /* @__PURE__ */ jsx19("p", { className: "sk-portal-panel__placeholder", children: "Checking your sign-in\u2026" }) : null,
4610
- state.kind === "link-out" ? /* @__PURE__ */ jsx19("p", { className: "sk-portal-panel__placeholder", children: /* @__PURE__ */ jsx19("a", { className: "sk-portal-panel__link", href: signInHref, children: "Sign in to your patient portal" }) }) : null,
4611
- state.kind === "signed-out" ? /* @__PURE__ */ jsx19(
4642
+ /* @__PURE__ */ jsx20("h2", { className: "sk-portal-panel__heading", children: heading2 }),
4643
+ state.kind === "loading" ? /* @__PURE__ */ jsx20("p", { className: "sk-portal-panel__placeholder", children: "Checking your sign-in\u2026" }) : null,
4644
+ state.kind === "link-out" ? /* @__PURE__ */ jsx20("p", { className: "sk-portal-panel__placeholder", children: /* @__PURE__ */ jsx20("a", { className: "sk-portal-panel__link", href: signInHref, children: "Sign in to your patient portal" }) }) : null,
4645
+ state.kind === "signed-out" ? /* @__PURE__ */ jsx20(
4612
4646
  PortalSignInRamp,
4613
4647
  {
4614
4648
  idSuffix: surface,
4615
- submit: (email) => requestPortalMagicLink(surface, email, fetchImpl ?? ((i, init) => fetch(i, init))),
4649
+ submit: (email) => client.requestMagicLink(email, `/portal/${surface}`).then((ok) => ({ ok })),
4616
4650
  onResult: ({ ok, email }) => setState(ok ? { kind: "link-sent", email } : { kind: "link-out" })
4617
4651
  }
4618
4652
  ) : null,
4619
- state.kind === "link-sent" ? /* @__PURE__ */ jsx19(PortalLinkSentNotice, { email: state.email }) : null,
4653
+ state.kind === "link-sent" ? /* @__PURE__ */ jsx20(PortalLinkSentNotice, { email: state.email }) : null,
4620
4654
  state.kind === "signed-in" ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
4621
- state.items.length === 0 ? /* @__PURE__ */ jsx19("p", { className: "sk-portal-panel__empty", children: "Nothing to show here yet." }) : /* @__PURE__ */ jsx19("ul", { className: "sk-portal-panel__list", children: state.items.map((item) => {
4655
+ state.items.length === 0 ? /* @__PURE__ */ jsx20("p", { className: "sk-portal-panel__empty", children: "Nothing to show here yet." }) : /* @__PURE__ */ jsx20("ul", { className: "sk-portal-panel__list", children: state.items.map((item) => {
4622
4656
  const meta = itemMeta(item);
4623
4657
  return /* @__PURE__ */ jsxs18("li", { className: "sk-portal-panel__item", children: [
4624
- /* @__PURE__ */ jsx19("span", { className: "sk-portal-panel__item-title", children: item.title ?? "\u2014" }),
4625
- meta ? /* @__PURE__ */ jsx19("span", { className: "sk-portal-panel__item-meta", children: meta }) : null,
4626
- item.status ? /* @__PURE__ */ jsx19("span", { className: "sk-portal-panel__item-status", children: item.status }) : null
4658
+ /* @__PURE__ */ jsx20("span", { className: "sk-portal-panel__item-title", children: item.title ?? "\u2014" }),
4659
+ meta ? /* @__PURE__ */ jsx20("span", { className: "sk-portal-panel__item-meta", children: meta }) : null,
4660
+ item.status ? /* @__PURE__ */ jsx20("span", { className: "sk-portal-panel__item-status", children: item.status }) : null
4627
4661
  ] }, item.id);
4628
4662
  }) }),
4629
- /* @__PURE__ */ jsx19("a", { className: "sk-portal-panel__link", href, children: "Open portal" })
4663
+ /* @__PURE__ */ jsx20("a", { className: "sk-portal-panel__link", href, children: "Open portal" })
4630
4664
  ] }) : null
4631
4665
  ] });
4632
4666
  }
4633
4667
 
4634
4668
  // src/portal-account.client.tsx
4635
- import * as React20 from "react";
4669
+ import * as React21 from "react";
4636
4670
 
4637
4671
  // ../website-sdk/src/types.ts
4638
4672
  var EMPTY_CLINIC_SNAPSHOT = {
@@ -10190,11 +10224,11 @@ MarkdownIt.prototype.renderInline = function(src, env) {
10190
10224
  var lib_default = MarkdownIt;
10191
10225
 
10192
10226
  // ../website-sdk/src/primitives.tsx
10193
- import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
10227
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
10194
10228
  var md = new lib_default({ html: false, linkify: true });
10195
10229
 
10196
10230
  // src/portal-book-launcher.tsx
10197
- import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
10231
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
10198
10232
  var DEFAULT_FUNNEL_HREF = "/certificates";
10199
10233
  function funnelServiceHref(funnelHref, serviceKey) {
10200
10234
  const trimmed = (funnelHref ?? DEFAULT_FUNNEL_HREF).replace(/\/$/, "");
@@ -10213,9 +10247,9 @@ function ServiceLauncherList({
10213
10247
  clinicPhone ? ` Please call the clinic on ${clinicPhone}.` : " Please call the clinic."
10214
10248
  ] });
10215
10249
  }
10216
- return /* @__PURE__ */ jsx21("ul", { className: "sk-portal-launcher", children: services.map((s) => {
10250
+ return /* @__PURE__ */ jsx22("ul", { className: "sk-portal-launcher", children: services.map((s) => {
10217
10251
  const price = prices?.[s.key] ?? "";
10218
- return /* @__PURE__ */ jsx21("li", { children: /* @__PURE__ */ jsxs20(
10252
+ return /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsxs20(
10219
10253
  "a",
10220
10254
  {
10221
10255
  className: "sk-portal-launcher__service",
@@ -10223,10 +10257,10 @@ function ServiceLauncherList({
10223
10257
  "data-sk-service": s.key,
10224
10258
  children: [
10225
10259
  /* @__PURE__ */ jsxs20("span", { className: "sk-portal-launcher__body", children: [
10226
- /* @__PURE__ */ jsx21("span", { className: "sk-portal-launcher__label", children: s.label }),
10227
- price ? /* @__PURE__ */ jsx21("span", { className: "sk-portal-launcher__fee", children: price }) : null
10260
+ /* @__PURE__ */ jsx22("span", { className: "sk-portal-launcher__label", children: s.label }),
10261
+ price ? /* @__PURE__ */ jsx22("span", { className: "sk-portal-launcher__fee", children: price }) : null
10228
10262
  ] }),
10229
- /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "sk-portal-launcher__chevron", children: "\u2192" })
10263
+ /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "sk-portal-launcher__chevron", children: "\u2192" })
10230
10264
  ]
10231
10265
  }
10232
10266
  ) }, s.key);
@@ -10234,7 +10268,7 @@ function ServiceLauncherList({
10234
10268
  }
10235
10269
 
10236
10270
  // src/portal-account.tsx
10237
- import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
10271
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
10238
10272
  var PORTAL_ACCOUNT_HEADING = {
10239
10273
  appointments: "Your appointments",
10240
10274
  documents: "Your documents",
@@ -10287,7 +10321,7 @@ function PortalAccount({
10287
10321
  },
10288
10322
  className: ["sk-portal-account", className].filter(Boolean).join(" "),
10289
10323
  children: [
10290
- /* @__PURE__ */ jsx22("h2", { className: "sk-portal-account__heading", children: PORTAL_ACCOUNT_HEADING[surface] ?? "Your account" }),
10324
+ /* @__PURE__ */ jsx23("h2", { className: "sk-portal-account__heading", children: PORTAL_ACCOUNT_HEADING[surface] ?? "Your account" }),
10291
10325
  isBook ? (
10292
10326
  // A REAL, working list — not a sign-in card. Every link here is valid before any
10293
10327
  // JavaScript runs, because the services and their destinations are both known at
@@ -10295,7 +10329,7 @@ function PortalAccount({
10295
10329
  // carry. This is the surface a crawler indexes and a patient with JS blocked
10296
10330
  // keeps permanently, and for a launcher that is the whole feature rather than a
10297
10331
  // degraded copy of it.
10298
- /* @__PURE__ */ jsx22(
10332
+ /* @__PURE__ */ jsx23(
10299
10333
  ServiceLauncherList,
10300
10334
  {
10301
10335
  services,
@@ -10304,8 +10338,8 @@ function PortalAccount({
10304
10338
  }
10305
10339
  )
10306
10340
  ) : /* @__PURE__ */ jsxs21("div", { className: "sk-portal-account__signin-card", children: [
10307
- /* @__PURE__ */ jsx22("p", { className: "sk-portal-account__placeholder", children: SURFACE_PROMPT[surface] ?? "Sign in to see your account." }),
10308
- /* @__PURE__ */ jsx22("a", { className: "sk-portal-link", href, children: "Sign in to your patient portal" })
10341
+ /* @__PURE__ */ jsx23("p", { className: "sk-portal-account__placeholder", children: SURFACE_PROMPT[surface] ?? "Sign in to see your account." }),
10342
+ /* @__PURE__ */ jsx23("a", { className: "sk-portal-link", href, children: "Sign in to your patient portal" })
10309
10343
  ] })
10310
10344
  ]
10311
10345
  }
@@ -10313,18 +10347,18 @@ function PortalAccount({
10313
10347
  }
10314
10348
 
10315
10349
  // src/portal-book-launcher.client.tsx
10316
- import * as React17 from "react";
10317
- import { jsx as jsx23 } from "react/jsx-runtime";
10350
+ import * as React18 from "react";
10351
+ import { jsx as jsx24 } from "react/jsx-runtime";
10318
10352
  function PortalBookLauncher({
10319
10353
  services,
10320
10354
  funnelHref,
10321
10355
  clinicPhone,
10322
10356
  publicApi
10323
10357
  }) {
10324
- const [prices, setPrices] = React17.useState({});
10358
+ const [prices, setPrices] = React18.useState({});
10325
10359
  const publishableKey = publicApi?.publishableKey ?? "";
10326
10360
  const apiBase = publicApi?.apiBase ?? "";
10327
- React17.useEffect(() => {
10361
+ React18.useEffect(() => {
10328
10362
  if (!publishableKey) return;
10329
10363
  let alive = true;
10330
10364
  void (async () => {
@@ -10348,7 +10382,7 @@ function PortalBookLauncher({
10348
10382
  alive = false;
10349
10383
  };
10350
10384
  }, [publishableKey, apiBase]);
10351
- return /* @__PURE__ */ jsx23(
10385
+ return /* @__PURE__ */ jsx24(
10352
10386
  ServiceLauncherList,
10353
10387
  {
10354
10388
  services,
@@ -10360,8 +10394,8 @@ function PortalBookLauncher({
10360
10394
  }
10361
10395
 
10362
10396
  // src/portal-addresses.client.tsx
10363
- import * as React18 from "react";
10364
- import { Fragment as Fragment9, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
10397
+ import * as React19 from "react";
10398
+ import { Fragment as Fragment9, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
10365
10399
  var ADDRESSES_URL = "/portal/api/addresses";
10366
10400
  var PORTAL_ADDRESSES_URL = ADDRESSES_URL;
10367
10401
  var ADDRESS_SAVE_FAILED_COPY = "We couldn't save that address just now. Please try again.";
@@ -10384,31 +10418,42 @@ function portalAddressPatchOf(a) {
10384
10418
  }
10385
10419
  var AUTOCOMPLETE_URL = "/api/address/autocomplete";
10386
10420
  var VALIDATE_URL = "/api/address/validate";
10387
- async function searchPortalAddresses(query) {
10421
+ async function searchPortalAddresses(query, client) {
10388
10422
  const q = query.trim();
10389
10423
  if (q.length < 3) return [];
10390
- const res = await fetch(portalApiUrl(`${AUTOCOMPLETE_URL}?q=${encodeURIComponent(q)}`), {
10391
- // `include`, not `same-origin`: on a separately-deployed clinic site this resolves to
10392
- // the APP's origin, and the endpoint's only door for a patient is the portal session
10393
- // cookie (address-google.server.ts `hasAddressAccess`). Same-origin it is identical.
10394
- credentials: "include",
10395
- headers: { accept: "application/json" }
10396
- });
10397
- if (!res.ok) return [];
10398
- const body = await res.json();
10399
- return body.suggestions ?? [];
10424
+ try {
10425
+ const res = await client.fetch(
10426
+ client.url(`${AUTOCOMPLETE_URL}?q=${encodeURIComponent(q)}`),
10427
+ {
10428
+ // `include`, not `same-origin`: on a separately-deployed clinic site this resolves
10429
+ // to the APP's origin, and the endpoint's only door for a patient is the portal
10430
+ // session cookie (address-google.server.ts `hasAddressAccess`).
10431
+ credentials: "include",
10432
+ headers: { accept: "application/json" }
10433
+ }
10434
+ );
10435
+ if (!res.ok) return [];
10436
+ const body = await res.json();
10437
+ return body.suggestions ?? [];
10438
+ } catch {
10439
+ return [];
10440
+ }
10400
10441
  }
10401
- async function validatePortalAddress(address) {
10402
- const res = await fetch(portalApiUrl(VALIDATE_URL), {
10403
- method: "POST",
10404
- credentials: "include",
10405
- headers: { "content-type": "application/json" },
10406
- body: JSON.stringify({ address })
10407
- });
10408
- if (!res.ok) return null;
10409
- const v = await res.json();
10410
- if (v.error || !v.formattedAddress) return null;
10411
- return { address: v.formattedAddress, placeId: v.googlePlaceId ?? null };
10442
+ async function validatePortalAddress(address, client) {
10443
+ try {
10444
+ const res = await client.fetch(client.url(VALIDATE_URL), {
10445
+ method: "POST",
10446
+ credentials: "include",
10447
+ headers: { "content-type": "application/json" },
10448
+ body: JSON.stringify({ address })
10449
+ });
10450
+ if (!res.ok) return null;
10451
+ const v = await res.json();
10452
+ if (v.error || !v.formattedAddress) return null;
10453
+ return { address: v.formattedAddress, placeId: v.googlePlaceId ?? null };
10454
+ } catch {
10455
+ return null;
10456
+ }
10412
10457
  }
10413
10458
  async function reload(fetchImpl) {
10414
10459
  const res = await portalGet(ADDRESSES_URL, fetchImpl);
@@ -10439,17 +10484,18 @@ async function deletePortalAddressAndReload(id, fetchImpl) {
10439
10484
  }
10440
10485
  function PortalAccountAddresses({
10441
10486
  data,
10487
+ client,
10442
10488
  fetchImpl,
10443
10489
  onReloaded,
10444
10490
  initialUi
10445
10491
  }) {
10446
- const [editing, setEditing] = React18.useState(initialUi?.editing ?? null);
10447
- const [form, setForm] = React18.useState(
10492
+ const [editing, setEditing] = React19.useState(initialUi?.editing ?? null);
10493
+ const [form, setForm] = React19.useState(
10448
10494
  initialUi?.form ?? emptyPortalAddressPatch()
10449
10495
  );
10450
- const [deletingId, setDeletingId] = React18.useState(initialUi?.deletingId ?? null);
10451
- const [error2, setError] = React18.useState(initialUi?.error ?? null);
10452
- const [busy, setBusy] = React18.useState(false);
10496
+ const [deletingId, setDeletingId] = React19.useState(initialUi?.deletingId ?? null);
10497
+ const [error2, setError] = React19.useState(initialUi?.error ?? null);
10498
+ const [busy, setBusy] = React19.useState(false);
10453
10499
  function openEdit(a) {
10454
10500
  setEditing(a ? a.id : "new");
10455
10501
  setForm(portalAddressPatchOf(a));
@@ -10490,15 +10536,15 @@ function PortalAccountAddresses({
10490
10536
  }
10491
10537
  const set2 = (k) => (v) => setForm((prev) => ({ ...prev, [k]: v }));
10492
10538
  return /* @__PURE__ */ jsxs22(Fragment9, { children: [
10493
- error2 ? /* @__PURE__ */ jsx24("p", { className: "sk-portal-error", role: "alert", children: error2 }) : null,
10494
- data.items.length === 0 && editing !== "new" ? /* @__PURE__ */ jsx24("p", { className: "sk-portal-account__empty", children: "We don't have an address for you yet." }) : null,
10495
- data.items.length > 0 ? /* @__PURE__ */ jsx24("ul", { className: "sk-portal-account__list", children: data.items.map((address) => /* @__PURE__ */ jsxs22("li", { className: "sk-portal-account__item", children: [
10539
+ error2 ? /* @__PURE__ */ jsx25("p", { className: "sk-portal-error", role: "alert", children: error2 }) : null,
10540
+ data.items.length === 0 && editing !== "new" ? /* @__PURE__ */ jsx25("p", { className: "sk-portal-account__empty", children: "We don't have an address for you yet." }) : null,
10541
+ data.items.length > 0 ? /* @__PURE__ */ jsx25("ul", { className: "sk-portal-account__list", children: data.items.map((address) => /* @__PURE__ */ jsxs22("li", { className: "sk-portal-account__item", children: [
10496
10542
  /* @__PURE__ */ jsxs22("div", { className: "sk-portal-account__item-head", children: [
10497
- /* @__PURE__ */ jsx24("span", { className: "sk-portal-account__item-title", children: address.label || formatPortalAddress(address) || "Address" }),
10498
- address.isPrimary ? /* @__PURE__ */ jsx24("span", { className: "sk-portal-account__status", children: "Main address" }) : null
10543
+ /* @__PURE__ */ jsx25("span", { className: "sk-portal-account__item-title", children: address.label || formatPortalAddress(address) || "Address" }),
10544
+ address.isPrimary ? /* @__PURE__ */ jsx25("span", { className: "sk-portal-account__status", children: "Main address" }) : null
10499
10545
  ] }),
10500
- address.label ? /* @__PURE__ */ jsx24("span", { className: "sk-portal-account__item-meta", children: formatPortalAddress(address) }) : null,
10501
- editing === address.id ? /* @__PURE__ */ jsx24(
10546
+ address.label ? /* @__PURE__ */ jsx25("span", { className: "sk-portal-account__item-meta", children: formatPortalAddress(address) }) : null,
10547
+ editing === address.id ? /* @__PURE__ */ jsx25(
10502
10548
  AddressForm,
10503
10549
  {
10504
10550
  idPrefix: address.id,
@@ -10507,10 +10553,11 @@ function PortalAccountAddresses({
10507
10553
  busy,
10508
10554
  submitLabel: "Save address",
10509
10555
  onSubmit: (e) => void save(e),
10510
- onCancel: () => setEditing(null)
10556
+ onCancel: () => setEditing(null),
10557
+ client
10511
10558
  }
10512
10559
  ) : /* @__PURE__ */ jsxs22("div", { className: "sk-portal-account__actions", children: [
10513
- /* @__PURE__ */ jsx24(
10560
+ /* @__PURE__ */ jsx25(
10514
10561
  "button",
10515
10562
  {
10516
10563
  type: "button",
@@ -10519,7 +10566,7 @@ function PortalAccountAddresses({
10519
10566
  children: "Edit"
10520
10567
  }
10521
10568
  ),
10522
- !address.isPrimary ? /* @__PURE__ */ jsx24(
10569
+ !address.isPrimary ? /* @__PURE__ */ jsx25(
10523
10570
  "button",
10524
10571
  {
10525
10572
  type: "button",
@@ -10529,7 +10576,7 @@ function PortalAccountAddresses({
10529
10576
  children: "Make main"
10530
10577
  }
10531
10578
  ) : null,
10532
- /* @__PURE__ */ jsx24(
10579
+ /* @__PURE__ */ jsx25(
10533
10580
  "button",
10534
10581
  {
10535
10582
  type: "button",
@@ -10547,9 +10594,9 @@ function PortalAccountAddresses({
10547
10594
  // In-place confirm, same as cancelling an appointment: removing the
10548
10595
  // address a prescription is posted to is not an undo-able tap.
10549
10596
  /* @__PURE__ */ jsxs22("div", { className: "sk-portal-account__confirm", children: [
10550
- /* @__PURE__ */ jsx24("p", { className: "sk-portal-account__confirm-title", children: "Remove this address?" }),
10597
+ /* @__PURE__ */ jsx25("p", { className: "sk-portal-account__confirm-title", children: "Remove this address?" }),
10551
10598
  /* @__PURE__ */ jsxs22("div", { className: "sk-portal-account__confirm-actions", children: [
10552
- /* @__PURE__ */ jsx24(
10599
+ /* @__PURE__ */ jsx25(
10553
10600
  "button",
10554
10601
  {
10555
10602
  type: "button",
@@ -10559,7 +10606,7 @@ function PortalAccountAddresses({
10559
10606
  children: busy ? "Removing\u2026" : "Remove address"
10560
10607
  }
10561
10608
  ),
10562
- /* @__PURE__ */ jsx24(
10609
+ /* @__PURE__ */ jsx25(
10563
10610
  "button",
10564
10611
  {
10565
10612
  type: "button",
@@ -10573,7 +10620,7 @@ function PortalAccountAddresses({
10573
10620
  ] })
10574
10621
  ) : null
10575
10622
  ] }, address.id)) }) : null,
10576
- editing === "new" ? /* @__PURE__ */ jsx24(
10623
+ editing === "new" ? /* @__PURE__ */ jsx25(
10577
10624
  AddressForm,
10578
10625
  {
10579
10626
  idPrefix: "new",
@@ -10582,9 +10629,10 @@ function PortalAccountAddresses({
10582
10629
  busy,
10583
10630
  submitLabel: "Add address",
10584
10631
  onSubmit: (e) => void save(e),
10585
- onCancel: () => setEditing(null)
10632
+ onCancel: () => setEditing(null),
10633
+ client
10586
10634
  }
10587
- ) : /* @__PURE__ */ jsx24(
10635
+ ) : /* @__PURE__ */ jsx25(
10588
10636
  "button",
10589
10637
  {
10590
10638
  type: "button",
@@ -10603,11 +10651,12 @@ function AddressForm({
10603
10651
  busy,
10604
10652
  submitLabel,
10605
10653
  onSubmit,
10606
- onCancel
10654
+ onCancel,
10655
+ client
10607
10656
  }) {
10608
10657
  const id = (field) => `sk-portal-address-${field}-${idPrefix}`;
10609
10658
  return /* @__PURE__ */ jsxs22("form", { className: "sk-portal-account__form", onSubmit, children: [
10610
- /* @__PURE__ */ jsx24(
10659
+ /* @__PURE__ */ jsx25(
10611
10660
  AddressPicker,
10612
10661
  {
10613
10662
  idPrefix: `sk-portal-address-${idPrefix}`,
@@ -10618,13 +10667,13 @@ function AddressForm({
10618
10667
  set2("address")(place?.address ?? "");
10619
10668
  set2("placeId")(place?.placeId ?? "");
10620
10669
  },
10621
- search: searchPortalAddresses,
10622
- validate: validatePortalAddress
10670
+ search: (query) => searchPortalAddresses(query, client),
10671
+ validate: (address) => validatePortalAddress(address, client)
10623
10672
  }
10624
10673
  ),
10625
10674
  /* @__PURE__ */ jsxs22("div", { className: "sk-portal-account__confirm-actions", children: [
10626
- /* @__PURE__ */ jsx24("button", { className: "sk-portal-button", type: "submit", disabled: busy, children: busy ? "Saving\u2026" : submitLabel }),
10627
- /* @__PURE__ */ jsx24(
10675
+ /* @__PURE__ */ jsx25("button", { className: "sk-portal-button", type: "submit", disabled: busy, children: busy ? "Saving\u2026" : submitLabel }),
10676
+ /* @__PURE__ */ jsx25(
10628
10677
  "button",
10629
10678
  {
10630
10679
  type: "button",
@@ -10639,8 +10688,8 @@ function AddressForm({
10639
10688
  }
10640
10689
 
10641
10690
  // src/portal-consult.client.tsx
10642
- import * as React19 from "react";
10643
- import { Fragment as Fragment10, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
10691
+ import * as React20 from "react";
10692
+ import { Fragment as Fragment10, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
10644
10693
  function consultChunkUrl(base2 = import.meta.url) {
10645
10694
  return new URL(CONSULT_CHUNK_PATH, base2).href;
10646
10695
  }
@@ -10690,12 +10739,12 @@ function PortalConsultPanel({
10690
10739
  loadModule,
10691
10740
  initialUi
10692
10741
  }) {
10693
- const hostRef = React19.useRef(null);
10694
- const [status, setStatus] = React19.useState(initialUi?.status ?? "loading");
10695
- const [error2, setError] = React19.useState(null);
10696
- const closeRef = React19.useRef(onClose);
10742
+ const hostRef = React20.useRef(null);
10743
+ const [status, setStatus] = React20.useState(initialUi?.status ?? "loading");
10744
+ const [error2, setError] = React20.useState(null);
10745
+ const closeRef = React20.useRef(onClose);
10697
10746
  closeRef.current = onClose;
10698
- React19.useEffect(() => {
10747
+ React20.useEffect(() => {
10699
10748
  const el = hostRef.current;
10700
10749
  if (!el) return;
10701
10750
  let live = true;
@@ -10722,7 +10771,7 @@ function PortalConsultPanel({
10722
10771
  teardown?.();
10723
10772
  };
10724
10773
  }, [appointmentId, fetchImpl, loadModule]);
10725
- React19.useEffect(() => {
10774
+ React20.useEffect(() => {
10726
10775
  function onKeyDown(e) {
10727
10776
  if (e.key === "Escape") closeRef.current();
10728
10777
  }
@@ -10731,8 +10780,8 @@ function PortalConsultPanel({
10731
10780
  }, []);
10732
10781
  return /* @__PURE__ */ jsxs23("div", { className: "sk-consult", role: "group", "aria-label": "Video consult", children: [
10733
10782
  /* @__PURE__ */ jsxs23("div", { className: "sk-consult__head", children: [
10734
- /* @__PURE__ */ jsx25("p", { className: "sk-consult__title", children: "Video consult" }),
10735
- /* @__PURE__ */ jsx25(
10783
+ /* @__PURE__ */ jsx26("p", { className: "sk-consult__title", children: "Video consult" }),
10784
+ /* @__PURE__ */ jsx26(
10736
10785
  "button",
10737
10786
  {
10738
10787
  type: "button",
@@ -10742,17 +10791,17 @@ function PortalConsultPanel({
10742
10791
  }
10743
10792
  )
10744
10793
  ] }),
10745
- status === "loading" ? /* @__PURE__ */ jsx25("p", { className: "sk-portal-account__placeholder", role: "status", children: "Starting your video call\u2026" }) : null,
10794
+ status === "loading" ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", role: "status", children: "Starting your video call\u2026" }) : null,
10746
10795
  status === "failed" ? /* @__PURE__ */ jsxs23(Fragment10, { children: [
10747
- /* @__PURE__ */ jsx25("p", { className: "sk-portal-error", role: "alert", children: error2 ?? CONSULT_LOAD_FAILED_COPY }),
10748
- /* @__PURE__ */ jsx25("a", { className: "sk-portal-button", href: fallbackHref, children: CONSULT_FALLBACK_LINK_COPY })
10796
+ /* @__PURE__ */ jsx26("p", { className: "sk-portal-error", role: "alert", children: error2 ?? CONSULT_LOAD_FAILED_COPY }),
10797
+ /* @__PURE__ */ jsx26("a", { className: "sk-portal-button", href: fallbackHref, children: CONSULT_FALLBACK_LINK_COPY })
10749
10798
  ] }) : null,
10750
- /* @__PURE__ */ jsx25("div", { className: "sk-consult__host", ref: hostRef })
10799
+ /* @__PURE__ */ jsx26("div", { className: "sk-consult__host", ref: hostRef })
10751
10800
  ] });
10752
10801
  }
10753
10802
 
10754
10803
  // src/portal-account.client.tsx
10755
- import { Fragment as Fragment11, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
10804
+ import { Fragment as Fragment11, jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
10756
10805
  var APPOINTMENTS_URL = "/portal/api/appointments";
10757
10806
  var CANCEL_REASONS_URL = "/portal/api/appointments/cancel-reasons";
10758
10807
  var DOCUMENTS_URL = "/portal/api/documents";
@@ -10860,11 +10909,25 @@ async function savePortalProfileAndReload(patch, fetchImpl) {
10860
10909
  if (!next.ok) return { ok: false, error: PROFILE_SAVE_FAILED_COPY };
10861
10910
  return { ok: true, data: next.data ?? {} };
10862
10911
  }
10912
+ function refetchedGivenName(data) {
10913
+ if (!hasPortalIdentity(data)) return void 0;
10914
+ return data.givenName ?? null;
10915
+ }
10863
10916
  function PortalAccountClient(props) {
10917
+ const client = React21.useMemo(
10918
+ () => createPortalClient({
10919
+ apiOrigin: props.portalApiOrigin,
10920
+ portalUrl: props.portalUrl,
10921
+ fetchImpl: props.fetchImpl
10922
+ }),
10923
+ [props.portalApiOrigin, props.portalUrl, props.fetchImpl]
10924
+ );
10925
+ return /* @__PURE__ */ jsx27(PortalProvider, { client, children: /* @__PURE__ */ jsx27(PortalAccountContent, { ...props }) });
10926
+ }
10927
+ function PortalAccountContent(props) {
10864
10928
  const { surface } = props;
10865
- configurePortalApiOrigin(props.portalApiOrigin);
10866
- if (surface === "book") return /* @__PURE__ */ jsx26(PortalAccountBookLauncher, { ...props });
10867
- return /* @__PURE__ */ jsx26(PortalAccountSurfaceClient, { ...props, surface });
10929
+ if (surface === "book") return /* @__PURE__ */ jsx27(PortalAccountBookLauncher, { ...props });
10930
+ return /* @__PURE__ */ jsx27(PortalAccountSurfaceClient, { ...props, surface });
10868
10931
  }
10869
10932
  function PortalAccountBookLauncher({
10870
10933
  funnelHref,
@@ -10873,8 +10936,8 @@ function PortalAccountBookLauncher({
10873
10936
  clinicPhone
10874
10937
  }) {
10875
10938
  return /* @__PURE__ */ jsxs24("section", { className: "sk-portal-account__body", children: [
10876
- /* @__PURE__ */ jsx26("h2", { className: "sk-portal-account__heading", children: PORTAL_ACCOUNT_HEADING.book }),
10877
- /* @__PURE__ */ jsx26(
10939
+ /* @__PURE__ */ jsx27("h2", { className: "sk-portal-account__heading", children: PORTAL_ACCOUNT_HEADING.book }),
10940
+ /* @__PURE__ */ jsx27(
10878
10941
  PortalBookLauncher,
10879
10942
  {
10880
10943
  services: services ?? [],
@@ -10890,21 +10953,26 @@ function PortalAccountSurfaceClient({
10890
10953
  portalUrl,
10891
10954
  bookHref,
10892
10955
  initialState,
10893
- fetchImpl,
10956
+ fetchImpl: rawFetchImpl,
10894
10957
  openUrl
10895
10958
  }) {
10896
- const [state, setState] = React20.useState(
10959
+ const portalClient = usePortalClient();
10960
+ const fetchImpl = React21.useMemo(
10961
+ () => portalFetchForClient(portalClient, rawFetchImpl),
10962
+ [portalClient, rawFetchImpl]
10963
+ );
10964
+ const [state, setState] = React21.useState(
10897
10965
  // `readPortalSignedInHint` is in the initialiser (not an effect) on purpose: the
10898
10966
  // whole point is that the FIRST paint already knows, so there is no placeholder
10899
10967
  // swap. It reads one boolean out of sessionStorage — no PHI, no network.
10900
10968
  () => initialState ?? { kind: "loading", hinted: readPortalSignedInHint() }
10901
10969
  );
10902
- const [signingOut, setSigningOut] = React20.useState(false);
10903
- const commit = React20.useCallback((next) => {
10970
+ const [signingOut, setSigningOut] = React21.useState(false);
10971
+ const commit = React21.useCallback((next) => {
10904
10972
  writePortalSignedInHint(next.kind === "signed-in" || next.kind === "not-available");
10905
10973
  setState(next);
10906
10974
  }, []);
10907
- React20.useEffect(() => {
10975
+ React21.useEffect(() => {
10908
10976
  if (initialState) return;
10909
10977
  let live = true;
10910
10978
  void loadPortalAccount(surface, fetchImpl).then((next) => {
@@ -10926,28 +10994,31 @@ function PortalAccountSurfaceClient({
10926
10994
  commit(next);
10927
10995
  }
10928
10996
  function replaceData(data) {
10929
- setState((prev) => prev.kind === "signed-in" ? { ...prev, data } : prev);
10997
+ const refetched = refetchedGivenName(data);
10998
+ setState(
10999
+ (prev) => prev.kind === "signed-in" ? { ...prev, data, givenName: refetched === void 0 ? prev.givenName : refetched } : prev
11000
+ );
10930
11001
  }
10931
11002
  return /* @__PURE__ */ jsxs24("section", { className: "sk-portal-account__body", "aria-busy": state.kind === "loading", children: [
10932
- /* @__PURE__ */ jsx26("h2", { className: "sk-portal-account__heading", children: heading2 }),
10933
- state.kind === "loading" && !state.hinted ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", children: "Checking your sign-in\u2026" }) : null,
10934
- state.kind === "loading" && state.hinted ? /* @__PURE__ */ jsx26(PortalAccountSkeleton, {}) : null,
10935
- state.kind === "link-out" ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", children: /* @__PURE__ */ jsx26("a", { className: "sk-portal-link", href: base2, children: "Sign in to your patient portal" }) }) : null,
10936
- state.kind === "signed-out" ? /* @__PURE__ */ jsx26(
11003
+ /* @__PURE__ */ jsx27("h2", { className: "sk-portal-account__heading", children: heading2 }),
11004
+ state.kind === "loading" && !state.hinted ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__placeholder", children: "Checking your sign-in\u2026" }) : null,
11005
+ state.kind === "loading" && state.hinted ? /* @__PURE__ */ jsx27(PortalAccountSkeleton, {}) : null,
11006
+ state.kind === "link-out" ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__placeholder", children: /* @__PURE__ */ jsx27("a", { className: "sk-portal-link", href: base2, children: "Sign in to your patient portal" }) }) : null,
11007
+ state.kind === "signed-out" ? /* @__PURE__ */ jsx27(
10937
11008
  PortalSignInRamp,
10938
11009
  {
10939
11010
  idSuffix: `account-${surface}`,
10940
- submit: (email) => requestPortalSignInLink(email, currentPagePath(), fetchImpl),
11011
+ submit: (email) => portalClient.requestMagicLink(email).then((ok) => ({ ok })),
10941
11012
  onResult: ({ ok, email }) => setState(ok ? { kind: "link-sent", email } : { kind: "link-out" })
10942
11013
  }
10943
11014
  ) : null,
10944
- state.kind === "link-sent" ? /* @__PURE__ */ jsx26(PortalLinkSentNotice, { email: state.email }) : null,
11015
+ state.kind === "link-sent" ? /* @__PURE__ */ jsx27(PortalLinkSentNotice, { email: state.email }) : null,
10945
11016
  state.kind === "not-available" || state.kind === "signed-in" ? /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__header", children: [
10946
11017
  /* @__PURE__ */ jsxs24("span", { className: "sk-portal-account__who", children: [
10947
11018
  "Signed in as ",
10948
11019
  state.givenName ?? "you"
10949
11020
  ] }),
10950
- /* @__PURE__ */ jsx26(
11021
+ /* @__PURE__ */ jsx27(
10951
11022
  "button",
10952
11023
  {
10953
11024
  type: "button",
@@ -10958,8 +11029,8 @@ function PortalAccountSurfaceClient({
10958
11029
  }
10959
11030
  )
10960
11031
  ] }) : null,
10961
- state.kind === "not-available" ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__note", role: "note", children: "This isn't available online at this clinic." }) : null,
10962
- state.kind === "signed-in" && surface === "appointments" ? /* @__PURE__ */ jsx26(
11032
+ state.kind === "not-available" ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__note", role: "note", children: "This isn't available online at this clinic." }) : null,
11033
+ state.kind === "signed-in" && surface === "appointments" ? /* @__PURE__ */ jsx27(
10963
11034
  PortalAccountAppointments,
10964
11035
  {
10965
11036
  data: state.data,
@@ -10969,15 +11040,16 @@ function PortalAccountSurfaceClient({
10969
11040
  onReloaded: replaceData
10970
11041
  }
10971
11042
  ) : null,
10972
- state.kind === "signed-in" && surface === "addresses" ? /* @__PURE__ */ jsx26(
11043
+ state.kind === "signed-in" && surface === "addresses" ? /* @__PURE__ */ jsx27(
10973
11044
  PortalAccountAddresses,
10974
11045
  {
10975
11046
  data: state.data,
11047
+ client: portalClient,
10976
11048
  fetchImpl,
10977
11049
  onReloaded: replaceData
10978
11050
  }
10979
11051
  ) : null,
10980
- state.kind === "signed-in" && surface === "documents" ? /* @__PURE__ */ jsx26(
11052
+ state.kind === "signed-in" && surface === "documents" ? /* @__PURE__ */ jsx27(
10981
11053
  PortalAccountDocuments,
10982
11054
  {
10983
11055
  data: state.data,
@@ -10985,7 +11057,7 @@ function PortalAccountSurfaceClient({
10985
11057
  openUrl
10986
11058
  }
10987
11059
  ) : null,
10988
- state.kind === "signed-in" && surface === "orders" ? /* @__PURE__ */ jsx26(
11060
+ state.kind === "signed-in" && surface === "orders" ? /* @__PURE__ */ jsx27(
10989
11061
  PortalAccountOrders,
10990
11062
  {
10991
11063
  data: state.data,
@@ -10993,7 +11065,7 @@ function PortalAccountSurfaceClient({
10993
11065
  openUrl
10994
11066
  }
10995
11067
  ) : null,
10996
- state.kind === "signed-in" && surface === "profile" ? /* @__PURE__ */ jsx26(
11068
+ state.kind === "signed-in" && surface === "profile" ? /* @__PURE__ */ jsx27(
10997
11069
  PortalAccountProfile,
10998
11070
  {
10999
11071
  data: state.data,
@@ -11005,18 +11077,18 @@ function PortalAccountSurfaceClient({
11005
11077
  }
11006
11078
  function PortalAccountSkeleton() {
11007
11079
  return /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__skeleton", "aria-hidden": "true", children: [
11008
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-row" }),
11009
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-row" }),
11010
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-row" })
11080
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__skeleton-row" }),
11081
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__skeleton-row" }),
11082
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__skeleton-row" })
11011
11083
  ] });
11012
11084
  }
11013
11085
  function StatusBadge({ status }) {
11014
11086
  if (!status) return null;
11015
- return /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__status", children: status });
11087
+ return /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__status", children: status });
11016
11088
  }
11017
11089
  function ErrorNote({ message }) {
11018
11090
  if (!message) return null;
11019
- return /* @__PURE__ */ jsx26("p", { className: "sk-portal-error", role: "alert", children: message });
11091
+ return /* @__PURE__ */ jsx27("p", { className: "sk-portal-error", role: "alert", children: message });
11020
11092
  }
11021
11093
  function PortalAccountAppointments({
11022
11094
  data,
@@ -11028,17 +11100,17 @@ function PortalAccountAppointments({
11028
11100
  now,
11029
11101
  initialUi
11030
11102
  }) {
11031
- const [cancelFor, setCancelFor] = React20.useState(initialUi?.cancelFor ?? null);
11032
- const [rescheduleFor, setRescheduleFor] = React20.useState(
11103
+ const [cancelFor, setCancelFor] = React21.useState(initialUi?.cancelFor ?? null);
11104
+ const [rescheduleFor, setRescheduleFor] = React21.useState(
11033
11105
  initialUi?.rescheduleFor ?? null
11034
11106
  );
11035
- const [consultFor, setConsultFor] = React20.useState(initialUi?.consultFor ?? null);
11036
- const [reasons, setReasons] = React20.useState(initialUi?.reasons ?? []);
11037
- const reasonsLoaded = React20.useRef(initialUi?.reasons !== void 0);
11038
- const [reasonId, setReasonId] = React20.useState("");
11039
- const [note, setNote] = React20.useState("");
11040
- const [busy, setBusy] = React20.useState(false);
11041
- const [error2, setError] = React20.useState(initialUi?.error ?? null);
11107
+ const [consultFor, setConsultFor] = React21.useState(initialUi?.consultFor ?? null);
11108
+ const [reasons, setReasons] = React21.useState(initialUi?.reasons ?? []);
11109
+ const reasonsLoaded = React21.useRef(initialUi?.reasons !== void 0);
11110
+ const [reasonId, setReasonId] = React21.useState("");
11111
+ const [note, setNote] = React21.useState("");
11112
+ const [busy, setBusy] = React21.useState(false);
11113
+ const [error2, setError] = React21.useState(initialUi?.error ?? null);
11042
11114
  async function openCancel(id) {
11043
11115
  setCancelFor(id);
11044
11116
  setReasonId("");
@@ -11071,20 +11143,20 @@ function PortalAccountAppointments({
11071
11143
  ];
11072
11144
  const empty = data.upcoming.length === 0 && data.past.length === 0;
11073
11145
  return /* @__PURE__ */ jsxs24(Fragment11, { children: [
11074
- empty ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__empty", children: "You have no appointments with us yet." }) : groups.filter((g) => g.items.length > 0).map((group) => /* @__PURE__ */ jsxs24("section", { className: "sk-portal-account__group", children: [
11075
- /* @__PURE__ */ jsx26("h3", { className: "sk-portal-account__group-title", children: group.title }),
11076
- /* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__list", children: group.items.map((item) => {
11146
+ empty ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__empty", children: "You have no appointments with us yet." }) : groups.filter((g) => g.items.length > 0).map((group) => /* @__PURE__ */ jsxs24("section", { className: "sk-portal-account__group", children: [
11147
+ /* @__PURE__ */ jsx27("h3", { className: "sk-portal-account__group-title", children: group.title }),
11148
+ /* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__list", children: group.items.map((item) => {
11077
11149
  const join = consultJoinAffordance(item, now);
11078
11150
  return /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
11079
11151
  /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__item-head", children: [
11080
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-title", children: item.title ?? "\u2014" }),
11081
- item.telehealth ? /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__status", children: "Telehealth" }) : null,
11082
- /* @__PURE__ */ jsx26(StatusBadge, { status: item.status })
11152
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-title", children: item.title ?? "\u2014" }),
11153
+ item.telehealth ? /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__status", children: "Telehealth" }) : null,
11154
+ /* @__PURE__ */ jsx27(StatusBadge, { status: item.status })
11083
11155
  ] }),
11084
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-meta", children: formatPortalDateTime(item.start, item.timezone) ?? "Time to be confirmed" }),
11085
- item.locationName || item.practitionerName ? /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-meta", children: [item.locationName, item.practitionerName].filter(Boolean).join(" \xB7 ") }) : null,
11156
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: formatPortalDateTime(item.start, item.timezone) ?? "Time to be confirmed" }),
11157
+ item.locationName || item.practitionerName ? /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: [item.locationName, item.practitionerName].filter(Boolean).join(" \xB7 ") }) : null,
11086
11158
  /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__actions", children: [
11087
- join.kind === "join" ? /* @__PURE__ */ jsx26(
11159
+ join.kind === "join" ? /* @__PURE__ */ jsx27(
11088
11160
  "button",
11089
11161
  {
11090
11162
  type: "button",
@@ -11101,7 +11173,7 @@ function PortalAccountAppointments({
11101
11173
  item.canReschedule ? (
11102
11174
  // INLINE since PAT-789. It was a link into the portal; the round
11103
11175
  // trip through a second host to pick a time was the seam.
11104
- /* @__PURE__ */ jsx26(
11176
+ /* @__PURE__ */ jsx27(
11105
11177
  "button",
11106
11178
  {
11107
11179
  type: "button",
@@ -11115,7 +11187,7 @@ function PortalAccountAppointments({
11115
11187
  }
11116
11188
  )
11117
11189
  ) : null,
11118
- item.canCancel ? /* @__PURE__ */ jsx26(
11190
+ item.canCancel ? /* @__PURE__ */ jsx27(
11119
11191
  "button",
11120
11192
  {
11121
11193
  type: "button",
@@ -11130,7 +11202,7 @@ function PortalAccountAppointments({
11130
11202
  "Video opens at ",
11131
11203
  formatPortalTime(join.at, item.timezone) ?? "your appointment time"
11132
11204
  ] }) : null,
11133
- consultFor === item.id ? /* @__PURE__ */ jsx26(
11205
+ consultFor === item.id ? /* @__PURE__ */ jsx27(
11134
11206
  PortalConsultPanel,
11135
11207
  {
11136
11208
  appointmentId: item.id,
@@ -11140,7 +11212,7 @@ function PortalAccountAppointments({
11140
11212
  loadModule: loadConsultModule2
11141
11213
  }
11142
11214
  ) : null,
11143
- rescheduleFor === item.id ? /* @__PURE__ */ jsx26(
11215
+ rescheduleFor === item.id ? /* @__PURE__ */ jsx27(
11144
11216
  PortalRescheduleInline,
11145
11217
  {
11146
11218
  appointment: item,
@@ -11153,11 +11225,11 @@ function PortalAccountAppointments({
11153
11225
  }
11154
11226
  ) : null,
11155
11227
  cancelFor === item.id ? /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm", children: [
11156
- /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__confirm-title", children: "Cancel this appointment?" }),
11228
+ /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__confirm-title", children: "Cancel this appointment?" }),
11157
11229
  reasons.length > 0 ? /* @__PURE__ */ jsxs24("fieldset", { className: "sk-portal-account__reasons", children: [
11158
- /* @__PURE__ */ jsx26("legend", { className: "sk-portal-label", children: "Reason (optional)" }),
11230
+ /* @__PURE__ */ jsx27("legend", { className: "sk-portal-label", children: "Reason (optional)" }),
11159
11231
  reasons.map((reason) => /* @__PURE__ */ jsxs24("label", { className: "sk-portal-account__reason", children: [
11160
- /* @__PURE__ */ jsx26(
11232
+ /* @__PURE__ */ jsx27(
11161
11233
  "input",
11162
11234
  {
11163
11235
  type: "radio",
@@ -11170,7 +11242,7 @@ function PortalAccountAppointments({
11170
11242
  reason.label
11171
11243
  ] }, reason.id))
11172
11244
  ] }) : null,
11173
- /* @__PURE__ */ jsx26(
11245
+ /* @__PURE__ */ jsx27(
11174
11246
  "label",
11175
11247
  {
11176
11248
  className: "sk-portal-label",
@@ -11178,7 +11250,7 @@ function PortalAccountAppointments({
11178
11250
  children: "Anything you'd like us to know? (optional)"
11179
11251
  }
11180
11252
  ),
11181
- /* @__PURE__ */ jsx26(
11253
+ /* @__PURE__ */ jsx27(
11182
11254
  "textarea",
11183
11255
  {
11184
11256
  id: `sk-portal-cancel-note-${item.id}`,
@@ -11188,9 +11260,9 @@ function PortalAccountAppointments({
11188
11260
  onChange: (e) => setNote(e.target.value)
11189
11261
  }
11190
11262
  ),
11191
- /* @__PURE__ */ jsx26(ErrorNote, { message: error2 }),
11263
+ /* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
11192
11264
  /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm-actions", children: [
11193
- /* @__PURE__ */ jsx26(
11265
+ /* @__PURE__ */ jsx27(
11194
11266
  "button",
11195
11267
  {
11196
11268
  type: "button",
@@ -11200,7 +11272,7 @@ function PortalAccountAppointments({
11200
11272
  children: busy ? "Cancelling\u2026" : "Cancel appointment"
11201
11273
  }
11202
11274
  ),
11203
- /* @__PURE__ */ jsx26(
11275
+ /* @__PURE__ */ jsx27(
11204
11276
  "button",
11205
11277
  {
11206
11278
  type: "button",
@@ -11218,7 +11290,7 @@ function PortalAccountAppointments({
11218
11290
  ] }, item.id);
11219
11291
  }) })
11220
11292
  ] }, group.key)),
11221
- /* @__PURE__ */ jsx26("a", { className: "sk-portal-button", href: portalBookHref(bookHref), children: "Book an appointment" })
11293
+ /* @__PURE__ */ jsx27("a", { className: "sk-portal-button", href: portalBookHref(bookHref), children: "Book an appointment" })
11222
11294
  ] });
11223
11295
  }
11224
11296
  function PortalAccountDocuments({
@@ -11227,8 +11299,8 @@ function PortalAccountDocuments({
11227
11299
  openUrl,
11228
11300
  initialUi
11229
11301
  }) {
11230
- const [busyId, setBusyId] = React20.useState(initialUi?.busyId ?? null);
11231
- const [error2, setError] = React20.useState(initialUi?.error ?? null);
11302
+ const [busyId, setBusyId] = React21.useState(initialUi?.busyId ?? null);
11303
+ const [error2, setError] = React21.useState(initialUi?.error ?? null);
11232
11304
  async function download(id) {
11233
11305
  if (busyId) return;
11234
11306
  setBusyId(id);
@@ -11238,17 +11310,17 @@ function PortalAccountDocuments({
11238
11310
  if (!res.ok) setError(res.error ?? DOWNLOAD_FAILED_COPY);
11239
11311
  }
11240
11312
  if (data.items.length === 0) {
11241
- return /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__empty", children: "You have no documents from us yet." });
11313
+ return /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__empty", children: "You have no documents from us yet." });
11242
11314
  }
11243
11315
  return /* @__PURE__ */ jsxs24(Fragment11, { children: [
11244
- /* @__PURE__ */ jsx26(ErrorNote, { message: error2 }),
11245
- /* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__list", children: data.items.map((doc) => /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
11316
+ /* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
11317
+ /* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__list", children: data.items.map((doc) => /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
11246
11318
  /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__item-head", children: [
11247
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-title", children: doc.title ?? "Document" }),
11248
- /* @__PURE__ */ jsx26(StatusBadge, { status: doc.status })
11319
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-title", children: doc.title ?? "Document" }),
11320
+ /* @__PURE__ */ jsx27(StatusBadge, { status: doc.status })
11249
11321
  ] }),
11250
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-meta", children: formatPortalDate(doc.date) ?? "" }),
11251
- /* @__PURE__ */ jsx26("div", { className: "sk-portal-account__actions", children: /* @__PURE__ */ jsx26(
11322
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: formatPortalDate(doc.date) ?? "" }),
11323
+ /* @__PURE__ */ jsx27("div", { className: "sk-portal-account__actions", children: /* @__PURE__ */ jsx27(
11252
11324
  "button",
11253
11325
  {
11254
11326
  type: "button",
@@ -11267,10 +11339,10 @@ function PortalAccountOrders({
11267
11339
  openUrl,
11268
11340
  initialUi
11269
11341
  }) {
11270
- const [expandedId, setExpandedId] = React20.useState(initialUi?.expandedId ?? null);
11271
- const [detail, setDetail] = React20.useState(initialUi?.detail ?? null);
11272
- const [loading, setLoading] = React20.useState(false);
11273
- const [error2, setError] = React20.useState(initialUi?.error ?? null);
11342
+ const [expandedId, setExpandedId] = React21.useState(initialUi?.expandedId ?? null);
11343
+ const [detail, setDetail] = React21.useState(initialUi?.detail ?? null);
11344
+ const [loading, setLoading] = React21.useState(false);
11345
+ const [error2, setError] = React21.useState(initialUi?.error ?? null);
11274
11346
  async function toggle(id) {
11275
11347
  if (expandedId === id) {
11276
11348
  setExpandedId(null);
@@ -11290,11 +11362,11 @@ function PortalAccountOrders({
11290
11362
  if (!res.ok) setError(res.error ?? RECEIPT_FAILED_COPY);
11291
11363
  }
11292
11364
  if (data.items.length === 0) {
11293
- return /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__empty", children: "You haven't ordered anything from us yet." });
11365
+ return /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__empty", children: "You haven't ordered anything from us yet." });
11294
11366
  }
11295
11367
  return /* @__PURE__ */ jsxs24(Fragment11, { children: [
11296
- /* @__PURE__ */ jsx26(ErrorNote, { message: error2 }),
11297
- /* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__list", children: data.items.map((order) => {
11368
+ /* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
11369
+ /* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__list", children: data.items.map((order) => {
11298
11370
  const open = expandedId === order.id;
11299
11371
  return /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
11300
11372
  /* @__PURE__ */ jsxs24(
@@ -11305,9 +11377,9 @@ function PortalAccountOrders({
11305
11377
  "aria-expanded": open,
11306
11378
  onClick: () => void toggle(order.id),
11307
11379
  children: [
11308
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-title", children: order.title ?? "Order" }),
11309
- /* @__PURE__ */ jsx26(StatusBadge, { status: order.status }),
11310
- /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__item-meta", children: [
11380
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-title", children: order.title ?? "Order" }),
11381
+ /* @__PURE__ */ jsx27(StatusBadge, { status: order.status }),
11382
+ /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: [
11311
11383
  formatPortalDate(order.placedAt),
11312
11384
  order.paymentStatus,
11313
11385
  formatPortalMoney(order.total, order.currency)
@@ -11315,19 +11387,19 @@ function PortalAccountOrders({
11315
11387
  ]
11316
11388
  }
11317
11389
  ),
11318
- open ? /* @__PURE__ */ jsx26("div", { className: "sk-portal-account__detail", children: loading ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", role: "status", children: "Loading this order\u2026" }) : !detail ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__note", role: "note", children: "We couldn't load this order just now." }) : /* @__PURE__ */ jsxs24(Fragment11, { children: [
11319
- /* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__lines", children: (detail.lines ?? []).map((line) => /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__line", children: [
11390
+ open ? /* @__PURE__ */ jsx27("div", { className: "sk-portal-account__detail", children: loading ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__placeholder", role: "status", children: "Loading this order\u2026" }) : !detail ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__note", role: "note", children: "We couldn't load this order just now." }) : /* @__PURE__ */ jsxs24(Fragment11, { children: [
11391
+ /* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__lines", children: (detail.lines ?? []).map((line) => /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__line", children: [
11320
11392
  /* @__PURE__ */ jsxs24("span", { children: [
11321
11393
  line.title ?? "\u2014",
11322
11394
  line.quantity && line.quantity > 1 ? ` \xD7 ${line.quantity}` : ""
11323
11395
  ] }),
11324
- /* @__PURE__ */ jsx26("span", { children: formatPortalMoney(line.total, detail.currency) ?? "" })
11396
+ /* @__PURE__ */ jsx27("span", { children: formatPortalMoney(line.total, detail.currency) ?? "" })
11325
11397
  ] }, line.id)) }),
11326
11398
  /* @__PURE__ */ jsxs24("p", { className: "sk-portal-account__total", children: [
11327
11399
  "Total ",
11328
11400
  formatPortalMoney(detail.total, detail.currency) ?? ""
11329
11401
  ] }),
11330
- detail.hasReceipt !== false ? /* @__PURE__ */ jsx26("div", { className: "sk-portal-account__actions", children: /* @__PURE__ */ jsx26(
11402
+ detail.hasReceipt !== false ? /* @__PURE__ */ jsx27("div", { className: "sk-portal-account__actions", children: /* @__PURE__ */ jsx27(
11331
11403
  "button",
11332
11404
  {
11333
11405
  type: "button",
@@ -11347,12 +11419,12 @@ function PortalAccountProfile({
11347
11419
  onSaved,
11348
11420
  initialUi
11349
11421
  }) {
11350
- const [editing, setEditing] = React20.useState(initialUi?.editing ?? false);
11351
- const [givenName, setGivenName] = React20.useState(data.givenName ?? "");
11352
- const [familyName, setFamilyName] = React20.useState(data.familyName ?? "");
11353
- const [phone, setPhone] = React20.useState(data.phone ?? "");
11354
- const [saving, setSaving] = React20.useState(false);
11355
- const [error2, setError] = React20.useState(initialUi?.error ?? null);
11422
+ const [editing, setEditing] = React21.useState(initialUi?.editing ?? false);
11423
+ const [givenName, setGivenName] = React21.useState(data.givenName ?? "");
11424
+ const [familyName, setFamilyName] = React21.useState(data.familyName ?? "");
11425
+ const [phone, setPhone] = React21.useState(data.phone ?? "");
11426
+ const [saving, setSaving] = React21.useState(false);
11427
+ const [error2, setError] = React21.useState(initialUi?.error ?? null);
11356
11428
  async function save(e) {
11357
11429
  e.preventDefault();
11358
11430
  if (saving) return;
@@ -11370,13 +11442,13 @@ function PortalAccountProfile({
11370
11442
  if (!editing) {
11371
11443
  return /* @__PURE__ */ jsxs24(Fragment11, { children: [
11372
11444
  /* @__PURE__ */ jsxs24("dl", { className: "sk-portal-account__fields", children: [
11373
- /* @__PURE__ */ jsx26(Field2, { label: "First name", value: data.givenName }),
11374
- /* @__PURE__ */ jsx26(Field2, { label: "Last name", value: data.familyName }),
11375
- /* @__PURE__ */ jsx26(Field2, { label: "Email", value: data.email }),
11376
- /* @__PURE__ */ jsx26(Field2, { label: "Mobile", value: data.phone }),
11377
- /* @__PURE__ */ jsx26(Field2, { label: "Date of birth", value: formatPortalDate(data.dateOfBirth) })
11445
+ /* @__PURE__ */ jsx27(Field2, { label: "First name", value: data.givenName }),
11446
+ /* @__PURE__ */ jsx27(Field2, { label: "Last name", value: data.familyName }),
11447
+ /* @__PURE__ */ jsx27(Field2, { label: "Email", value: data.email }),
11448
+ /* @__PURE__ */ jsx27(Field2, { label: "Mobile", value: data.phone }),
11449
+ /* @__PURE__ */ jsx27(Field2, { label: "Date of birth", value: formatPortalDate(data.dateOfBirth) })
11378
11450
  ] }),
11379
- /* @__PURE__ */ jsx26(
11451
+ /* @__PURE__ */ jsx27(
11380
11452
  "button",
11381
11453
  {
11382
11454
  type: "button",
@@ -11394,8 +11466,8 @@ function PortalAccountProfile({
11394
11466
  ] });
11395
11467
  }
11396
11468
  return /* @__PURE__ */ jsxs24("form", { className: "sk-portal-account__form", onSubmit: (e) => void save(e), children: [
11397
- /* @__PURE__ */ jsx26("label", { className: "sk-portal-label", htmlFor: "sk-portal-given-name", children: "First name" }),
11398
- /* @__PURE__ */ jsx26(
11469
+ /* @__PURE__ */ jsx27("label", { className: "sk-portal-label", htmlFor: "sk-portal-given-name", children: "First name" }),
11470
+ /* @__PURE__ */ jsx27(
11399
11471
  "input",
11400
11472
  {
11401
11473
  id: "sk-portal-given-name",
@@ -11406,8 +11478,8 @@ function PortalAccountProfile({
11406
11478
  onChange: (e) => setGivenName(e.target.value)
11407
11479
  }
11408
11480
  ),
11409
- /* @__PURE__ */ jsx26("label", { className: "sk-portal-label", htmlFor: "sk-portal-family-name", children: "Last name" }),
11410
- /* @__PURE__ */ jsx26(
11481
+ /* @__PURE__ */ jsx27("label", { className: "sk-portal-label", htmlFor: "sk-portal-family-name", children: "Last name" }),
11482
+ /* @__PURE__ */ jsx27(
11411
11483
  "input",
11412
11484
  {
11413
11485
  id: "sk-portal-family-name",
@@ -11418,8 +11490,8 @@ function PortalAccountProfile({
11418
11490
  onChange: (e) => setFamilyName(e.target.value)
11419
11491
  }
11420
11492
  ),
11421
- /* @__PURE__ */ jsx26("label", { className: "sk-portal-label", htmlFor: "sk-portal-phone", children: "Mobile" }),
11422
- /* @__PURE__ */ jsx26(
11493
+ /* @__PURE__ */ jsx27("label", { className: "sk-portal-label", htmlFor: "sk-portal-phone", children: "Mobile" }),
11494
+ /* @__PURE__ */ jsx27(
11423
11495
  "input",
11424
11496
  {
11425
11497
  id: "sk-portal-phone",
@@ -11432,14 +11504,14 @@ function PortalAccountProfile({
11432
11504
  }
11433
11505
  ),
11434
11506
  /* @__PURE__ */ jsxs24("dl", { className: "sk-portal-account__fields", children: [
11435
- /* @__PURE__ */ jsx26(Field2, { label: "Email", value: data.email }),
11436
- /* @__PURE__ */ jsx26(Field2, { label: "Date of birth", value: formatPortalDate(data.dateOfBirth) })
11507
+ /* @__PURE__ */ jsx27(Field2, { label: "Email", value: data.email }),
11508
+ /* @__PURE__ */ jsx27(Field2, { label: "Date of birth", value: formatPortalDate(data.dateOfBirth) })
11437
11509
  ] }),
11438
- /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__hint", children: "Your email and date of birth identify your record \u2014 call the clinic to change either." }),
11439
- /* @__PURE__ */ jsx26(ErrorNote, { message: error2 }),
11510
+ /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__hint", children: "Your email and date of birth identify your record \u2014 call the clinic to change either." }),
11511
+ /* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
11440
11512
  /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm-actions", children: [
11441
- /* @__PURE__ */ jsx26("button", { className: "sk-portal-button", type: "submit", disabled: saving, children: saving ? "Saving\u2026" : "Save details" }),
11442
- /* @__PURE__ */ jsx26(
11513
+ /* @__PURE__ */ jsx27("button", { className: "sk-portal-button", type: "submit", disabled: saving, children: saving ? "Saving\u2026" : "Save details" }),
11514
+ /* @__PURE__ */ jsx27(
11443
11515
  "button",
11444
11516
  {
11445
11517
  type: "button",
@@ -11454,13 +11526,13 @@ function PortalAccountProfile({
11454
11526
  }
11455
11527
  function Field2({ label, value }) {
11456
11528
  return /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__field", children: [
11457
- /* @__PURE__ */ jsx26("dt", { className: "sk-portal-account__field-label", children: label }),
11458
- /* @__PURE__ */ jsx26("dd", { className: "sk-portal-account__field-value", children: value || "Not recorded" })
11529
+ /* @__PURE__ */ jsx27("dt", { className: "sk-portal-account__field-label", children: label }),
11530
+ /* @__PURE__ */ jsx27("dd", { className: "sk-portal-account__field-value", children: value || "Not recorded" })
11459
11531
  ] });
11460
11532
  }
11461
11533
 
11462
11534
  // src/store-block.client.tsx
11463
- import * as React21 from "react";
11535
+ import * as React22 from "react";
11464
11536
 
11465
11537
  // src/cart-storage.ts
11466
11538
  var CART_STORAGE_KEY = "patientos.cart.v1";
@@ -11597,21 +11669,21 @@ function subscribeToCart(fn) {
11597
11669
  }
11598
11670
 
11599
11671
  // src/store-block.client.tsx
11600
- import { Fragment as Fragment12, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
11672
+ import { Fragment as Fragment12, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
11601
11673
  function formatMoney(value) {
11602
11674
  const n = Number(value);
11603
11675
  if (!Number.isFinite(n)) return value;
11604
11676
  return `$${n.toFixed(2)}`;
11605
11677
  }
11606
11678
  function StoreClient({ categoryHandle, title, columns }) {
11607
- const [catalog, setCatalog] = React21.useState(null);
11608
- const [failed, setFailed] = React21.useState(false);
11609
- const [count, setCount] = React21.useState(0);
11610
- React21.useEffect(() => {
11679
+ const [catalog, setCatalog] = React22.useState(null);
11680
+ const [failed, setFailed] = React22.useState(false);
11681
+ const [count, setCount] = React22.useState(0);
11682
+ React22.useEffect(() => {
11611
11683
  setCount(cartItemCount(readCart()));
11612
11684
  return subscribeToCart((cart) => setCount(cartItemCount(cart)));
11613
11685
  }, []);
11614
- React21.useEffect(() => {
11686
+ React22.useEffect(() => {
11615
11687
  let alive = true;
11616
11688
  fetch("/api/store/catalog", { headers: { accept: "application/json" } }).then(
11617
11689
  (res) => res.ok ? res.json() : Promise.reject(new Error(String(res.status)))
@@ -11624,40 +11696,40 @@ function StoreClient({ categoryHandle, title, columns }) {
11624
11696
  alive = false;
11625
11697
  };
11626
11698
  }, []);
11627
- const products = React21.useMemo(() => {
11699
+ const products = React22.useMemo(() => {
11628
11700
  if (!catalog) return [];
11629
11701
  if (!categoryHandle) return catalog.products;
11630
11702
  return catalog.products.filter((p) => p.handle.startsWith(categoryHandle));
11631
11703
  }, [catalog, categoryHandle]);
11632
11704
  if (failed) {
11633
11705
  return /* @__PURE__ */ jsxs25(Fragment12, { children: [
11634
- /* @__PURE__ */ jsx27("h2", { className: "sk-store__heading", children: title ?? "Shop" }),
11635
- /* @__PURE__ */ jsx27("p", { className: "sk-store__placeholder", role: "note", children: "Our shop is unavailable right now. Please contact the clinic to order." })
11706
+ /* @__PURE__ */ jsx28("h2", { className: "sk-store__heading", children: title ?? "Shop" }),
11707
+ /* @__PURE__ */ jsx28("p", { className: "sk-store__placeholder", role: "note", children: "Our shop is unavailable right now. Please contact the clinic to order." })
11636
11708
  ] });
11637
11709
  }
11638
11710
  return /* @__PURE__ */ jsxs25(Fragment12, { children: [
11639
11711
  /* @__PURE__ */ jsxs25("div", { className: "sk-store__header", children: [
11640
- /* @__PURE__ */ jsx27("h2", { className: "sk-store__heading", children: title ?? "Shop" }),
11712
+ /* @__PURE__ */ jsx28("h2", { className: "sk-store__heading", children: title ?? "Shop" }),
11641
11713
  /* @__PURE__ */ jsxs25("a", { className: "sk-store__cart-link", href: "/cart", children: [
11642
11714
  "Cart",
11643
11715
  count > 0 ? ` (${count})` : ""
11644
11716
  ] })
11645
11717
  ] }),
11646
- !catalog ? /* @__PURE__ */ jsx27("p", { className: "sk-store__placeholder", role: "status", children: "Loading the shop\u2026" }) : products.length === 0 ? /* @__PURE__ */ jsx27("p", { className: "sk-store__placeholder", role: "status", children: "Nothing is available to order online just now." }) : /* @__PURE__ */ jsx27(
11718
+ !catalog ? /* @__PURE__ */ jsx28("p", { className: "sk-store__placeholder", role: "status", children: "Loading the shop\u2026" }) : products.length === 0 ? /* @__PURE__ */ jsx28("p", { className: "sk-store__placeholder", role: "status", children: "Nothing is available to order online just now." }) : /* @__PURE__ */ jsx28(
11647
11719
  "ul",
11648
11720
  {
11649
11721
  className: "sk-store__grid",
11650
11722
  style: columns ? { "--sk-store-columns": columns } : void 0,
11651
- children: products.map((product) => /* @__PURE__ */ jsx27(StoreCard, { product }, product.id))
11723
+ children: products.map((product) => /* @__PURE__ */ jsx28(StoreCard, { product }, product.id))
11652
11724
  }
11653
11725
  )
11654
11726
  ] });
11655
11727
  }
11656
11728
  function StoreCard({ product }) {
11657
- const [variantId, setVariantId] = React21.useState(
11729
+ const [variantId, setVariantId] = React22.useState(
11658
11730
  () => (product.variants.find((v) => v.inStock) ?? product.variants[0]).id
11659
11731
  );
11660
- const [added, setAdded] = React21.useState(false);
11732
+ const [added, setAdded] = React22.useState(false);
11661
11733
  const variant = product.variants.find((v) => v.id === variantId) ?? product.variants[0];
11662
11734
  const image2 = product.thumbnailUrl ?? product.images[0]?.url ?? null;
11663
11735
  function onAdd() {
@@ -11667,18 +11739,18 @@ function StoreCard({ product }) {
11667
11739
  }
11668
11740
  return /* @__PURE__ */ jsxs25("li", { className: "sk-store__card", children: [
11669
11741
  /* @__PURE__ */ jsxs25("a", { className: "sk-store__card-link", href: `/store/${product.handle}`, children: [
11670
- image2 ? /* @__PURE__ */ jsx27("img", { className: "sk-store__image", src: image2, alt: product.images[0]?.alt ?? "" }) : /* @__PURE__ */ jsx27("span", { className: "sk-store__image sk-store__image--empty", "aria-hidden": true }),
11671
- /* @__PURE__ */ jsx27("span", { className: "sk-store__title", children: product.title })
11742
+ image2 ? /* @__PURE__ */ jsx28("img", { className: "sk-store__image", src: image2, alt: product.images[0]?.alt ?? "" }) : /* @__PURE__ */ jsx28("span", { className: "sk-store__image sk-store__image--empty", "aria-hidden": true }),
11743
+ /* @__PURE__ */ jsx28("span", { className: "sk-store__title", children: product.title })
11672
11744
  ] }),
11673
11745
  /* @__PURE__ */ jsxs25("span", { className: "sk-store__price", children: [
11674
11746
  formatMoney(variant.price),
11675
- product.gstApplicable ? /* @__PURE__ */ jsx27("span", { className: "sk-store__gst", children: " incl. GST" }) : null
11747
+ product.gstApplicable ? /* @__PURE__ */ jsx28("span", { className: "sk-store__gst", children: " incl. GST" }) : null
11676
11748
  ] }),
11677
11749
  product.variants.length > 1 ? /* @__PURE__ */ jsxs25("label", { className: "sk-store__variant", children: [
11678
- /* @__PURE__ */ jsx27("span", { className: "sk-store__variant-label", children: "Option" }),
11679
- /* @__PURE__ */ jsx27("select", { value: variantId, onChange: (e) => setVariantId(e.target.value), children: product.variants.map((v) => /* @__PURE__ */ jsx27("option", { value: v.id, disabled: !v.inStock, children: (v.options.length ? v.options.join(" / ") : v.title) + (v.inStock ? "" : " \u2014 sold out") }, v.id)) })
11750
+ /* @__PURE__ */ jsx28("span", { className: "sk-store__variant-label", children: "Option" }),
11751
+ /* @__PURE__ */ jsx28("select", { value: variantId, onChange: (e) => setVariantId(e.target.value), children: product.variants.map((v) => /* @__PURE__ */ jsx28("option", { value: v.id, disabled: !v.inStock, children: (v.options.length ? v.options.join(" / ") : v.title) + (v.inStock ? "" : " \u2014 sold out") }, v.id)) })
11680
11752
  ] }) : null,
11681
- /* @__PURE__ */ jsx27(
11753
+ /* @__PURE__ */ jsx28(
11682
11754
  "button",
11683
11755
  {
11684
11756
  type: "button",
@@ -11692,14 +11764,14 @@ function StoreCard({ product }) {
11692
11764
  }
11693
11765
 
11694
11766
  // src/cart-block.client.tsx
11695
- import * as React22 from "react";
11696
- import { Fragment as Fragment13, jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
11767
+ import * as React23 from "react";
11768
+ import { Fragment as Fragment13, jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
11697
11769
  function CartClient(_props) {
11698
- const [cart, setCart] = React22.useState(() => readCart());
11699
- const [quote, setQuote] = React22.useState(null);
11700
- const [failed, setFailed] = React22.useState(false);
11701
- React22.useEffect(() => subscribeToCart(setCart), []);
11702
- React22.useEffect(() => {
11770
+ const [cart, setCart] = React23.useState(() => readCart());
11771
+ const [quote, setQuote] = React23.useState(null);
11772
+ const [failed, setFailed] = React23.useState(false);
11773
+ React23.useEffect(() => subscribeToCart(setCart), []);
11774
+ React23.useEffect(() => {
11703
11775
  if (cart.lines.length === 0) {
11704
11776
  setQuote(null);
11705
11777
  setFailed(false);
@@ -11725,24 +11797,24 @@ function CartClient(_props) {
11725
11797
  }, [cart]);
11726
11798
  if (cart.lines.length === 0) {
11727
11799
  return /* @__PURE__ */ jsxs26(Fragment13, { children: [
11728
- /* @__PURE__ */ jsx28("h2", { className: "sk-cart__heading", children: "Your cart" }),
11729
- /* @__PURE__ */ jsx28("p", { className: "sk-cart__placeholder", role: "status", children: "Your cart is empty." }),
11730
- /* @__PURE__ */ jsx28("a", { className: "sk-cart__continue", href: "/store", children: "Browse the shop" })
11800
+ /* @__PURE__ */ jsx29("h2", { className: "sk-cart__heading", children: "Your cart" }),
11801
+ /* @__PURE__ */ jsx29("p", { className: "sk-cart__placeholder", role: "status", children: "Your cart is empty." }),
11802
+ /* @__PURE__ */ jsx29("a", { className: "sk-cart__continue", href: "/store", children: "Browse the shop" })
11731
11803
  ] });
11732
11804
  }
11733
11805
  return /* @__PURE__ */ jsxs26(Fragment13, { children: [
11734
- /* @__PURE__ */ jsx28("h2", { className: "sk-cart__heading", children: "Your cart" }),
11735
- quote && quote.problems.length > 0 ? /* @__PURE__ */ jsx28("ul", { className: "sk-cart__problems", role: "status", children: quote.problems.map((p, i) => /* @__PURE__ */ jsx28("li", { children: p.message }, `${p.code}-${p.variantId ?? i}`)) }) : null,
11736
- failed ? /* @__PURE__ */ jsx28("p", { className: "sk-cart__placeholder", role: "alert", children: "We couldn't price your cart just now. Please try again in a moment." }) : null,
11737
- !quote ? /* @__PURE__ */ jsx28("p", { className: "sk-cart__placeholder", role: "status", children: "Pricing your cart\u2026" }) : /* @__PURE__ */ jsxs26(Fragment13, { children: [
11738
- /* @__PURE__ */ jsx28("ul", { className: "sk-cart__lines", children: quote.lines.map((line) => /* @__PURE__ */ jsxs26("li", { className: "sk-cart__line", children: [
11739
- /* @__PURE__ */ jsx28("a", { className: "sk-cart__line-title", href: `/store/${line.productHandle}`, children: line.title }),
11806
+ /* @__PURE__ */ jsx29("h2", { className: "sk-cart__heading", children: "Your cart" }),
11807
+ quote && quote.problems.length > 0 ? /* @__PURE__ */ jsx29("ul", { className: "sk-cart__problems", role: "status", children: quote.problems.map((p, i) => /* @__PURE__ */ jsx29("li", { children: p.message }, `${p.code}-${p.variantId ?? i}`)) }) : null,
11808
+ failed ? /* @__PURE__ */ jsx29("p", { className: "sk-cart__placeholder", role: "alert", children: "We couldn't price your cart just now. Please try again in a moment." }) : null,
11809
+ !quote ? /* @__PURE__ */ jsx29("p", { className: "sk-cart__placeholder", role: "status", children: "Pricing your cart\u2026" }) : /* @__PURE__ */ jsxs26(Fragment13, { children: [
11810
+ /* @__PURE__ */ jsx29("ul", { className: "sk-cart__lines", children: quote.lines.map((line) => /* @__PURE__ */ jsxs26("li", { className: "sk-cart__line", children: [
11811
+ /* @__PURE__ */ jsx29("a", { className: "sk-cart__line-title", href: `/store/${line.productHandle}`, children: line.title }),
11740
11812
  /* @__PURE__ */ jsxs26("span", { className: "sk-cart__line-unit", children: [
11741
11813
  formatMoney(line.unitPrice),
11742
11814
  " each"
11743
11815
  ] }),
11744
11816
  /* @__PURE__ */ jsxs26("span", { className: "sk-cart__qty", children: [
11745
- /* @__PURE__ */ jsx28(
11817
+ /* @__PURE__ */ jsx29(
11746
11818
  "button",
11747
11819
  {
11748
11820
  type: "button",
@@ -11751,8 +11823,8 @@ function CartClient(_props) {
11751
11823
  children: "\u2212"
11752
11824
  }
11753
11825
  ),
11754
- /* @__PURE__ */ jsx28("span", { "aria-live": "polite", children: line.quantity }),
11755
- /* @__PURE__ */ jsx28(
11826
+ /* @__PURE__ */ jsx29("span", { "aria-live": "polite", children: line.quantity }),
11827
+ /* @__PURE__ */ jsx29(
11756
11828
  "button",
11757
11829
  {
11758
11830
  type: "button",
@@ -11762,8 +11834,8 @@ function CartClient(_props) {
11762
11834
  }
11763
11835
  )
11764
11836
  ] }),
11765
- /* @__PURE__ */ jsx28("span", { className: "sk-cart__line-total", children: formatMoney(line.lineTotal) }),
11766
- /* @__PURE__ */ jsx28(
11837
+ /* @__PURE__ */ jsx29("span", { className: "sk-cart__line-total", children: formatMoney(line.lineTotal) }),
11838
+ /* @__PURE__ */ jsx29(
11767
11839
  "button",
11768
11840
  {
11769
11841
  type: "button",
@@ -11775,22 +11847,22 @@ function CartClient(_props) {
11775
11847
  ] }, line.variantId)) }),
11776
11848
  /* @__PURE__ */ jsxs26("dl", { className: "sk-cart__totals", children: [
11777
11849
  /* @__PURE__ */ jsxs26("div", { children: [
11778
- /* @__PURE__ */ jsx28("dt", { children: "Subtotal" }),
11779
- /* @__PURE__ */ jsx28("dd", { children: formatMoney(quote.subtotal) })
11850
+ /* @__PURE__ */ jsx29("dt", { children: "Subtotal" }),
11851
+ /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.subtotal) })
11780
11852
  ] }),
11781
11853
  /* @__PURE__ */ jsxs26("div", { className: "sk-cart__gst-row", children: [
11782
- /* @__PURE__ */ jsx28("dt", { children: "GST included" }),
11783
- /* @__PURE__ */ jsx28("dd", { children: formatMoney(quote.taxTotal) })
11854
+ /* @__PURE__ */ jsx29("dt", { children: "GST included" }),
11855
+ /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.taxTotal) })
11784
11856
  ] }),
11785
11857
  /* @__PURE__ */ jsxs26("div", { className: "sk-cart__total-row", children: [
11786
- /* @__PURE__ */ jsx28("dt", { children: "Total" }),
11787
- /* @__PURE__ */ jsx28("dd", { children: formatMoney(quote.total) })
11858
+ /* @__PURE__ */ jsx29("dt", { children: "Total" }),
11859
+ /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.total) })
11788
11860
  ] })
11789
11861
  ] }),
11790
- quote.requiresShipping ? /* @__PURE__ */ jsx28("p", { className: "sk-cart__note", children: "Delivery is chosen at checkout." }) : null,
11862
+ quote.requiresShipping ? /* @__PURE__ */ jsx29("p", { className: "sk-cart__note", children: "Delivery is chosen at checkout." }) : null,
11791
11863
  /* @__PURE__ */ jsxs26("div", { className: "sk-cart__actions", children: [
11792
- /* @__PURE__ */ jsx28("a", { className: "sk-cart__continue", href: "/store", children: "Keep shopping" }),
11793
- /* @__PURE__ */ jsx28(
11864
+ /* @__PURE__ */ jsx29("a", { className: "sk-cart__continue", href: "/store", children: "Keep shopping" }),
11865
+ /* @__PURE__ */ jsx29(
11794
11866
  "a",
11795
11867
  {
11796
11868
  className: "sk-cart__checkout",
@@ -11805,8 +11877,8 @@ function CartClient(_props) {
11805
11877
  }
11806
11878
 
11807
11879
  // src/checkout-block.client.tsx
11808
- import * as React23 from "react";
11809
- import { Fragment as Fragment14, jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
11880
+ import * as React24 from "react";
11881
+ import { Fragment as Fragment14, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
11810
11882
  async function searchStoreAddresses(query) {
11811
11883
  const q = query.trim();
11812
11884
  if (q.length < 3) return [];
@@ -11831,21 +11903,21 @@ async function validateStoreAddress(address) {
11831
11903
  return { address: v.formattedAddress, placeId: v.googlePlaceId ?? null };
11832
11904
  }
11833
11905
  function CheckoutClient(_props) {
11834
- const [stage, setStage] = React23.useState("loading");
11835
- const [givenName, setGivenName] = React23.useState(null);
11836
- const [cart] = React23.useState(() => readCart());
11837
- const [quote, setQuote] = React23.useState(null);
11838
- const [shippingOptions, setShippingOptions] = React23.useState([]);
11839
- const [error2, setError] = React23.useState(null);
11840
- const [fulfilment, setFulfilment] = React23.useState("pickup");
11841
- const [shippingOptionId, setShippingOptionId] = React23.useState(null);
11842
- const [address, setAddress] = React23.useState(null);
11843
- const [card, setCard] = React23.useState({ number: "", expiry: "", name: "", cvn: "" });
11844
- const orderRef = React23.useRef(null);
11845
- const [iframeUrl, setIframeUrl] = React23.useState(null);
11846
- const iframeOriginRef = React23.useRef(null);
11847
- const iframeElRef = React23.useRef(null);
11848
- React23.useEffect(() => {
11906
+ const [stage, setStage] = React24.useState("loading");
11907
+ const [givenName, setGivenName] = React24.useState(null);
11908
+ const [cart] = React24.useState(() => readCart());
11909
+ const [quote, setQuote] = React24.useState(null);
11910
+ const [shippingOptions, setShippingOptions] = React24.useState([]);
11911
+ const [error2, setError] = React24.useState(null);
11912
+ const [fulfilment, setFulfilment] = React24.useState("pickup");
11913
+ const [shippingOptionId, setShippingOptionId] = React24.useState(null);
11914
+ const [address, setAddress] = React24.useState(null);
11915
+ const [card, setCard] = React24.useState({ number: "", expiry: "", name: "", cvn: "" });
11916
+ const orderRef = React24.useRef(null);
11917
+ const [iframeUrl, setIframeUrl] = React24.useState(null);
11918
+ const iframeOriginRef = React24.useRef(null);
11919
+ const iframeElRef = React24.useRef(null);
11920
+ React24.useEffect(() => {
11849
11921
  let alive = true;
11850
11922
  if (cart.lines.length === 0) {
11851
11923
  setStage("empty");
@@ -11876,7 +11948,7 @@ function CheckoutClient(_props) {
11876
11948
  alive = false;
11877
11949
  };
11878
11950
  }, [cart]);
11879
- React23.useEffect(() => {
11951
+ React24.useEffect(() => {
11880
11952
  if (stage !== "details" || cart.lines.length === 0) return;
11881
11953
  let alive = true;
11882
11954
  fetch("/api/store/quote", {
@@ -11893,7 +11965,7 @@ function CheckoutClient(_props) {
11893
11965
  alive = false;
11894
11966
  };
11895
11967
  }, [fulfilment, shippingOptionId]);
11896
- React23.useEffect(() => {
11968
+ React24.useEffect(() => {
11897
11969
  if (stage !== "three_ds") return;
11898
11970
  function onMessage(event) {
11899
11971
  if (iframeOriginRef.current && event.origin !== iframeOriginRef.current) return;
@@ -12024,41 +12096,41 @@ function CheckoutClient(_props) {
12024
12096
  }
12025
12097
  if (stage === "loading") {
12026
12098
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12027
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: "Checkout" }),
12028
- /* @__PURE__ */ jsx29("p", { className: "sk-checkout__placeholder", role: "status", children: "Loading your order\u2026" })
12099
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Checkout" }),
12100
+ /* @__PURE__ */ jsx30("p", { className: "sk-checkout__placeholder", role: "status", children: "Loading your order\u2026" })
12029
12101
  ] });
12030
12102
  }
12031
12103
  if (stage === "empty") {
12032
12104
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12033
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: "Checkout" }),
12034
- /* @__PURE__ */ jsx29("p", { className: "sk-checkout__placeholder", role: "status", children: "Your cart is empty." }),
12035
- /* @__PURE__ */ jsx29("a", { className: "sk-checkout__link", href: "/store", children: "Browse the shop" })
12105
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Checkout" }),
12106
+ /* @__PURE__ */ jsx30("p", { className: "sk-checkout__placeholder", role: "status", children: "Your cart is empty." }),
12107
+ /* @__PURE__ */ jsx30("a", { className: "sk-checkout__link", href: "/store", children: "Browse the shop" })
12036
12108
  ] });
12037
12109
  }
12038
12110
  if (stage === "signed_out") {
12039
12111
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12040
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: "Checkout" }),
12041
- /* @__PURE__ */ jsx29("p", { className: "sk-checkout__note", children: "Please sign in to finish your order. Your order is kept with your clinic record so you can see it later." }),
12042
- /* @__PURE__ */ jsx29("a", { className: "sk-checkout__signin", href: "/portal/sign-in?redirect=/checkout", children: "Sign in to continue" })
12112
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Checkout" }),
12113
+ /* @__PURE__ */ jsx30("p", { className: "sk-checkout__note", children: "Please sign in to finish your order. Your order is kept with your clinic record so you can see it later." }),
12114
+ /* @__PURE__ */ jsx30("a", { className: "sk-checkout__signin", href: "/portal/sign-in?redirect=/checkout", children: "Sign in to continue" })
12043
12115
  ] });
12044
12116
  }
12045
12117
  if (stage === "paid") {
12046
12118
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12047
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: "Payment received" }),
12048
- /* @__PURE__ */ jsx29("p", { className: "sk-checkout__note", role: "status", children: "Taking you to your order\u2026" })
12119
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Payment received" }),
12120
+ /* @__PURE__ */ jsx30("p", { className: "sk-checkout__note", role: "status", children: "Taking you to your order\u2026" })
12049
12121
  ] });
12050
12122
  }
12051
12123
  if (stage === "pending") {
12052
12124
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12053
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: "Confirming your payment" }),
12054
- /* @__PURE__ */ jsx29("p", { className: "sk-checkout__note", role: "status", children: "Your bank hasn't confirmed the result yet. We're checking with them \u2014 please don't pay again. You'll see the order in your account once it's confirmed." }),
12055
- /* @__PURE__ */ jsx29("a", { className: "sk-checkout__link", href: "/portal/orders", children: "Go to my orders" })
12125
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Confirming your payment" }),
12126
+ /* @__PURE__ */ jsx30("p", { className: "sk-checkout__note", role: "status", children: "Your bank hasn't confirmed the result yet. We're checking with them \u2014 please don't pay again. You'll see the order in your account once it's confirmed." }),
12127
+ /* @__PURE__ */ jsx30("a", { className: "sk-checkout__link", href: "/portal/orders", children: "Go to my orders" })
12056
12128
  ] });
12057
12129
  }
12058
12130
  if (stage === "three_ds" && iframeUrl) {
12059
12131
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12060
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: "Your bank needs to check this payment" }),
12061
- /* @__PURE__ */ jsx29(
12132
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Your bank needs to check this payment" }),
12133
+ /* @__PURE__ */ jsx30(
12062
12134
  "iframe",
12063
12135
  {
12064
12136
  ref: iframeElRef,
@@ -12071,41 +12143,41 @@ function CheckoutClient(_props) {
12071
12143
  }
12072
12144
  const busy = stage === "paying";
12073
12145
  return /* @__PURE__ */ jsxs27(Fragment14, { children: [
12074
- /* @__PURE__ */ jsx29("h2", { className: "sk-checkout__heading", children: givenName ? `Checkout \u2014 hello, ${givenName}` : "Checkout" }),
12075
- error2 ? /* @__PURE__ */ jsx29("p", { className: "sk-checkout__error", role: "alert", children: error2 }) : null,
12146
+ /* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: givenName ? `Checkout \u2014 hello, ${givenName}` : "Checkout" }),
12147
+ error2 ? /* @__PURE__ */ jsx30("p", { className: "sk-checkout__error", role: "alert", children: error2 }) : null,
12076
12148
  quote ? /* @__PURE__ */ jsxs27("div", { className: "sk-checkout__summary", children: [
12077
- /* @__PURE__ */ jsx29("ul", { className: "sk-checkout__lines", children: quote.lines.map((l) => /* @__PURE__ */ jsxs27("li", { children: [
12149
+ /* @__PURE__ */ jsx30("ul", { className: "sk-checkout__lines", children: quote.lines.map((l) => /* @__PURE__ */ jsxs27("li", { children: [
12078
12150
  /* @__PURE__ */ jsxs27("span", { children: [
12079
12151
  l.title,
12080
12152
  " \xD7 ",
12081
12153
  l.quantity
12082
12154
  ] }),
12083
- /* @__PURE__ */ jsx29("span", { children: formatMoney(l.lineTotal) })
12155
+ /* @__PURE__ */ jsx30("span", { children: formatMoney(l.lineTotal) })
12084
12156
  ] }, l.variantId)) }),
12085
12157
  /* @__PURE__ */ jsxs27("dl", { className: "sk-checkout__totals", children: [
12086
12158
  /* @__PURE__ */ jsxs27("div", { children: [
12087
- /* @__PURE__ */ jsx29("dt", { children: "Subtotal" }),
12088
- /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.subtotal) })
12159
+ /* @__PURE__ */ jsx30("dt", { children: "Subtotal" }),
12160
+ /* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.subtotal) })
12089
12161
  ] }),
12090
12162
  Number(quote.shippingTotal) > 0 ? /* @__PURE__ */ jsxs27("div", { children: [
12091
- /* @__PURE__ */ jsx29("dt", { children: "Delivery" }),
12092
- /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.shippingTotal) })
12163
+ /* @__PURE__ */ jsx30("dt", { children: "Delivery" }),
12164
+ /* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.shippingTotal) })
12093
12165
  ] }) : null,
12094
12166
  /* @__PURE__ */ jsxs27("div", { children: [
12095
- /* @__PURE__ */ jsx29("dt", { children: "GST included" }),
12096
- /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.taxTotal) })
12167
+ /* @__PURE__ */ jsx30("dt", { children: "GST included" }),
12168
+ /* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.taxTotal) })
12097
12169
  ] }),
12098
12170
  /* @__PURE__ */ jsxs27("div", { className: "sk-checkout__total-row", children: [
12099
- /* @__PURE__ */ jsx29("dt", { children: "Total" }),
12100
- /* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.total) })
12171
+ /* @__PURE__ */ jsx30("dt", { children: "Total" }),
12172
+ /* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.total) })
12101
12173
  ] })
12102
12174
  ] })
12103
12175
  ] }) : null,
12104
12176
  /* @__PURE__ */ jsxs27("form", { className: "sk-checkout__form", onSubmit: onPay, children: [
12105
12177
  quote?.requiresShipping ? /* @__PURE__ */ jsxs27("fieldset", { className: "sk-checkout__fieldset", children: [
12106
- /* @__PURE__ */ jsx29("legend", { children: "How would you like to get this?" }),
12178
+ /* @__PURE__ */ jsx30("legend", { children: "How would you like to get this?" }),
12107
12179
  /* @__PURE__ */ jsxs27("label", { children: [
12108
- /* @__PURE__ */ jsx29(
12180
+ /* @__PURE__ */ jsx30(
12109
12181
  "input",
12110
12182
  {
12111
12183
  type: "radio",
@@ -12117,7 +12189,7 @@ function CheckoutClient(_props) {
12117
12189
  "Collect from the clinic"
12118
12190
  ] }),
12119
12191
  /* @__PURE__ */ jsxs27("label", { children: [
12120
- /* @__PURE__ */ jsx29(
12192
+ /* @__PURE__ */ jsx30(
12121
12193
  "input",
12122
12194
  {
12123
12195
  type: "radio",
@@ -12130,7 +12202,7 @@ function CheckoutClient(_props) {
12130
12202
  ] }),
12131
12203
  fulfilment === "ship" ? /* @__PURE__ */ jsxs27("div", { className: "sk-checkout__ship", children: [
12132
12204
  /* @__PURE__ */ jsxs27("label", { children: [
12133
- /* @__PURE__ */ jsx29("span", { children: "Delivery option" }),
12205
+ /* @__PURE__ */ jsx30("span", { children: "Delivery option" }),
12134
12206
  /* @__PURE__ */ jsxs27(
12135
12207
  "select",
12136
12208
  {
@@ -12138,7 +12210,7 @@ function CheckoutClient(_props) {
12138
12210
  value: shippingOptionId ?? "",
12139
12211
  onChange: (e) => setShippingOptionId(e.target.value || null),
12140
12212
  children: [
12141
- /* @__PURE__ */ jsx29("option", { value: "", children: "Choose\u2026" }),
12213
+ /* @__PURE__ */ jsx30("option", { value: "", children: "Choose\u2026" }),
12142
12214
  shippingOptions.map((o) => /* @__PURE__ */ jsxs27("option", { value: o.id, children: [
12143
12215
  o.name,
12144
12216
  " \u2014 ",
@@ -12148,7 +12220,7 @@ function CheckoutClient(_props) {
12148
12220
  }
12149
12221
  )
12150
12222
  ] }),
12151
- /* @__PURE__ */ jsx29(
12223
+ /* @__PURE__ */ jsx30(
12152
12224
  AddressPicker,
12153
12225
  {
12154
12226
  idPrefix: "sk-checkout",
@@ -12162,10 +12234,10 @@ function CheckoutClient(_props) {
12162
12234
  ] }) : null
12163
12235
  ] }) : null,
12164
12236
  /* @__PURE__ */ jsxs27("fieldset", { className: "sk-checkout__fieldset", children: [
12165
- /* @__PURE__ */ jsx29("legend", { children: "Card details" }),
12237
+ /* @__PURE__ */ jsx30("legend", { children: "Card details" }),
12166
12238
  /* @__PURE__ */ jsxs27("label", { children: [
12167
- /* @__PURE__ */ jsx29("span", { children: "Name on card" }),
12168
- /* @__PURE__ */ jsx29(
12239
+ /* @__PURE__ */ jsx30("span", { children: "Name on card" }),
12240
+ /* @__PURE__ */ jsx30(
12169
12241
  "input",
12170
12242
  {
12171
12243
  required: true,
@@ -12176,8 +12248,8 @@ function CheckoutClient(_props) {
12176
12248
  )
12177
12249
  ] }),
12178
12250
  /* @__PURE__ */ jsxs27("label", { children: [
12179
- /* @__PURE__ */ jsx29("span", { children: "Card number" }),
12180
- /* @__PURE__ */ jsx29(
12251
+ /* @__PURE__ */ jsx30("span", { children: "Card number" }),
12252
+ /* @__PURE__ */ jsx30(
12181
12253
  "input",
12182
12254
  {
12183
12255
  required: true,
@@ -12189,8 +12261,8 @@ function CheckoutClient(_props) {
12189
12261
  )
12190
12262
  ] }),
12191
12263
  /* @__PURE__ */ jsxs27("label", { children: [
12192
- /* @__PURE__ */ jsx29("span", { children: "Expiry (MM/YY)" }),
12193
- /* @__PURE__ */ jsx29(
12264
+ /* @__PURE__ */ jsx30("span", { children: "Expiry (MM/YY)" }),
12265
+ /* @__PURE__ */ jsx30(
12194
12266
  "input",
12195
12267
  {
12196
12268
  required: true,
@@ -12203,8 +12275,8 @@ function CheckoutClient(_props) {
12203
12275
  )
12204
12276
  ] }),
12205
12277
  /* @__PURE__ */ jsxs27("label", { children: [
12206
- /* @__PURE__ */ jsx29("span", { children: "Security code" }),
12207
- /* @__PURE__ */ jsx29(
12278
+ /* @__PURE__ */ jsx30("span", { children: "Security code" }),
12279
+ /* @__PURE__ */ jsx30(
12208
12280
  "input",
12209
12281
  {
12210
12282
  required: true,
@@ -12215,14 +12287,17 @@ function CheckoutClient(_props) {
12215
12287
  }
12216
12288
  )
12217
12289
  ] }),
12218
- /* @__PURE__ */ jsx29("p", { className: "sk-checkout__note", children: "Your card details go straight to our payment provider \u2014 they never reach this clinic's systems." })
12290
+ /* @__PURE__ */ jsx30("p", { className: "sk-checkout__note", children: "Your card details go straight to our payment provider \u2014 they never reach this clinic's systems." })
12219
12291
  ] }),
12220
- /* @__PURE__ */ jsx29("button", { type: "submit", className: "sk-checkout__pay", disabled: busy, children: busy ? "Processing\u2026" : quote ? `Pay ${formatMoney(quote.total)}` : "Pay" })
12292
+ /* @__PURE__ */ jsx30("button", { type: "submit", className: "sk-checkout__pay", disabled: busy, children: busy ? "Processing\u2026" : quote ? `Pay ${formatMoney(quote.total)}` : "Pay" })
12221
12293
  ] })
12222
12294
  ] });
12223
12295
  }
12224
12296
 
12225
12297
  export {
12298
+ PortalProvider,
12299
+ usePortalClient,
12300
+ usePortalSession,
12226
12301
  BookingBlockClient,
12227
12302
  PortalPanel,
12228
12303
  CertificateFunnelClient,