@everfur/sdk 0.4.0 → 0.5.1
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 +220 -0
- package/README.md +9 -8
- package/dist/{Chat-BZZ-Py5l.d.ts → Chat-Rzplrf5M.d.ts} +17 -3
- package/dist/{Chat-Dq4fffIO.d.cts → Chat-ypo6miKm.d.cts} +17 -3
- package/dist/{DepthViews-BG3E25MD.d.ts → DepthViews-CeTfPUBX.d.ts} +1 -1
- package/dist/{DepthViews-B_hIypI6.d.cts → DepthViews-ClykXOJj.d.cts} +1 -1
- package/dist/{DepthViews-CL75jyRA.d.cts → DepthViews-Cui3oonj.d.cts} +1 -1
- package/dist/{DepthViews-CkYri51q.d.ts → DepthViews-baYLMNQ-.d.ts} +1 -1
- package/dist/{ErrorPolicyPort-CwbfmxzJ.d.ts → ErrorPolicyPort-D22LUVrK.d.ts} +1 -1
- package/dist/{ErrorPolicyPort-CNf4uQZP.d.cts → ErrorPolicyPort-D6CybiqJ.d.cts} +1 -1
- package/dist/{EverfurResult-DN9pL2Ab.d.cts → EverfurError-DmELDpXp.d.cts} +1 -67
- package/dist/{EverfurResult-DN9pL2Ab.d.ts → EverfurError-DmELDpXp.d.ts} +1 -67
- package/dist/EverfurResult-SGvHKsCB.d.ts +69 -0
- package/dist/EverfurResult-ZtH-YV1h.d.cts +69 -0
- package/dist/animations/index.cjs +1 -1
- package/dist/animations/index.d.cts +6 -5
- package/dist/animations/index.d.ts +6 -5
- package/dist/animations/index.js +1 -1
- package/dist/{attachments-D_SECjr1.d.cts → attachments-CwsR-bPN.d.cts} +7 -6
- package/dist/{attachments-BrUWQYNK.d.ts → attachments-CzZ7in24.d.ts} +7 -6
- package/dist/{attachments-DpldrvIW.d.ts → attachments-D3HCBmOE.d.ts} +3 -3
- package/dist/{attachments-BorG422I.d.cts → attachments-Nk73Lll8.d.cts} +3 -3
- package/dist/{bookingCopy-SREvkG19.d.cts → bookingCopy-Dv8rKqyV.d.cts} +417 -14
- package/dist/{bookingCopy-CqtDYvCR.d.ts → bookingCopy-SDkXaxDf.d.ts} +417 -14
- package/dist/branding-Xb_wL8N1.d.cts +212 -0
- package/dist/branding-xpQ056sM.d.ts +212 -0
- package/dist/callCopy-rDH9JTFo.d.cts +45 -0
- package/dist/callCopy-rDH9JTFo.d.ts +45 -0
- package/dist/callRoom-7wrE3RP2.d.ts +62 -0
- package/dist/callRoom-B_EqaUzx.d.cts +62 -0
- package/dist/{casesRepository-v6QczS9N.d.ts → casesRepository-BTAecTnF.d.ts} +14 -2
- package/dist/{casesRepository-DwtZVsbj.d.cts → casesRepository-aryld7fJ.d.cts} +14 -2
- package/dist/chat/index.cjs +1 -1
- package/dist/chat/index.d.cts +12 -11
- package/dist/chat/index.d.ts +12 -11
- package/dist/chat/index.js +1 -1
- package/dist/client/index.cjs +5 -5
- package/dist/client/index.d.cts +14 -12
- package/dist/client/index.d.ts +14 -12
- package/dist/client/index.js +5 -5
- package/dist/{config-C7eb_IMD.d.ts → config-6qS7Sohy.d.cts} +3 -2
- package/dist/{config--Wu1Umhd.d.cts → config-X6BtwDwQ.d.ts} +3 -2
- package/dist/consent/index.cjs +1 -1
- package/dist/consent/index.d.cts +9 -8
- package/dist/consent/index.d.ts +9 -8
- package/dist/consent/index.js +1 -1
- package/dist/{context-CahAEha8.d.ts → context-7f3Nb_xE.d.ts} +9 -8
- package/dist/{context-CL3lyuy1.d.cts → context-CkqPM4Ml.d.cts} +9 -8
- package/dist/{copy-UeUJVk8X.d.cts → copy-Bd__Pw5s.d.cts} +5 -4
- package/dist/{copy-DdVFDL01.d.ts → copy-NgKgOOET.d.ts} +5 -4
- package/dist/core/index.cjs +9 -9
- package/dist/core/index.d.cts +19 -17
- package/dist/core/index.d.ts +19 -17
- package/dist/core/index.js +9 -9
- package/dist/{depth-DvPwPuT_.d.ts → depth-CYPH92jE.d.ts} +6 -5
- package/dist/{depth-D5HwcvKC.d.cts → depth-CyjaJJ6V.d.cts} +6 -5
- package/dist/{entitlementRepository-B7egEdW6.d.ts → entitlementRepository-DdeFuEKp.d.ts} +4 -4
- package/dist/{entitlementRepository-BpJ7tiwl.d.cts → entitlementRepository-Dl1qRLcJ.d.cts} +4 -4
- package/dist/{identity-C2-08BZW.d.cts → identity-DjqhDm5Z.d.cts} +2 -2
- package/dist/{identity-CEi9GRFZ.d.ts → identity-Dy_L7Yq4.d.ts} +2 -2
- package/dist/index.cjs +6 -6
- package/dist/index.d.cts +19 -17
- package/dist/index.d.ts +19 -17
- package/dist/index.js +6 -6
- package/dist/{models-D2EUxPZY.d.cts → models-Bn2z0NNo.d.cts} +1 -1
- package/dist/{models-B-Uh2LTf.d.ts → models-DSqA5Ahs.d.ts} +1 -1
- package/dist/notifications/index.cjs +2 -2
- package/dist/notifications/index.d.cts +5 -4
- package/dist/notifications/index.d.ts +5 -4
- package/dist/notifications/index.js +2 -2
- package/dist/{pets-JVCXgRgR.d.cts → pets-BSG2qbr_.d.cts} +2 -2
- package/dist/{pets-DJv2sj2H.d.ts → pets-D7cZutrX.d.ts} +2 -2
- package/dist/{petsRepository-B_gKbAzJ.d.cts → petsRepository-D1bnxDZg.d.cts} +2 -2
- package/dist/{petsRepository-Bk6GDwLs.d.ts → petsRepository-DhsX3GLw.d.ts} +2 -2
- package/dist/photo/index.cjs +1 -1
- package/dist/photo/index.d.cts +3 -2
- package/dist/photo/index.d.ts +3 -2
- package/dist/photo/index.js +1 -1
- package/dist/{ports-D7YW8qz9.d.ts → ports-C0m1G1fS.d.ts} +13 -6
- package/dist/{ports-BY2ph0_y.d.cts → ports-DNXyyzZF.d.cts} +13 -6
- package/dist/records/depth/index.cjs +2 -2
- package/dist/records/depth/index.d.cts +11 -10
- package/dist/records/depth/index.d.ts +11 -10
- package/dist/records/depth/index.js +2 -2
- package/dist/records/index.cjs +3 -3
- package/dist/records/index.d.cts +25 -14
- package/dist/records/index.d.ts +25 -14
- package/dist/records/index.js +3 -3
- package/dist/{requestFunnel-BjDpqqvm.d.cts → requestFunnel-Bqc1inM9.d.cts} +5 -4
- package/dist/{requestFunnel-DFMGcluw.d.ts → requestFunnel-FvE5yLDD.d.ts} +5 -4
- package/dist/{runtimeTypes-w5KqBMcs.d.ts → runtimeTypes-C0yPBz89.d.ts} +7 -7
- package/dist/{runtimeTypes-gZEJu-da.d.cts → runtimeTypes-RN-VXTFV.d.cts} +7 -7
- package/dist/server/events/index.cjs +1 -1
- package/dist/server/events/index.d.cts +4 -3
- package/dist/server/events/index.d.ts +4 -3
- package/dist/server/events/index.js +1 -1
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.d.cts +5 -4
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.js +1 -1
- package/dist/televet/booking/index.cjs +1 -1
- package/dist/televet/booking/index.d.cts +310 -32
- package/dist/televet/booking/index.d.ts +310 -32
- package/dist/televet/booking/index.js +1 -1
- package/dist/televet/call/index.cjs +1 -1
- package/dist/televet/call/index.d.cts +25 -5
- package/dist/televet/call/index.d.ts +25 -5
- package/dist/televet/call/index.js +1 -1
- package/dist/televet/index.cjs +1 -1
- package/dist/televet/index.d.cts +41 -71
- package/dist/televet/index.d.ts +41 -71
- package/dist/televet/index.js +1 -1
- package/dist/televetGlobal-CEk0_cW9.d.cts +34 -0
- package/dist/televetGlobal-Cs9Wbqsy.d.ts +34 -0
- package/dist/testing/index.cjs +3 -3
- package/dist/testing/index.d.cts +3 -2
- package/dist/testing/index.d.ts +3 -2
- package/dist/testing/index.js +3 -3
- package/dist/testing/rn/index.cjs +1 -1
- package/dist/testing/rn/index.d.cts +13 -11
- package/dist/testing/rn/index.d.ts +13 -11
- package/dist/testing/rn/index.js +1 -1
- package/dist/testing/web/index.cjs +1 -1
- package/dist/testing/web/index.d.cts +14 -13
- package/dist/testing/web/index.d.ts +14 -13
- package/dist/testing/web/index.js +1 -1
- package/dist/{timelineRows-C15jxFFH.d.ts → timelineRows-D4U6A8zE.d.ts} +1 -1
- package/dist/{timelineRows-odO8g9r2.d.cts → timelineRows-DAB5dpjF.d.cts} +1 -1
- package/dist/{branding-CsRdeNwK.d.cts → tokens-CIngRkvt.d.cts} +7 -211
- package/dist/{branding-CsRdeNwK.d.ts → tokens-CIngRkvt.d.ts} +7 -211
- package/dist/{typeStyle-DmoyacDG.d.ts → typeStyle-DHJzDaUo.d.cts} +2 -1
- package/dist/{typeStyle-CKqVYD6L.d.cts → typeStyle-YPS_MXeI.d.ts} +2 -1
- package/dist/{useRecordsDepth-crhBllQK.d.ts → useRecordsDepth--ObtMyjH.d.ts} +24 -5
- package/dist/{useRecordsDepth-C6rjEaLn.d.cts → useRecordsDepth-B35y8bV-.d.cts} +24 -5
- package/dist/{useVetVisit-CjmMa896.d.ts → useVetVisit-BsjoDO-n.d.ts} +21 -6
- package/dist/{useVetVisit-Bc84hWUU.d.cts → useVetVisit-Ds8f1peV.d.cts} +21 -6
- package/dist/video/index.cjs +1 -1
- package/dist/video/index.d.cts +3 -2
- package/dist/video/index.d.ts +3 -2
- package/dist/video/index.js +1 -1
- package/dist/{view-DyitEO0m.d.cts → view-B-Toym_j.d.cts} +5 -4
- package/dist/{view-Bxwxp4xD.d.ts → view-D9JqNQai.d.ts} +5 -4
- package/dist/web/consent/index.cjs +1 -1
- package/dist/web/consent/index.d.cts +9 -8
- package/dist/web/consent/index.d.ts +9 -8
- package/dist/web/consent/index.js +1 -1
- package/dist/web/index.cjs +10 -10
- package/dist/web/index.d.cts +42 -19
- package/dist/web/index.d.ts +42 -19
- package/dist/web/index.js +10 -10
- package/dist/web/notifications/index.cjs +2 -2
- package/dist/web/notifications/index.d.cts +7 -6
- package/dist/web/notifications/index.d.ts +7 -6
- package/dist/web/notifications/index.js +2 -2
- package/dist/web/records/depth/index.cjs +2 -2
- package/dist/web/records/depth/index.d.cts +11 -10
- package/dist/web/records/depth/index.d.ts +11 -10
- package/dist/web/records/depth/index.js +2 -2
- package/dist/web/records/index.cjs +3 -3
- package/dist/web/records/index.d.cts +53 -35
- package/dist/web/records/index.d.ts +53 -35
- package/dist/web/records/index.js +3 -3
- package/dist/web/televet/booking/index.cjs +2 -1
- package/dist/web/televet/booking/index.d.cts +458 -33
- package/dist/web/televet/booking/index.d.ts +458 -33
- package/dist/web/televet/booking/index.js +2 -1
- package/dist/web/televet/call/index.cjs +1 -1
- package/dist/web/televet/call/index.d.cts +3 -1
- package/dist/web/televet/call/index.d.ts +3 -1
- package/dist/web/televet/call/index.js +1 -1
- package/dist/web/televet/index.cjs +1 -1
- package/dist/web/televet/index.d.cts +40 -74
- package/dist/web/televet/index.d.ts +40 -74
- package/dist/web/televet/index.js +1 -1
- package/package.json +3 -2
- package/dist/callCopy-DoQKG3-L.d.cts +0 -40
- package/dist/callCopy-DoQKG3-L.d.ts +0 -40
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { E as EverfurError } from './EverfurError-DmELDpXp.js';
|
|
2
|
+
import { E as EverfurResult } from './EverfurResult-SGvHKsCB.js';
|
|
3
|
+
import { R as RequestFunnel } from './requestFunnel-FvE5yLDD.js';
|
|
4
|
+
import { A as AuthContext } from './identity-Dy_L7Yq4.js';
|
|
5
|
+
import { E as ErrorPolicyPort } from './ErrorPolicyPort-D22LUVrK.js';
|
|
5
6
|
import { T as TelemetryPort } from './TelemetryPort-BDNr00hu.js';
|
|
7
|
+
import { b as VetCallCredential, c as VetCallJoinRefusal } from './callRoom-7wrE3RP2.js';
|
|
6
8
|
|
|
7
9
|
/** The consult lifecycle, as the platform names it. `unknown` for a status this SDK build has not heard of. */
|
|
8
10
|
declare const CONSULT_STATUSES: readonly ["scheduled", "in_progress", "awaiting_summary", "completed", "cancelled_owner", "cancelled_ops", "no_show_owner", "no_show_vet"];
|
|
@@ -89,6 +91,13 @@ interface TelevetConsult {
|
|
|
89
91
|
readonly kind: ConsultKind;
|
|
90
92
|
readonly scheduledAt: string;
|
|
91
93
|
readonly emergencyFlagged: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Has the visit's video room been created? Read from the presence of `meeting_url`, which is the same
|
|
96
|
+
* signal the backend's `assert_joinable` checks; the URL itself is NOT kept, because the room credential
|
|
97
|
+
* is minted by the join and a list read is the last place to hold a link to a recorded clinical room.
|
|
98
|
+
* False moments after booking, while the provisioning outbox drains.
|
|
99
|
+
*/
|
|
100
|
+
readonly hasRoom: boolean;
|
|
92
101
|
}
|
|
93
102
|
/** The televet entitlement verdict. True only for a live PAID subscription; promo and trial are not enough. */
|
|
94
103
|
interface TelevetBookingEntitlement {
|
|
@@ -162,6 +171,26 @@ declare const REASON_TEXT_MAX = 2000;
|
|
|
162
171
|
declare const MEDIA_REFS_MAX = 10;
|
|
163
172
|
/** A two-letter US state code, the only shape the booking wire accepts for `state`. */
|
|
164
173
|
declare function isWellFormedStateCode(state: string | null | undefined): boolean;
|
|
174
|
+
/**
|
|
175
|
+
* What cancelling cost, as the server recorded it (`CancelConsultResponse`).
|
|
176
|
+
*
|
|
177
|
+
* `summary` IS THE SERVER'S SENTENCE, rendered verbatim: it is derived from the amount the cancel transaction
|
|
178
|
+
* itself computed, and the backend states the one rule it keeps (a recorded fee is worded as recorded and
|
|
179
|
+
* payable, never as "you will not be charged"). A client-side sentence built from `feeCents` would be a
|
|
180
|
+
* second author for a commercial statement.
|
|
181
|
+
*/
|
|
182
|
+
interface TelevetCancelReceipt {
|
|
183
|
+
/** What was recorded against this cancellation, in cents. Zero inside the free window. */
|
|
184
|
+
readonly feeCents: number;
|
|
185
|
+
/** ISO-4217, lowercase. */
|
|
186
|
+
readonly currency: string;
|
|
187
|
+
/** The flag to branch on, rather than comparing `feeCents` to zero or parsing `summary`. */
|
|
188
|
+
readonly feeRecorded: boolean;
|
|
189
|
+
/** The served sentence for the confirmation. Null when the server sent none; never composed here. */
|
|
190
|
+
readonly summary: string | null;
|
|
191
|
+
}
|
|
192
|
+
/** The server's own bound on a cancellation reason (`PartnerCancelRequest.reason`, 1..240). */
|
|
193
|
+
declare const CANCEL_REASON_MAX = 240;
|
|
165
194
|
|
|
166
195
|
/** The partner booking surface, relative to the API base. One prefix, so a dark tenant is dark for all of it. */
|
|
167
196
|
declare const TELEVET_BOOKING_BASE = "/widget/v1/televet";
|
|
@@ -177,6 +206,20 @@ declare const TELEVET_BOOKING_BASE = "/widget/v1/televet";
|
|
|
177
206
|
declare function televetHoldCall(slotId: string): string;
|
|
178
207
|
/** What a consult reschedule is addressed to. */
|
|
179
208
|
declare function televetRescheduleCall(consultId: string): string;
|
|
209
|
+
/** One consult of this member's. */
|
|
210
|
+
declare function televetConsultCall(consultId: string): string;
|
|
211
|
+
/** What minting the room credential is addressed to. */
|
|
212
|
+
declare function televetJoinCall(consultId: string): string;
|
|
213
|
+
/** What a cancellation is addressed to. */
|
|
214
|
+
declare function televetCancelCall(consultId: string): string;
|
|
215
|
+
/**
|
|
216
|
+
* How many of the member's consults one read asks for: the route's own maximum.
|
|
217
|
+
*
|
|
218
|
+
* The consumer app's reasoning, carried over (everfur-mobile televetApi.ts `listConsults`): the route defaults
|
|
219
|
+
* to 50, answers a bare list with no cursor to resend, and documents its cursor as opaque, so a client can
|
|
220
|
+
* neither page nor mint one. Asking for the maximum is the honest ceiling until the server returns a cursor.
|
|
221
|
+
*/
|
|
222
|
+
declare const TELEVET_CONSULT_PAGE_LIMIT = 100;
|
|
180
223
|
/**
|
|
181
224
|
* The booking port every ported screen reads through.
|
|
182
225
|
*
|
|
@@ -186,9 +229,9 @@ declare function televetRescheduleCall(consultId: string): string;
|
|
|
186
229
|
* route produces.
|
|
187
230
|
*/
|
|
188
231
|
interface TelevetBookingController {
|
|
189
|
-
/** What this US state permits. A dark route
|
|
232
|
+
/** What this US state permits. A dark route settles its 404 as an error, never as a refusal. */
|
|
190
233
|
statePolicy?(state: string, signal?: AbortSignal): Promise<EverfurResult<TelevetStatePolicy>>;
|
|
191
|
-
/** Whether this member's
|
|
234
|
+
/** Whether this member's visit is covered. A dark route settles its 404 as an error, never as `{active: false}`. */
|
|
192
235
|
entitlement?(signal?: AbortSignal): Promise<EverfurResult<TelevetBookingEntitlement>>;
|
|
193
236
|
/**
|
|
194
237
|
* The cancellation terms and their version token. A dark route answers null, and the review screen then
|
|
@@ -213,6 +256,17 @@ interface TelevetBookingController {
|
|
|
213
256
|
book(body: TelevetBookingBody, idempotencyKey: string): Promise<EverfurResult<TelevetConsult>>;
|
|
214
257
|
/** Move an existing consult to an already-held slot. One server operation, not a book-then-cancel. */
|
|
215
258
|
reschedule(consultId: string, slotId: string): Promise<EverfurResult<TelevetConsult>>;
|
|
259
|
+
/** This member's visits, newest first. A dark route answers an empty list. */
|
|
260
|
+
listConsults?(signal?: AbortSignal): Promise<EverfurResult<readonly TelevetConsult[]>>;
|
|
261
|
+
/** One of this member's visits. A 404 is the opaque "not this member's, or dark" answer, and is an error. */
|
|
262
|
+
getConsult?(consultId: string, signal?: AbortSignal): Promise<EverfurResult<TelevetConsult>>;
|
|
263
|
+
/**
|
|
264
|
+
* Mint the room credential for a visit whose join window is open. ONE ATTEMPT: every mint is a new token
|
|
265
|
+
* and, on the clinician's side, a new arrival, so a retry is the member's to ask for.
|
|
266
|
+
*/
|
|
267
|
+
joinConsult?(consultId: string): Promise<EverfurResult<VetCallCredential>>;
|
|
268
|
+
/** Cancel a visit, answering what it cost. `reason` is the member's own words, 1 to 240 characters. */
|
|
269
|
+
cancelConsult?(consultId: string, reason: string): Promise<EverfurResult<TelevetCancelReceipt>>;
|
|
216
270
|
}
|
|
217
271
|
interface TelevetBookingControllerDeps {
|
|
218
272
|
readonly auth: AuthContext;
|
|
@@ -237,7 +291,199 @@ interface TelevetBookingControllerDeps {
|
|
|
237
291
|
declare function validateBookingBody(body: TelevetBookingBody): string | null;
|
|
238
292
|
declare function createTelevetBookingController(deps: TelevetBookingControllerDeps): Required<TelevetBookingController>;
|
|
239
293
|
|
|
240
|
-
|
|
294
|
+
/**
|
|
295
|
+
* The classifier's answer about one piece of free text.
|
|
296
|
+
*
|
|
297
|
+
* TWO FIELDS, AND `fallback` IS NOT A FAILURE. The consumer treats "the classifier could not give a verdict"
|
|
298
|
+
* as an emergency for this purpose, because the booking route refuses it the same way
|
|
299
|
+
* (useEarlyTriage.ts:70: `verdict.isEmergency || verdict.fallback`). A read that never completed is a
|
|
300
|
+
* different thing and is handled by the absence of a verdict, not by a field on one.
|
|
301
|
+
*/
|
|
302
|
+
interface TelevetTriageVerdict {
|
|
303
|
+
readonly isEmergency: boolean;
|
|
304
|
+
/** The classifier ran and declined to decide. Refused like an emergency, by the booking route and here. */
|
|
305
|
+
readonly fallback: boolean;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* The seam the triage read arrives through.
|
|
309
|
+
*
|
|
310
|
+
* A PROMISE THAT RESOLVES TO NULL, NEVER A REJECTION THE CALLER HAS TO CATCH: null means "no verdict" (the
|
|
311
|
+
* route is dark, the request failed, the owner left), which this hook treats as "go on". A host or the
|
|
312
|
+
* controller supplies it; absent, no question is asked.
|
|
313
|
+
*/
|
|
314
|
+
type TelevetTriageRead = (reasonText: string, signal: AbortSignal) => Promise<TelevetTriageVerdict | null>;
|
|
315
|
+
interface TelevetEarlyTriage {
|
|
316
|
+
/** The warning is up. While true the flow must not advance past Describe. */
|
|
317
|
+
readonly open: boolean;
|
|
318
|
+
/** A read is in flight. The Continue control shows it rather than appearing dead. */
|
|
319
|
+
readonly checking: boolean;
|
|
320
|
+
/** True when the flow should go on; false when it must not move (a warning opened, or a read is running). */
|
|
321
|
+
check(reasonText: string): Promise<boolean>;
|
|
322
|
+
/** "I have handled this, keep booking", recorded against the EXACT words it was answered for. */
|
|
323
|
+
acknowledge(reasonText: string): void;
|
|
324
|
+
/** Back from the warning: closes it without recording an acknowledgement. */
|
|
325
|
+
close(): void;
|
|
326
|
+
/** Abort an in-flight read (unmount, or leaving the step). */
|
|
327
|
+
cancel(): void;
|
|
328
|
+
/** A different pet is a different booking: its words are asked about afresh. */
|
|
329
|
+
reset(): void;
|
|
330
|
+
/** Whether these exact words carry an acknowledgement, so the booking body can say so truthfully. */
|
|
331
|
+
isAcknowledged(reasonText: string): boolean;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* The hook. `read` absent (a dark tenant, or a host that wired no seam) means `check` always answers "go on",
|
|
335
|
+
* which is the same behaviour as a read that failed and is deliberately indistinguishable from it.
|
|
336
|
+
*/
|
|
337
|
+
declare function useEarlyTriage(read: TelevetTriageRead | null | undefined): TelevetEarlyTriage;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* The server's own demand bucket. A CLOSED SET, and callers may not substitute free text.
|
|
341
|
+
*
|
|
342
|
+
* THE TWO ARE CLOSED BY DIFFERENT FIXES, which is why the server distinguishes them and why a call site that
|
|
343
|
+
* guesses is wrong in a way nobody can see: `no_licensed_vet` is closed by licensing a clinician in that
|
|
344
|
+
* state, `no_prescribing` by a change in what that state permits remotely. The consumer container is explicit
|
|
345
|
+
* about picking the first for an empty roster and for a blocked state
|
|
346
|
+
* (TelevetBookingContainer.tsx, the `no_licensed_vet, not no_prescribing` comment).
|
|
347
|
+
*/
|
|
348
|
+
type TelevetStateInterestReason = 'no_licensed_vet' | 'no_prescribing';
|
|
349
|
+
/** What the control needs to render its lifecycle. Null means there is nothing to render; see the header. */
|
|
350
|
+
interface TelevetStateInterestAction {
|
|
351
|
+
/** The write SUCCEEDED in this session. Never inferred, never optimistic. */
|
|
352
|
+
readonly joined: boolean;
|
|
353
|
+
readonly pending: boolean;
|
|
354
|
+
readonly failed: boolean;
|
|
355
|
+
onPress(): void;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* The seam the write goes through. Resolves true on a recorded interest and false otherwise; a rejection is
|
|
359
|
+
* caught here and read as false, so a host cannot turn a throw into a silent success.
|
|
360
|
+
*/
|
|
361
|
+
type TelevetStateInterestWrite = (state: string, reason: TelevetStateInterestReason) => Promise<boolean>;
|
|
362
|
+
/**
|
|
363
|
+
* Local, per-mounted-booking feedback for the owner-initiated state-interest write.
|
|
364
|
+
*
|
|
365
|
+
* LOCAL SUCCESS IS DELIBERATELY EPHEMERAL, verbatim from the consumer's reasoning: the server is idempotent,
|
|
366
|
+
* so this only prevents repeat taps in this session and "does not pretend we know the owner's durable
|
|
367
|
+
* subscription state" (useBookingStateInterest.ts:20-25). Nothing here is persisted, because a remembered
|
|
368
|
+
* "you are on the list" that outlived a state change would be a claim this client cannot stand behind.
|
|
369
|
+
*/
|
|
370
|
+
declare function useStateInterest(state: string | null | undefined, write: TelevetStateInterestWrite | null | undefined): {
|
|
371
|
+
actionFor(reason: TelevetStateInterestReason): TelevetStateInterestAction | null;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
/** Why the roster is empty. Closed, because each value picks a different true sentence. */
|
|
375
|
+
type TelevetEmptyRosterCause =
|
|
376
|
+
/** A real, state-scoped read answered a literal empty list. A licensure gap. */
|
|
377
|
+
'roster'
|
|
378
|
+
/** The route is dark for this tenant, so no read happened. Not a licensure fact. */
|
|
379
|
+
| 'dark';
|
|
380
|
+
/** What the empty-roster screen renders. Derived, never chosen at a call site. */
|
|
381
|
+
interface TelevetEmptyRosterView {
|
|
382
|
+
readonly title: string;
|
|
383
|
+
readonly message: string;
|
|
384
|
+
/**
|
|
385
|
+
* The retry label, or null when a retry cannot help.
|
|
386
|
+
*
|
|
387
|
+
* NULL IS LOAD BEARING and is not a styling preference. `TelevetStateCard` renders its action only when a
|
|
388
|
+
* label AND a handler are both present, so a null label removes the control rather than disabling it. A
|
|
389
|
+
* `Check again` on a licensure gap is a button whose every press repeats the same answer.
|
|
390
|
+
*/
|
|
391
|
+
readonly retryLabel: string | null;
|
|
392
|
+
/**
|
|
393
|
+
* Which demand bucket a state-interest write would carry from this screen, or null when interest cannot be
|
|
394
|
+
* offered here.
|
|
395
|
+
*
|
|
396
|
+
* `no_licensed_vet`, NOT `no_prescribing`, and only on the licensure cause. The server treats the two as
|
|
397
|
+
* distinct fixes; this one is closed by licensing a clinician in the state, which is exactly what an empty
|
|
398
|
+
* state-scoped roster reports. Offering interest on the DARK cause would record a demand signal for a
|
|
399
|
+
* state nobody established anything about.
|
|
400
|
+
*/
|
|
401
|
+
readonly interestReason: 'no_licensed_vet' | null;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* The view for an empty roster, from the cause.
|
|
405
|
+
*
|
|
406
|
+
* A PURE FUNCTION over the copy deck, so both platform ports read the same three fields and neither can pick
|
|
407
|
+
* its own sentence. It takes the CAUSE rather than a boolean, because a boolean at a call site is how the
|
|
408
|
+
* dark tenant and the licensure gap got the same words in the first place.
|
|
409
|
+
*/
|
|
410
|
+
declare function televetEmptyRosterView(cause: TelevetEmptyRosterCause): TelevetEmptyRosterView;
|
|
411
|
+
/**
|
|
412
|
+
* The cause, from what the flow knows.
|
|
413
|
+
*
|
|
414
|
+
* `surfaceServed` IS THE CALLER'S ONE FACT: has anything on this booking surface answered a real response?
|
|
415
|
+
* The container derives it from the reads it has already made, and it is deliberately NOT re-derived here
|
|
416
|
+
* from a 404, because `clinicians` has already swallowed that into `ok([])` by the time a screen sees it.
|
|
417
|
+
* That swallow is the right call for rendering and the wrong one for this decision, which is exactly why
|
|
418
|
+
* the fact has to be carried alongside the empty list rather than recovered from it.
|
|
419
|
+
*/
|
|
420
|
+
declare function televetEmptyRosterCause(surfaceServed: boolean): TelevetEmptyRosterCause;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Why a pick was refused before it was ever sent.
|
|
424
|
+
*
|
|
425
|
+
* THE CONSUMER'S OWN THREE BUCKETS, not a set invented here: mobile's `ConsultAttachmentOutcome.refused` and
|
|
426
|
+
* the web app's `ConsultAttachmentRefusal` both carry exactly `size`, `type` and `unreadable`, and each has a
|
|
427
|
+
* ported sentence. A fourth cause with no consumer sentence would have nothing to say, so the type is closed.
|
|
428
|
+
*/
|
|
429
|
+
type TelevetMediaRefusal = 'size' | 'type' | 'unreadable';
|
|
430
|
+
/** Counts of what did not reach the vet, by cause. The consumer web app's `ConsultAttachmentShortfall`. */
|
|
431
|
+
interface TelevetMediaShortfall {
|
|
432
|
+
/** Passed the rules, then the send did not carry it. On this surface that is every pick; see the header. */
|
|
433
|
+
readonly failed: number;
|
|
434
|
+
readonly refused: Readonly<Record<TelevetMediaRefusal, number>>;
|
|
435
|
+
}
|
|
436
|
+
/** Nothing to say. Frozen and shared so a caller cannot mutate the empty case into a false report. */
|
|
437
|
+
declare const NO_MEDIA_SHORTFALL: TelevetMediaShortfall;
|
|
438
|
+
/** True when there is literally nothing to tell the owner. */
|
|
439
|
+
declare function isMediaShortfallEmpty(shortfall: TelevetMediaShortfall): boolean;
|
|
440
|
+
/**
|
|
441
|
+
* One sentence per cause, in the consumer's order, or an empty list when there is nothing to say.
|
|
442
|
+
*
|
|
443
|
+
* THE ORDER IS THE CONSUMER'S AND IS NOT ALPHABETICAL: dropped, then size, then type, then unreadable. Both
|
|
444
|
+
* consumer apps list them that way (MediaDropNotice.tsx:31-36 and consultAttachmentUpload.ts:385-403), which
|
|
445
|
+
* puts the thing that got furthest through the flow first.
|
|
446
|
+
*
|
|
447
|
+
* A NEGATIVE OR NON-FINITE COUNT IS TREATED AS ZERO rather than trusted. These numbers can arrive from a
|
|
448
|
+
* host's own upload seam, and `{n}` is interpolated straight into a sentence an owner reads: "-1 attachment
|
|
449
|
+
* did not upload." is a defect wearing a report. It is floored rather than thrown on, because failing a
|
|
450
|
+
* booking confirmation over a bad count would cost the owner the one screen that tells them anything.
|
|
451
|
+
*/
|
|
452
|
+
declare function televetMediaShortfallLines(shortfall: TelevetMediaShortfall): readonly string[];
|
|
453
|
+
/**
|
|
454
|
+
* The shortfall THIS SURFACE actually has: every pick the owner made, reported as not sent.
|
|
455
|
+
*
|
|
456
|
+
* WHY THIS FUNCTION EXISTS AT ALL, and why it is not a stub for a future upload. The consumer apps derive
|
|
457
|
+
* their shortfall from an upload RESULT. The SDK has no upload: `media_refs` leaves as `[]` whatever the
|
|
458
|
+
* owner picked, and that is a decision with a written reason (no confirmed ref format, no read path, no
|
|
459
|
+
* attachment purpose on the partner plane), not a gap about to close. So the honest count is knowable
|
|
460
|
+
* without a network call: it is the length of the tray.
|
|
461
|
+
*
|
|
462
|
+
* `failed`, NOT A REFUSAL BUCKET. The picks passed every local rule - the row accepted them, capped them at
|
|
463
|
+
* `MEDIA_REFS_MAX` and showed them as thumbnails. Nothing about their size, type or readability is why they
|
|
464
|
+
* did not arrive. "{n} attachments did not upload." is the true sentence; "too large to send" would be a
|
|
465
|
+
* false explanation, and a false explanation invites the owner to re-pick a smaller photo that will be
|
|
466
|
+
* dropped in exactly the same way.
|
|
467
|
+
*
|
|
468
|
+
* IT REPORTS ZERO WHEN THE TRAY IS EMPTY, so the notice mounts unconditionally and renders nothing on the
|
|
469
|
+
* common path, which is the property the consumer component was built around (MediaDropNotice.tsx:19-20).
|
|
470
|
+
*/
|
|
471
|
+
declare function mediaShortfallFromUnsentPicks(pickCount: number): TelevetMediaShortfall;
|
|
472
|
+
/**
|
|
473
|
+
* Add a refusal the ATTACHMENT ROW itself made, so a silently discarded pick is stated.
|
|
474
|
+
*
|
|
475
|
+
* THE ROW ALREADY DISCARDS PICKS AND SAID NOTHING. `IntakeMedia` drops a pick whose uri is already attached
|
|
476
|
+
* and then `.slice(0, MEDIA_REFS_MAX)` cuts whatever is past the cap. Both are correct behaviours and both
|
|
477
|
+
* were silent, so an owner who selected eight photos into a tray with three slots left saw five of them
|
|
478
|
+
* vanish with no explanation. The consumer mobile app's cap refusal is `size`; this one is neither a size
|
|
479
|
+
* nor a type nor an unreadable file, so it is reported as `failed` for the same reason the unsent picks are:
|
|
480
|
+
* it is the only one of the four sentences that is TRUE, and a true vague sentence beats a false precise one.
|
|
481
|
+
*
|
|
482
|
+
* Returns a new object; the input is never mutated (house rule, and these are frozen anyway).
|
|
483
|
+
*/
|
|
484
|
+
declare function withUnsentPicks(shortfall: TelevetMediaShortfall, pickCount: number): TelevetMediaShortfall;
|
|
485
|
+
|
|
486
|
+
type TelevetBookingStep = 'pet' | 'issues' | 'clinician' | 'time' | 'reason' | 'review' | 'booked';
|
|
241
487
|
/**
|
|
242
488
|
* Ordered for the progress rail. `booked` is terminal and counts toward nothing: the flow is over, and
|
|
243
489
|
* including it would show a rail at 6/7 on a screen with no next step.
|
|
@@ -265,6 +511,8 @@ declare const emptyTelevetDraft: TelevetBookingDraft;
|
|
|
265
511
|
interface TelevetBookingContext {
|
|
266
512
|
/** Skips the picker for a single-pet household. */
|
|
267
513
|
readonly ownedPetCount: number;
|
|
514
|
+
/** Shows the issues step. The web flow sets it, mirroring the consumer web funnel; absent, it is skipped. */
|
|
515
|
+
readonly withIssues?: boolean;
|
|
268
516
|
}
|
|
269
517
|
interface TelevetBookingState {
|
|
270
518
|
readonly index: number;
|
|
@@ -366,6 +614,82 @@ declare function attestation(stateAttested: boolean, termsAttested: boolean, pol
|
|
|
366
614
|
readonly cancellation_policy_version: string;
|
|
367
615
|
} | Record<string, never>;
|
|
368
616
|
|
|
617
|
+
/**
|
|
618
|
+
* Why a booking did not complete.
|
|
619
|
+
*
|
|
620
|
+
* DECLARED HERE because this module is what produces every value, and both platform containers re-export it
|
|
621
|
+
* as their own `TelevetBookingFailure` so a host's existing import keeps working. `not_entitled` is separate
|
|
622
|
+
* from `failed` because the two need opposite affordances: a transient failure invites a retry and a 402
|
|
623
|
+
* must not. `unavailable` is separate from both because no retry can succeed.
|
|
624
|
+
*/
|
|
625
|
+
type TelevetBookingFailure = 'taken' | 'expired' | 'failed' | 'not_entitled'
|
|
626
|
+
/** The remedy is a DIFFERENT VET, not a different time: re-picking a slot with the same clinician refuses again. */
|
|
627
|
+
| 'clinician_unavailable'
|
|
628
|
+
/** Per-owner caps. The remedy is WAITING, so this must never render as an invitation to press again. */
|
|
629
|
+
| 'rate_limited'
|
|
630
|
+
/** The partner booking surface is dark here. No retry can fix it, so the flow says so and offers its exit. */
|
|
631
|
+
| 'unavailable' | null;
|
|
632
|
+
|
|
633
|
+
/** How early the join arms, in minutes before `scheduled_at`. Both consumer apps: 15. */
|
|
634
|
+
declare const TELEVET_JOIN_OPENS_MINUTES_BEFORE = 15;
|
|
635
|
+
/** How late the join stays armed, in minutes after `scheduled_at`: 10 minute consult plus a 4 hour grace. */
|
|
636
|
+
declare const TELEVET_JOIN_CLOSES_MINUTES_AFTER = 250;
|
|
637
|
+
/** When the join window opens, as epoch milliseconds; null for an unreadable time. */
|
|
638
|
+
declare function televetJoinOpensAtMs(consult: Pick<TelevetConsult, 'scheduledAt'>): number | null;
|
|
639
|
+
/** The mobile readiness: ready, or why not. */
|
|
640
|
+
type TelevetJoinReadiness = {
|
|
641
|
+
readonly ready: true;
|
|
642
|
+
} | {
|
|
643
|
+
readonly ready: false;
|
|
644
|
+
readonly reason: 'not_open_yet' | 'consult_over';
|
|
645
|
+
};
|
|
646
|
+
/**
|
|
647
|
+
* May the member press Join now? The consumer MOBILE rule, verbatim in order.
|
|
648
|
+
*
|
|
649
|
+
* `in_progress` BEATS THE CLOCK: the server is asserting the call is happening, and refusing on our own
|
|
650
|
+
* arithmetic would lock the member out of a call their vet is sitting in. AN UNREADABLE TIME DOES NOT ARM THE
|
|
651
|
+
* BUTTON: opening a room for a visit whose time we cannot read is worse than a stated "not yet".
|
|
652
|
+
*/
|
|
653
|
+
declare function televetJoinReadiness(consult: TelevetConsult | null, nowMs: number): TelevetJoinReadiness;
|
|
654
|
+
/**
|
|
655
|
+
* Why the web row's Join is dark, in the backend's own vocabulary (`assert_joinable`'s 409 `detail.reason`):
|
|
656
|
+
* `status_{status}` for a visit that is not scheduled or in progress, `room_not_ready` for a visit whose
|
|
657
|
+
* video room has not been created yet, and the two window edges.
|
|
658
|
+
*/
|
|
659
|
+
type TelevetJoinBlock = 'too_early' | 'too_late' | 'room_not_ready' | `status_${string}`;
|
|
660
|
+
type TelevetJoinDecision = {
|
|
661
|
+
readonly joinable: true;
|
|
662
|
+
} | {
|
|
663
|
+
readonly joinable: false;
|
|
664
|
+
readonly reason: TelevetJoinBlock;
|
|
665
|
+
};
|
|
666
|
+
/**
|
|
667
|
+
* May the member press Join now? The consumer WEB rule, which mirrors the backend's order: STATUS FIRST, so a
|
|
668
|
+
* cancelled visit reads as cancelled rather than as "too late"; THE ROOM BEFORE THE WINDOW, so a member who
|
|
669
|
+
* opens the page moments after booking hears that the room is being set up rather than that they are early.
|
|
670
|
+
*/
|
|
671
|
+
declare function televetJoinDecision(consult: TelevetConsult, nowMs: number): TelevetJoinDecision;
|
|
672
|
+
/**
|
|
673
|
+
* The visits, split into what is still ahead and what is over. Both consumer apps' `splitConsults` /
|
|
674
|
+
* `splitVisits`, which agree.
|
|
675
|
+
*
|
|
676
|
+
* A visit is UPCOMING while its status is one the member could still join AND its join window has not
|
|
677
|
+
* closed: the same two facts the Join control reads, so a row can never be joinable and filed under the past
|
|
678
|
+
* at once. `awaiting_summary` is not upcoming: the call has ended. Upcoming is soonest first, because the visit
|
|
679
|
+
* that needs the member next belongs at the top; the past is newest first. An unreadable time sinks to the
|
|
680
|
+
* past rather than corrupting the sort.
|
|
681
|
+
*/
|
|
682
|
+
declare function splitTelevetVisits(consults: readonly TelevetConsult[], nowMs: number): {
|
|
683
|
+
readonly upcoming: readonly TelevetConsult[];
|
|
684
|
+
readonly past: readonly TelevetConsult[];
|
|
685
|
+
};
|
|
686
|
+
/**
|
|
687
|
+
* May the member move or cancel this visit? Only while it is SCHEDULED, which is the backend writer's own
|
|
688
|
+
* lock (`_lock_scheduled`) and both consumer apps' predicate. `awaiting_summary` is non-terminal only because
|
|
689
|
+
* the clinician may still write the record; offering Cancel there invites a refusal for a visit that happened.
|
|
690
|
+
*/
|
|
691
|
+
declare function canManageTelevetVisit(status: ConsultStatus): boolean;
|
|
692
|
+
|
|
369
693
|
/** One read, in the shape the ported screens branch on. */
|
|
370
694
|
interface TelevetRead<T> {
|
|
371
695
|
/** False when the question cannot be asked yet. A disabled read is never pending and never errors. */
|
|
@@ -447,6 +771,23 @@ declare function useTelevetBookConsult(controller: TelevetBookingController | nu
|
|
|
447
771
|
/** Move an existing consult to an already-held slot. */
|
|
448
772
|
declare function useTelevetRescheduleConsult(consultId: string | null, controller: TelevetBookingController | null): TelevetWrite<[slotId: string], TelevetConsult>;
|
|
449
773
|
|
|
774
|
+
/** Where a join is. `reason` is the server's own refusal reason, for a surface that words each one. */
|
|
775
|
+
type TelevetJoinState = {
|
|
776
|
+
readonly status: 'joining';
|
|
777
|
+
} | {
|
|
778
|
+
readonly status: 'ready';
|
|
779
|
+
readonly credential: VetCallCredential;
|
|
780
|
+
} | {
|
|
781
|
+
readonly status: 'refused';
|
|
782
|
+
readonly refusal: VetCallJoinRefusal;
|
|
783
|
+
readonly reason: string | null;
|
|
784
|
+
};
|
|
785
|
+
/** Mint the room credential for `consultId` on mount; `retry` asks again. */
|
|
786
|
+
declare function useTelevetJoin(consultId: string, controller: TelevetBookingController | null): {
|
|
787
|
+
readonly state: TelevetJoinState;
|
|
788
|
+
readonly retry: () => void;
|
|
789
|
+
};
|
|
790
|
+
|
|
450
791
|
type TelevetBookingRefusal =
|
|
451
792
|
/** Triage flagged an emergency. Carries `categories`. MUST show the warning. */
|
|
452
793
|
{
|
|
@@ -487,8 +828,8 @@ type TelevetBookingRefusal =
|
|
|
487
828
|
*
|
|
488
829
|
* NOT IN THE CONSUMER'S UNION, and it is the one member the port adds. The consumer app talks to its own
|
|
489
830
|
* 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
|
|
491
|
-
*
|
|
831
|
+
* granted and the in-app booking routes withheld, and no retry fixes that: the flow shows its unavailable
|
|
832
|
+
* state, inside the partner app. Folding it into `failed` would offer a retry that can never work.
|
|
492
833
|
*/
|
|
493
834
|
| {
|
|
494
835
|
readonly kind: 'unavailable';
|
|
@@ -524,6 +865,7 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
|
|
|
524
865
|
/** WHY, not just "none". An empty roster is a real, temporary answer. */
|
|
525
866
|
noCliniciansBody: string;
|
|
526
867
|
noCliniciansRetryCta: string;
|
|
868
|
+
noCliniciansRegionBody: string;
|
|
527
869
|
/** The matched vet, not a roster. */
|
|
528
870
|
yourVetTitle: string;
|
|
529
871
|
/** Suffix on the star line: "5.0 · 774 reviews". */
|
|
@@ -548,6 +890,59 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
|
|
|
548
890
|
shareRecordsOff: string;
|
|
549
891
|
confirmNotEntitled: string;
|
|
550
892
|
confirmFailed: string;
|
|
893
|
+
checkAvailabilityCta: string;
|
|
894
|
+
/**
|
|
895
|
+
* THE STATE-INTEREST WRITE: the one way out of a refusal this flow cannot fix.
|
|
896
|
+
*
|
|
897
|
+
* PORTED FROM BOTH CONSUMER APPS, which agree on every string. Mobile's `liveVetCopy.region.waitlist*`
|
|
898
|
+
* (everfur-mobile src/features/liveVet/copy.ts:202-209, rendered by
|
|
899
|
+
* `TelevetStateInterestAction.tsx:27-51`) and the consumer WEB app's `ownerTelevetCopy.stateInterest*`
|
|
900
|
+
* (everfur-frontend app/product/televet/ownerCopy.ts:520-527, rendered by
|
|
901
|
+
* `StateInterestPanel.tsx:100-130`) are the same words. `submitting` exists only on the web side
|
|
902
|
+
* (ownerCopy.ts:524); mobile renders the pending state as a spinner inside its button instead, so the
|
|
903
|
+
* RN port uses `loading` and the DOM port uses this label, each following its own consumer app.
|
|
904
|
+
*
|
|
905
|
+
* NOT `waitlist` IN THE KEY NAMES. The server's enum calls this state interest and buckets it by REASON
|
|
906
|
+
* (`no_licensed_vet` vs `no_prescribing`), and the two are closed by different fixes. Naming the keys
|
|
907
|
+
* after the UI word would invite a call site to post the wrong bucket.
|
|
908
|
+
*/
|
|
909
|
+
stateInterest: Readonly<{
|
|
910
|
+
cta: string;
|
|
911
|
+
/** Web only. Mobile shows a spinner in the button; see the block comment above. */
|
|
912
|
+
submitting: string;
|
|
913
|
+
joinedTitle: string;
|
|
914
|
+
joinedBody: string;
|
|
915
|
+
failed: string;
|
|
916
|
+
}>;
|
|
917
|
+
/**
|
|
918
|
+
* WHAT HAPPENED TO THE OWNER'S ATTACHMENTS, one sentence per cause.
|
|
919
|
+
*
|
|
920
|
+
* PORTED FROM BOTH CONSUMER APPS, which again agree character for character: mobile's
|
|
921
|
+
* `liveVetCopy.booking.media*Template` (everfur-mobile src/features/liveVet/copy.ts:484-491, rendered by
|
|
922
|
+
* `MediaDropNotice.tsx:31-36`) and the consumer WEB app's `ownerTelevetCopy.media.*Template`
|
|
923
|
+
* (everfur-frontend app/product/televet/ownerCopy.ts:486-494, rendered through
|
|
924
|
+
* `consultAttachmentShortfallLines` in consultAttachmentUpload.ts:382-407, whose own docblock calls itself
|
|
925
|
+
* "mobile's `MediaDropNotice` in pure form").
|
|
926
|
+
*
|
|
927
|
+
* `{n}` IS DATA and is filled at the call site through `fill`. Singular and plural are separate keys
|
|
928
|
+
* rather than a pluralisation rule, because that is what both consumer apps do and a rule invented here
|
|
929
|
+
* would produce a third grammar for the same sentence.
|
|
930
|
+
*
|
|
931
|
+
* WHY THIS DECK CARRIES `dropped` AT ALL, given the SDK never uploads. See `mediaShortfall.ts`: the SDK's
|
|
932
|
+
* booking sends `media_refs: []` unconditionally, so on this surface EVERY attachment an owner picked is
|
|
933
|
+
* dropped, and `dropped` is the sentence for exactly that. It is the most load-bearing line here, not a
|
|
934
|
+
* spare one.
|
|
935
|
+
*/
|
|
936
|
+
media: Readonly<{
|
|
937
|
+
droppedTemplate: string;
|
|
938
|
+
droppedPluralTemplate: string;
|
|
939
|
+
refusedSizeTemplate: string;
|
|
940
|
+
refusedSizePluralTemplate: string;
|
|
941
|
+
refusedTypeTemplate: string;
|
|
942
|
+
refusedTypePluralTemplate: string;
|
|
943
|
+
refusedUnreadableTemplate: string;
|
|
944
|
+
refusedUnreadablePluralTemplate: string;
|
|
945
|
+
}>;
|
|
551
946
|
navTitle: string;
|
|
552
947
|
/** The chrome must not say "Book a visit" while the user is moving one they already have. */
|
|
553
948
|
rescheduleNavTitle: string;
|
|
@@ -610,15 +1005,23 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
|
|
|
610
1005
|
/**
|
|
611
1006
|
* The emergency refusal. This is the one screen on the surface that interrupts.
|
|
612
1007
|
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
*
|
|
616
|
-
*
|
|
1008
|
+
* THE EXIT ROWS. This used to say the three rows were missing "in the consumer and here", which was wrong
|
|
1009
|
+
* twice: the consumer mobile screen draws the find-a-vet row and the primary-vet row
|
|
1010
|
+
* (TelevetEarlyEmergency.tsx:73-75, :91) and the consumer web draws all three with poison control
|
|
1011
|
+
* (BookingFunnel.tsx:713-774). The RN screens now draw the mobile two, the find row only when the host
|
|
1012
|
+
* passes its own locator (`onFindEmergencyVet`, the SDK opens nothing outside the app) and the clinic row
|
|
1013
|
+
* only when the host holds the clinic (`primaryVet`). The web screens draw the web cards from
|
|
1014
|
+
* `bookingCopyWeb.ts` on the same two host seams, with poison control held for the owner's approval (see
|
|
1015
|
+
* `src/web/televet/booking/EmergencyExits.tsx`). No number is ever invented for this screen.
|
|
617
1016
|
*/
|
|
618
1017
|
emergency: Readonly<{
|
|
619
1018
|
bannerTitle: string;
|
|
620
1019
|
keepBookingCta: string;
|
|
621
1020
|
lede: string;
|
|
1021
|
+
exitPrimaryVetTitle: string;
|
|
1022
|
+
/** everfur-mobile copy.ts:734 `emergency.exitFindErTitle`, the consumer web's `findEmergencyVet` word for word. */
|
|
1023
|
+
exitFindErTitle: string;
|
|
1024
|
+
startCallHint: string;
|
|
622
1025
|
}>;
|
|
623
1026
|
/** The calendar entry's own title, from the consumer's `visit` block. */
|
|
624
1027
|
visit: Readonly<{
|
|
@@ -729,4 +1132,4 @@ type TelevetBookingCopy = typeof TELEVET_BOOKING_COPY;
|
|
|
729
1132
|
*/
|
|
730
1133
|
declare function isTelevetBookingCopyReady(): boolean;
|
|
731
1134
|
|
|
732
|
-
export {
|
|
1135
|
+
export { createTelevetBookingController as $, type TelevetBookingCopy as A, type TelevetBookingDraft as B, CANCELLATION_POLICY_VERSION_MAX as C, type TelevetBookingEntitlement as D, type TelevetBookingFailure as E, type TelevetBookingRefusal as F, type TelevetBookingState as G, type TelevetCancellationPolicy as H, type TelevetClinician as I, type TelevetEarlyTriage as J, type TelevetEmptyRosterView as K, type TelevetJoinReadiness as L, MEDIA_REFS_MAX as M, NO_MEDIA_SHORTFALL as N, type TelevetJoinState as O, type TelevetMediaRefusal as P, type TelevetRead as Q, REASON_TEXT_MAX as R, type TelevetSlotHold as S, type TelevetEmptyRosterCause as T, type TelevetStateInterestReason as U, type TelevetStatePolicy as V, type TelevetTriageVerdict as W, type TelevetWrite as X, attestation as Y, canConfirm as Z, canManageTelevetVisit as _, type TelevetStateInterestAction as a, currentStep as a0, emptyTelevetDraft as a1, formatVisitRange as a2, formatWhen as a3, formatWhenWithDay as a4, hasPreviousStep as a5, initialTelevetBookingState as a6, isHoldExpired as a7, isMediaShortfallEmpty as a8, isSkipped as a9, useTelevetJoin as aA, useTelevetNextSlot as aB, useTelevetRescheduleConsult as aC, useTelevetSlots as aD, useTelevetStatePolicy as aE, validateBookingBody as aF, withUnsentPicks as aG, type TelevetJoinBlock as aH, type TelevetJoinDecision as aI, televetJoinDecision as aJ, isTelevetBookingCopyReady as aa, isWellFormedStateCode as ab, mediaShortfallFromUnsentPicks as ac, splitTelevetVisits as ad, televetBookingKey as ae, televetBookingReducer as af, televetBookingRefusal as ag, televetCancelCall as ah, televetConsultCall as ai, televetEmptyRosterCause as aj, televetEmptyRosterView as ak, televetHoldCall as al, televetJoinCall as am, televetJoinOpensAtMs as an, televetJoinReadiness as ao, televetMediaShortfallLines as ap, televetRescheduleCall as aq, useEarlyTriage as ar, useStateInterest as as, useTelevetBookConsult as at, useTelevetBookingAvailable as au, useTelevetBookingController as av, useTelevetBookingEntitlement as aw, useTelevetCancellationPolicy as ax, useTelevetClinicians as ay, useTelevetHoldSlot as az, type TelevetMediaShortfall as b, type TelevetConsult as c, type TelevetBookingStep as d, type TelevetBookingController as e, type TelevetTriageRead as f, type TelevetStateInterestWrite as g, type TelevetCancelReceipt as h, type TelevetSlot as i, CANCEL_REASON_MAX as j, CONSULT_KINDS as k, CONSULT_MINUTES as l, CONSULT_STATUSES as m, type ConsultKind as n, type ConsultStatus as o, TELEVET_BOOKING_BASE as p, TELEVET_BOOKING_COPY as q, TELEVET_BOOKING_STEPS as r, TELEVET_CONSULT_PAGE_LIMIT as s, TELEVET_JOIN_CLOSES_MINUTES_AFTER as t, TELEVET_JOIN_OPENS_MINUTES_BEFORE as u, TERMINAL_CONSULT_STATUSES as v, type TelevetBookingAction as w, type TelevetBookingBody as x, type TelevetBookingContext as y, type TelevetBookingControllerDeps as z };
|