@everfur/sdk 0.1.1 → 0.4.0
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/CHANGELOG.md +703 -4
- package/README.md +63 -23
- package/consent/package.json +8 -0
- package/dist/Chat-BZZ-Py5l.d.ts +128 -0
- package/dist/Chat-Dq4fffIO.d.cts +128 -0
- package/dist/DepthViews-BG3E25MD.d.ts +16 -0
- package/dist/DepthViews-B_hIypI6.d.cts +19 -0
- package/dist/DepthViews-CL75jyRA.d.cts +16 -0
- package/dist/DepthViews-CkYri51q.d.ts +19 -0
- package/dist/ErrorPolicyPort-CNf4uQZP.d.cts +22 -0
- package/dist/ErrorPolicyPort-CwbfmxzJ.d.ts +22 -0
- package/dist/{EverfurResult-D92-uL82.d.cts → EverfurResult-DN9pL2Ab.d.cts} +11 -10
- package/dist/{EverfurResult-D92-uL82.d.ts → EverfurResult-DN9pL2Ab.d.ts} +11 -10
- package/dist/{PhotoController-BItt5M7u.d.cts → PhotoController-3l7MT9jA.d.cts} +1 -1
- package/dist/{PhotoController-D8zMTdcW.d.ts → PhotoController-vzY5bfY_.d.ts} +1 -1
- package/dist/animations/index.cjs +1 -1997
- package/dist/animations/index.d.cts +35 -35
- package/dist/animations/index.d.ts +35 -35
- package/dist/animations/index.js +1 -1972
- package/dist/attachments-BorG422I.d.cts +146 -0
- package/dist/attachments-BrUWQYNK.d.ts +257 -0
- package/dist/attachments-D_SECjr1.d.cts +257 -0
- package/dist/attachments-DpldrvIW.d.ts +146 -0
- package/dist/bookingCopy-CqtDYvCR.d.ts +732 -0
- package/dist/bookingCopy-SREvkG19.d.cts +732 -0
- package/dist/branding-CsRdeNwK.d.cts +566 -0
- package/dist/branding-CsRdeNwK.d.ts +566 -0
- package/dist/callCopy-DoQKG3-L.d.cts +40 -0
- package/dist/callCopy-DoQKG3-L.d.ts +40 -0
- package/dist/casesRepository-DwtZVsbj.d.cts +51 -0
- package/dist/casesRepository-v6QczS9N.d.ts +51 -0
- package/dist/chat/index.cjs +1 -1170
- package/dist/chat/index.d.cts +32 -53
- package/dist/chat/index.d.ts +32 -53
- package/dist/chat/index.js +1 -1167
- package/dist/client/index.cjs +9 -2315
- package/dist/client/index.d.cts +80 -16
- package/dist/client/index.d.ts +80 -16
- package/dist/client/index.js +9 -2215
- package/dist/{config-CiJ0PVBB.d.ts → config--Wu1Umhd.d.cts} +64 -26
- package/dist/{config-BSjBdxrZ.d.cts → config-C7eb_IMD.d.ts} +64 -26
- package/dist/consent/index.cjs +1 -0
- package/dist/consent/index.d.cts +33 -0
- package/dist/consent/index.d.ts +33 -0
- package/dist/consent/index.js +1 -0
- package/dist/context-CL3lyuy1.d.cts +159 -0
- package/dist/context-CahAEha8.d.ts +159 -0
- package/dist/copy-DdVFDL01.d.ts +198 -0
- package/dist/copy-UeUJVk8X.d.cts +198 -0
- package/dist/core/index.cjs +13 -3178
- package/dist/core/index.d.cts +164 -29
- package/dist/core/index.d.ts +164 -29
- package/dist/core/index.js +13 -3166
- package/dist/depth-D5HwcvKC.d.cts +533 -0
- package/dist/depth-DvPwPuT_.d.ts +533 -0
- package/dist/entitlementRepository-B7egEdW6.d.ts +43 -0
- package/dist/entitlementRepository-BpJ7tiwl.d.cts +43 -0
- package/dist/{identity-Brl-lDd6.d.cts → identity-C2-08BZW.d.cts} +20 -7
- package/dist/{identity-DK9zORrG.d.ts → identity-CEi9GRFZ.d.ts} +20 -7
- package/dist/{ids-CJ1S6adf.d.cts → ids-B2GAAifq.d.cts} +1 -1
- package/dist/{ids-CJ1S6adf.d.ts → ids-B2GAAifq.d.ts} +1 -1
- package/dist/index.cjs +12 -4494
- package/dist/index.d.cts +30 -121
- package/dist/index.d.ts +30 -121
- package/dist/index.js +12 -4470
- package/dist/models-B-Uh2LTf.d.ts +214 -0
- package/dist/models-D2EUxPZY.d.cts +214 -0
- package/dist/notifications/index.cjs +2 -0
- package/dist/notifications/index.d.cts +17 -0
- package/dist/notifications/index.d.ts +17 -0
- package/dist/notifications/index.js +2 -0
- package/dist/optionalModule-DbJmsq5f.d.cts +21 -0
- package/dist/optionalModule-DbJmsq5f.d.ts +21 -0
- package/dist/pets-DJv2sj2H.d.ts +92 -0
- package/dist/pets-JVCXgRgR.d.cts +92 -0
- package/dist/petsRepository-B_gKbAzJ.d.cts +142 -0
- package/dist/petsRepository-Bk6GDwLs.d.ts +142 -0
- package/dist/photo/index.cjs +1 -2189
- package/dist/photo/index.d.cts +6 -6
- package/dist/photo/index.d.ts +6 -6
- package/dist/photo/index.js +1 -2186
- package/dist/ports-BN6RHF9W.d.cts +48 -0
- package/dist/ports-BN6RHF9W.d.ts +48 -0
- package/dist/ports-BY2ph0_y.d.cts +376 -0
- package/dist/ports-D7YW8qz9.d.ts +376 -0
- package/dist/profile-CSs1wlXT.d.cts +93 -0
- package/dist/profile-CSs1wlXT.d.ts +93 -0
- package/dist/records/depth/index.cjs +2 -0
- package/dist/records/depth/index.d.cts +13 -0
- package/dist/records/depth/index.d.ts +13 -0
- package/dist/records/depth/index.js +2 -0
- package/dist/records/index.cjs +3 -2839
- package/dist/records/index.d.cts +137 -203
- package/dist/records/index.d.ts +137 -203
- package/dist/records/index.js +3 -2833
- package/dist/requestFunnel-BjDpqqvm.d.cts +110 -0
- package/dist/requestFunnel-DFMGcluw.d.ts +110 -0
- package/dist/{resolve-Dq_4_agU.d.ts → resolve-D4Ywz5OS.d.cts} +10 -4
- package/dist/{resolve-Dq_4_agU.d.cts → resolve-D4Ywz5OS.d.ts} +10 -4
- package/dist/{runtime-Bvr8yqXm.d.cts → runtimeTypes-gZEJu-da.d.cts} +104 -132
- package/dist/{runtime-BIYzf9cK.d.ts → runtimeTypes-w5KqBMcs.d.ts} +104 -132
- package/dist/server/events/index.cjs +2 -0
- package/dist/server/events/index.d.cts +550 -0
- package/dist/server/events/index.d.ts +550 -0
- package/dist/server/events/index.js +2 -0
- package/dist/server/index.cjs +2 -533
- package/dist/server/index.d.cts +73 -18
- package/dist/server/index.d.ts +73 -18
- package/dist/server/index.js +2 -530
- package/dist/species-BXAIMh7I.d.cts +9 -0
- package/dist/species-BXAIMh7I.d.ts +9 -0
- package/dist/televet/booking/index.cjs +1 -0
- package/dist/televet/booking/index.d.cts +294 -0
- package/dist/televet/booking/index.d.ts +294 -0
- package/dist/televet/booking/index.js +1 -0
- package/dist/televet/call/index.cjs +1 -0
- package/dist/televet/call/index.d.cts +141 -0
- package/dist/televet/call/index.d.ts +141 -0
- package/dist/televet/call/index.js +1 -0
- package/dist/televet/index.cjs +1 -0
- package/dist/televet/index.d.cts +142 -0
- package/dist/televet/index.d.ts +142 -0
- package/dist/televet/index.js +1 -0
- package/dist/testing/index.cjs +5 -823
- package/dist/testing/index.d.cts +18 -4
- package/dist/testing/index.d.ts +18 -4
- package/dist/testing/index.js +5 -820
- package/dist/testing/rn/index.cjs +1 -449
- package/dist/testing/rn/index.d.cts +18 -29
- package/dist/testing/rn/index.d.ts +18 -29
- package/dist/testing/rn/index.js +1 -444
- package/dist/testing/web/index.cjs +1 -0
- package/dist/testing/web/index.d.cts +132 -0
- package/dist/testing/web/index.d.ts +132 -0
- package/dist/testing/web/index.js +1 -0
- package/dist/timelineRows-C15jxFFH.d.ts +19 -0
- package/dist/timelineRows-odO8g9r2.d.cts +19 -0
- package/dist/typeStyle-CKqVYD6L.d.cts +111 -0
- package/dist/typeStyle-DmoyacDG.d.ts +111 -0
- package/dist/uploadTransport-D0M0T4hN.d.ts +38 -0
- package/dist/uploadTransport-DKJHs3Yj.d.cts +38 -0
- package/dist/useRecordsDepth-C6rjEaLn.d.cts +237 -0
- package/dist/useRecordsDepth-crhBllQK.d.ts +237 -0
- package/dist/useVetVisit-Bc84hWUU.d.cts +187 -0
- package/dist/useVetVisit-CjmMa896.d.ts +187 -0
- package/dist/video/index.cjs +1 -1941
- package/dist/video/index.d.cts +4 -4
- package/dist/video/index.d.ts +4 -4
- package/dist/video/index.js +1 -1938
- package/dist/view-Bxwxp4xD.d.ts +310 -0
- package/dist/view-DyitEO0m.d.cts +310 -0
- package/dist/visitIntent-D7_yVp1I.d.cts +8 -0
- package/dist/visitIntent-D7_yVp1I.d.ts +8 -0
- package/dist/web/consent/index.cjs +1 -0
- package/dist/web/consent/index.d.cts +34 -0
- package/dist/web/consent/index.d.ts +34 -0
- package/dist/web/consent/index.js +1 -0
- package/dist/web/index.cjs +14 -0
- package/dist/web/index.d.cts +218 -0
- package/dist/web/index.d.ts +218 -0
- package/dist/web/index.js +14 -0
- package/dist/web/notifications/index.cjs +2 -0
- package/dist/web/notifications/index.d.cts +213 -0
- package/dist/web/notifications/index.d.ts +213 -0
- package/dist/web/notifications/index.js +2 -0
- package/dist/web/records/depth/index.cjs +2 -0
- package/dist/web/records/depth/index.d.cts +12 -0
- package/dist/web/records/depth/index.d.ts +12 -0
- package/dist/web/records/depth/index.js +2 -0
- package/dist/web/records/index.cjs +4 -0
- package/dist/web/records/index.d.cts +285 -0
- package/dist/web/records/index.d.ts +285 -0
- package/dist/web/records/index.js +4 -0
- package/dist/web/televet/booking/index.cjs +1 -0
- package/dist/web/televet/booking/index.d.cts +349 -0
- package/dist/web/televet/booking/index.d.ts +349 -0
- package/dist/web/televet/booking/index.js +1 -0
- package/dist/web/televet/call/index.cjs +1 -0
- package/dist/web/televet/call/index.d.cts +142 -0
- package/dist/web/televet/call/index.d.ts +142 -0
- package/dist/web/televet/call/index.js +1 -0
- package/dist/web/televet/index.cjs +1 -0
- package/dist/web/televet/index.d.cts +136 -0
- package/dist/web/televet/index.d.ts +136 -0
- package/dist/web/televet/index.js +1 -0
- package/notifications/package.json +8 -0
- package/package.json +266 -10
- package/records/depth/package.json +8 -0
- package/server/events/device-blocked.cjs +15 -0
- package/server/events/package.json +9 -0
- package/televet/booking/package.json +8 -0
- package/televet/call/package.json +8 -0
- package/televet/package.json +8 -0
- package/testing/web/native-blocked.cjs +12 -0
- package/testing/web/package.json +8 -0
- package/web/consent/native-blocked.cjs +12 -0
- package/web/consent/package.json +8 -0
- package/web/native-blocked.cjs +12 -0
- package/web/notifications/native-blocked.cjs +12 -0
- package/web/notifications/package.json +8 -0
- package/web/package.json +8 -0
- package/web/records/depth/native-blocked.cjs +12 -0
- package/web/records/depth/package.json +8 -0
- package/web/records/native-blocked.cjs +12 -0
- package/web/records/package.json +8 -0
- package/web/televet/booking/native-blocked.cjs +12 -0
- package/web/televet/booking/package.json +8 -0
- package/web/televet/call/native-blocked.cjs +12 -0
- package/web/televet/call/package.json +8 -0
- package/web/televet/native-blocked.cjs +12 -0
- package/web/televet/package.json +8 -0
- package/dist/ChatController-CKdBvPj2.d.ts +0 -146
- package/dist/ChatController-CpUMvvZf.d.cts +0 -146
- package/dist/FilePort-BabWrv7I.d.cts +0 -22
- package/dist/FilePort-BabWrv7I.d.ts +0 -22
- package/dist/petsRepository-BEGb97M9.d.cts +0 -326
- package/dist/petsRepository-Bu18r2kK.d.ts +0 -326
- package/dist/requestFunnel-DuUH-kAe.d.cts +0 -28
- package/dist/requestFunnel-dio5OmR9.d.ts +0 -28
|
@@ -0,0 +1,732 @@
|
|
|
1
|
+
import { c as EverfurResult, E as EverfurError } from './EverfurResult-DN9pL2Ab.cjs';
|
|
2
|
+
import { R as RequestFunnel } from './requestFunnel-BjDpqqvm.cjs';
|
|
3
|
+
import { A as AuthContext } from './identity-C2-08BZW.cjs';
|
|
4
|
+
import { E as ErrorPolicyPort } from './ErrorPolicyPort-CNf4uQZP.cjs';
|
|
5
|
+
import { T as TelemetryPort } from './TelemetryPort-BDNr00hu.cjs';
|
|
6
|
+
|
|
7
|
+
/** The consult lifecycle, as the platform names it. `unknown` for a status this SDK build has not heard of. */
|
|
8
|
+
declare const CONSULT_STATUSES: readonly ["scheduled", "in_progress", "awaiting_summary", "completed", "cancelled_owner", "cancelled_ops", "no_show_owner", "no_show_vet"];
|
|
9
|
+
type ConsultStatus = (typeof CONSULT_STATUSES)[number] | 'unknown';
|
|
10
|
+
/**
|
|
11
|
+
* Statuses after which a consult can never change again.
|
|
12
|
+
*
|
|
13
|
+
* `awaiting_summary` is deliberately NOT terminal: the call is over but the write-up has not landed, and that
|
|
14
|
+
* is precisely the window a summary surface polls through.
|
|
15
|
+
*/
|
|
16
|
+
declare const TERMINAL_CONSULT_STATUSES: ReadonlySet<ConsultStatus>;
|
|
17
|
+
declare const CONSULT_KINDS: readonly ["wellness", "prescription"];
|
|
18
|
+
type ConsultKind = (typeof CONSULT_KINDS)[number] | 'unknown';
|
|
19
|
+
/**
|
|
20
|
+
* What a US state permits. TWO INDEPENDENT SERVER FACTS, not one.
|
|
21
|
+
*
|
|
22
|
+
* `wellnessAvailable` and `prescriptionsAvailable` are separate because "we cannot prescribe here but a
|
|
23
|
+
* wellness visit is available" is a real state the booking flow reads, not a copy decision.
|
|
24
|
+
*/
|
|
25
|
+
interface TelevetStatePolicy {
|
|
26
|
+
readonly state: string;
|
|
27
|
+
readonly wellnessAvailable: boolean;
|
|
28
|
+
readonly prescriptionsAvailable: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* ALWAYS NULL against a real server, and kept only so a host that reads it still compiles.
|
|
31
|
+
*
|
|
32
|
+
* `StateCapabilitiesResponse` has no `cancellation_policy_text` and never did: it is the jurisdiction
|
|
33
|
+
* matrix, and its own docstring refuses to carry a booking acknowledgement. The terms live on
|
|
34
|
+
* `GET /cancellation-policy` with the version token that makes them reportable, which is what
|
|
35
|
+
* `TelevetCancellationPolicy` and `TelevetBookingController.cancellationPolicy` read. Prefer that; this
|
|
36
|
+
* field is a wire that was never connected, left in place rather than removed because dropping a public
|
|
37
|
+
* field is a release decision, and documented rather than quietly parsed so the next surface does not
|
|
38
|
+
* build a tick on it.
|
|
39
|
+
*/
|
|
40
|
+
readonly cancellationPolicyText: string | null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A clinician card. BIOS ONLY AT LAUNCH, per the platform's own docstring: `photoRef` is an image REF and not a
|
|
44
|
+
* URL, so a surface that has no presign path renders initials rather than a broken image.
|
|
45
|
+
*/
|
|
46
|
+
interface TelevetClinician {
|
|
47
|
+
readonly clinicianId: string;
|
|
48
|
+
readonly displayName: string;
|
|
49
|
+
readonly credentials: string | null;
|
|
50
|
+
/** Null below the platform's publication threshold. NEVER coerce to 0: no stars is not zero stars. */
|
|
51
|
+
readonly rating: number | null;
|
|
52
|
+
readonly ratingCount: number | null;
|
|
53
|
+
/** The clinician's own words, or null until they write one. Rendered verbatim, never summarised. */
|
|
54
|
+
readonly bio: string | null;
|
|
55
|
+
/** An image ref, not a URL. Null for a clinician without a photo. */
|
|
56
|
+
readonly photoRef: string | null;
|
|
57
|
+
/** Where they may practise and what they may do there. Empty until served. */
|
|
58
|
+
readonly licensedStates: readonly {
|
|
59
|
+
readonly state: string;
|
|
60
|
+
readonly canPrescribe: boolean;
|
|
61
|
+
}[];
|
|
62
|
+
}
|
|
63
|
+
/** One bookable opening. */
|
|
64
|
+
interface TelevetSlot {
|
|
65
|
+
readonly slotId: string;
|
|
66
|
+
readonly startsAt: string;
|
|
67
|
+
readonly endsAt: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* An awarded hold. NO HOLD ID: the hold is identified by the slot it sits on plus an expiry, which is why the
|
|
71
|
+
* booking's idempotency key is derived from the SLOT and not from a hold reference that does not exist.
|
|
72
|
+
*/
|
|
73
|
+
interface TelevetSlotHold {
|
|
74
|
+
readonly slotId: string;
|
|
75
|
+
readonly expiresAt: string;
|
|
76
|
+
}
|
|
77
|
+
/** A booked consult, as the server created it. What we asked for is the draft; this is what we got. */
|
|
78
|
+
interface TelevetConsult {
|
|
79
|
+
readonly consultId: string;
|
|
80
|
+
readonly petId: string;
|
|
81
|
+
readonly clinicianId: string;
|
|
82
|
+
/** The clinician's name, or null when the server has none. Never invented. */
|
|
83
|
+
readonly clinicianName: string | null;
|
|
84
|
+
/** What the owner wrote at booking, echoed back. */
|
|
85
|
+
readonly reasonText: string | null;
|
|
86
|
+
/** Attachment refs as stored against the consult. */
|
|
87
|
+
readonly mediaRefs: readonly string[];
|
|
88
|
+
readonly status: ConsultStatus;
|
|
89
|
+
readonly kind: ConsultKind;
|
|
90
|
+
readonly scheduledAt: string;
|
|
91
|
+
readonly emergencyFlagged: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** The televet entitlement verdict. True only for a live PAID subscription; promo and trial are not enough. */
|
|
94
|
+
interface TelevetBookingEntitlement {
|
|
95
|
+
readonly active: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The cancellation terms, and the token that says WHICH terms they are.
|
|
99
|
+
*
|
|
100
|
+
* WHY THIS IS ITS OWN READ. `TelevetStatePolicy.cancellationPolicyText` was parsed off the state-policy
|
|
101
|
+
* response, and no such field exists on it: `StateCapabilitiesResponse` carries the jurisdiction matrix and
|
|
102
|
+
* says so in its own docstring, and its `policy_version` is the state matrix's effective date, not the
|
|
103
|
+
* cancellation terms. So the terms tick could never render and there was no version to report, which is why
|
|
104
|
+
* the booking body omitted the attestation pair entirely. The server has always served this on its own route
|
|
105
|
+
* (`GET /cancellation-policy`, CancellationPolicyResponse), unfenced by entitlement precisely so someone
|
|
106
|
+
* deciding whether to book can read what cancelling costs.
|
|
107
|
+
*
|
|
108
|
+
* NEITHER FIELD IS EVER LOCAL. `summary` is the sentence the server derives from the numbers it enforces (the
|
|
109
|
+
* consumer app shipped a placeholder and a wrong hardcoded fee before this route existed), and `version` is
|
|
110
|
+
* evidence of what was on screen: a client-authored token would make the audit row a fiction, and a stale one
|
|
111
|
+
* is refused with a typed 409 rather than recorded as agreement to terms nobody saw.
|
|
112
|
+
*/
|
|
113
|
+
interface TelevetCancellationPolicy {
|
|
114
|
+
/** The served sentence, rendered verbatim. Never composed, templated or abbreviated by a client. */
|
|
115
|
+
readonly summary: string;
|
|
116
|
+
/** The server's own version token, reported back in `cancellation_policy_version`. */
|
|
117
|
+
readonly version: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The booking request body, in the platform's own field names. Built by `buildBookingBody`, never by hand.
|
|
121
|
+
*
|
|
122
|
+
* THE ATTESTATION PAIR IS BOUND, and the binding is the server's, not a house convention. `BookConsultRequest`
|
|
123
|
+
* declares `state_attested` and `cancellation_policy_version` individually optional and then refuses a request
|
|
124
|
+
* carrying exactly one (`_attestation_evidence_is_whole`, a 422). The compatibility case the pair is optional
|
|
125
|
+
* FOR is a client that predates the review screen and sends neither; a client that renders the tick and the
|
|
126
|
+
* terms and reports half of what the owner did writes an audit row nobody can read. So the SDK models both
|
|
127
|
+
* fields as jointly present or jointly absent and `validateBookingBody` refuses the half pair locally, before
|
|
128
|
+
* it can become a 422 the owner reads as "booking failed".
|
|
129
|
+
*/
|
|
130
|
+
interface TelevetBookingBody {
|
|
131
|
+
readonly pet_id: string;
|
|
132
|
+
readonly clinician_id: string;
|
|
133
|
+
readonly slot_id: string;
|
|
134
|
+
readonly state: string;
|
|
135
|
+
readonly reason_text: string;
|
|
136
|
+
readonly species: string | null;
|
|
137
|
+
readonly media_refs: readonly string[];
|
|
138
|
+
readonly emergency_acknowledged: boolean;
|
|
139
|
+
readonly share_health_records: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* The review screen's jurisdiction tick, as evidence.
|
|
142
|
+
*
|
|
143
|
+
* `true` ONLY, never `false`: the server's field is `Literal[True] | None` because persisting an explicit
|
|
144
|
+
* `false` is evidence of nothing and accepting it would let a client "attest false". An owner who has not
|
|
145
|
+
* ticked sends the pair absent, not a `false` half of it.
|
|
146
|
+
*/
|
|
147
|
+
readonly state_attested?: true;
|
|
148
|
+
/**
|
|
149
|
+
* Which cancellation terms the owner was SHOWN: the served version token, never a client-authored value.
|
|
150
|
+
*
|
|
151
|
+
* Paired with `state_attested` above. A stale token is refused with a typed 409 rather than recorded as if
|
|
152
|
+
* the owner had read the current terms, which is why it is the SERVER's token and why there is no local
|
|
153
|
+
* default: a build with no version to report sends the pair absent and the audit row says so honestly.
|
|
154
|
+
*/
|
|
155
|
+
readonly cancellation_policy_version?: string;
|
|
156
|
+
}
|
|
157
|
+
/** The server's own ceiling on `cancellation_policy_version` (`Field(max_length=64)`). */
|
|
158
|
+
declare const CANCELLATION_POLICY_VERSION_MAX = 64;
|
|
159
|
+
/** The server's own bound on `reason_text`. Enforced locally so an over-long description fails on the screen. */
|
|
160
|
+
declare const REASON_TEXT_MAX = 2000;
|
|
161
|
+
/** The server's own ceiling on `media_refs`. */
|
|
162
|
+
declare const MEDIA_REFS_MAX = 10;
|
|
163
|
+
/** A two-letter US state code, the only shape the booking wire accepts for `state`. */
|
|
164
|
+
declare function isWellFormedStateCode(state: string | null | undefined): boolean;
|
|
165
|
+
|
|
166
|
+
/** The partner booking surface, relative to the API base. One prefix, so a dark tenant is dark for all of it. */
|
|
167
|
+
declare const TELEVET_BOOKING_BASE = "/widget/v1/televet";
|
|
168
|
+
/**
|
|
169
|
+
* What taking a slot is addressed to: the slot is IN THE PATH, not in the body.
|
|
170
|
+
*
|
|
171
|
+
* THIS WAS `POST /slots/holds` WITH `{slot_id}` IN THE BODY, and it was invented rather than mirrored. The
|
|
172
|
+
* consumer route the partner plane is being built against is `POST /slots/{slot_id}/hold`
|
|
173
|
+
* (televet_consumer_router.py), a per-slot write whose rate limit and entitlement fence are both keyed on the
|
|
174
|
+
* path. A collection-style hold endpoint does not exist on either plane, so the old shape could never have
|
|
175
|
+
* matched, and nothing said so because the route table was silent about booking (see `knownRoutes.ts`).
|
|
176
|
+
*/
|
|
177
|
+
declare function televetHoldCall(slotId: string): string;
|
|
178
|
+
/** What a consult reschedule is addressed to. */
|
|
179
|
+
declare function televetRescheduleCall(consultId: string): string;
|
|
180
|
+
/**
|
|
181
|
+
* The booking port every ported screen reads through.
|
|
182
|
+
*
|
|
183
|
+
* EVERY METHOD IS OPTIONAL except the three writes and the grid, because a host or a test may inject a
|
|
184
|
+
* controller that answers only what its surface needs. A missing method is treated as "that answer is not
|
|
185
|
+
* available", never as an error: `useTelevetBooking` degrades each absence to the same deliberate state a dark
|
|
186
|
+
* route produces.
|
|
187
|
+
*/
|
|
188
|
+
interface TelevetBookingController {
|
|
189
|
+
/** What this US state permits. A dark route answers a policy with both facts false. */
|
|
190
|
+
statePolicy?(state: string, signal?: AbortSignal): Promise<EverfurResult<TelevetStatePolicy>>;
|
|
191
|
+
/** Whether this member's plan covers a video visit. A dark route answers `{active: false}`. */
|
|
192
|
+
entitlement?(signal?: AbortSignal): Promise<EverfurResult<TelevetBookingEntitlement>>;
|
|
193
|
+
/**
|
|
194
|
+
* The cancellation terms and their version token. A dark route answers null, and the review screen then
|
|
195
|
+
* omits the terms tick and books with the attestation pair absent, which is the honest audit row.
|
|
196
|
+
*/
|
|
197
|
+
cancellationPolicy?(signal?: AbortSignal): Promise<EverfurResult<TelevetCancellationPolicy | null>>;
|
|
198
|
+
/** Clinicians licensed in a STATE. `state` is required by the route, not a filter: there is no unfiltered roster. */
|
|
199
|
+
clinicians?(state: string, signal?: AbortSignal): Promise<EverfurResult<readonly TelevetClinician[]>>;
|
|
200
|
+
/** This clinician's whole offered window. Never paginated: the range is server-owned and takes no cursor. */
|
|
201
|
+
slots(clinicianId: string, signal?: AbortSignal): Promise<EverfurResult<readonly TelevetSlot[]>>;
|
|
202
|
+
/** The soonest opening across ALL clinicians, or null. Powers the no-slots state and nothing else. */
|
|
203
|
+
nextSlot?(signal?: AbortSignal): Promise<EverfurResult<TelevetSlot | null>>;
|
|
204
|
+
/** Take the slot. The server requires a hold before a booking or a reschedule; it is what resolves the race. */
|
|
205
|
+
holdSlot(slotId: string): Promise<EverfurResult<TelevetSlotHold>>;
|
|
206
|
+
/**
|
|
207
|
+
* Create the consult.
|
|
208
|
+
*
|
|
209
|
+
* `idempotencyKey` is the IDENTITY of this booking, derived once from the held slot when the draft is
|
|
210
|
+
* composed. It seeds the header the funnel writes, so a resubmit after a timeout is the same booking and
|
|
211
|
+
* cannot create a second consult. It is not itself the header: see `book` in the factory below.
|
|
212
|
+
*/
|
|
213
|
+
book(body: TelevetBookingBody, idempotencyKey: string): Promise<EverfurResult<TelevetConsult>>;
|
|
214
|
+
/** Move an existing consult to an already-held slot. One server operation, not a book-then-cancel. */
|
|
215
|
+
reschedule(consultId: string, slotId: string): Promise<EverfurResult<TelevetConsult>>;
|
|
216
|
+
}
|
|
217
|
+
interface TelevetBookingControllerDeps {
|
|
218
|
+
readonly auth: AuthContext;
|
|
219
|
+
/** The partner's `EverfurConfig.errorPolicy`. It can only narrow what the funnel already allows. */
|
|
220
|
+
readonly errorPolicy?: ErrorPolicyPort;
|
|
221
|
+
readonly telemetry?: TelemetryPort;
|
|
222
|
+
/** Injected in tests. Built from `auth` when absent. */
|
|
223
|
+
readonly funnel?: RequestFunnel;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Validate the booking body against the server's own bounds, BEFORE it is sent.
|
|
227
|
+
*
|
|
228
|
+
* The consumer app does this in its reducer (`canConfirm`) and again in its schema; the SDK does it here, in
|
|
229
|
+
* the layer that owns the wire, so a host that drives the controller directly gets the same refusal a screen
|
|
230
|
+
* does rather than a 422 halfway through.
|
|
231
|
+
*
|
|
232
|
+
* THE ATTESTATION PAIR IS CHECKED HERE RATHER THAN LEFT TO THE SERVER because a half pair is the one refusal
|
|
233
|
+
* the owner cannot act on. Every other rule above names something they can fix (pick a pet, write a reason);
|
|
234
|
+
* a 422 for "you sent the tick without the terms version" is a client bug wearing a booking failure, and it
|
|
235
|
+
* arrives after they pressed Confirm. Refusing locally keeps it a programming error, where it belongs.
|
|
236
|
+
*/
|
|
237
|
+
declare function validateBookingBody(body: TelevetBookingBody): string | null;
|
|
238
|
+
declare function createTelevetBookingController(deps: TelevetBookingControllerDeps): Required<TelevetBookingController>;
|
|
239
|
+
|
|
240
|
+
type TelevetBookingStep = 'pet' | 'clinician' | 'time' | 'reason' | 'review' | 'booked';
|
|
241
|
+
/**
|
|
242
|
+
* Ordered for the progress rail. `booked` is terminal and counts toward nothing: the flow is over, and
|
|
243
|
+
* including it would show a rail at 6/7 on a screen with no next step.
|
|
244
|
+
*/
|
|
245
|
+
declare const TELEVET_BOOKING_STEPS: readonly TelevetBookingStep[];
|
|
246
|
+
interface TelevetBookingDraft {
|
|
247
|
+
readonly petId: string | null;
|
|
248
|
+
/** Two letters, re-confirmed on EVERY booking: the server pattern demands it. */
|
|
249
|
+
readonly state: string | null;
|
|
250
|
+
readonly clinicianId: string | null;
|
|
251
|
+
/** The held slot. A hold has no id of its own on this wire. */
|
|
252
|
+
readonly slot: TelevetSlot | null;
|
|
253
|
+
readonly holdExpiresAt: string | null;
|
|
254
|
+
/** The consent tick that mints a records grant in the booking transaction. */
|
|
255
|
+
readonly shareHealthRecords: boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Minted ONCE per composed booking and reused across retries.
|
|
258
|
+
*
|
|
259
|
+
* Derived from the SLOT rather than a hold id, which this wire does not have. A timeout followed by a retry
|
|
260
|
+
* must not create a second consult.
|
|
261
|
+
*/
|
|
262
|
+
readonly idempotencyKey: string | null;
|
|
263
|
+
}
|
|
264
|
+
declare const emptyTelevetDraft: TelevetBookingDraft;
|
|
265
|
+
interface TelevetBookingContext {
|
|
266
|
+
/** Skips the picker for a single-pet household. */
|
|
267
|
+
readonly ownedPetCount: number;
|
|
268
|
+
}
|
|
269
|
+
interface TelevetBookingState {
|
|
270
|
+
readonly index: number;
|
|
271
|
+
readonly draft: TelevetBookingDraft;
|
|
272
|
+
/** The furthest step reached, so the rail never appears to go backwards. */
|
|
273
|
+
readonly furthestIndex: number;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The starting state, OPENED ON THE FIRST VISIBLE STEP.
|
|
277
|
+
*
|
|
278
|
+
* Index 0 is `pet`, which a one-pet household skips, so starting there opens the flow on a screen that renders
|
|
279
|
+
* nothing and never advances. The skip rule must be applied at every place an index is chosen, not only when
|
|
280
|
+
* stepping.
|
|
281
|
+
*
|
|
282
|
+
* `ctx` is required rather than optional: an initial state that does not know the household size cannot know
|
|
283
|
+
* where to start. The seeded draft matters too - a host that seeds `state` (and, for a one-pet household,
|
|
284
|
+
* `petId`) must open PAST both of those steps.
|
|
285
|
+
*/
|
|
286
|
+
declare function initialTelevetBookingState(ctx: TelevetBookingContext, seed?: Partial<TelevetBookingDraft>): TelevetBookingState;
|
|
287
|
+
type TelevetBookingAction = {
|
|
288
|
+
readonly type: 'patch';
|
|
289
|
+
readonly patch: Partial<TelevetBookingDraft>;
|
|
290
|
+
} | {
|
|
291
|
+
readonly type: 'next';
|
|
292
|
+
} | {
|
|
293
|
+
readonly type: 'back';
|
|
294
|
+
} | {
|
|
295
|
+
readonly type: 'goTo';
|
|
296
|
+
readonly step: TelevetBookingStep;
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* Whether a step is skipped for STRUCTURAL reasons rather than user choice.
|
|
300
|
+
*
|
|
301
|
+
* NO DRAFT PARAMETER. The consumer's version takes one because an earlier shape skipped a `state` step once
|
|
302
|
+
* the draft held a code; that step is gone, so a parameter nothing reads would only invite a future skip rule
|
|
303
|
+
* that depends on draft contents without the attestation that made the old one safe.
|
|
304
|
+
*
|
|
305
|
+
* A skipped step must still have its value SET. The worst defect a flow of this shape can carry is skipping
|
|
306
|
+
* the pet picker for a one-pet household and never writing `petId`, which dead-ends the majority case; the
|
|
307
|
+
* flow seeds it instead.
|
|
308
|
+
*/
|
|
309
|
+
declare function isSkipped(step: TelevetBookingStep, ctx: TelevetBookingContext): boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Is there a visible step behind this one?
|
|
312
|
+
*
|
|
313
|
+
* EXPORTED because a host deciding with `state.index > 0` is answering a different question: a one-pet
|
|
314
|
+
* household starts at index 1 (its `pet` step is skipped), so that test says "yes" on the FIRST screen and
|
|
315
|
+
* produces a Back that dispatches, finds nothing behind it, and leaves the index unchanged - a dead press.
|
|
316
|
+
*/
|
|
317
|
+
declare function hasPreviousStep(state: {
|
|
318
|
+
readonly index: number;
|
|
319
|
+
}, ctx: TelevetBookingContext): boolean;
|
|
320
|
+
declare function televetBookingReducer(state: TelevetBookingState, action: TelevetBookingAction, ctx: TelevetBookingContext): TelevetBookingState;
|
|
321
|
+
/** The step currently on screen. */
|
|
322
|
+
declare function currentStep(state: TelevetBookingState): TelevetBookingStep;
|
|
323
|
+
/**
|
|
324
|
+
* Is the draft complete enough to book?
|
|
325
|
+
*
|
|
326
|
+
* Mirrors the wire's own required fields, so an incomplete draft fails HERE rather than as a 422 after the
|
|
327
|
+
* owner presses Confirm.
|
|
328
|
+
*/
|
|
329
|
+
declare function canConfirm(draft: TelevetBookingDraft, reasonText: string): boolean;
|
|
330
|
+
/**
|
|
331
|
+
* Has the hold expired?
|
|
332
|
+
*
|
|
333
|
+
* `nowMs` is INJECTED so the screen, the countdown and the confirm all answer to one clock rather than three
|
|
334
|
+
* calls to `Date.now()`.
|
|
335
|
+
*/
|
|
336
|
+
declare function isHoldExpired(draft: TelevetBookingDraft, nowMs: number): boolean;
|
|
337
|
+
/**
|
|
338
|
+
* The idempotency key for a composed booking, derived from the SLOT.
|
|
339
|
+
*
|
|
340
|
+
* One definition, because the reducer clears it and the flow mints it: two spellings would let a retry after a
|
|
341
|
+
* cleared draft create a second consult.
|
|
342
|
+
*/
|
|
343
|
+
declare function televetBookingKey(slotId: string): string;
|
|
344
|
+
/**
|
|
345
|
+
* The attestation half of the booking body: both fields, or nothing.
|
|
346
|
+
*
|
|
347
|
+
* ONE DEFINITION FOR BOTH PLATFORMS, and it lives here rather than in either container, because "did the owner
|
|
348
|
+
* attest" is a view DECISION made from the same three inputs on RN and on web, and two spellings of a bound
|
|
349
|
+
* pair is how one of them ships a 422. The server refuses exactly one of the two
|
|
350
|
+
* (`_attestation_evidence_is_whole`), so this returns a whole pair or an empty object and never a half.
|
|
351
|
+
*
|
|
352
|
+
* THREE CONDITIONS, ALL REQUIRED, and each one is a distinct fact rather than a redundant check:
|
|
353
|
+
* - `stateAttested` the owner ticked the jurisdiction. Evidence.
|
|
354
|
+
* - `termsAttested` the owner ticked the terms they were shown. Evidence.
|
|
355
|
+
* - `policy` terms with a SERVED version token were actually on screen. Without it there is nothing
|
|
356
|
+
* to name, and naming the wrong token is a typed 409 or, worse, an audit row that cites
|
|
357
|
+
* terms nobody presented.
|
|
358
|
+
*
|
|
359
|
+
* An owner shown no terms row has nothing to tick and books with the pair absent, which is exactly the
|
|
360
|
+
* compatibility case the server's optional fields exist for.
|
|
361
|
+
*/
|
|
362
|
+
declare function attestation(stateAttested: boolean, termsAttested: boolean, policy: {
|
|
363
|
+
readonly version: string;
|
|
364
|
+
} | null | undefined): {
|
|
365
|
+
readonly state_attested: true;
|
|
366
|
+
readonly cancellation_policy_version: string;
|
|
367
|
+
} | Record<string, never>;
|
|
368
|
+
|
|
369
|
+
/** One read, in the shape the ported screens branch on. */
|
|
370
|
+
interface TelevetRead<T> {
|
|
371
|
+
/** False when the question cannot be asked yet. A disabled read is never pending and never errors. */
|
|
372
|
+
readonly enabled: boolean;
|
|
373
|
+
readonly data: T | null;
|
|
374
|
+
readonly isPending: boolean;
|
|
375
|
+
readonly isError: boolean;
|
|
376
|
+
readonly error: EverfurError | null;
|
|
377
|
+
refetch(): void;
|
|
378
|
+
}
|
|
379
|
+
/** One write, in the shape the ported screens branch on. */
|
|
380
|
+
interface TelevetWrite<Args extends readonly unknown[], T> {
|
|
381
|
+
readonly isPending: boolean;
|
|
382
|
+
/** The argument of the in-flight call, so a grid can mark the one row it is acting on. Null when idle. */
|
|
383
|
+
readonly variables: Args[0] | null;
|
|
384
|
+
mutate(...args: [...Args, {
|
|
385
|
+
readonly onSuccess?: (value: T) => void;
|
|
386
|
+
readonly onError?: (error: EverfurError) => void;
|
|
387
|
+
}?]): void;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* The booking controller for the current scope: the injected one, or one built from the provider's session.
|
|
391
|
+
*
|
|
392
|
+
* `scopeEpoch` is a real dependency, exactly as it is for `useVetVisit`: an anonymous logout changes no
|
|
393
|
+
* identity string but rotates the session, and a controller that kept the previous session's auth would book a
|
|
394
|
+
* visit for the previous user.
|
|
395
|
+
*/
|
|
396
|
+
declare function useTelevetBookingController(injected?: TelevetBookingController): TelevetBookingController | null;
|
|
397
|
+
/**
|
|
398
|
+
* True only when the server grants `televet` AND the provider is scoped to a user.
|
|
399
|
+
*
|
|
400
|
+
* The same predicate `useVetVisit` uses, so the button and the in-app flow cannot disagree about whether this
|
|
401
|
+
* member can have a visit at all.
|
|
402
|
+
*/
|
|
403
|
+
declare function useTelevetBookingAvailable(): {
|
|
404
|
+
readonly available: boolean;
|
|
405
|
+
readonly isPending: boolean;
|
|
406
|
+
};
|
|
407
|
+
/** What this US state permits. Disabled until a well-formed two-letter code is known. */
|
|
408
|
+
declare function useTelevetStatePolicy(state: string | null, controller: TelevetBookingController | null): TelevetRead<TelevetStatePolicy>;
|
|
409
|
+
/**
|
|
410
|
+
* Whether this member's plan covers a video visit.
|
|
411
|
+
*
|
|
412
|
+
* UNCONDITIONAL AND PARAMETERLESS, so it starts in parallel with the state policy rather than after it.
|
|
413
|
+
* Gating it behind a step or a chosen state would recreate the waterfall the gate exists to remove: the answer
|
|
414
|
+
* does not depend on anything the owner has filled in yet.
|
|
415
|
+
*/
|
|
416
|
+
declare function useTelevetBookingEntitlement(controller: TelevetBookingController | null): TelevetRead<{
|
|
417
|
+
readonly active: boolean;
|
|
418
|
+
}>;
|
|
419
|
+
/**
|
|
420
|
+
* The cancellation terms and their version token.
|
|
421
|
+
*
|
|
422
|
+
* UNCONDITIONAL, like the entitlement: the terms do not depend on the state, the vet or the slot, and the
|
|
423
|
+
* review screen needs them the moment it renders. Reading them on entry to the review step would show the
|
|
424
|
+
* owner a Confirm button whose terms row appears a beat later.
|
|
425
|
+
*
|
|
426
|
+
* A CONTROLLER WITHOUT THE METHOD reads as no terms, which is the same deliberate off-state a dark route
|
|
427
|
+
* produces: the tick is omitted and the booking sends the attestation pair absent, rather than a tick the
|
|
428
|
+
* SDK could not report.
|
|
429
|
+
*/
|
|
430
|
+
declare function useTelevetCancellationPolicy(controller: TelevetBookingController | null): TelevetRead<TelevetCancellationPolicy | null>;
|
|
431
|
+
/** Clinicians licensed in a STATE. `state` is the route's required parameter, not a filter. */
|
|
432
|
+
declare function useTelevetClinicians(state: string | null, controller: TelevetBookingController | null): TelevetRead<readonly TelevetClinician[]>;
|
|
433
|
+
/** This clinician's whole offered window. Disabled until one is chosen. */
|
|
434
|
+
declare function useTelevetSlots(clinicianId: string | null, controller: TelevetBookingController | null): TelevetRead<readonly TelevetSlot[]>;
|
|
435
|
+
/**
|
|
436
|
+
* The soonest opening across ALL clinicians, for the no-slots state only.
|
|
437
|
+
*
|
|
438
|
+
* Read UNCONDITIONALLY rather than lazily on the empty case: it is a cheap cross-clinician lookup, and
|
|
439
|
+
* fetching it only after discovering the grid is empty would make the useful half of that state arrive a
|
|
440
|
+
* round-trip after the disappointing half.
|
|
441
|
+
*/
|
|
442
|
+
declare function useTelevetNextSlot(controller: TelevetBookingController | null): TelevetRead<TelevetSlot | null>;
|
|
443
|
+
/** Take the slot. The server requires a hold before a booking or a reschedule. */
|
|
444
|
+
declare function useTelevetHoldSlot(controller: TelevetBookingController | null): TelevetWrite<[slotId: string], TelevetSlotHold>;
|
|
445
|
+
/** Create the consult. */
|
|
446
|
+
declare function useTelevetBookConsult(controller: TelevetBookingController | null): TelevetWrite<[body: TelevetBookingBody, idempotencyKey: string], TelevetConsult>;
|
|
447
|
+
/** Move an existing consult to an already-held slot. */
|
|
448
|
+
declare function useTelevetRescheduleConsult(consultId: string | null, controller: TelevetBookingController | null): TelevetWrite<[slotId: string], TelevetConsult>;
|
|
449
|
+
|
|
450
|
+
type TelevetBookingRefusal =
|
|
451
|
+
/** Triage flagged an emergency. Carries `categories`. MUST show the warning. */
|
|
452
|
+
{
|
|
453
|
+
readonly kind: 'emergency';
|
|
454
|
+
readonly categories: readonly string[];
|
|
455
|
+
}
|
|
456
|
+
/** No live paid subscription (402). Deterministic: never invite a retry. */
|
|
457
|
+
| {
|
|
458
|
+
readonly kind: 'not_entitled';
|
|
459
|
+
}
|
|
460
|
+
/** The slot went, or the hold lapsed. Re-fetch the grid. */
|
|
461
|
+
| {
|
|
462
|
+
readonly kind: 'slot_taken';
|
|
463
|
+
}
|
|
464
|
+
/** That clinician cannot host this consult. Pick another; a different TIME refuses again. */
|
|
465
|
+
| {
|
|
466
|
+
readonly kind: 'clinician_unavailable';
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Too many attempts. Distinct from `failed` because the remedy is WAITING, and `failed` invites an immediate
|
|
470
|
+
* retry that fails again and, on a fixed window, can push the reset further out. Carries the server's own
|
|
471
|
+
* wait hint when it sends one.
|
|
472
|
+
*/
|
|
473
|
+
| {
|
|
474
|
+
readonly kind: 'rate_limited';
|
|
475
|
+
readonly retryAfterSeconds: number | null;
|
|
476
|
+
/**
|
|
477
|
+
* The SERVER'S OWN wording, when it sends any.
|
|
478
|
+
*
|
|
479
|
+
* Carried rather than replaced with a string written here: a wait message is the server's to phrase, it
|
|
480
|
+
* can change without an app release, and this SDK does not author user-facing copy. Null renders no line
|
|
481
|
+
* at all rather than a placeholder.
|
|
482
|
+
*/
|
|
483
|
+
readonly message: string | null;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* The partner booking surface is not served for this tenant (404), so no request on it can succeed.
|
|
487
|
+
*
|
|
488
|
+
* NOT IN THE CONSUMER'S UNION, and it is the one member the port adds. The consumer app talks to its own
|
|
489
|
+
* consumer surface, which is either on or dark for everybody; a PARTNER integration can have vet visits
|
|
490
|
+
* granted and the in-app booking routes withheld, and the remedy there is the hosted handoff rather than any
|
|
491
|
+
* retry. Folding it into `failed` would offer a retry that can never work.
|
|
492
|
+
*/
|
|
493
|
+
| {
|
|
494
|
+
readonly kind: 'unavailable';
|
|
495
|
+
}
|
|
496
|
+
/** Anything else, including a transport failure. A retry is reasonable. */
|
|
497
|
+
| {
|
|
498
|
+
readonly kind: 'failed';
|
|
499
|
+
};
|
|
500
|
+
declare function televetBookingRefusal(error: EverfurError): TelevetBookingRefusal;
|
|
501
|
+
|
|
502
|
+
/** The platform-fixed consult length. */
|
|
503
|
+
declare const CONSULT_MINUTES = 10;
|
|
504
|
+
/**
|
|
505
|
+
* "9:20 PM - 9:30 PM EDT", the visit's bracket, zone-qualified.
|
|
506
|
+
*
|
|
507
|
+
* THE END TIME IS DERIVED, not served: a consult response carries `scheduled_at` only, and the platform fixes
|
|
508
|
+
* the consult at `CONSULT_MINUTES`. Falls back to the bare bracket when the zone cannot be named.
|
|
509
|
+
*/
|
|
510
|
+
declare function formatVisitRange(iso: string): string;
|
|
511
|
+
/** "August 20, 9:20 PM EDT". */
|
|
512
|
+
declare function formatWhen(iso: string): string;
|
|
513
|
+
/**
|
|
514
|
+
* "Wed, August 20, 9:20 PM EDT". The booking confirmation only.
|
|
515
|
+
*
|
|
516
|
+
* The weekday is computed from the SAME instant in the SAME zone as the clock beside it, so the two cannot
|
|
517
|
+
* disagree.
|
|
518
|
+
*/
|
|
519
|
+
declare function formatWhenWithDay(iso: string): string;
|
|
520
|
+
|
|
521
|
+
declare const TELEVET_BOOKING_COPY: Readonly<{
|
|
522
|
+
stateBlockedTitle: string;
|
|
523
|
+
noCliniciansTitle: string;
|
|
524
|
+
/** WHY, not just "none". An empty roster is a real, temporary answer. */
|
|
525
|
+
noCliniciansBody: string;
|
|
526
|
+
noCliniciansRetryCta: string;
|
|
527
|
+
/** The matched vet, not a roster. */
|
|
528
|
+
yourVetTitle: string;
|
|
529
|
+
/** Suffix on the star line: "5.0 · 774 reviews". */
|
|
530
|
+
reviewsLabel: string;
|
|
531
|
+
rescheduleFromTemplate: string;
|
|
532
|
+
rescheduleFailed: string;
|
|
533
|
+
keepExistingCta: string;
|
|
534
|
+
bookingPausedTitle: string;
|
|
535
|
+
slotsErrorTitle: string;
|
|
536
|
+
noSlotsTitle: string;
|
|
537
|
+
/** The cross-clinician next opening, shown UNDER `noSlotsTitle`. `{when}` is DATA. */
|
|
538
|
+
nextOpeningTemplate: string;
|
|
539
|
+
/** The row that acts on it. Returns the owner to the clinician step. */
|
|
540
|
+
seeOtherVetsCta: string;
|
|
541
|
+
retryCta: string;
|
|
542
|
+
/** The hold lapsed while the owner was on a later step. */
|
|
543
|
+
holdExpired: string;
|
|
544
|
+
slotTaken: string;
|
|
545
|
+
reasonPlaceholder: string;
|
|
546
|
+
reasonTooLong: string;
|
|
547
|
+
/** Default OFF: sharing a pet's medical history is opt-in, and it is revocable afterwards. */
|
|
548
|
+
shareRecordsOff: string;
|
|
549
|
+
confirmNotEntitled: string;
|
|
550
|
+
confirmFailed: string;
|
|
551
|
+
navTitle: string;
|
|
552
|
+
/** The chrome must not say "Book a visit" while the user is moving one they already have. */
|
|
553
|
+
rescheduleNavTitle: string;
|
|
554
|
+
close: string;
|
|
555
|
+
continueCta: string;
|
|
556
|
+
petSelectTitle: string;
|
|
557
|
+
addPetCta: string;
|
|
558
|
+
locationUnknownTitle: string;
|
|
559
|
+
locationUnknownBody: string;
|
|
560
|
+
locationUnknownCta: string;
|
|
561
|
+
locationBlockedTitle: string;
|
|
562
|
+
locationBlockedBody: string;
|
|
563
|
+
locationBlockedCta: string;
|
|
564
|
+
/** A real coordinate the host could not name. Retrying will not help. */
|
|
565
|
+
locationUnavailableTitle: string;
|
|
566
|
+
locationUnavailableBody: string;
|
|
567
|
+
stateAttestTemplate: string;
|
|
568
|
+
describeHeading: string;
|
|
569
|
+
describeHelpLong: string;
|
|
570
|
+
addPhotoCta: string;
|
|
571
|
+
removePhotoLabel: string;
|
|
572
|
+
summaryPet: string;
|
|
573
|
+
summaryVet: string;
|
|
574
|
+
summaryWhen: string;
|
|
575
|
+
summaryLength: string;
|
|
576
|
+
summaryReason: string;
|
|
577
|
+
/** "10 minutes" as a DERIVED fact: `{n}` is filled from `CONSULT_MINUTES` so the two cannot drift. */
|
|
578
|
+
summaryLengthTemplate: string;
|
|
579
|
+
confirmCta: string;
|
|
580
|
+
bookedTitle: string;
|
|
581
|
+
addToCalendarCta: string;
|
|
582
|
+
doneCta: string;
|
|
583
|
+
/** The confirmation's three steps. `{pet}` is DATA. */
|
|
584
|
+
booked: Readonly<{
|
|
585
|
+
remindPromise: string;
|
|
586
|
+
summaryPromise: string;
|
|
587
|
+
joinPromise: string;
|
|
588
|
+
backToPet: string;
|
|
589
|
+
calendarAdded: string;
|
|
590
|
+
calendarFailedBody: string;
|
|
591
|
+
}>;
|
|
592
|
+
/**
|
|
593
|
+
* THE FLOW CHROME, not a step: the shell every step renders inside, the discard guard, the hint on Close,
|
|
594
|
+
* and the states shown before any step screen has something to draw.
|
|
595
|
+
*
|
|
596
|
+
* `navTitle` and `close` are deliberately NOT duplicated here. The chrome reads the keys the flow already
|
|
597
|
+
* owns, so approving the bar's wording is one edit, not two that can drift apart.
|
|
598
|
+
*/
|
|
599
|
+
chrome: Readonly<{
|
|
600
|
+
/** Announced after "Close", so a screen reader hears what the press costs. */
|
|
601
|
+
closeHint: string;
|
|
602
|
+
discardTitle: string;
|
|
603
|
+
discardBody: string;
|
|
604
|
+
discardConfirmCta: string;
|
|
605
|
+
discardKeepCta: string;
|
|
606
|
+
noPetsTitle: string;
|
|
607
|
+
loadFailedTitle: string;
|
|
608
|
+
retryCta: string;
|
|
609
|
+
}>;
|
|
610
|
+
/**
|
|
611
|
+
* The emergency refusal. This is the one screen on the surface that interrupts.
|
|
612
|
+
*
|
|
613
|
+
* WHAT IS DELIBERATELY MISSING, in the consumer and here: the three exit rows (find an ER, poison control,
|
|
614
|
+
* call the primary vet). Those need a dialled number and the pet's primary vet, and NO number may be
|
|
615
|
+
* invented for a screen an owner reads in an emergency. The warning and the acknowledgement are wired; the
|
|
616
|
+
* exits are a separate build with real data behind them.
|
|
617
|
+
*/
|
|
618
|
+
emergency: Readonly<{
|
|
619
|
+
bannerTitle: string;
|
|
620
|
+
keepBookingCta: string;
|
|
621
|
+
lede: string;
|
|
622
|
+
}>;
|
|
623
|
+
/** The calendar entry's own title, from the consumer's `visit` block. */
|
|
624
|
+
visit: Readonly<{
|
|
625
|
+
title: string;
|
|
626
|
+
}>;
|
|
627
|
+
/**
|
|
628
|
+
* THE SPOKEN NAME OF EACH LOADING REGION, AND THE SPOKEN POSITION OF THE STEP RAIL.
|
|
629
|
+
*
|
|
630
|
+
* ── WHY THESE EXIST AT ALL ───────────────────────────────────────────────────────────────────────────
|
|
631
|
+
* Each booking step renders its wait as a `role="progressbar"` container of grey blocks. The blocks are
|
|
632
|
+
* `aria-hidden` (a reader announcing eight rectangles is noise), so the CONTAINER's accessible name is the
|
|
633
|
+
* only thing a screen-reader user is told while the step is loading. Six of these containers shipped with
|
|
634
|
+
* no name at all, which a reader announces as an unnamed busy region: the user hears that something is
|
|
635
|
+
* happening and nothing about what. The records port established the convention this fixes
|
|
636
|
+
* (`DASHBOARD_COPY.loading`, `REQUEST_SCREEN_COPY.loading`, `DEPTH_COPY.loadingTimeline`,
|
|
637
|
+
* `CLINIC_PICKER_COPY.loading`, `SHARE_COPY.loadingLinks`): the name is an `aria-label` sourced from a
|
|
638
|
+
* copy module, phrased as what is being loaded.
|
|
639
|
+
*
|
|
640
|
+
* ── THESE WERE BRACKETED PLACEHOLDERS, AND THEY ARE NOT ANY MORE. WHAT CHANGED IS THE SOURCE ─────────
|
|
641
|
+
* The previous round wrote `[PLACEHOLDER: ...]` here on the reasoning that the consumer booking deck has
|
|
642
|
+
* no loading strings, so there was nothing to port and inventing the words would be this SDK authoring
|
|
643
|
+
* product voice for a partner's customers. The first half of that was simply not measured: the CONSUMER
|
|
644
|
+
* WEB APP has carried both of these strings for months, and the round that bracketed these keys looked at
|
|
645
|
+
* the React Native deck rather than at the web app this surface is a port OF.
|
|
646
|
+
*
|
|
647
|
+
* `everfur-frontend app/product/televet/components/SystemStates.tsx:46`
|
|
648
|
+
* `const LOADING_LABEL_COPY = 'Loading. Nothing to read yet.';`
|
|
649
|
+
* and its own docblock, verbatim: "The written line says that this region is fetching and has nothing
|
|
650
|
+
* to read yet, and it NAMES NO SCREEN, because the default is rendered on five different ones. A caller
|
|
651
|
+
* that knows its surface should pass `label` instead, which is a one-line change at each call site and
|
|
652
|
+
* the reason the prop exists."
|
|
653
|
+
*
|
|
654
|
+
* `everfur-frontend app/product/see-a-vet/copy.ts:194`
|
|
655
|
+
* `progressLabel: (step: number, total: number) => `Step ${step} of ${total}``
|
|
656
|
+
*
|
|
657
|
+
* So the convention the consumer settled is: ONE written sentence for the generic busy region, and a
|
|
658
|
+
* per-surface name where the caller knows its surface. That is what this block now is. Each name is the
|
|
659
|
+
* consumer's own sentence with the surface named, in the consumer's own grammar.
|
|
660
|
+
*
|
|
661
|
+
* ── WHY AUTHORING THESE IS IN SCOPE AND AUTHORING THE REST IS NOT ────────────────────────────────────
|
|
662
|
+
* The consumer copy deck draws this exact fence around this exact category, and the wording is worth
|
|
663
|
+
* quoting because it is the licence under which these five keys are written
|
|
664
|
+
* (`everfur-frontend app/product/see-a-vet/copy.ts:185-189`):
|
|
665
|
+
*
|
|
666
|
+
* "assistive-technology labels: the narrowest category of string it is defensible for an engineer to
|
|
667
|
+
* author, and none of them makes a clinical, urgency or prescribing claim. They still want review
|
|
668
|
+
* before this page is armed."
|
|
669
|
+
*
|
|
670
|
+
* Every value below is a functional name for a region or a position. None names a product, makes a
|
|
671
|
+
* clinical or urgency claim, promises a time, or says anything an owner could act on wrongly. They are
|
|
672
|
+
* what a screen reader says INSTEAD OF SILENCE. The rest of this deck stays draft-ported and the ship
|
|
673
|
+
* gate below still holds it, because a marketing or clinical sentence is a different category and this
|
|
674
|
+
* fence is the reason the two can be told apart.
|
|
675
|
+
*/
|
|
676
|
+
loading: Readonly<{
|
|
677
|
+
/**
|
|
678
|
+
* The pet step's roster read.
|
|
679
|
+
*
|
|
680
|
+
* "Pets" and not "Your pets": the host supplies the account, and on a partner's multi-pet dashboard the
|
|
681
|
+
* surface may be mounted for a household rather than for one person. The consumer's own default names
|
|
682
|
+
* no owner for the same reason it names no screen.
|
|
683
|
+
*/
|
|
684
|
+
pets: "Loading pets. Nothing to read yet.";
|
|
685
|
+
/** The clinician step's roster read. "Vets", the word every consumer frame uses for this list. */
|
|
686
|
+
clinicians: "Loading vets. Nothing to read yet.";
|
|
687
|
+
/**
|
|
688
|
+
* The slot step's availability read, and the reschedule screen's own slot read.
|
|
689
|
+
*
|
|
690
|
+
* "Times" rather than "availability" or "slots": `3668:5240` is headed "Pick a date and time", so this
|
|
691
|
+
* is the word the owner has just read on the screen the wait belongs to.
|
|
692
|
+
*/
|
|
693
|
+
slots: "Loading times. Nothing to read yet.";
|
|
694
|
+
/** The reschedule screen waiting for the consult it is moving. "Visit", as `visit.title` already says. */
|
|
695
|
+
consult: "Loading your visit. Nothing to read yet.";
|
|
696
|
+
/**
|
|
697
|
+
* THE STEP RAIL'S SPOKEN POSITION, and it is a TEMPLATE rather than a name, because the consumer does
|
|
698
|
+
* not name this region at all.
|
|
699
|
+
*
|
|
700
|
+
* `FunnelProgress` (`everfur-frontend app/product/televet/components/BookingFunnel.tsx:126-141`) draws
|
|
701
|
+
* the rail as `aria-hidden` bars beside ONE `sr-only` paragraph reading
|
|
702
|
+
* `intakeSystemCopy.progressLabel(current, total)`, and its docblock states the rule: "It is a labelled
|
|
703
|
+
* group, not decoration: the position is stated in text for assistive technology, in the intake's own
|
|
704
|
+
* words, and the bars are `aria-hidden` so nothing reads eight empty items after it."
|
|
705
|
+
*
|
|
706
|
+
* A `progressbar` with a value and a region NAME is a different announcement from the consumer's: the
|
|
707
|
+
* reader says the name, then "4 of 6", which is two utterances for one fact and neither of them is the
|
|
708
|
+
* sentence the consumer app says. So the web chrome now carries the consumer's sentence, filled with the
|
|
709
|
+
* step and the total, and `{step}` / `{total}` are DATA through `fill`.
|
|
710
|
+
*/
|
|
711
|
+
progressTemplate: "Step {step} of {total}";
|
|
712
|
+
}>;
|
|
713
|
+
}>;
|
|
714
|
+
type TelevetBookingCopy = typeof TELEVET_BOOKING_COPY;
|
|
715
|
+
/**
|
|
716
|
+
* THE SHIP GATE. False while the deck is unapproved OR any value is still a bracketed placeholder, so a
|
|
717
|
+
* partial approval cannot half-ship. Deliberately blunt: the failure it prevents is a partner's user reading
|
|
718
|
+
* a string Everfur drafted for its own app and never signed off for someone else's.
|
|
719
|
+
*
|
|
720
|
+
* BOTH CONDITIONS ARE STILL CHECKED EVEN THOUGH ONE OF THEM NOW HAS NOTHING TO FIND. The placeholder scan
|
|
721
|
+
* finds no placeholder in the deck today, which is the point of the accessibility names having landed; it
|
|
722
|
+
* stays because the next string added here is as likely to be a bracket as not, and a gate deleted once it
|
|
723
|
+
* passes is a gate that was never load-bearing. `TELEVET_BOOKING_COPY_APPROVED` is the condition holding the
|
|
724
|
+
* screens dark now, and its own note says why that is the honest answer rather than a leftover.
|
|
725
|
+
*
|
|
726
|
+
* THIS IS LOAD-BEARING, not advisory. `EverfurTelevetBooking`, `EverfurTelevetReschedule` and
|
|
727
|
+
* `TelevetBookedScreen` each refuse to render their ported screens while it answers false, and hand over to
|
|
728
|
+
* the hosted visit instead. See `tests/component/televetCopyGate.test.tsx`, which mounts them and pins it.
|
|
729
|
+
*/
|
|
730
|
+
declare function isTelevetBookingCopyReady(): boolean;
|
|
731
|
+
|
|
732
|
+
export { useTelevetBookingEntitlement as $, type TelevetWrite as A, attestation as B, CANCELLATION_POLICY_VERSION_MAX as C, canConfirm as D, createTelevetBookingController as E, currentStep as F, emptyTelevetDraft as G, formatVisitRange as H, formatWhen as I, formatWhenWithDay as J, hasPreviousStep as K, initialTelevetBookingState as L, MEDIA_REFS_MAX as M, isHoldExpired as N, isSkipped as O, isTelevetBookingCopyReady as P, isWellFormedStateCode as Q, REASON_TEXT_MAX as R, televetBookingKey as S, type TelevetConsult as T, televetBookingReducer as U, televetBookingRefusal as V, televetHoldCall as W, televetRescheduleCall as X, useTelevetBookConsult as Y, useTelevetBookingAvailable as Z, useTelevetBookingController as _, type TelevetBookingStep as a, useTelevetCancellationPolicy as a0, useTelevetClinicians as a1, useTelevetHoldSlot as a2, useTelevetNextSlot as a3, useTelevetRescheduleConsult as a4, useTelevetSlots as a5, useTelevetStatePolicy as a6, validateBookingBody as a7, type TelevetBookingController as b, type TelevetSlot as c, CONSULT_KINDS as d, CONSULT_MINUTES as e, CONSULT_STATUSES as f, type ConsultKind as g, type ConsultStatus as h, TELEVET_BOOKING_BASE as i, TELEVET_BOOKING_COPY as j, TELEVET_BOOKING_STEPS as k, TERMINAL_CONSULT_STATUSES as l, type TelevetBookingAction as m, type TelevetBookingBody as n, type TelevetBookingContext as o, type TelevetBookingControllerDeps as p, type TelevetBookingCopy as q, type TelevetBookingDraft as r, type TelevetBookingEntitlement as s, type TelevetBookingRefusal as t, type TelevetBookingState as u, type TelevetCancellationPolicy as v, type TelevetClinician as w, type TelevetRead as x, type TelevetSlotHold as y, type TelevetStatePolicy as z };
|