@patientos/website-kit 0.2.1 → 0.2.2
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-CRYD7EXD.js → chunk-N6IGS47W.js} +1 -1
- package/dist/{chunk-EO64UB5F.js → chunk-UTCKIWE7.js} +914 -846
- 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";
|
|
@@ -10861,10 +10910,20 @@ async function savePortalProfileAndReload(patch, fetchImpl) {
|
|
|
10861
10910
|
return { ok: true, data: next.data ?? {} };
|
|
10862
10911
|
}
|
|
10863
10912
|
function PortalAccountClient(props) {
|
|
10913
|
+
const client = React21.useMemo(
|
|
10914
|
+
() => createPortalClient({
|
|
10915
|
+
apiOrigin: props.portalApiOrigin,
|
|
10916
|
+
portalUrl: props.portalUrl,
|
|
10917
|
+
fetchImpl: props.fetchImpl
|
|
10918
|
+
}),
|
|
10919
|
+
[props.portalApiOrigin, props.portalUrl, props.fetchImpl]
|
|
10920
|
+
);
|
|
10921
|
+
return /* @__PURE__ */ jsx27(PortalProvider, { client, children: /* @__PURE__ */ jsx27(PortalAccountContent, { ...props }) });
|
|
10922
|
+
}
|
|
10923
|
+
function PortalAccountContent(props) {
|
|
10864
10924
|
const { surface } = props;
|
|
10865
|
-
|
|
10866
|
-
|
|
10867
|
-
return /* @__PURE__ */ jsx26(PortalAccountSurfaceClient, { ...props, surface });
|
|
10925
|
+
if (surface === "book") return /* @__PURE__ */ jsx27(PortalAccountBookLauncher, { ...props });
|
|
10926
|
+
return /* @__PURE__ */ jsx27(PortalAccountSurfaceClient, { ...props, surface });
|
|
10868
10927
|
}
|
|
10869
10928
|
function PortalAccountBookLauncher({
|
|
10870
10929
|
funnelHref,
|
|
@@ -10873,8 +10932,8 @@ function PortalAccountBookLauncher({
|
|
|
10873
10932
|
clinicPhone
|
|
10874
10933
|
}) {
|
|
10875
10934
|
return /* @__PURE__ */ jsxs24("section", { className: "sk-portal-account__body", children: [
|
|
10876
|
-
/* @__PURE__ */
|
|
10877
|
-
/* @__PURE__ */
|
|
10935
|
+
/* @__PURE__ */ jsx27("h2", { className: "sk-portal-account__heading", children: PORTAL_ACCOUNT_HEADING.book }),
|
|
10936
|
+
/* @__PURE__ */ jsx27(
|
|
10878
10937
|
PortalBookLauncher,
|
|
10879
10938
|
{
|
|
10880
10939
|
services: services ?? [],
|
|
@@ -10890,21 +10949,26 @@ function PortalAccountSurfaceClient({
|
|
|
10890
10949
|
portalUrl,
|
|
10891
10950
|
bookHref,
|
|
10892
10951
|
initialState,
|
|
10893
|
-
fetchImpl,
|
|
10952
|
+
fetchImpl: rawFetchImpl,
|
|
10894
10953
|
openUrl
|
|
10895
10954
|
}) {
|
|
10896
|
-
const
|
|
10955
|
+
const portalClient = usePortalClient();
|
|
10956
|
+
const fetchImpl = React21.useMemo(
|
|
10957
|
+
() => portalFetchForClient(portalClient, rawFetchImpl),
|
|
10958
|
+
[portalClient, rawFetchImpl]
|
|
10959
|
+
);
|
|
10960
|
+
const [state, setState] = React21.useState(
|
|
10897
10961
|
// `readPortalSignedInHint` is in the initialiser (not an effect) on purpose: the
|
|
10898
10962
|
// whole point is that the FIRST paint already knows, so there is no placeholder
|
|
10899
10963
|
// swap. It reads one boolean out of sessionStorage — no PHI, no network.
|
|
10900
10964
|
() => initialState ?? { kind: "loading", hinted: readPortalSignedInHint() }
|
|
10901
10965
|
);
|
|
10902
|
-
const [signingOut, setSigningOut] =
|
|
10903
|
-
const commit =
|
|
10966
|
+
const [signingOut, setSigningOut] = React21.useState(false);
|
|
10967
|
+
const commit = React21.useCallback((next) => {
|
|
10904
10968
|
writePortalSignedInHint(next.kind === "signed-in" || next.kind === "not-available");
|
|
10905
10969
|
setState(next);
|
|
10906
10970
|
}, []);
|
|
10907
|
-
|
|
10971
|
+
React21.useEffect(() => {
|
|
10908
10972
|
if (initialState) return;
|
|
10909
10973
|
let live = true;
|
|
10910
10974
|
void loadPortalAccount(surface, fetchImpl).then((next) => {
|
|
@@ -10929,25 +10993,25 @@ function PortalAccountSurfaceClient({
|
|
|
10929
10993
|
setState((prev) => prev.kind === "signed-in" ? { ...prev, data } : prev);
|
|
10930
10994
|
}
|
|
10931
10995
|
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__ */
|
|
10996
|
+
/* @__PURE__ */ jsx27("h2", { className: "sk-portal-account__heading", children: heading2 }),
|
|
10997
|
+
state.kind === "loading" && !state.hinted ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__placeholder", children: "Checking your sign-in\u2026" }) : null,
|
|
10998
|
+
state.kind === "loading" && state.hinted ? /* @__PURE__ */ jsx27(PortalAccountSkeleton, {}) : null,
|
|
10999
|
+
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,
|
|
11000
|
+
state.kind === "signed-out" ? /* @__PURE__ */ jsx27(
|
|
10937
11001
|
PortalSignInRamp,
|
|
10938
11002
|
{
|
|
10939
11003
|
idSuffix: `account-${surface}`,
|
|
10940
|
-
submit: (email) =>
|
|
11004
|
+
submit: (email) => portalClient.requestMagicLink(email).then((ok) => ({ ok })),
|
|
10941
11005
|
onResult: ({ ok, email }) => setState(ok ? { kind: "link-sent", email } : { kind: "link-out" })
|
|
10942
11006
|
}
|
|
10943
11007
|
) : null,
|
|
10944
|
-
state.kind === "link-sent" ? /* @__PURE__ */
|
|
11008
|
+
state.kind === "link-sent" ? /* @__PURE__ */ jsx27(PortalLinkSentNotice, { email: state.email }) : null,
|
|
10945
11009
|
state.kind === "not-available" || state.kind === "signed-in" ? /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__header", children: [
|
|
10946
11010
|
/* @__PURE__ */ jsxs24("span", { className: "sk-portal-account__who", children: [
|
|
10947
11011
|
"Signed in as ",
|
|
10948
11012
|
state.givenName ?? "you"
|
|
10949
11013
|
] }),
|
|
10950
|
-
/* @__PURE__ */
|
|
11014
|
+
/* @__PURE__ */ jsx27(
|
|
10951
11015
|
"button",
|
|
10952
11016
|
{
|
|
10953
11017
|
type: "button",
|
|
@@ -10958,8 +11022,8 @@ function PortalAccountSurfaceClient({
|
|
|
10958
11022
|
}
|
|
10959
11023
|
)
|
|
10960
11024
|
] }) : null,
|
|
10961
|
-
state.kind === "not-available" ? /* @__PURE__ */
|
|
10962
|
-
state.kind === "signed-in" && surface === "appointments" ? /* @__PURE__ */
|
|
11025
|
+
state.kind === "not-available" ? /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__note", role: "note", children: "This isn't available online at this clinic." }) : null,
|
|
11026
|
+
state.kind === "signed-in" && surface === "appointments" ? /* @__PURE__ */ jsx27(
|
|
10963
11027
|
PortalAccountAppointments,
|
|
10964
11028
|
{
|
|
10965
11029
|
data: state.data,
|
|
@@ -10969,15 +11033,16 @@ function PortalAccountSurfaceClient({
|
|
|
10969
11033
|
onReloaded: replaceData
|
|
10970
11034
|
}
|
|
10971
11035
|
) : null,
|
|
10972
|
-
state.kind === "signed-in" && surface === "addresses" ? /* @__PURE__ */
|
|
11036
|
+
state.kind === "signed-in" && surface === "addresses" ? /* @__PURE__ */ jsx27(
|
|
10973
11037
|
PortalAccountAddresses,
|
|
10974
11038
|
{
|
|
10975
11039
|
data: state.data,
|
|
11040
|
+
client: portalClient,
|
|
10976
11041
|
fetchImpl,
|
|
10977
11042
|
onReloaded: replaceData
|
|
10978
11043
|
}
|
|
10979
11044
|
) : null,
|
|
10980
|
-
state.kind === "signed-in" && surface === "documents" ? /* @__PURE__ */
|
|
11045
|
+
state.kind === "signed-in" && surface === "documents" ? /* @__PURE__ */ jsx27(
|
|
10981
11046
|
PortalAccountDocuments,
|
|
10982
11047
|
{
|
|
10983
11048
|
data: state.data,
|
|
@@ -10985,7 +11050,7 @@ function PortalAccountSurfaceClient({
|
|
|
10985
11050
|
openUrl
|
|
10986
11051
|
}
|
|
10987
11052
|
) : null,
|
|
10988
|
-
state.kind === "signed-in" && surface === "orders" ? /* @__PURE__ */
|
|
11053
|
+
state.kind === "signed-in" && surface === "orders" ? /* @__PURE__ */ jsx27(
|
|
10989
11054
|
PortalAccountOrders,
|
|
10990
11055
|
{
|
|
10991
11056
|
data: state.data,
|
|
@@ -10993,7 +11058,7 @@ function PortalAccountSurfaceClient({
|
|
|
10993
11058
|
openUrl
|
|
10994
11059
|
}
|
|
10995
11060
|
) : null,
|
|
10996
|
-
state.kind === "signed-in" && surface === "profile" ? /* @__PURE__ */
|
|
11061
|
+
state.kind === "signed-in" && surface === "profile" ? /* @__PURE__ */ jsx27(
|
|
10997
11062
|
PortalAccountProfile,
|
|
10998
11063
|
{
|
|
10999
11064
|
data: state.data,
|
|
@@ -11005,18 +11070,18 @@ function PortalAccountSurfaceClient({
|
|
|
11005
11070
|
}
|
|
11006
11071
|
function PortalAccountSkeleton() {
|
|
11007
11072
|
return /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__skeleton", "aria-hidden": "true", children: [
|
|
11008
|
-
/* @__PURE__ */
|
|
11009
|
-
/* @__PURE__ */
|
|
11010
|
-
/* @__PURE__ */
|
|
11073
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__skeleton-row" }),
|
|
11074
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__skeleton-row" }),
|
|
11075
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__skeleton-row" })
|
|
11011
11076
|
] });
|
|
11012
11077
|
}
|
|
11013
11078
|
function StatusBadge({ status }) {
|
|
11014
11079
|
if (!status) return null;
|
|
11015
|
-
return /* @__PURE__ */
|
|
11080
|
+
return /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__status", children: status });
|
|
11016
11081
|
}
|
|
11017
11082
|
function ErrorNote({ message }) {
|
|
11018
11083
|
if (!message) return null;
|
|
11019
|
-
return /* @__PURE__ */
|
|
11084
|
+
return /* @__PURE__ */ jsx27("p", { className: "sk-portal-error", role: "alert", children: message });
|
|
11020
11085
|
}
|
|
11021
11086
|
function PortalAccountAppointments({
|
|
11022
11087
|
data,
|
|
@@ -11028,17 +11093,17 @@ function PortalAccountAppointments({
|
|
|
11028
11093
|
now,
|
|
11029
11094
|
initialUi
|
|
11030
11095
|
}) {
|
|
11031
|
-
const [cancelFor, setCancelFor] =
|
|
11032
|
-
const [rescheduleFor, setRescheduleFor] =
|
|
11096
|
+
const [cancelFor, setCancelFor] = React21.useState(initialUi?.cancelFor ?? null);
|
|
11097
|
+
const [rescheduleFor, setRescheduleFor] = React21.useState(
|
|
11033
11098
|
initialUi?.rescheduleFor ?? null
|
|
11034
11099
|
);
|
|
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] =
|
|
11100
|
+
const [consultFor, setConsultFor] = React21.useState(initialUi?.consultFor ?? null);
|
|
11101
|
+
const [reasons, setReasons] = React21.useState(initialUi?.reasons ?? []);
|
|
11102
|
+
const reasonsLoaded = React21.useRef(initialUi?.reasons !== void 0);
|
|
11103
|
+
const [reasonId, setReasonId] = React21.useState("");
|
|
11104
|
+
const [note, setNote] = React21.useState("");
|
|
11105
|
+
const [busy, setBusy] = React21.useState(false);
|
|
11106
|
+
const [error2, setError] = React21.useState(initialUi?.error ?? null);
|
|
11042
11107
|
async function openCancel(id) {
|
|
11043
11108
|
setCancelFor(id);
|
|
11044
11109
|
setReasonId("");
|
|
@@ -11071,20 +11136,20 @@ function PortalAccountAppointments({
|
|
|
11071
11136
|
];
|
|
11072
11137
|
const empty = data.upcoming.length === 0 && data.past.length === 0;
|
|
11073
11138
|
return /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
11074
|
-
empty ? /* @__PURE__ */
|
|
11075
|
-
/* @__PURE__ */
|
|
11076
|
-
/* @__PURE__ */
|
|
11139
|
+
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: [
|
|
11140
|
+
/* @__PURE__ */ jsx27("h3", { className: "sk-portal-account__group-title", children: group.title }),
|
|
11141
|
+
/* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__list", children: group.items.map((item) => {
|
|
11077
11142
|
const join = consultJoinAffordance(item, now);
|
|
11078
11143
|
return /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
|
|
11079
11144
|
/* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__item-head", children: [
|
|
11080
|
-
/* @__PURE__ */
|
|
11081
|
-
item.telehealth ? /* @__PURE__ */
|
|
11082
|
-
/* @__PURE__ */
|
|
11145
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-title", children: item.title ?? "\u2014" }),
|
|
11146
|
+
item.telehealth ? /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__status", children: "Telehealth" }) : null,
|
|
11147
|
+
/* @__PURE__ */ jsx27(StatusBadge, { status: item.status })
|
|
11083
11148
|
] }),
|
|
11084
|
-
/* @__PURE__ */
|
|
11085
|
-
item.locationName || item.practitionerName ? /* @__PURE__ */
|
|
11149
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: formatPortalDateTime(item.start, item.timezone) ?? "Time to be confirmed" }),
|
|
11150
|
+
item.locationName || item.practitionerName ? /* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: [item.locationName, item.practitionerName].filter(Boolean).join(" \xB7 ") }) : null,
|
|
11086
11151
|
/* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__actions", children: [
|
|
11087
|
-
join.kind === "join" ? /* @__PURE__ */
|
|
11152
|
+
join.kind === "join" ? /* @__PURE__ */ jsx27(
|
|
11088
11153
|
"button",
|
|
11089
11154
|
{
|
|
11090
11155
|
type: "button",
|
|
@@ -11101,7 +11166,7 @@ function PortalAccountAppointments({
|
|
|
11101
11166
|
item.canReschedule ? (
|
|
11102
11167
|
// INLINE since PAT-789. It was a link into the portal; the round
|
|
11103
11168
|
// trip through a second host to pick a time was the seam.
|
|
11104
|
-
/* @__PURE__ */
|
|
11169
|
+
/* @__PURE__ */ jsx27(
|
|
11105
11170
|
"button",
|
|
11106
11171
|
{
|
|
11107
11172
|
type: "button",
|
|
@@ -11115,7 +11180,7 @@ function PortalAccountAppointments({
|
|
|
11115
11180
|
}
|
|
11116
11181
|
)
|
|
11117
11182
|
) : null,
|
|
11118
|
-
item.canCancel ? /* @__PURE__ */
|
|
11183
|
+
item.canCancel ? /* @__PURE__ */ jsx27(
|
|
11119
11184
|
"button",
|
|
11120
11185
|
{
|
|
11121
11186
|
type: "button",
|
|
@@ -11130,7 +11195,7 @@ function PortalAccountAppointments({
|
|
|
11130
11195
|
"Video opens at ",
|
|
11131
11196
|
formatPortalTime(join.at, item.timezone) ?? "your appointment time"
|
|
11132
11197
|
] }) : null,
|
|
11133
|
-
consultFor === item.id ? /* @__PURE__ */
|
|
11198
|
+
consultFor === item.id ? /* @__PURE__ */ jsx27(
|
|
11134
11199
|
PortalConsultPanel,
|
|
11135
11200
|
{
|
|
11136
11201
|
appointmentId: item.id,
|
|
@@ -11140,7 +11205,7 @@ function PortalAccountAppointments({
|
|
|
11140
11205
|
loadModule: loadConsultModule2
|
|
11141
11206
|
}
|
|
11142
11207
|
) : null,
|
|
11143
|
-
rescheduleFor === item.id ? /* @__PURE__ */
|
|
11208
|
+
rescheduleFor === item.id ? /* @__PURE__ */ jsx27(
|
|
11144
11209
|
PortalRescheduleInline,
|
|
11145
11210
|
{
|
|
11146
11211
|
appointment: item,
|
|
@@ -11153,11 +11218,11 @@ function PortalAccountAppointments({
|
|
|
11153
11218
|
}
|
|
11154
11219
|
) : null,
|
|
11155
11220
|
cancelFor === item.id ? /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm", children: [
|
|
11156
|
-
/* @__PURE__ */
|
|
11221
|
+
/* @__PURE__ */ jsx27("p", { className: "sk-portal-account__confirm-title", children: "Cancel this appointment?" }),
|
|
11157
11222
|
reasons.length > 0 ? /* @__PURE__ */ jsxs24("fieldset", { className: "sk-portal-account__reasons", children: [
|
|
11158
|
-
/* @__PURE__ */
|
|
11223
|
+
/* @__PURE__ */ jsx27("legend", { className: "sk-portal-label", children: "Reason (optional)" }),
|
|
11159
11224
|
reasons.map((reason) => /* @__PURE__ */ jsxs24("label", { className: "sk-portal-account__reason", children: [
|
|
11160
|
-
/* @__PURE__ */
|
|
11225
|
+
/* @__PURE__ */ jsx27(
|
|
11161
11226
|
"input",
|
|
11162
11227
|
{
|
|
11163
11228
|
type: "radio",
|
|
@@ -11170,7 +11235,7 @@ function PortalAccountAppointments({
|
|
|
11170
11235
|
reason.label
|
|
11171
11236
|
] }, reason.id))
|
|
11172
11237
|
] }) : null,
|
|
11173
|
-
/* @__PURE__ */
|
|
11238
|
+
/* @__PURE__ */ jsx27(
|
|
11174
11239
|
"label",
|
|
11175
11240
|
{
|
|
11176
11241
|
className: "sk-portal-label",
|
|
@@ -11178,7 +11243,7 @@ function PortalAccountAppointments({
|
|
|
11178
11243
|
children: "Anything you'd like us to know? (optional)"
|
|
11179
11244
|
}
|
|
11180
11245
|
),
|
|
11181
|
-
/* @__PURE__ */
|
|
11246
|
+
/* @__PURE__ */ jsx27(
|
|
11182
11247
|
"textarea",
|
|
11183
11248
|
{
|
|
11184
11249
|
id: `sk-portal-cancel-note-${item.id}`,
|
|
@@ -11188,9 +11253,9 @@ function PortalAccountAppointments({
|
|
|
11188
11253
|
onChange: (e) => setNote(e.target.value)
|
|
11189
11254
|
}
|
|
11190
11255
|
),
|
|
11191
|
-
/* @__PURE__ */
|
|
11256
|
+
/* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
|
|
11192
11257
|
/* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm-actions", children: [
|
|
11193
|
-
/* @__PURE__ */
|
|
11258
|
+
/* @__PURE__ */ jsx27(
|
|
11194
11259
|
"button",
|
|
11195
11260
|
{
|
|
11196
11261
|
type: "button",
|
|
@@ -11200,7 +11265,7 @@ function PortalAccountAppointments({
|
|
|
11200
11265
|
children: busy ? "Cancelling\u2026" : "Cancel appointment"
|
|
11201
11266
|
}
|
|
11202
11267
|
),
|
|
11203
|
-
/* @__PURE__ */
|
|
11268
|
+
/* @__PURE__ */ jsx27(
|
|
11204
11269
|
"button",
|
|
11205
11270
|
{
|
|
11206
11271
|
type: "button",
|
|
@@ -11218,7 +11283,7 @@ function PortalAccountAppointments({
|
|
|
11218
11283
|
] }, item.id);
|
|
11219
11284
|
}) })
|
|
11220
11285
|
] }, group.key)),
|
|
11221
|
-
/* @__PURE__ */
|
|
11286
|
+
/* @__PURE__ */ jsx27("a", { className: "sk-portal-button", href: portalBookHref(bookHref), children: "Book an appointment" })
|
|
11222
11287
|
] });
|
|
11223
11288
|
}
|
|
11224
11289
|
function PortalAccountDocuments({
|
|
@@ -11227,8 +11292,8 @@ function PortalAccountDocuments({
|
|
|
11227
11292
|
openUrl,
|
|
11228
11293
|
initialUi
|
|
11229
11294
|
}) {
|
|
11230
|
-
const [busyId, setBusyId] =
|
|
11231
|
-
const [error2, setError] =
|
|
11295
|
+
const [busyId, setBusyId] = React21.useState(initialUi?.busyId ?? null);
|
|
11296
|
+
const [error2, setError] = React21.useState(initialUi?.error ?? null);
|
|
11232
11297
|
async function download(id) {
|
|
11233
11298
|
if (busyId) return;
|
|
11234
11299
|
setBusyId(id);
|
|
@@ -11238,17 +11303,17 @@ function PortalAccountDocuments({
|
|
|
11238
11303
|
if (!res.ok) setError(res.error ?? DOWNLOAD_FAILED_COPY);
|
|
11239
11304
|
}
|
|
11240
11305
|
if (data.items.length === 0) {
|
|
11241
|
-
return /* @__PURE__ */
|
|
11306
|
+
return /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__empty", children: "You have no documents from us yet." });
|
|
11242
11307
|
}
|
|
11243
11308
|
return /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
11244
|
-
/* @__PURE__ */
|
|
11245
|
-
/* @__PURE__ */
|
|
11309
|
+
/* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
|
|
11310
|
+
/* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__list", children: data.items.map((doc) => /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
|
|
11246
11311
|
/* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__item-head", children: [
|
|
11247
|
-
/* @__PURE__ */
|
|
11248
|
-
/* @__PURE__ */
|
|
11312
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-title", children: doc.title ?? "Document" }),
|
|
11313
|
+
/* @__PURE__ */ jsx27(StatusBadge, { status: doc.status })
|
|
11249
11314
|
] }),
|
|
11250
|
-
/* @__PURE__ */
|
|
11251
|
-
/* @__PURE__ */
|
|
11315
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: formatPortalDate(doc.date) ?? "" }),
|
|
11316
|
+
/* @__PURE__ */ jsx27("div", { className: "sk-portal-account__actions", children: /* @__PURE__ */ jsx27(
|
|
11252
11317
|
"button",
|
|
11253
11318
|
{
|
|
11254
11319
|
type: "button",
|
|
@@ -11267,10 +11332,10 @@ function PortalAccountOrders({
|
|
|
11267
11332
|
openUrl,
|
|
11268
11333
|
initialUi
|
|
11269
11334
|
}) {
|
|
11270
|
-
const [expandedId, setExpandedId] =
|
|
11271
|
-
const [detail, setDetail] =
|
|
11272
|
-
const [loading, setLoading] =
|
|
11273
|
-
const [error2, setError] =
|
|
11335
|
+
const [expandedId, setExpandedId] = React21.useState(initialUi?.expandedId ?? null);
|
|
11336
|
+
const [detail, setDetail] = React21.useState(initialUi?.detail ?? null);
|
|
11337
|
+
const [loading, setLoading] = React21.useState(false);
|
|
11338
|
+
const [error2, setError] = React21.useState(initialUi?.error ?? null);
|
|
11274
11339
|
async function toggle(id) {
|
|
11275
11340
|
if (expandedId === id) {
|
|
11276
11341
|
setExpandedId(null);
|
|
@@ -11290,11 +11355,11 @@ function PortalAccountOrders({
|
|
|
11290
11355
|
if (!res.ok) setError(res.error ?? RECEIPT_FAILED_COPY);
|
|
11291
11356
|
}
|
|
11292
11357
|
if (data.items.length === 0) {
|
|
11293
|
-
return /* @__PURE__ */
|
|
11358
|
+
return /* @__PURE__ */ jsx27("p", { className: "sk-portal-account__empty", children: "You haven't ordered anything from us yet." });
|
|
11294
11359
|
}
|
|
11295
11360
|
return /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
11296
|
-
/* @__PURE__ */
|
|
11297
|
-
/* @__PURE__ */
|
|
11361
|
+
/* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
|
|
11362
|
+
/* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__list", children: data.items.map((order) => {
|
|
11298
11363
|
const open = expandedId === order.id;
|
|
11299
11364
|
return /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__item", children: [
|
|
11300
11365
|
/* @__PURE__ */ jsxs24(
|
|
@@ -11305,9 +11370,9 @@ function PortalAccountOrders({
|
|
|
11305
11370
|
"aria-expanded": open,
|
|
11306
11371
|
onClick: () => void toggle(order.id),
|
|
11307
11372
|
children: [
|
|
11308
|
-
/* @__PURE__ */
|
|
11309
|
-
/* @__PURE__ */
|
|
11310
|
-
/* @__PURE__ */
|
|
11373
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-title", children: order.title ?? "Order" }),
|
|
11374
|
+
/* @__PURE__ */ jsx27(StatusBadge, { status: order.status }),
|
|
11375
|
+
/* @__PURE__ */ jsx27("span", { className: "sk-portal-account__item-meta", children: [
|
|
11311
11376
|
formatPortalDate(order.placedAt),
|
|
11312
11377
|
order.paymentStatus,
|
|
11313
11378
|
formatPortalMoney(order.total, order.currency)
|
|
@@ -11315,19 +11380,19 @@ function PortalAccountOrders({
|
|
|
11315
11380
|
]
|
|
11316
11381
|
}
|
|
11317
11382
|
),
|
|
11318
|
-
open ? /* @__PURE__ */
|
|
11319
|
-
/* @__PURE__ */
|
|
11383
|
+
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: [
|
|
11384
|
+
/* @__PURE__ */ jsx27("ul", { className: "sk-portal-account__lines", children: (detail.lines ?? []).map((line) => /* @__PURE__ */ jsxs24("li", { className: "sk-portal-account__line", children: [
|
|
11320
11385
|
/* @__PURE__ */ jsxs24("span", { children: [
|
|
11321
11386
|
line.title ?? "\u2014",
|
|
11322
11387
|
line.quantity && line.quantity > 1 ? ` \xD7 ${line.quantity}` : ""
|
|
11323
11388
|
] }),
|
|
11324
|
-
/* @__PURE__ */
|
|
11389
|
+
/* @__PURE__ */ jsx27("span", { children: formatPortalMoney(line.total, detail.currency) ?? "" })
|
|
11325
11390
|
] }, line.id)) }),
|
|
11326
11391
|
/* @__PURE__ */ jsxs24("p", { className: "sk-portal-account__total", children: [
|
|
11327
11392
|
"Total ",
|
|
11328
11393
|
formatPortalMoney(detail.total, detail.currency) ?? ""
|
|
11329
11394
|
] }),
|
|
11330
|
-
detail.hasReceipt !== false ? /* @__PURE__ */
|
|
11395
|
+
detail.hasReceipt !== false ? /* @__PURE__ */ jsx27("div", { className: "sk-portal-account__actions", children: /* @__PURE__ */ jsx27(
|
|
11331
11396
|
"button",
|
|
11332
11397
|
{
|
|
11333
11398
|
type: "button",
|
|
@@ -11347,12 +11412,12 @@ function PortalAccountProfile({
|
|
|
11347
11412
|
onSaved,
|
|
11348
11413
|
initialUi
|
|
11349
11414
|
}) {
|
|
11350
|
-
const [editing, setEditing] =
|
|
11351
|
-
const [givenName, setGivenName] =
|
|
11352
|
-
const [familyName, setFamilyName] =
|
|
11353
|
-
const [phone, setPhone] =
|
|
11354
|
-
const [saving, setSaving] =
|
|
11355
|
-
const [error2, setError] =
|
|
11415
|
+
const [editing, setEditing] = React21.useState(initialUi?.editing ?? false);
|
|
11416
|
+
const [givenName, setGivenName] = React21.useState(data.givenName ?? "");
|
|
11417
|
+
const [familyName, setFamilyName] = React21.useState(data.familyName ?? "");
|
|
11418
|
+
const [phone, setPhone] = React21.useState(data.phone ?? "");
|
|
11419
|
+
const [saving, setSaving] = React21.useState(false);
|
|
11420
|
+
const [error2, setError] = React21.useState(initialUi?.error ?? null);
|
|
11356
11421
|
async function save(e) {
|
|
11357
11422
|
e.preventDefault();
|
|
11358
11423
|
if (saving) return;
|
|
@@ -11370,13 +11435,13 @@ function PortalAccountProfile({
|
|
|
11370
11435
|
if (!editing) {
|
|
11371
11436
|
return /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
11372
11437
|
/* @__PURE__ */ jsxs24("dl", { className: "sk-portal-account__fields", children: [
|
|
11373
|
-
/* @__PURE__ */
|
|
11374
|
-
/* @__PURE__ */
|
|
11375
|
-
/* @__PURE__ */
|
|
11376
|
-
/* @__PURE__ */
|
|
11377
|
-
/* @__PURE__ */
|
|
11438
|
+
/* @__PURE__ */ jsx27(Field2, { label: "First name", value: data.givenName }),
|
|
11439
|
+
/* @__PURE__ */ jsx27(Field2, { label: "Last name", value: data.familyName }),
|
|
11440
|
+
/* @__PURE__ */ jsx27(Field2, { label: "Email", value: data.email }),
|
|
11441
|
+
/* @__PURE__ */ jsx27(Field2, { label: "Mobile", value: data.phone }),
|
|
11442
|
+
/* @__PURE__ */ jsx27(Field2, { label: "Date of birth", value: formatPortalDate(data.dateOfBirth) })
|
|
11378
11443
|
] }),
|
|
11379
|
-
/* @__PURE__ */
|
|
11444
|
+
/* @__PURE__ */ jsx27(
|
|
11380
11445
|
"button",
|
|
11381
11446
|
{
|
|
11382
11447
|
type: "button",
|
|
@@ -11394,8 +11459,8 @@ function PortalAccountProfile({
|
|
|
11394
11459
|
] });
|
|
11395
11460
|
}
|
|
11396
11461
|
return /* @__PURE__ */ jsxs24("form", { className: "sk-portal-account__form", onSubmit: (e) => void save(e), children: [
|
|
11397
|
-
/* @__PURE__ */
|
|
11398
|
-
/* @__PURE__ */
|
|
11462
|
+
/* @__PURE__ */ jsx27("label", { className: "sk-portal-label", htmlFor: "sk-portal-given-name", children: "First name" }),
|
|
11463
|
+
/* @__PURE__ */ jsx27(
|
|
11399
11464
|
"input",
|
|
11400
11465
|
{
|
|
11401
11466
|
id: "sk-portal-given-name",
|
|
@@ -11406,8 +11471,8 @@ function PortalAccountProfile({
|
|
|
11406
11471
|
onChange: (e) => setGivenName(e.target.value)
|
|
11407
11472
|
}
|
|
11408
11473
|
),
|
|
11409
|
-
/* @__PURE__ */
|
|
11410
|
-
/* @__PURE__ */
|
|
11474
|
+
/* @__PURE__ */ jsx27("label", { className: "sk-portal-label", htmlFor: "sk-portal-family-name", children: "Last name" }),
|
|
11475
|
+
/* @__PURE__ */ jsx27(
|
|
11411
11476
|
"input",
|
|
11412
11477
|
{
|
|
11413
11478
|
id: "sk-portal-family-name",
|
|
@@ -11418,8 +11483,8 @@ function PortalAccountProfile({
|
|
|
11418
11483
|
onChange: (e) => setFamilyName(e.target.value)
|
|
11419
11484
|
}
|
|
11420
11485
|
),
|
|
11421
|
-
/* @__PURE__ */
|
|
11422
|
-
/* @__PURE__ */
|
|
11486
|
+
/* @__PURE__ */ jsx27("label", { className: "sk-portal-label", htmlFor: "sk-portal-phone", children: "Mobile" }),
|
|
11487
|
+
/* @__PURE__ */ jsx27(
|
|
11423
11488
|
"input",
|
|
11424
11489
|
{
|
|
11425
11490
|
id: "sk-portal-phone",
|
|
@@ -11432,14 +11497,14 @@ function PortalAccountProfile({
|
|
|
11432
11497
|
}
|
|
11433
11498
|
),
|
|
11434
11499
|
/* @__PURE__ */ jsxs24("dl", { className: "sk-portal-account__fields", children: [
|
|
11435
|
-
/* @__PURE__ */
|
|
11436
|
-
/* @__PURE__ */
|
|
11500
|
+
/* @__PURE__ */ jsx27(Field2, { label: "Email", value: data.email }),
|
|
11501
|
+
/* @__PURE__ */ jsx27(Field2, { label: "Date of birth", value: formatPortalDate(data.dateOfBirth) })
|
|
11437
11502
|
] }),
|
|
11438
|
-
/* @__PURE__ */
|
|
11439
|
-
/* @__PURE__ */
|
|
11503
|
+
/* @__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." }),
|
|
11504
|
+
/* @__PURE__ */ jsx27(ErrorNote, { message: error2 }),
|
|
11440
11505
|
/* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__confirm-actions", children: [
|
|
11441
|
-
/* @__PURE__ */
|
|
11442
|
-
/* @__PURE__ */
|
|
11506
|
+
/* @__PURE__ */ jsx27("button", { className: "sk-portal-button", type: "submit", disabled: saving, children: saving ? "Saving\u2026" : "Save details" }),
|
|
11507
|
+
/* @__PURE__ */ jsx27(
|
|
11443
11508
|
"button",
|
|
11444
11509
|
{
|
|
11445
11510
|
type: "button",
|
|
@@ -11454,13 +11519,13 @@ function PortalAccountProfile({
|
|
|
11454
11519
|
}
|
|
11455
11520
|
function Field2({ label, value }) {
|
|
11456
11521
|
return /* @__PURE__ */ jsxs24("div", { className: "sk-portal-account__field", children: [
|
|
11457
|
-
/* @__PURE__ */
|
|
11458
|
-
/* @__PURE__ */
|
|
11522
|
+
/* @__PURE__ */ jsx27("dt", { className: "sk-portal-account__field-label", children: label }),
|
|
11523
|
+
/* @__PURE__ */ jsx27("dd", { className: "sk-portal-account__field-value", children: value || "Not recorded" })
|
|
11459
11524
|
] });
|
|
11460
11525
|
}
|
|
11461
11526
|
|
|
11462
11527
|
// src/store-block.client.tsx
|
|
11463
|
-
import * as
|
|
11528
|
+
import * as React22 from "react";
|
|
11464
11529
|
|
|
11465
11530
|
// src/cart-storage.ts
|
|
11466
11531
|
var CART_STORAGE_KEY = "patientos.cart.v1";
|
|
@@ -11597,21 +11662,21 @@ function subscribeToCart(fn) {
|
|
|
11597
11662
|
}
|
|
11598
11663
|
|
|
11599
11664
|
// src/store-block.client.tsx
|
|
11600
|
-
import { Fragment as Fragment12, jsx as
|
|
11665
|
+
import { Fragment as Fragment12, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
11601
11666
|
function formatMoney(value) {
|
|
11602
11667
|
const n = Number(value);
|
|
11603
11668
|
if (!Number.isFinite(n)) return value;
|
|
11604
11669
|
return `$${n.toFixed(2)}`;
|
|
11605
11670
|
}
|
|
11606
11671
|
function StoreClient({ categoryHandle, title, columns }) {
|
|
11607
|
-
const [catalog, setCatalog] =
|
|
11608
|
-
const [failed, setFailed] =
|
|
11609
|
-
const [count, setCount] =
|
|
11610
|
-
|
|
11672
|
+
const [catalog, setCatalog] = React22.useState(null);
|
|
11673
|
+
const [failed, setFailed] = React22.useState(false);
|
|
11674
|
+
const [count, setCount] = React22.useState(0);
|
|
11675
|
+
React22.useEffect(() => {
|
|
11611
11676
|
setCount(cartItemCount(readCart()));
|
|
11612
11677
|
return subscribeToCart((cart) => setCount(cartItemCount(cart)));
|
|
11613
11678
|
}, []);
|
|
11614
|
-
|
|
11679
|
+
React22.useEffect(() => {
|
|
11615
11680
|
let alive = true;
|
|
11616
11681
|
fetch("/api/store/catalog", { headers: { accept: "application/json" } }).then(
|
|
11617
11682
|
(res) => res.ok ? res.json() : Promise.reject(new Error(String(res.status)))
|
|
@@ -11624,40 +11689,40 @@ function StoreClient({ categoryHandle, title, columns }) {
|
|
|
11624
11689
|
alive = false;
|
|
11625
11690
|
};
|
|
11626
11691
|
}, []);
|
|
11627
|
-
const products =
|
|
11692
|
+
const products = React22.useMemo(() => {
|
|
11628
11693
|
if (!catalog) return [];
|
|
11629
11694
|
if (!categoryHandle) return catalog.products;
|
|
11630
11695
|
return catalog.products.filter((p) => p.handle.startsWith(categoryHandle));
|
|
11631
11696
|
}, [catalog, categoryHandle]);
|
|
11632
11697
|
if (failed) {
|
|
11633
11698
|
return /* @__PURE__ */ jsxs25(Fragment12, { children: [
|
|
11634
|
-
/* @__PURE__ */
|
|
11635
|
-
/* @__PURE__ */
|
|
11699
|
+
/* @__PURE__ */ jsx28("h2", { className: "sk-store__heading", children: title ?? "Shop" }),
|
|
11700
|
+
/* @__PURE__ */ jsx28("p", { className: "sk-store__placeholder", role: "note", children: "Our shop is unavailable right now. Please contact the clinic to order." })
|
|
11636
11701
|
] });
|
|
11637
11702
|
}
|
|
11638
11703
|
return /* @__PURE__ */ jsxs25(Fragment12, { children: [
|
|
11639
11704
|
/* @__PURE__ */ jsxs25("div", { className: "sk-store__header", children: [
|
|
11640
|
-
/* @__PURE__ */
|
|
11705
|
+
/* @__PURE__ */ jsx28("h2", { className: "sk-store__heading", children: title ?? "Shop" }),
|
|
11641
11706
|
/* @__PURE__ */ jsxs25("a", { className: "sk-store__cart-link", href: "/cart", children: [
|
|
11642
11707
|
"Cart",
|
|
11643
11708
|
count > 0 ? ` (${count})` : ""
|
|
11644
11709
|
] })
|
|
11645
11710
|
] }),
|
|
11646
|
-
!catalog ? /* @__PURE__ */
|
|
11711
|
+
!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
11712
|
"ul",
|
|
11648
11713
|
{
|
|
11649
11714
|
className: "sk-store__grid",
|
|
11650
11715
|
style: columns ? { "--sk-store-columns": columns } : void 0,
|
|
11651
|
-
children: products.map((product) => /* @__PURE__ */
|
|
11716
|
+
children: products.map((product) => /* @__PURE__ */ jsx28(StoreCard, { product }, product.id))
|
|
11652
11717
|
}
|
|
11653
11718
|
)
|
|
11654
11719
|
] });
|
|
11655
11720
|
}
|
|
11656
11721
|
function StoreCard({ product }) {
|
|
11657
|
-
const [variantId, setVariantId] =
|
|
11722
|
+
const [variantId, setVariantId] = React22.useState(
|
|
11658
11723
|
() => (product.variants.find((v) => v.inStock) ?? product.variants[0]).id
|
|
11659
11724
|
);
|
|
11660
|
-
const [added, setAdded] =
|
|
11725
|
+
const [added, setAdded] = React22.useState(false);
|
|
11661
11726
|
const variant = product.variants.find((v) => v.id === variantId) ?? product.variants[0];
|
|
11662
11727
|
const image2 = product.thumbnailUrl ?? product.images[0]?.url ?? null;
|
|
11663
11728
|
function onAdd() {
|
|
@@ -11667,18 +11732,18 @@ function StoreCard({ product }) {
|
|
|
11667
11732
|
}
|
|
11668
11733
|
return /* @__PURE__ */ jsxs25("li", { className: "sk-store__card", children: [
|
|
11669
11734
|
/* @__PURE__ */ jsxs25("a", { className: "sk-store__card-link", href: `/store/${product.handle}`, children: [
|
|
11670
|
-
image2 ? /* @__PURE__ */
|
|
11671
|
-
/* @__PURE__ */
|
|
11735
|
+
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 }),
|
|
11736
|
+
/* @__PURE__ */ jsx28("span", { className: "sk-store__title", children: product.title })
|
|
11672
11737
|
] }),
|
|
11673
11738
|
/* @__PURE__ */ jsxs25("span", { className: "sk-store__price", children: [
|
|
11674
11739
|
formatMoney(variant.price),
|
|
11675
|
-
product.gstApplicable ? /* @__PURE__ */
|
|
11740
|
+
product.gstApplicable ? /* @__PURE__ */ jsx28("span", { className: "sk-store__gst", children: " incl. GST" }) : null
|
|
11676
11741
|
] }),
|
|
11677
11742
|
product.variants.length > 1 ? /* @__PURE__ */ jsxs25("label", { className: "sk-store__variant", children: [
|
|
11678
|
-
/* @__PURE__ */
|
|
11679
|
-
/* @__PURE__ */
|
|
11743
|
+
/* @__PURE__ */ jsx28("span", { className: "sk-store__variant-label", children: "Option" }),
|
|
11744
|
+
/* @__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
11745
|
] }) : null,
|
|
11681
|
-
/* @__PURE__ */
|
|
11746
|
+
/* @__PURE__ */ jsx28(
|
|
11682
11747
|
"button",
|
|
11683
11748
|
{
|
|
11684
11749
|
type: "button",
|
|
@@ -11692,14 +11757,14 @@ function StoreCard({ product }) {
|
|
|
11692
11757
|
}
|
|
11693
11758
|
|
|
11694
11759
|
// src/cart-block.client.tsx
|
|
11695
|
-
import * as
|
|
11696
|
-
import { Fragment as Fragment13, jsx as
|
|
11760
|
+
import * as React23 from "react";
|
|
11761
|
+
import { Fragment as Fragment13, jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
11697
11762
|
function CartClient(_props) {
|
|
11698
|
-
const [cart, setCart] =
|
|
11699
|
-
const [quote, setQuote] =
|
|
11700
|
-
const [failed, setFailed] =
|
|
11701
|
-
|
|
11702
|
-
|
|
11763
|
+
const [cart, setCart] = React23.useState(() => readCart());
|
|
11764
|
+
const [quote, setQuote] = React23.useState(null);
|
|
11765
|
+
const [failed, setFailed] = React23.useState(false);
|
|
11766
|
+
React23.useEffect(() => subscribeToCart(setCart), []);
|
|
11767
|
+
React23.useEffect(() => {
|
|
11703
11768
|
if (cart.lines.length === 0) {
|
|
11704
11769
|
setQuote(null);
|
|
11705
11770
|
setFailed(false);
|
|
@@ -11725,24 +11790,24 @@ function CartClient(_props) {
|
|
|
11725
11790
|
}, [cart]);
|
|
11726
11791
|
if (cart.lines.length === 0) {
|
|
11727
11792
|
return /* @__PURE__ */ jsxs26(Fragment13, { children: [
|
|
11728
|
-
/* @__PURE__ */
|
|
11729
|
-
/* @__PURE__ */
|
|
11730
|
-
/* @__PURE__ */
|
|
11793
|
+
/* @__PURE__ */ jsx29("h2", { className: "sk-cart__heading", children: "Your cart" }),
|
|
11794
|
+
/* @__PURE__ */ jsx29("p", { className: "sk-cart__placeholder", role: "status", children: "Your cart is empty." }),
|
|
11795
|
+
/* @__PURE__ */ jsx29("a", { className: "sk-cart__continue", href: "/store", children: "Browse the shop" })
|
|
11731
11796
|
] });
|
|
11732
11797
|
}
|
|
11733
11798
|
return /* @__PURE__ */ jsxs26(Fragment13, { children: [
|
|
11734
|
-
/* @__PURE__ */
|
|
11735
|
-
quote && quote.problems.length > 0 ? /* @__PURE__ */
|
|
11736
|
-
failed ? /* @__PURE__ */
|
|
11737
|
-
!quote ? /* @__PURE__ */
|
|
11738
|
-
/* @__PURE__ */
|
|
11739
|
-
/* @__PURE__ */
|
|
11799
|
+
/* @__PURE__ */ jsx29("h2", { className: "sk-cart__heading", children: "Your cart" }),
|
|
11800
|
+
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,
|
|
11801
|
+
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,
|
|
11802
|
+
!quote ? /* @__PURE__ */ jsx29("p", { className: "sk-cart__placeholder", role: "status", children: "Pricing your cart\u2026" }) : /* @__PURE__ */ jsxs26(Fragment13, { children: [
|
|
11803
|
+
/* @__PURE__ */ jsx29("ul", { className: "sk-cart__lines", children: quote.lines.map((line) => /* @__PURE__ */ jsxs26("li", { className: "sk-cart__line", children: [
|
|
11804
|
+
/* @__PURE__ */ jsx29("a", { className: "sk-cart__line-title", href: `/store/${line.productHandle}`, children: line.title }),
|
|
11740
11805
|
/* @__PURE__ */ jsxs26("span", { className: "sk-cart__line-unit", children: [
|
|
11741
11806
|
formatMoney(line.unitPrice),
|
|
11742
11807
|
" each"
|
|
11743
11808
|
] }),
|
|
11744
11809
|
/* @__PURE__ */ jsxs26("span", { className: "sk-cart__qty", children: [
|
|
11745
|
-
/* @__PURE__ */
|
|
11810
|
+
/* @__PURE__ */ jsx29(
|
|
11746
11811
|
"button",
|
|
11747
11812
|
{
|
|
11748
11813
|
type: "button",
|
|
@@ -11751,8 +11816,8 @@ function CartClient(_props) {
|
|
|
11751
11816
|
children: "\u2212"
|
|
11752
11817
|
}
|
|
11753
11818
|
),
|
|
11754
|
-
/* @__PURE__ */
|
|
11755
|
-
/* @__PURE__ */
|
|
11819
|
+
/* @__PURE__ */ jsx29("span", { "aria-live": "polite", children: line.quantity }),
|
|
11820
|
+
/* @__PURE__ */ jsx29(
|
|
11756
11821
|
"button",
|
|
11757
11822
|
{
|
|
11758
11823
|
type: "button",
|
|
@@ -11762,8 +11827,8 @@ function CartClient(_props) {
|
|
|
11762
11827
|
}
|
|
11763
11828
|
)
|
|
11764
11829
|
] }),
|
|
11765
|
-
/* @__PURE__ */
|
|
11766
|
-
/* @__PURE__ */
|
|
11830
|
+
/* @__PURE__ */ jsx29("span", { className: "sk-cart__line-total", children: formatMoney(line.lineTotal) }),
|
|
11831
|
+
/* @__PURE__ */ jsx29(
|
|
11767
11832
|
"button",
|
|
11768
11833
|
{
|
|
11769
11834
|
type: "button",
|
|
@@ -11775,22 +11840,22 @@ function CartClient(_props) {
|
|
|
11775
11840
|
] }, line.variantId)) }),
|
|
11776
11841
|
/* @__PURE__ */ jsxs26("dl", { className: "sk-cart__totals", children: [
|
|
11777
11842
|
/* @__PURE__ */ jsxs26("div", { children: [
|
|
11778
|
-
/* @__PURE__ */
|
|
11779
|
-
/* @__PURE__ */
|
|
11843
|
+
/* @__PURE__ */ jsx29("dt", { children: "Subtotal" }),
|
|
11844
|
+
/* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.subtotal) })
|
|
11780
11845
|
] }),
|
|
11781
11846
|
/* @__PURE__ */ jsxs26("div", { className: "sk-cart__gst-row", children: [
|
|
11782
|
-
/* @__PURE__ */
|
|
11783
|
-
/* @__PURE__ */
|
|
11847
|
+
/* @__PURE__ */ jsx29("dt", { children: "GST included" }),
|
|
11848
|
+
/* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.taxTotal) })
|
|
11784
11849
|
] }),
|
|
11785
11850
|
/* @__PURE__ */ jsxs26("div", { className: "sk-cart__total-row", children: [
|
|
11786
|
-
/* @__PURE__ */
|
|
11787
|
-
/* @__PURE__ */
|
|
11851
|
+
/* @__PURE__ */ jsx29("dt", { children: "Total" }),
|
|
11852
|
+
/* @__PURE__ */ jsx29("dd", { children: formatMoney(quote.total) })
|
|
11788
11853
|
] })
|
|
11789
11854
|
] }),
|
|
11790
|
-
quote.requiresShipping ? /* @__PURE__ */
|
|
11855
|
+
quote.requiresShipping ? /* @__PURE__ */ jsx29("p", { className: "sk-cart__note", children: "Delivery is chosen at checkout." }) : null,
|
|
11791
11856
|
/* @__PURE__ */ jsxs26("div", { className: "sk-cart__actions", children: [
|
|
11792
|
-
/* @__PURE__ */
|
|
11793
|
-
/* @__PURE__ */
|
|
11857
|
+
/* @__PURE__ */ jsx29("a", { className: "sk-cart__continue", href: "/store", children: "Keep shopping" }),
|
|
11858
|
+
/* @__PURE__ */ jsx29(
|
|
11794
11859
|
"a",
|
|
11795
11860
|
{
|
|
11796
11861
|
className: "sk-cart__checkout",
|
|
@@ -11805,8 +11870,8 @@ function CartClient(_props) {
|
|
|
11805
11870
|
}
|
|
11806
11871
|
|
|
11807
11872
|
// src/checkout-block.client.tsx
|
|
11808
|
-
import * as
|
|
11809
|
-
import { Fragment as Fragment14, jsx as
|
|
11873
|
+
import * as React24 from "react";
|
|
11874
|
+
import { Fragment as Fragment14, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
11810
11875
|
async function searchStoreAddresses(query) {
|
|
11811
11876
|
const q = query.trim();
|
|
11812
11877
|
if (q.length < 3) return [];
|
|
@@ -11831,21 +11896,21 @@ async function validateStoreAddress(address) {
|
|
|
11831
11896
|
return { address: v.formattedAddress, placeId: v.googlePlaceId ?? null };
|
|
11832
11897
|
}
|
|
11833
11898
|
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
|
-
|
|
11899
|
+
const [stage, setStage] = React24.useState("loading");
|
|
11900
|
+
const [givenName, setGivenName] = React24.useState(null);
|
|
11901
|
+
const [cart] = React24.useState(() => readCart());
|
|
11902
|
+
const [quote, setQuote] = React24.useState(null);
|
|
11903
|
+
const [shippingOptions, setShippingOptions] = React24.useState([]);
|
|
11904
|
+
const [error2, setError] = React24.useState(null);
|
|
11905
|
+
const [fulfilment, setFulfilment] = React24.useState("pickup");
|
|
11906
|
+
const [shippingOptionId, setShippingOptionId] = React24.useState(null);
|
|
11907
|
+
const [address, setAddress] = React24.useState(null);
|
|
11908
|
+
const [card, setCard] = React24.useState({ number: "", expiry: "", name: "", cvn: "" });
|
|
11909
|
+
const orderRef = React24.useRef(null);
|
|
11910
|
+
const [iframeUrl, setIframeUrl] = React24.useState(null);
|
|
11911
|
+
const iframeOriginRef = React24.useRef(null);
|
|
11912
|
+
const iframeElRef = React24.useRef(null);
|
|
11913
|
+
React24.useEffect(() => {
|
|
11849
11914
|
let alive = true;
|
|
11850
11915
|
if (cart.lines.length === 0) {
|
|
11851
11916
|
setStage("empty");
|
|
@@ -11876,7 +11941,7 @@ function CheckoutClient(_props) {
|
|
|
11876
11941
|
alive = false;
|
|
11877
11942
|
};
|
|
11878
11943
|
}, [cart]);
|
|
11879
|
-
|
|
11944
|
+
React24.useEffect(() => {
|
|
11880
11945
|
if (stage !== "details" || cart.lines.length === 0) return;
|
|
11881
11946
|
let alive = true;
|
|
11882
11947
|
fetch("/api/store/quote", {
|
|
@@ -11893,7 +11958,7 @@ function CheckoutClient(_props) {
|
|
|
11893
11958
|
alive = false;
|
|
11894
11959
|
};
|
|
11895
11960
|
}, [fulfilment, shippingOptionId]);
|
|
11896
|
-
|
|
11961
|
+
React24.useEffect(() => {
|
|
11897
11962
|
if (stage !== "three_ds") return;
|
|
11898
11963
|
function onMessage(event) {
|
|
11899
11964
|
if (iframeOriginRef.current && event.origin !== iframeOriginRef.current) return;
|
|
@@ -12024,41 +12089,41 @@ function CheckoutClient(_props) {
|
|
|
12024
12089
|
}
|
|
12025
12090
|
if (stage === "loading") {
|
|
12026
12091
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12027
|
-
/* @__PURE__ */
|
|
12028
|
-
/* @__PURE__ */
|
|
12092
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Checkout" }),
|
|
12093
|
+
/* @__PURE__ */ jsx30("p", { className: "sk-checkout__placeholder", role: "status", children: "Loading your order\u2026" })
|
|
12029
12094
|
] });
|
|
12030
12095
|
}
|
|
12031
12096
|
if (stage === "empty") {
|
|
12032
12097
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12033
|
-
/* @__PURE__ */
|
|
12034
|
-
/* @__PURE__ */
|
|
12035
|
-
/* @__PURE__ */
|
|
12098
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Checkout" }),
|
|
12099
|
+
/* @__PURE__ */ jsx30("p", { className: "sk-checkout__placeholder", role: "status", children: "Your cart is empty." }),
|
|
12100
|
+
/* @__PURE__ */ jsx30("a", { className: "sk-checkout__link", href: "/store", children: "Browse the shop" })
|
|
12036
12101
|
] });
|
|
12037
12102
|
}
|
|
12038
12103
|
if (stage === "signed_out") {
|
|
12039
12104
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12040
|
-
/* @__PURE__ */
|
|
12041
|
-
/* @__PURE__ */
|
|
12042
|
-
/* @__PURE__ */
|
|
12105
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Checkout" }),
|
|
12106
|
+
/* @__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." }),
|
|
12107
|
+
/* @__PURE__ */ jsx30("a", { className: "sk-checkout__signin", href: "/portal/sign-in?redirect=/checkout", children: "Sign in to continue" })
|
|
12043
12108
|
] });
|
|
12044
12109
|
}
|
|
12045
12110
|
if (stage === "paid") {
|
|
12046
12111
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12047
|
-
/* @__PURE__ */
|
|
12048
|
-
/* @__PURE__ */
|
|
12112
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Payment received" }),
|
|
12113
|
+
/* @__PURE__ */ jsx30("p", { className: "sk-checkout__note", role: "status", children: "Taking you to your order\u2026" })
|
|
12049
12114
|
] });
|
|
12050
12115
|
}
|
|
12051
12116
|
if (stage === "pending") {
|
|
12052
12117
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12053
|
-
/* @__PURE__ */
|
|
12054
|
-
/* @__PURE__ */
|
|
12055
|
-
/* @__PURE__ */
|
|
12118
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Confirming your payment" }),
|
|
12119
|
+
/* @__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." }),
|
|
12120
|
+
/* @__PURE__ */ jsx30("a", { className: "sk-checkout__link", href: "/portal/orders", children: "Go to my orders" })
|
|
12056
12121
|
] });
|
|
12057
12122
|
}
|
|
12058
12123
|
if (stage === "three_ds" && iframeUrl) {
|
|
12059
12124
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12060
|
-
/* @__PURE__ */
|
|
12061
|
-
/* @__PURE__ */
|
|
12125
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: "Your bank needs to check this payment" }),
|
|
12126
|
+
/* @__PURE__ */ jsx30(
|
|
12062
12127
|
"iframe",
|
|
12063
12128
|
{
|
|
12064
12129
|
ref: iframeElRef,
|
|
@@ -12071,41 +12136,41 @@ function CheckoutClient(_props) {
|
|
|
12071
12136
|
}
|
|
12072
12137
|
const busy = stage === "paying";
|
|
12073
12138
|
return /* @__PURE__ */ jsxs27(Fragment14, { children: [
|
|
12074
|
-
/* @__PURE__ */
|
|
12075
|
-
error2 ? /* @__PURE__ */
|
|
12139
|
+
/* @__PURE__ */ jsx30("h2", { className: "sk-checkout__heading", children: givenName ? `Checkout \u2014 hello, ${givenName}` : "Checkout" }),
|
|
12140
|
+
error2 ? /* @__PURE__ */ jsx30("p", { className: "sk-checkout__error", role: "alert", children: error2 }) : null,
|
|
12076
12141
|
quote ? /* @__PURE__ */ jsxs27("div", { className: "sk-checkout__summary", children: [
|
|
12077
|
-
/* @__PURE__ */
|
|
12142
|
+
/* @__PURE__ */ jsx30("ul", { className: "sk-checkout__lines", children: quote.lines.map((l) => /* @__PURE__ */ jsxs27("li", { children: [
|
|
12078
12143
|
/* @__PURE__ */ jsxs27("span", { children: [
|
|
12079
12144
|
l.title,
|
|
12080
12145
|
" \xD7 ",
|
|
12081
12146
|
l.quantity
|
|
12082
12147
|
] }),
|
|
12083
|
-
/* @__PURE__ */
|
|
12148
|
+
/* @__PURE__ */ jsx30("span", { children: formatMoney(l.lineTotal) })
|
|
12084
12149
|
] }, l.variantId)) }),
|
|
12085
12150
|
/* @__PURE__ */ jsxs27("dl", { className: "sk-checkout__totals", children: [
|
|
12086
12151
|
/* @__PURE__ */ jsxs27("div", { children: [
|
|
12087
|
-
/* @__PURE__ */
|
|
12088
|
-
/* @__PURE__ */
|
|
12152
|
+
/* @__PURE__ */ jsx30("dt", { children: "Subtotal" }),
|
|
12153
|
+
/* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.subtotal) })
|
|
12089
12154
|
] }),
|
|
12090
12155
|
Number(quote.shippingTotal) > 0 ? /* @__PURE__ */ jsxs27("div", { children: [
|
|
12091
|
-
/* @__PURE__ */
|
|
12092
|
-
/* @__PURE__ */
|
|
12156
|
+
/* @__PURE__ */ jsx30("dt", { children: "Delivery" }),
|
|
12157
|
+
/* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.shippingTotal) })
|
|
12093
12158
|
] }) : null,
|
|
12094
12159
|
/* @__PURE__ */ jsxs27("div", { children: [
|
|
12095
|
-
/* @__PURE__ */
|
|
12096
|
-
/* @__PURE__ */
|
|
12160
|
+
/* @__PURE__ */ jsx30("dt", { children: "GST included" }),
|
|
12161
|
+
/* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.taxTotal) })
|
|
12097
12162
|
] }),
|
|
12098
12163
|
/* @__PURE__ */ jsxs27("div", { className: "sk-checkout__total-row", children: [
|
|
12099
|
-
/* @__PURE__ */
|
|
12100
|
-
/* @__PURE__ */
|
|
12164
|
+
/* @__PURE__ */ jsx30("dt", { children: "Total" }),
|
|
12165
|
+
/* @__PURE__ */ jsx30("dd", { children: formatMoney(quote.total) })
|
|
12101
12166
|
] })
|
|
12102
12167
|
] })
|
|
12103
12168
|
] }) : null,
|
|
12104
12169
|
/* @__PURE__ */ jsxs27("form", { className: "sk-checkout__form", onSubmit: onPay, children: [
|
|
12105
12170
|
quote?.requiresShipping ? /* @__PURE__ */ jsxs27("fieldset", { className: "sk-checkout__fieldset", children: [
|
|
12106
|
-
/* @__PURE__ */
|
|
12171
|
+
/* @__PURE__ */ jsx30("legend", { children: "How would you like to get this?" }),
|
|
12107
12172
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12108
|
-
/* @__PURE__ */
|
|
12173
|
+
/* @__PURE__ */ jsx30(
|
|
12109
12174
|
"input",
|
|
12110
12175
|
{
|
|
12111
12176
|
type: "radio",
|
|
@@ -12117,7 +12182,7 @@ function CheckoutClient(_props) {
|
|
|
12117
12182
|
"Collect from the clinic"
|
|
12118
12183
|
] }),
|
|
12119
12184
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12120
|
-
/* @__PURE__ */
|
|
12185
|
+
/* @__PURE__ */ jsx30(
|
|
12121
12186
|
"input",
|
|
12122
12187
|
{
|
|
12123
12188
|
type: "radio",
|
|
@@ -12130,7 +12195,7 @@ function CheckoutClient(_props) {
|
|
|
12130
12195
|
] }),
|
|
12131
12196
|
fulfilment === "ship" ? /* @__PURE__ */ jsxs27("div", { className: "sk-checkout__ship", children: [
|
|
12132
12197
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12133
|
-
/* @__PURE__ */
|
|
12198
|
+
/* @__PURE__ */ jsx30("span", { children: "Delivery option" }),
|
|
12134
12199
|
/* @__PURE__ */ jsxs27(
|
|
12135
12200
|
"select",
|
|
12136
12201
|
{
|
|
@@ -12138,7 +12203,7 @@ function CheckoutClient(_props) {
|
|
|
12138
12203
|
value: shippingOptionId ?? "",
|
|
12139
12204
|
onChange: (e) => setShippingOptionId(e.target.value || null),
|
|
12140
12205
|
children: [
|
|
12141
|
-
/* @__PURE__ */
|
|
12206
|
+
/* @__PURE__ */ jsx30("option", { value: "", children: "Choose\u2026" }),
|
|
12142
12207
|
shippingOptions.map((o) => /* @__PURE__ */ jsxs27("option", { value: o.id, children: [
|
|
12143
12208
|
o.name,
|
|
12144
12209
|
" \u2014 ",
|
|
@@ -12148,7 +12213,7 @@ function CheckoutClient(_props) {
|
|
|
12148
12213
|
}
|
|
12149
12214
|
)
|
|
12150
12215
|
] }),
|
|
12151
|
-
/* @__PURE__ */
|
|
12216
|
+
/* @__PURE__ */ jsx30(
|
|
12152
12217
|
AddressPicker,
|
|
12153
12218
|
{
|
|
12154
12219
|
idPrefix: "sk-checkout",
|
|
@@ -12162,10 +12227,10 @@ function CheckoutClient(_props) {
|
|
|
12162
12227
|
] }) : null
|
|
12163
12228
|
] }) : null,
|
|
12164
12229
|
/* @__PURE__ */ jsxs27("fieldset", { className: "sk-checkout__fieldset", children: [
|
|
12165
|
-
/* @__PURE__ */
|
|
12230
|
+
/* @__PURE__ */ jsx30("legend", { children: "Card details" }),
|
|
12166
12231
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12167
|
-
/* @__PURE__ */
|
|
12168
|
-
/* @__PURE__ */
|
|
12232
|
+
/* @__PURE__ */ jsx30("span", { children: "Name on card" }),
|
|
12233
|
+
/* @__PURE__ */ jsx30(
|
|
12169
12234
|
"input",
|
|
12170
12235
|
{
|
|
12171
12236
|
required: true,
|
|
@@ -12176,8 +12241,8 @@ function CheckoutClient(_props) {
|
|
|
12176
12241
|
)
|
|
12177
12242
|
] }),
|
|
12178
12243
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12179
|
-
/* @__PURE__ */
|
|
12180
|
-
/* @__PURE__ */
|
|
12244
|
+
/* @__PURE__ */ jsx30("span", { children: "Card number" }),
|
|
12245
|
+
/* @__PURE__ */ jsx30(
|
|
12181
12246
|
"input",
|
|
12182
12247
|
{
|
|
12183
12248
|
required: true,
|
|
@@ -12189,8 +12254,8 @@ function CheckoutClient(_props) {
|
|
|
12189
12254
|
)
|
|
12190
12255
|
] }),
|
|
12191
12256
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12192
|
-
/* @__PURE__ */
|
|
12193
|
-
/* @__PURE__ */
|
|
12257
|
+
/* @__PURE__ */ jsx30("span", { children: "Expiry (MM/YY)" }),
|
|
12258
|
+
/* @__PURE__ */ jsx30(
|
|
12194
12259
|
"input",
|
|
12195
12260
|
{
|
|
12196
12261
|
required: true,
|
|
@@ -12203,8 +12268,8 @@ function CheckoutClient(_props) {
|
|
|
12203
12268
|
)
|
|
12204
12269
|
] }),
|
|
12205
12270
|
/* @__PURE__ */ jsxs27("label", { children: [
|
|
12206
|
-
/* @__PURE__ */
|
|
12207
|
-
/* @__PURE__ */
|
|
12271
|
+
/* @__PURE__ */ jsx30("span", { children: "Security code" }),
|
|
12272
|
+
/* @__PURE__ */ jsx30(
|
|
12208
12273
|
"input",
|
|
12209
12274
|
{
|
|
12210
12275
|
required: true,
|
|
@@ -12215,14 +12280,17 @@ function CheckoutClient(_props) {
|
|
|
12215
12280
|
}
|
|
12216
12281
|
)
|
|
12217
12282
|
] }),
|
|
12218
|
-
/* @__PURE__ */
|
|
12283
|
+
/* @__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
12284
|
] }),
|
|
12220
|
-
/* @__PURE__ */
|
|
12285
|
+
/* @__PURE__ */ jsx30("button", { type: "submit", className: "sk-checkout__pay", disabled: busy, children: busy ? "Processing\u2026" : quote ? `Pay ${formatMoney(quote.total)}` : "Pay" })
|
|
12221
12286
|
] })
|
|
12222
12287
|
] });
|
|
12223
12288
|
}
|
|
12224
12289
|
|
|
12225
12290
|
export {
|
|
12291
|
+
PortalProvider,
|
|
12292
|
+
usePortalClient,
|
|
12293
|
+
usePortalSession,
|
|
12226
12294
|
BookingBlockClient,
|
|
12227
12295
|
PortalPanel,
|
|
12228
12296
|
CertificateFunnelClient,
|