@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.
- package/dist/{checkout-block-CrO7OxI9.d.ts → checkout-block-Cog4H4I4.d.ts} +1 -0
- package/dist/{chunk-BW7YKCKH.js → chunk-BHVDY6SC.js} +146 -96
- package/dist/{chunk-EO64UB5F.js → chunk-LHP4RZ3N.js} +922 -847
- package/dist/{chunk-CRYD7EXD.js → chunk-MTOKBMBG.js} +1 -1
- package/dist/index.d.ts +28 -3
- package/dist/index.js +13 -4
- package/dist/islands-impl.d.ts +3 -4
- package/dist/islands-impl.js +2 -2
- package/dist/islands-registry.js +3 -3
- package/dist/{portal-account-CaK1lqSZ.d.ts → portal-account-pI1cWgsT.d.ts} +77 -1
- package/dist/{portal-account.client-CqnsCCiC.d.ts → portal-account.client-DPRRmfCJ.d.ts} +2 -29
- package/dist/portal-booking-client.d.ts +2 -2
- package/dist/portal-booking-client.js +1 -1
- package/dist/website-kit.css +3 -0
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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-
|
|
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
|
|
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
|
|
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-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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
|
|
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({
|
|
527
|
-
const
|
|
528
|
-
const [
|
|
529
|
-
const [
|
|
530
|
-
const [
|
|
531
|
-
const
|
|
532
|
-
const
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
552
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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(
|
|
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__ */
|
|
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__ */
|
|
595
|
-
prefill.dateOfBirth && /* @__PURE__ */
|
|
596
|
-
prefill.email && /* @__PURE__ */
|
|
597
|
-
prefill.phone && /* @__PURE__ */
|
|
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__ */
|
|
601
|
-
/* @__PURE__ */
|
|
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__ */
|
|
629
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
725
|
-
/* @__PURE__ */
|
|
726
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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 =
|
|
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__ */
|
|
782
|
+
/* @__PURE__ */ jsx3("label", { className: "sk-identity__label", htmlFor: id, children: label }),
|
|
767
783
|
control,
|
|
768
|
-
help && /* @__PURE__ */
|
|
769
|
-
/* @__PURE__ */
|
|
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
|
|
789
|
+
const who = await portal.whoAmI();
|
|
774
790
|
if (!who.signedIn) return { state: "anonymous" };
|
|
775
|
-
const prefill = await
|
|
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
|
|
782
|
-
import { jsx as
|
|
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 =
|
|
804
|
-
const widgetIdRef =
|
|
805
|
-
const onTokenRef =
|
|
806
|
-
const onErrorRef =
|
|
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
|
-
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
);
|
|
873
|
-
const
|
|
874
|
-
const [
|
|
875
|
-
const [
|
|
876
|
-
const [
|
|
877
|
-
const [
|
|
878
|
-
const [
|
|
879
|
-
const [
|
|
880
|
-
const
|
|
881
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
1019
|
-
if (!state) return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1057
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1145
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
1476
|
-
var FlowShapeContext =
|
|
1494
|
+
import * as React5 from "react";
|
|
1495
|
+
var FlowShapeContext = React5.createContext(DEFAULT_SHAPE);
|
|
1477
1496
|
function useStepProgress(step, questionIndex = 0) {
|
|
1478
|
-
return stepProgress(step,
|
|
1497
|
+
return stepProgress(step, React5.useContext(FlowShapeContext), questionIndex);
|
|
1479
1498
|
}
|
|
1480
1499
|
|
|
1481
1500
|
// src/portal-panel.tsx
|
|
1482
|
-
import { jsx as
|
|
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__ */
|
|
1508
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
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] =
|
|
1651
|
-
const [providerKey, setProviderKey] =
|
|
1652
|
-
const [authKey, setAuthKey] =
|
|
1653
|
-
const [amount, setAmount] =
|
|
1654
|
-
const [artifacts, setArtifacts] =
|
|
1655
|
-
const [error2, setError] =
|
|
1656
|
-
const [card, setCard] =
|
|
1657
|
-
const [cardErrors, setCardErrors] =
|
|
1658
|
-
const [initAttempt, setInitAttempt] =
|
|
1659
|
-
const iframeRef =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
1825
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1918
|
-
microcopy && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1950
|
-
feeText && /* @__PURE__ */
|
|
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__ */
|
|
1979
|
+
/* @__PURE__ */ jsx7("label", { className: "sk-pay__label", htmlFor: id, children: label }),
|
|
1961
1980
|
children,
|
|
1962
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2015
|
-
deliveryNote && /* @__PURE__ */
|
|
2016
|
-
note && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2024
|
-
services.some((s) => printsPrice(fees?.[s.key])) && /* @__PURE__ */
|
|
2025
|
-
!deliveryPending && services.some((s) => !!deliveryModes?.[s.key]) && /* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
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
|
|
2034
|
-
import { Fragment as Fragment2, jsx as
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2165
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2170
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2198
|
-
import { Fragment as Fragment3, jsx as
|
|
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,
|
|
2233
|
+
const { client, mode, onSignedIn, onRejected, onStarted, onBack, documentTitle } = props;
|
|
2234
|
+
const portal = usePortalClient();
|
|
2215
2235
|
const progress = useStepProgress(mode);
|
|
2216
|
-
const [identity, setIdentity] =
|
|
2236
|
+
const [identity, setIdentity] = React8.useState(
|
|
2217
2237
|
props.draft?.identity ?? EMPTY_IDENTITY
|
|
2218
2238
|
);
|
|
2219
|
-
const [address, setAddress] =
|
|
2220
|
-
const [identityErrors, setIdentityErrors] =
|
|
2221
|
-
const [addressErrors, setAddressErrors] =
|
|
2222
|
-
const [turnstileToken, setTurnstileToken] =
|
|
2223
|
-
const [busy, setBusy] =
|
|
2224
|
-
const [error2, setError] =
|
|
2225
|
-
const [prefill, setPrefill] =
|
|
2226
|
-
const [probing, setProbing] =
|
|
2227
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2275
|
+
React8.useEffect(() => {
|
|
2256
2276
|
onDraftChange?.({ identity, address });
|
|
2257
2277
|
}, [identity, address, onDraftChange]);
|
|
2258
|
-
const addressSearch =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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__ */
|
|
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__ */
|
|
2378
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2394
|
-
children: probing ? /* @__PURE__ */
|
|
2395
|
-
/* @__PURE__ */
|
|
2396
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2451
|
+
import * as React10 from "react";
|
|
2432
2452
|
|
|
2433
2453
|
// src/question-render.tsx
|
|
2434
|
-
import * as
|
|
2435
|
-
import { jsx as
|
|
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__ */
|
|
2488
|
-
const errorNode = error2 ? /* @__PURE__ */
|
|
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__ */
|
|
2524
|
+
question.required && /* @__PURE__ */ jsx11(RequiredMark, {})
|
|
2505
2525
|
] }),
|
|
2506
2526
|
help,
|
|
2507
|
-
/* @__PURE__ */
|
|
2508
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2576
|
+
question.required && /* @__PURE__ */ jsx11(RequiredMark, {})
|
|
2557
2577
|
] }),
|
|
2558
2578
|
help,
|
|
2559
|
-
question.kind === "number" ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
2606
|
-
|
|
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__ */
|
|
2632
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2669
|
+
question.required && /* @__PURE__ */ jsx11(RequiredMark, {})
|
|
2650
2670
|
] }),
|
|
2651
2671
|
help,
|
|
2652
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2679
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2725
|
+
/* @__PURE__ */ jsx12(FlowButton, { type: "button", variant: "primary", onClick: onRetry, children: "Try again" })
|
|
2706
2726
|
) : void 0,
|
|
2707
|
-
children: error2 ? /* @__PURE__ */
|
|
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] =
|
|
2733
|
-
const [answers, setAnswers] =
|
|
2734
|
-
const [index, setIndex] =
|
|
2735
|
-
const [draft, setDraft] =
|
|
2736
|
-
const [busy, setBusy] =
|
|
2737
|
-
const [error2, setError] =
|
|
2738
|
-
const [reload2, setReload] =
|
|
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
|
-
|
|
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
|
-
|
|
2785
|
+
React10.useEffect(() => {
|
|
2766
2786
|
if (questions && questions.length === 0 && !busy) onComplete();
|
|
2767
2787
|
}, [questions, busy, onComplete]);
|
|
2768
|
-
const visible =
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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] =
|
|
2965
|
-
const [irn, setIrn] =
|
|
2966
|
-
const [month, setMonth] =
|
|
2967
|
-
const [year, setYear] =
|
|
2968
|
-
const savedKey =
|
|
2969
|
-
const [errors2, setErrors] =
|
|
2970
|
-
const [error2, setError] =
|
|
2971
|
-
const [busy, setBusy] =
|
|
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
|
-
|
|
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__ */
|
|
3042
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3058
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3077
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3092
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3097
|
-
/* @__PURE__ */
|
|
3098
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3114
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3150
|
+
/* @__PURE__ */ jsx13(FlowFieldError, { id: "sk-mc-expiry-error", children: errors2.expiry })
|
|
3131
3151
|
] })
|
|
3132
3152
|
] })
|
|
3133
3153
|
] }),
|
|
3134
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
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] =
|
|
3240
|
-
const [busy, setBusy] =
|
|
3241
|
-
const [error2, setError] =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3344
|
+
/* @__PURE__ */ jsx14(FlowLoading, { message: "Confirming the fee\u2026" })
|
|
3325
3345
|
) : /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3326
|
-
/* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
3328
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3331
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3343
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3366
|
+
/* @__PURE__ */ jsx14("a", { className: "sk-cf__link", href: POLICY_LINKS.terms, children: "terms" }),
|
|
3347
3367
|
" ",
|
|
3348
3368
|
"and the",
|
|
3349
3369
|
" ",
|
|
3350
|
-
/* @__PURE__ */
|
|
3370
|
+
/* @__PURE__ */ jsx14("a", { className: "sk-cf__link", href: POLICY_LINKS.privacy, children: "privacy policy" }),
|
|
3351
3371
|
"."
|
|
3352
3372
|
] }) }),
|
|
3353
|
-
/* @__PURE__ */
|
|
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
|
|
3361
|
-
import { jsx as
|
|
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__ */
|
|
3388
|
-
/* @__PURE__ */
|
|
3389
|
-
confirming && /* @__PURE__ */
|
|
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] =
|
|
3405
|
-
const [confirmCancel, setConfirmCancel] =
|
|
3406
|
-
const [cancelError, setCancelError] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
3492
|
-
import { Fragment as Fragment5, jsx as
|
|
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] =
|
|
3590
|
-
const [noSession, setNoSession] =
|
|
3591
|
-
const [unreachable, setUnreachable] =
|
|
3592
|
-
const [cancelling, setCancelling] =
|
|
3593
|
-
const [confirmCancel, setConfirmCancel] =
|
|
3594
|
-
const [notice, setNotice] =
|
|
3595
|
-
const [error2, setError] =
|
|
3596
|
-
|
|
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__ */
|
|
3661
|
-
/* @__PURE__ */
|
|
3662
|
-
!portalUrl && clinicPhone && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3686
|
-
children: row === void 0 ? /* @__PURE__ */
|
|
3687
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3690
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
notice && /* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
portalUrl && /* @__PURE__ */
|
|
3697
|
-
status && CANCELLABLE.has(status) && !notice && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3733
|
-
clinicPhone ? /* @__PURE__ */
|
|
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__ */
|
|
3745
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3786
|
-
confirming && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
3808
|
-
/* @__PURE__ */
|
|
3809
|
-
money && /* @__PURE__ */
|
|
3810
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3813
|
-
/* @__PURE__ */
|
|
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
|
|
3820
|
-
import { jsx as
|
|
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 =
|
|
3828
|
-
|
|
3847
|
+
const headingRef = React15.useRef(null);
|
|
3848
|
+
React15.useEffect(() => {
|
|
3829
3849
|
headingRef.current?.focus();
|
|
3830
3850
|
}, []);
|
|
3831
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3899
|
+
footer: /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "quiet", onClick: onRestart, children: "Start again" }),
|
|
3880
3900
|
children: [
|
|
3881
|
-
/* @__PURE__ */
|
|
3882
|
-
/* @__PURE__ */
|
|
3883
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3890
|
-
clinicPhone && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3941
|
+
footer: /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "primary", onClick: onRestart, children: "Start again with a different card" }),
|
|
3922
3942
|
children: [
|
|
3923
|
-
/* @__PURE__ */
|
|
3924
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3968
|
+
footer: onBack ? /* @__PURE__ */ jsx18(FlowButton, { type: "button", variant: "quiet", onClick: onBack, children: "Choose a different certificate" }) : void 0,
|
|
3949
3969
|
children: [
|
|
3950
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3953
|
-
/* @__PURE__ */
|
|
3954
|
-
/* @__PURE__ */
|
|
3955
|
-
/* @__PURE__ */
|
|
3956
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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 =
|
|
4046
|
+
const rawClient = React16.useMemo(
|
|
4015
4047
|
() => patientos({ publishableKey: api.publishableKey, apiBase: api.apiBase }),
|
|
4016
4048
|
[api.publishableKey, api.apiBase]
|
|
4017
4049
|
);
|
|
4018
|
-
const
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
);
|
|
4022
|
-
const
|
|
4023
|
-
const [
|
|
4024
|
-
const [
|
|
4025
|
-
const [
|
|
4026
|
-
const [
|
|
4027
|
-
const [
|
|
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 =
|
|
4035
|
-
const [medicareDraft, setMedicareDraft] =
|
|
4036
|
-
const onMedicareDraftChange =
|
|
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 =
|
|
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 =
|
|
4090
|
+
const client = React16.useMemo(
|
|
4063
4091
|
() => observeSessionExpiry(rawClient, () => dispatch({ type: "SESSION_EXPIRED" })),
|
|
4064
4092
|
[rawClient, dispatch]
|
|
4065
4093
|
);
|
|
4066
|
-
const [fees, setFees] =
|
|
4067
|
-
const [deliveryModes, setDeliveryModes] =
|
|
4094
|
+
const [fees, setFees] = React16.useState(null);
|
|
4095
|
+
const [deliveryModes, setDeliveryModes] = React16.useState(
|
|
4068
4096
|
null
|
|
4069
4097
|
);
|
|
4070
|
-
const [questionCounts, setQuestionCounts] =
|
|
4071
|
-
|
|
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 =
|
|
4131
|
+
const stateRef = React16.useRef(state);
|
|
4104
4132
|
stateRef.current = state;
|
|
4105
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
4165
|
-
const restart =
|
|
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 =
|
|
4199
|
+
const retryPayment = React16.useCallback(() => {
|
|
4172
4200
|
setSubmittedIdentitySnapshot(null);
|
|
4173
4201
|
dispatch({ type: "RETRY_PAYMENT" });
|
|
4174
4202
|
}, [dispatch]);
|
|
4175
|
-
const cancelLostSlot =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4331
|
+
/* @__PURE__ */ jsx19(FlowError, { children: resolveError })
|
|
4306
4332
|
]
|
|
4307
4333
|
}
|
|
4308
4334
|
);
|
|
4309
4335
|
case "intake":
|
|
4310
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4470
|
+
/* @__PURE__ */ jsx19(FlowError, { children: lostSlotCancelError })
|
|
4445
4471
|
]
|
|
4446
4472
|
}
|
|
4447
4473
|
)
|
|
4448
|
-
) : /* @__PURE__ */
|
|
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__ */
|
|
4481
|
+
children: /* @__PURE__ */ jsx19(FlowLoading, { message: "Loading your booking\u2026" })
|
|
4456
4482
|
}
|
|
4457
4483
|
);
|
|
4458
4484
|
case "submitted":
|
|
4459
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4511
|
+
return /* @__PURE__ */ jsx19(EscalateStep, { gate: state.gate, documentTitle: title });
|
|
4486
4512
|
case "payment-failed":
|
|
4487
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
4548
|
-
import { Fragment as Fragment7, jsx as
|
|
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
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
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
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
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
|
-
|
|
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,
|
|
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__ */
|
|
4609
|
-
state.kind === "loading" ? /* @__PURE__ */
|
|
4610
|
-
state.kind === "link-out" ? /* @__PURE__ */
|
|
4611
|
-
state.kind === "signed-out" ? /* @__PURE__ */
|
|
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) =>
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4625
|
-
meta ? /* @__PURE__ */
|
|
4626
|
-
item.status ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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
|
|
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__ */
|
|
10250
|
+
return /* @__PURE__ */ jsx22("ul", { className: "sk-portal-launcher", children: services.map((s) => {
|
|
10217
10251
|
const price = prices?.[s.key] ?? "";
|
|
10218
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
10227
|
-
price ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
10308
|
-
/* @__PURE__ */
|
|
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
|
|
10317
|
-
import { jsx as
|
|
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] =
|
|
10358
|
+
const [prices, setPrices] = React18.useState({});
|
|
10325
10359
|
const publishableKey = publicApi?.publishableKey ?? "";
|
|
10326
10360
|
const apiBase = publicApi?.apiBase ?? "";
|
|
10327
|
-
|
|
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__ */
|
|
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
|
|
10364
|
-
import { Fragment as Fragment9, jsx as
|
|
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
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
|
|
10399
|
-
|
|
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
|
-
|
|
10403
|
-
|
|
10404
|
-
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
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] =
|
|
10447
|
-
const [form, setForm] =
|
|
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] =
|
|
10451
|
-
const [error2, setError] =
|
|
10452
|
-
const [busy, setBusy] =
|
|
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__ */
|
|
10494
|
-
data.items.length === 0 && editing !== "new" ? /* @__PURE__ */
|
|
10495
|
-
data.items.length > 0 ? /* @__PURE__ */
|
|
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__ */
|
|
10498
|
-
address.isPrimary ? /* @__PURE__ */
|
|
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__ */
|
|
10501
|
-
editing === address.id ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
10627
|
-
/* @__PURE__ */
|
|
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
|
|
10643
|
-
import { Fragment as Fragment10, jsx as
|
|
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 =
|
|
10694
|
-
const [status, setStatus] =
|
|
10695
|
-
const [error2, setError] =
|
|
10696
|
-
const closeRef =
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
10735
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
10748
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
-
|
|
10866
|
-
|
|
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__ */
|
|
10877
|
-
/* @__PURE__ */
|
|
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
|
|
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] =
|
|
10903
|
-
const commit =
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
10933
|
-
state.kind === "loading" && !state.hinted ? /* @__PURE__ */
|
|
10934
|
-
state.kind === "loading" && state.hinted ? /* @__PURE__ */
|
|
10935
|
-
state.kind === "link-out" ? /* @__PURE__ */
|
|
10936
|
-
state.kind === "signed-out" ? /* @__PURE__ */
|
|
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) =>
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
10962
|
-
state.kind === "signed-in" && surface === "appointments" ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
11009
|
-
/* @__PURE__ */
|
|
11010
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
11032
|
-
const [rescheduleFor, setRescheduleFor] =
|
|
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] =
|
|
11036
|
-
const [reasons, setReasons] =
|
|
11037
|
-
const reasonsLoaded =
|
|
11038
|
-
const [reasonId, setReasonId] =
|
|
11039
|
-
const [note, setNote] =
|
|
11040
|
-
const [busy, setBusy] =
|
|
11041
|
-
const [error2, setError] =
|
|
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__ */
|
|
11075
|
-
/* @__PURE__ */
|
|
11076
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11081
|
-
item.telehealth ? /* @__PURE__ */
|
|
11082
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11085
|
-
item.locationName || item.practitionerName ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
11263
|
+
/* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
|
|
11192
11264
|
/* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm-actions", children: [
|
|
11193
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
11231
|
-
const [error2, setError] =
|
|
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__ */
|
|
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__ */
|
|
11245
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11248
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11251
|
-
/* @__PURE__ */
|
|
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] =
|
|
11271
|
-
const [detail, setDetail] =
|
|
11272
|
-
const [loading, setLoading] =
|
|
11273
|
-
const [error2, setError] =
|
|
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__ */
|
|
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__ */
|
|
11297
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11309
|
-
/* @__PURE__ */
|
|
11310
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11319
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
11351
|
-
const [givenName, setGivenName] =
|
|
11352
|
-
const [familyName, setFamilyName] =
|
|
11353
|
-
const [phone, setPhone] =
|
|
11354
|
-
const [saving, setSaving] =
|
|
11355
|
-
const [error2, setError] =
|
|
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__ */
|
|
11374
|
-
/* @__PURE__ */
|
|
11375
|
-
/* @__PURE__ */
|
|
11376
|
-
/* @__PURE__ */
|
|
11377
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
11398
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11410
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11422
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11436
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11439
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11442
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11458
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
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] =
|
|
11608
|
-
const [failed, setFailed] =
|
|
11609
|
-
const [count, setCount] =
|
|
11610
|
-
|
|
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
|
-
|
|
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 =
|
|
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__ */
|
|
11635
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
11729
|
+
const [variantId, setVariantId] = React22.useState(
|
|
11658
11730
|
() => (product.variants.find((v) => v.inStock) ?? product.variants[0]).id
|
|
11659
11731
|
);
|
|
11660
|
-
const [added, setAdded] =
|
|
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__ */
|
|
11671
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
11679
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
11696
|
-
import { Fragment as Fragment13, jsx as
|
|
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] =
|
|
11699
|
-
const [quote, setQuote] =
|
|
11700
|
-
const [failed, setFailed] =
|
|
11701
|
-
|
|
11702
|
-
|
|
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__ */
|
|
11729
|
-
/* @__PURE__ */
|
|
11730
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11735
|
-
quote && quote.problems.length > 0 ? /* @__PURE__ */
|
|
11736
|
-
failed ? /* @__PURE__ */
|
|
11737
|
-
!quote ? /* @__PURE__ */
|
|
11738
|
-
/* @__PURE__ */
|
|
11739
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
11755
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11766
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11779
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11783
|
-
/* @__PURE__ */
|
|
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__ */
|
|
11787
|
-
/* @__PURE__ */
|
|
11858
|
+
/* @__PURE__ */ jsx29("dt", { children: "Total" }),
|
|
11859
|
+
/* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.total) })
|
|
11788
11860
|
] })
|
|
11789
11861
|
] }),
|
|
11790
|
-
quote.requiresShipping ? /* @__PURE__ */
|
|
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__ */
|
|
11793
|
-
/* @__PURE__ */
|
|
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
|
|
11809
|
-
import { Fragment as Fragment14, jsx as
|
|
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] =
|
|
11835
|
-
const [givenName, setGivenName] =
|
|
11836
|
-
const [cart] =
|
|
11837
|
-
const [quote, setQuote] =
|
|
11838
|
-
const [shippingOptions, setShippingOptions] =
|
|
11839
|
-
const [error2, setError] =
|
|
11840
|
-
const [fulfilment, setFulfilment] =
|
|
11841
|
-
const [shippingOptionId, setShippingOptionId] =
|
|
11842
|
-
const [address, setAddress] =
|
|
11843
|
-
const [card, setCard] =
|
|
11844
|
-
const orderRef =
|
|
11845
|
-
const [iframeUrl, setIframeUrl] =
|
|
11846
|
-
const iframeOriginRef =
|
|
11847
|
-
const iframeElRef =
|
|
11848
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
12028
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12034
|
-
/* @__PURE__ */
|
|
12035
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12041
|
-
/* @__PURE__ */
|
|
12042
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12048
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12054
|
-
/* @__PURE__ */
|
|
12055
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12061
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12075
|
-
error2 ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
12088
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12092
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12096
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12100
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12178
|
+
/* @__PURE__ */ jsx30("legend", { children: "How would you like to get this?" }),
|
|
12107
12179
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12108
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
12237
|
+
/* @__PURE__ */ jsx30("legend", { children: "Card details" }),
|
|
12166
12238
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12167
|
-
/* @__PURE__ */
|
|
12168
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12180
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12193
|
-
/* @__PURE__ */
|
|
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__ */
|
|
12207
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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,
|