@medplum/react-scheduling 5.1.38 → 5.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +7 -2
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/cjs/index.css +1 -1
- package/dist/cjs/index.css.map +4 -4
- package/dist/cjs/index.d.ts +399 -59
- package/dist/esm/index.css +1 -1
- package/dist/esm/index.css.map +4 -4
- package/dist/esm/index.d.ts +399 -59
- package/dist/esm/index.mjs +7 -2
- package/dist/esm/index.mjs.map +4 -4
- package/package.json +12 -12
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Appointment } from '@medplum/fhirtypes';
|
|
2
|
+
import type { Bundle } from '@medplum/fhirtypes';
|
|
2
3
|
import type { Coding } from '@medplum/fhirtypes';
|
|
3
4
|
import type { Dereference } from '@medplum/core';
|
|
5
|
+
import type { Extension } from '@medplum/fhirtypes';
|
|
4
6
|
import type { HealthcareService } from '@medplum/fhirtypes';
|
|
5
7
|
import type { HealthcareServiceAvailableTime } from '@medplum/fhirtypes';
|
|
6
8
|
import type { JSX } from 'react';
|
|
@@ -9,8 +11,8 @@ import type { MantineThemeColors } from '@mantine/core';
|
|
|
9
11
|
import type { MedplumClient } from '@medplum/core';
|
|
10
12
|
import type { OperationOutcome } from '@medplum/fhirtypes';
|
|
11
13
|
import type { Patient } from '@medplum/fhirtypes';
|
|
14
|
+
import type { ReactNode } from 'react';
|
|
12
15
|
import type { Reference } from '@medplum/fhirtypes';
|
|
13
|
-
import type { Resource } from '@medplum/fhirtypes';
|
|
14
16
|
import type { Schedule } from '@medplum/fhirtypes';
|
|
15
17
|
import type { SchedulingRequirement } from '@medplum/core';
|
|
16
18
|
import type { Slot } from '@medplum/fhirtypes';
|
|
@@ -19,8 +21,8 @@ import type { WithId } from '@medplum/core';
|
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* One way of holding an appointment: a set of actors whose schedules `$find`
|
|
22
|
-
* intersects in a single request.
|
|
23
|
-
*
|
|
24
|
+
* intersects in a single request. Each requirement contributes exactly one
|
|
25
|
+
* actor, since a row is satisfied by any one of its alternatives.
|
|
24
26
|
*/
|
|
25
27
|
export declare interface ActorCombination {
|
|
26
28
|
/** Matches `getActorGroupKey` of the appointments offered for these actors. */
|
|
@@ -31,26 +33,70 @@ export declare interface ActorCombination {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
+
* One thing an appointment needs, of a single actor type.
|
|
37
|
+
*
|
|
38
|
+
* The candidates in it are alternatives: a row naming two
|
|
39
|
+
* providers asks for *either* of them rather than both.
|
|
36
40
|
*/
|
|
37
|
-
export declare
|
|
41
|
+
export declare interface ActorRequirement {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly candidates: readonly ScheduleCandidate[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* What an appointment is being asked for, per actor type.
|
|
48
|
+
*
|
|
49
|
+
* Each actor type holds a list of requirements, and the two directions read
|
|
50
|
+
* differently: requirements are ANDed, so two provider rows ask for two
|
|
51
|
+
* providers, while the candidates within one row are ORed.
|
|
52
|
+
*/
|
|
53
|
+
export declare type ActorSelections = Partial<Record<SchedulingActorType, readonly ActorRequirement[]>>;
|
|
38
54
|
|
|
39
55
|
export declare function addDays(date: Date, days: number): Date;
|
|
40
56
|
|
|
41
57
|
/**
|
|
42
|
-
* Chooses
|
|
58
|
+
* Chooses which actors of one type can hold an appointment.
|
|
43
59
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
60
|
+
* The names in one of these fields are **alternatives** to each other.
|
|
61
|
+
* Several actors that all have to attend go in a field each - see {@link AppointmentActorSelections},
|
|
62
|
+
* which arranges these into rows.
|
|
46
63
|
*
|
|
47
|
-
*
|
|
64
|
+
* The results are `Schedule` resources, bound to the actors that can hold the appointment.
|
|
48
65
|
*
|
|
49
66
|
* @param props - The React props.
|
|
50
67
|
* @returns The field for one actor type.
|
|
51
68
|
*/
|
|
52
69
|
export declare function AppointmentActorSelect(props: AppointmentActorSelectProps): JSX.Element;
|
|
53
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Asks what an appointment needs by actor type (e.g., provider, room, device).
|
|
73
|
+
*
|
|
74
|
+
* Each actor type gets a stack of rows. **The rows are ANDed and the names
|
|
75
|
+
* within a row are ORed**: two provider rows ask for two providers, while two
|
|
76
|
+
* names in one row ask for either of them.
|
|
77
|
+
*
|
|
78
|
+
* A row is one alternative set, so it is also one dimension of the search:
|
|
79
|
+
* `getActorCombinations` takes one name from each row, and every way of doing
|
|
80
|
+
* that is one `$find` request.
|
|
81
|
+
*
|
|
82
|
+
* @param props - The React props.
|
|
83
|
+
* @returns One group of rows per bookable actor type.
|
|
84
|
+
*/
|
|
85
|
+
export declare function AppointmentActorSelections(props: AppointmentActorSelectionsProps): JSX.Element;
|
|
86
|
+
|
|
87
|
+
export declare interface AppointmentActorSelectionsProps {
|
|
88
|
+
/** What the appointment is being asked for so far, per actor type. */
|
|
89
|
+
readonly value: ActorSelections;
|
|
90
|
+
/** The service being booked. Nothing is offered until it resolves. */
|
|
91
|
+
readonly service: Reference<HealthcareService> | WithId<HealthcareService> | undefined;
|
|
92
|
+
/** The site being booked at. Actors sited elsewhere are left out. */
|
|
93
|
+
readonly location?: Reference<Location_2> | WithId<Location_2>;
|
|
94
|
+
readonly disabled?: boolean;
|
|
95
|
+
/** What is wrong with a type's rows, shown under them. None by default. */
|
|
96
|
+
readonly errors?: Partial<Record<BookableActorType, string>>;
|
|
97
|
+
readonly onChange: (selections: ActorSelections) => void;
|
|
98
|
+
}
|
|
99
|
+
|
|
54
100
|
export declare interface AppointmentActorSelectProps {
|
|
55
101
|
readonly actorType: BookableActorType;
|
|
56
102
|
/** The service being booked. Nothing is offered until it resolves. */
|
|
@@ -65,19 +111,25 @@ export declare interface AppointmentActorSelectProps {
|
|
|
65
111
|
readonly onChange: (candidates: readonly ScheduleCandidate[]) => void;
|
|
66
112
|
readonly error?: string;
|
|
67
113
|
readonly disabled?: boolean;
|
|
114
|
+
/** Names the field. Defaults to the actor type's own label. */
|
|
115
|
+
readonly label?: ReactNode;
|
|
116
|
+
/** The line under the field. None by default. */
|
|
117
|
+
readonly description?: ReactNode;
|
|
118
|
+
/** What the empty field invites. Defaults to searching the actor type by name. */
|
|
119
|
+
readonly placeholder?: string;
|
|
120
|
+
/** Whether the field must be answered. Defaults to whether its actor type is required. */
|
|
121
|
+
readonly required?: boolean;
|
|
122
|
+
/** Whether to mark the field with an asterisk. Defaults to `required`. */
|
|
123
|
+
readonly withAsterisk?: boolean;
|
|
68
124
|
}
|
|
69
125
|
|
|
70
126
|
/** What a booking wrote, as `Appointment/$book` returned it. */
|
|
71
|
-
export declare
|
|
72
|
-
readonly appointment: WithId<Appointment>;
|
|
73
|
-
/** The times reserved for it, one per schedule it is held on. */
|
|
74
|
-
readonly slots: readonly WithId<Slot>[];
|
|
75
|
-
}
|
|
127
|
+
export declare type AppointmentBooking = AppointmentWrite;
|
|
76
128
|
|
|
77
129
|
/**
|
|
78
130
|
* The booking form, writing the booking itself.
|
|
79
131
|
*
|
|
80
|
-
* Wraps {@link AppointmentProposalForm}:
|
|
132
|
+
* Wraps {@link AppointmentProposalForm}: writes the booking, announces the
|
|
81
133
|
* appointment and every time it reserved so views reading them refresh, then
|
|
82
134
|
* reports what was written through `onBooked` — the only required prop.
|
|
83
135
|
*
|
|
@@ -88,7 +140,7 @@ export declare interface AppointmentBooking {
|
|
|
88
140
|
*/
|
|
89
141
|
export declare function AppointmentBookingForm(props: AppointmentBookingFormProps): JSX.Element;
|
|
90
142
|
|
|
91
|
-
export declare interface AppointmentBookingFormProps extends Omit<AppointmentProposalFormProps, '
|
|
143
|
+
export declare interface AppointmentBookingFormProps extends Omit<AppointmentProposalFormProps, 'onSubmit' | 'mode' | 'ignoreAppointment'> {
|
|
92
144
|
/**
|
|
93
145
|
* Called with what the booking wrote.
|
|
94
146
|
*
|
|
@@ -147,19 +199,13 @@ export declare interface AppointmentOptionRowProps {
|
|
|
147
199
|
|
|
148
200
|
/**
|
|
149
201
|
* Gathers what a visit is held on, finds a time every one of them is free, and
|
|
150
|
-
* hands the proposal out to be
|
|
151
|
-
*
|
|
152
|
-
* One field per scheduling role, each searching the schedules bookable for the
|
|
153
|
-
* chosen visit type. Everything named attends, because `$find` intersects their
|
|
154
|
-
* schedules — so naming a second room narrows the times rather than widening them.
|
|
202
|
+
* hands the proposal out to be written.
|
|
155
203
|
*
|
|
156
|
-
*
|
|
157
|
-
* input, so nothing can be booked onto time nobody checked availability for.
|
|
158
|
-
*
|
|
159
|
-
* Writes nothing and announces nothing: `onBook` owns that. Mount this to do
|
|
204
|
+
* Writes nothing and announces nothing: `onSubmit` owns that. Mount this to do
|
|
160
205
|
* something other than `$book` with the proposal — hold it through `$hold`, or
|
|
161
206
|
* write it inside a transaction of your own. {@link AppointmentBookingForm} is the
|
|
162
|
-
* one that books
|
|
207
|
+
* one that books, and {@link AppointmentRescheduleForm} the one that moves a visit
|
|
208
|
+
* already on file.
|
|
163
209
|
*
|
|
164
210
|
* @param props - The React props.
|
|
165
211
|
* @returns The form.
|
|
@@ -167,6 +213,8 @@ export declare interface AppointmentOptionRowProps {
|
|
|
167
213
|
export declare function AppointmentProposalForm(props: AppointmentProposalFormProps): JSX.Element;
|
|
168
214
|
|
|
169
215
|
export declare interface AppointmentProposalFormProps {
|
|
216
|
+
/** What the proposal is for. Defaults to booking a new visit. */
|
|
217
|
+
readonly mode?: AppointmentProposalMode;
|
|
170
218
|
/** Pre-fills where the visit is, for a host that already knows. */
|
|
171
219
|
readonly defaultLocation?: WithId<Location_2>;
|
|
172
220
|
/** Pre-fills the visit type, for a deep link or a reschedule. */
|
|
@@ -174,9 +222,23 @@ export declare interface AppointmentProposalFormProps {
|
|
|
174
222
|
/** Pre-fills who the visit is for, for a host launching from a patient's chart. */
|
|
175
223
|
readonly defaultPatient?: WithId<Patient>;
|
|
176
224
|
/**
|
|
177
|
-
*
|
|
225
|
+
* Pre-fills who and what the visit is held on, for a host that already knows — the
|
|
226
|
+
* actors an appointment being moved is currently held on, say.
|
|
227
|
+
*
|
|
228
|
+
* Read once, at mount: the fields own what they are asked for afterwards.
|
|
229
|
+
*/
|
|
230
|
+
readonly defaultSelections?: ActorSelections;
|
|
231
|
+
/**
|
|
232
|
+
* An appointment whose own times are not to count as taken.
|
|
178
233
|
*
|
|
179
|
-
*
|
|
234
|
+
* For a form searching on behalf of an appointment that already exists: without it,
|
|
235
|
+
* the time it holds blocks every search that keeps any of the actors holding it, and
|
|
236
|
+
* moving a visit to a different room at the same hour finds nothing.
|
|
237
|
+
*/
|
|
238
|
+
readonly ignoreAppointment?: Reference<Appointment> | WithId<Appointment>;
|
|
239
|
+
/**
|
|
240
|
+
* The day the time search opens on, and the day a typed time starts out on.
|
|
241
|
+
* Defaults to today.
|
|
180
242
|
*/
|
|
181
243
|
readonly defaultStart?: Date;
|
|
182
244
|
/**
|
|
@@ -209,12 +271,78 @@ export declare interface AppointmentProposalFormProps {
|
|
|
209
271
|
/** The ValueSet the diagnosis code field binds to. Defaults to the full ICD-10-CM value set. */
|
|
210
272
|
readonly diagnosisBinding?: string;
|
|
211
273
|
/**
|
|
212
|
-
*
|
|
274
|
+
* Writes the proposal the form assembled.
|
|
275
|
+
*
|
|
276
|
+
* Resolving marks the form written, so it stops offering to write until an answer
|
|
277
|
+
* changes; rejecting shows the reason as the write's refusal, every answer kept.
|
|
213
278
|
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
279
|
+
* In `book` mode the proposal carries the patient and the visit type's required
|
|
280
|
+
* codes; in `reschedule` mode it is the time as `$find` offered it, untouched.
|
|
281
|
+
*/
|
|
282
|
+
readonly onSubmit: (proposal: Appointment, options: BookOptions) => void | Promise<void>;
|
|
283
|
+
/** Extensions to put on every appointment this form books. */
|
|
284
|
+
readonly appointmentExtensions?: readonly Extension[];
|
|
285
|
+
/**
|
|
286
|
+
* Allows for manual entry of a time and length, bypassing the `$find` search and
|
|
287
|
+
* `$book` endpoint.
|
|
216
288
|
*/
|
|
217
|
-
readonly
|
|
289
|
+
readonly canBypassSchedulingRules?: boolean;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* What the proposal the form assembles is for, which decides what it asks for.
|
|
294
|
+
*
|
|
295
|
+
* `book` gathers everything a new visit is written with: who it is for, and whatever
|
|
296
|
+
* its visit type requires. `reschedule` gathers only what decides the time, because
|
|
297
|
+
* `Appointment/[id]/$reschedule` moves a visit already on file and writes nothing else
|
|
298
|
+
* about it — asking for details it would drop is asking for them under false pretences.
|
|
299
|
+
*
|
|
300
|
+
* The visit type goes the same way: in `reschedule` mode a `defaultService` is shown
|
|
301
|
+
* rather than asked for, since the operation is measured against it but will not change
|
|
302
|
+
* it. Without one it is still asked, because the search cannot run without a visit type.
|
|
303
|
+
*/
|
|
304
|
+
export declare type AppointmentProposalMode = 'book' | 'reschedule';
|
|
305
|
+
|
|
306
|
+
/** What a reschedule wrote, as `Appointment/[id]/$reschedule` returned it. */
|
|
307
|
+
export declare type AppointmentReschedule = AppointmentWrite;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* The form that moves a visit already on file, to another time or another set of actors.
|
|
311
|
+
*
|
|
312
|
+
* Wraps {@link AppointmentProposalForm}, opened on what the appointment is held on now
|
|
313
|
+
* and searching as though it were not: the time it occupies is the time it is being
|
|
314
|
+
* moved off, so `$find` is told to ignore it, which is what lets the same hour in a
|
|
315
|
+
* different room be found.
|
|
316
|
+
*
|
|
317
|
+
* Posts `Appointment/[id]/$reschedule`, announces the appointment, the times it gave up
|
|
318
|
+
* and the times it took, so views reading them refresh, then reports what was written
|
|
319
|
+
* through `onRescheduled`.
|
|
320
|
+
*
|
|
321
|
+
* Only the time and the actors are asked for. Everything else on the appointment — who
|
|
322
|
+
* it is for, its status, its visit type, whatever clinical detail it carries — is left
|
|
323
|
+
* exactly as it was, because that is all the operation will write. The visit type is
|
|
324
|
+
* shown rather than offered: `$reschedule` takes none, reading the one the appointment
|
|
325
|
+
* is on file for instead, since changing what a visit *is* would leave its required
|
|
326
|
+
* codes, its authorization, and anything applied at booking keyed to a type it no
|
|
327
|
+
* longer has.
|
|
328
|
+
*
|
|
329
|
+
* @param props - The React props.
|
|
330
|
+
* @returns The form.
|
|
331
|
+
*/
|
|
332
|
+
export declare function AppointmentRescheduleForm(props: AppointmentRescheduleFormProps): JSX.Element;
|
|
333
|
+
|
|
334
|
+
export declare interface AppointmentRescheduleFormProps extends Omit<AppointmentProposalFormProps, 'onSubmit' | 'mode' | 'defaultService' | 'defaultSelections' | 'defaultPatient' | 'ignoreAppointment' | 'mrnSystem' | 'procedureBinding' | 'diagnosisBinding' | 'canBypassSchedulingRules' | 'appointmentExtensions'> {
|
|
335
|
+
/** The appointment being moved. */
|
|
336
|
+
readonly appointment: WithId<Appointment>;
|
|
337
|
+
/**
|
|
338
|
+
* Called with what the move wrote.
|
|
339
|
+
*
|
|
340
|
+
* The answers stay on screen and the form stops offering to move until one of them
|
|
341
|
+
* changes, so a host can keep this mounted without it writing twice. A failure here
|
|
342
|
+
* is logged rather than shown as a refusal: the appointment has already moved by the
|
|
343
|
+
* time it runs.
|
|
344
|
+
*/
|
|
345
|
+
readonly onRescheduled: (reschedule: AppointmentReschedule) => void | Promise<void>;
|
|
218
346
|
}
|
|
219
347
|
|
|
220
348
|
/**
|
|
@@ -238,6 +366,8 @@ export declare interface AppointmentServiceSelectProps {
|
|
|
238
366
|
/** A chosen site, which narrows the services on offer to the ones held there. */
|
|
239
367
|
readonly location?: WithId<Location_2> | Reference<Location_2>;
|
|
240
368
|
readonly label?: string;
|
|
369
|
+
readonly placeholder?: string;
|
|
370
|
+
readonly required?: boolean;
|
|
241
371
|
readonly error?: string;
|
|
242
372
|
readonly disabled?: boolean;
|
|
243
373
|
}
|
|
@@ -246,7 +376,7 @@ export declare interface AppointmentServiceSelectProps {
|
|
|
246
376
|
export declare interface AppointmentSlotGroup {
|
|
247
377
|
/** Stable key derived from the actors, so React keys survive a refetch. */
|
|
248
378
|
readonly key: string;
|
|
249
|
-
readonly actors: readonly
|
|
379
|
+
readonly actors: readonly SchedulingActorValue[];
|
|
250
380
|
readonly durationMinutes: number;
|
|
251
381
|
/** Sorted by start time. */
|
|
252
382
|
readonly appointments: readonly Appointment[];
|
|
@@ -270,13 +400,22 @@ export declare interface AppointmentSlotGroupCardProps {
|
|
|
270
400
|
readonly disabled?: boolean;
|
|
271
401
|
}
|
|
272
402
|
|
|
403
|
+
/** What a scheduling operation wrote: the appointment, and the times it holds. */
|
|
404
|
+
export declare interface AppointmentWrite {
|
|
405
|
+
readonly appointment: WithId<Appointment>;
|
|
406
|
+
/** The times reserved for it, one set per schedule it is held on. */
|
|
407
|
+
readonly slots: readonly WithId<Slot>[];
|
|
408
|
+
}
|
|
409
|
+
|
|
273
410
|
/**
|
|
274
411
|
* Actor types whose schedules may be offered for booking, in the order they are
|
|
275
412
|
* asked about.
|
|
276
413
|
*
|
|
277
|
-
* Each type becomes
|
|
278
|
-
* given: a time is offered only when the practitioner *and* the location *and*
|
|
279
|
-
* the device are all free for it.
|
|
414
|
+
* Each type becomes its own question, because `$find` intersects the schedules it
|
|
415
|
+
* is given: a time is offered only when the practitioner *and* the location *and*
|
|
416
|
+
* the device are all free for it. Asking for *either* of two practitioners is a
|
|
417
|
+
* second request rather than a second schedule on the same one — see
|
|
418
|
+
* `getActorCombinations`.
|
|
280
419
|
*
|
|
281
420
|
* Does not include `PractitionerRole` to prevent double-booking a `Practitioner`
|
|
282
421
|
* who holds multiple roles. A practitioner is booked on their `Practitioner`,
|
|
@@ -297,6 +436,12 @@ export declare interface BookingRequirementValues {
|
|
|
297
436
|
readonly medicalNecessity: boolean;
|
|
298
437
|
}
|
|
299
438
|
|
|
439
|
+
/** What `onBook` is told about the proposal it was handed. */
|
|
440
|
+
export declare interface BookOptions {
|
|
441
|
+
/** True when the time was typed (& unvalidated) rather than chosen from the search. */
|
|
442
|
+
readonly manual: boolean;
|
|
443
|
+
}
|
|
444
|
+
|
|
300
445
|
export declare function Calendar(props: CalendarProps): JSX.Element;
|
|
301
446
|
|
|
302
447
|
export declare interface CalendarProps {
|
|
@@ -325,6 +470,26 @@ declare interface CommonProps {
|
|
|
325
470
|
readonly onCancel?: () => void;
|
|
326
471
|
}
|
|
327
472
|
|
|
473
|
+
/**
|
|
474
|
+
* Counts the combinations the selections expand into, without building them.
|
|
475
|
+
*
|
|
476
|
+
* An upper bound rather than an exact count: the ones that would name the same
|
|
477
|
+
* actor twice are only recognised while building. Enough to decide whether the
|
|
478
|
+
* product is worth expanding at all.
|
|
479
|
+
*
|
|
480
|
+
* @param selections - What has been chosen.
|
|
481
|
+
* @returns How many ways there are of satisfying every row, or 0 when nothing
|
|
482
|
+
* has been chosen.
|
|
483
|
+
*/
|
|
484
|
+
export declare function countActorCombinations(selections: ActorSelections): number;
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Opens a new requirement row.
|
|
488
|
+
* @param candidates - What it starts out asking for. Empty by default.
|
|
489
|
+
* @returns The row.
|
|
490
|
+
*/
|
|
491
|
+
export declare function createActorRequirement(candidates?: readonly ScheduleCandidate[]): ActorRequirement;
|
|
492
|
+
|
|
328
493
|
/** The days a search covers. Either end may be open. */
|
|
329
494
|
export declare interface DateRange {
|
|
330
495
|
readonly start?: Date;
|
|
@@ -426,11 +591,17 @@ export declare interface FormatZonedTimeOptions {
|
|
|
426
591
|
* Builds the sets of actors an appointment could be held on.
|
|
427
592
|
*
|
|
428
593
|
* One combination is one `$find` request: the schedules within it are
|
|
429
|
-
* intersected, so its times are the times all of those actors are free.
|
|
594
|
+
* intersected, so its times are the times all of those actors are free. Rows are
|
|
595
|
+
* ANDed and the alternatives within a row are ORed, so the combinations are the
|
|
596
|
+
* product of the rows — one alternative taken from each.
|
|
597
|
+
*
|
|
598
|
+
* Ordered as an odometer with the last row turning fastest, so the first
|
|
599
|
+
* combination is every row's first pick and the rounds the search runs stay
|
|
600
|
+
* predictable.
|
|
430
601
|
*
|
|
431
602
|
* @param selections - What has been chosen.
|
|
432
|
-
* @returns One combination
|
|
433
|
-
*
|
|
603
|
+
* @returns One combination per way of satisfying every row, or an empty list
|
|
604
|
+
* when nothing is chosen.
|
|
434
605
|
*/
|
|
435
606
|
export declare function getActorCombinations(selections: ActorSelections): ActorCombination[];
|
|
436
607
|
|
|
@@ -449,16 +620,16 @@ export declare function getActorGroupKey(appointment: Appointment): string;
|
|
|
449
620
|
export declare function getActorsKey(actors: readonly Reference[]): string;
|
|
450
621
|
|
|
451
622
|
/**
|
|
452
|
-
* Extracts the resource type
|
|
623
|
+
* Extracts the resource type of an actor, given as itself or as a reference.
|
|
453
624
|
*
|
|
454
625
|
* Only supports references that may be used for Scheduling operations, which are
|
|
455
626
|
* those that have a qualified `reference` attribute. The attribute must be present,
|
|
456
627
|
* and may not be a reference to a "contained" resource (eg. `{ reference: "#cid" }`)
|
|
457
628
|
*
|
|
458
|
-
* @param
|
|
459
|
-
* @returns The type
|
|
629
|
+
* @param actor - A schedulable resource, or a Reference to one
|
|
630
|
+
* @returns The type of the actor.
|
|
460
631
|
*/
|
|
461
|
-
export declare function getActorType(
|
|
632
|
+
export declare function getActorType(actor: SchedulingActorValue): SchedulingActorType;
|
|
462
633
|
|
|
463
634
|
/**
|
|
464
635
|
* Provides the label we use for scheduling resource types in this UI
|
|
@@ -468,6 +639,14 @@ export declare function getActorType(reference: SchedulingActor): SchedulingActo
|
|
|
468
639
|
*/
|
|
469
640
|
export declare function getActorTypeLabel(resourceType: SchedulingActorType): string;
|
|
470
641
|
|
|
642
|
+
/**
|
|
643
|
+
* Get the actor(s) of an appointment.
|
|
644
|
+
* @param appointment - The proposed appointment.
|
|
645
|
+
* @param actorResources - Map of actor resources that have already been previously loaded.
|
|
646
|
+
* @returns List of actors. Resource if it's already loaded, reference otherwise.
|
|
647
|
+
*/
|
|
648
|
+
export declare function getAppointmentActors(appointment: Appointment | undefined, actorResources?: ReadonlyMap<string, SchedulingActorResource>): SchedulingActorValue[];
|
|
649
|
+
|
|
471
650
|
/**
|
|
472
651
|
* Returns a key uniquely identifying a proposed appointment.
|
|
473
652
|
*
|
|
@@ -547,28 +726,51 @@ export declare function getFindWindowError(range: DateRange): string | undefined
|
|
|
547
726
|
/**
|
|
548
727
|
* Returns the input type to use for a date or time field.
|
|
549
728
|
*
|
|
550
|
-
* JSDOM does not fire change events for `<input type="date">`
|
|
551
|
-
* `<input type="
|
|
729
|
+
* JSDOM does not fire change events for `<input type="date">`, `<input type="time">`
|
|
730
|
+
* or `<input type="datetime-local">`, so tests get a plain text field, matching what
|
|
552
731
|
* `DateTimeInput` does.
|
|
553
732
|
*
|
|
554
733
|
* @param type - The native input type to use outside of tests.
|
|
555
734
|
* @returns The input type for the current environment.
|
|
556
735
|
*/
|
|
557
|
-
export declare function getNativeInputType(type: 'date' | 'time'): string;
|
|
736
|
+
export declare function getNativeInputType(type: 'date' | 'time' | 'datetime-local'): string;
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Returns every row across every actor type, in the order they are asked about.
|
|
740
|
+
* @param selections - What has been chosen.
|
|
741
|
+
* @returns The rows, empty ones included.
|
|
742
|
+
*/
|
|
743
|
+
export declare function getRequirements(selections: ActorSelections): ActorRequirement[];
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Flattens the loaded actor resources into a map, keyed by their reference.
|
|
747
|
+
* @param selections - What has been chosen.
|
|
748
|
+
* @returns The resource behind each chosen actor the search was able to include.
|
|
749
|
+
*/
|
|
750
|
+
export declare function getSelectedActorResources(selections: ActorSelections): Map<string, SchedulingActorResource>;
|
|
558
751
|
|
|
559
752
|
/**
|
|
560
|
-
* Returns everything chosen, across actor types
|
|
753
|
+
* Returns everything chosen, across rows and actor types.
|
|
561
754
|
* @param selections - What has been chosen.
|
|
562
|
-
* @returns The chosen candidates in `BOOKABLE_ACTOR_TYPES` order
|
|
755
|
+
* @returns The chosen candidates in `BOOKABLE_ACTOR_TYPES` order, then row order.
|
|
563
756
|
*/
|
|
564
757
|
export declare function getSelectedCandidates(selections: ActorSelections): ScheduleCandidate[];
|
|
565
758
|
|
|
566
759
|
/**
|
|
567
760
|
* Reports why the current selections cannot be searched, if they cannot.
|
|
568
761
|
* @param selections - What has been chosen.
|
|
569
|
-
* @returns
|
|
762
|
+
* @returns The blocker to show the user, or undefined when the search can run.
|
|
570
763
|
*/
|
|
571
|
-
export declare function getSelectionError(selections: ActorSelections):
|
|
764
|
+
export declare function getSelectionError(selections: ActorSelections): SelectionBlocker | undefined;
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Finds the rows that cannot all be filled at once, when there are any. Specifically happens
|
|
768
|
+
* when two rows offer the same resource, so one resource cannot fill both halves of a visit.
|
|
769
|
+
* @param selections - What has been chosen.
|
|
770
|
+
* @returns The first type whose rows have no answer between them, or undefined when
|
|
771
|
+
* every type can be satisfied.
|
|
772
|
+
*/
|
|
773
|
+
export declare function getUnsatisfiableRows(selections: ActorSelections): UnsatisfiableRows | undefined;
|
|
572
774
|
|
|
573
775
|
/**
|
|
574
776
|
* Search window for a calendar day in the given timezone, starting from now if that day is already underway.
|
|
@@ -587,9 +789,11 @@ export declare function getZonedDayRange(day: Date, timezone?: string): Required
|
|
|
587
789
|
* @param searched - Days to list whether or not they offer anything, so a searched day
|
|
588
790
|
* that came back empty still shows up rather than going missing. Read on the local
|
|
589
791
|
* calendar, matching how a day is picked.
|
|
792
|
+
* @param actorResources - The actors' own resources, keyed by reference, for
|
|
793
|
+
* whichever of them the caller has already read. See {@link getAppointmentActors}.
|
|
590
794
|
* @returns Days in ascending order, each holding its groups.
|
|
591
795
|
*/
|
|
592
|
-
export declare function groupAppointmentsByDay(appointments: readonly Appointment[], timezone?: string, searched?: DateRange): AppointmentDay[];
|
|
796
|
+
export declare function groupAppointmentsByDay(appointments: readonly Appointment[], timezone?: string, searched?: DateRange, actorResources?: ReadonlyMap<string, SchedulingActorResource>): AppointmentDay[];
|
|
593
797
|
|
|
594
798
|
/**
|
|
595
799
|
* Whether every requirement a visit type names has been answered.
|
|
@@ -624,6 +828,15 @@ export declare function isRequirementAnswered(requirement: SchedulingRequirement
|
|
|
624
828
|
*/
|
|
625
829
|
export declare function isViewerTimezone(timezone: string | undefined, viewer?: string): boolean;
|
|
626
830
|
|
|
831
|
+
/**
|
|
832
|
+
* The most alternatives worth expanding into requests at all.
|
|
833
|
+
*
|
|
834
|
+
* The search runs a few combinations at a time, so this is not the size of a
|
|
835
|
+
* round: it is the point past which the whole product is more than anyone is
|
|
836
|
+
* going to sit through, whatever order it is asked in.
|
|
837
|
+
*/
|
|
838
|
+
export declare const MAX_ACTOR_COMBINATIONS = 100;
|
|
839
|
+
|
|
627
840
|
/**
|
|
628
841
|
* The longest window `Appointment/$find` accepts. Requests wider than this are
|
|
629
842
|
* rejected outright, so callers have to keep their own date range inside it.
|
|
@@ -670,6 +883,14 @@ export declare interface MultiCalendarSource {
|
|
|
670
883
|
*/
|
|
671
884
|
export declare function parseDayKey(key: string): Date;
|
|
672
885
|
|
|
886
|
+
/**
|
|
887
|
+
* Reads a native datetime input's value as an instant in a timezone.
|
|
888
|
+
* @param value - A `YYYY-MM-DDTHH:MM` value, as the input reports it.
|
|
889
|
+
* @param timezone - IANA timezone identifier. Defaults to the browser's.
|
|
890
|
+
* @returns The instant, or undefined while the value is not a complete date and time.
|
|
891
|
+
*/
|
|
892
|
+
export declare function parseZonedDateTimeInput(value: string, timezone?: string): Date | undefined;
|
|
893
|
+
|
|
673
894
|
/**
|
|
674
895
|
* Reads a wall-clock time on a given day as an instant in a timezone.
|
|
675
896
|
*
|
|
@@ -680,6 +901,18 @@ export declare function parseDayKey(key: string): Date;
|
|
|
680
901
|
*/
|
|
681
902
|
export declare function parseZonedTime(day: Date, time: string, timezone?: string): Date | undefined;
|
|
682
903
|
|
|
904
|
+
/**
|
|
905
|
+
* Reads what a scheduling operation wrote out of the bundle it answers with.
|
|
906
|
+
*
|
|
907
|
+
* `$book` and `$reschedule` both answer with the appointment and every Slot they
|
|
908
|
+
* created, in one transaction bundle.
|
|
909
|
+
*
|
|
910
|
+
* @param written - The bundle the operation returned.
|
|
911
|
+
* @param operation - What was called, for the error a bundle without an appointment raises.
|
|
912
|
+
* @returns The appointment and the times reserved for it.
|
|
913
|
+
*/
|
|
914
|
+
export declare function readAppointmentWrite(written: Bundle<WithId<Appointment> | WithId<Slot>>, operation: string): AppointmentWrite;
|
|
915
|
+
|
|
683
916
|
/**
|
|
684
917
|
* Actor types that must be chosen before a search can run.
|
|
685
918
|
*
|
|
@@ -688,6 +921,35 @@ export declare function parseZonedTime(day: Date, time: string, timezone?: strin
|
|
|
688
921
|
*/
|
|
689
922
|
export declare const REQUIRED_ACTOR_TYPES: ReadonlySet<SchedulingActorType>;
|
|
690
923
|
|
|
924
|
+
export declare interface RescheduleDefaults {
|
|
925
|
+
/** The visit type the appointment is on file under, where it records one. */
|
|
926
|
+
readonly service: WithId<HealthcareService> | undefined;
|
|
927
|
+
/** Who and what it is held on now, arranged into the rows a form asks for them in. */
|
|
928
|
+
readonly selections: ActorSelections;
|
|
929
|
+
/**
|
|
930
|
+
* Actors the visit is held on whose schedules cannot be offered back, named where they
|
|
931
|
+
* could be read.
|
|
932
|
+
*
|
|
933
|
+
* A Schedule that is inactive, no longer names the visit type, or is held on an actor
|
|
934
|
+
* this form does not book leaves its actors out of the rows above — and a move writes
|
|
935
|
+
* the actors it is given, so these are about to be dropped off the visit.
|
|
936
|
+
*/
|
|
937
|
+
readonly droppedActors: readonly SchedulingActor[];
|
|
938
|
+
/**
|
|
939
|
+
* Set when the visit type, or a Slot or Schedule the visit is held on, could not be read.
|
|
940
|
+
*
|
|
941
|
+
* `$reschedule` reads those same references, so no move from here would be accepted.
|
|
942
|
+
*/
|
|
943
|
+
readonly error: unknown;
|
|
944
|
+
/**
|
|
945
|
+
* True until the reads settle.
|
|
946
|
+
*
|
|
947
|
+
* A form reads its defaults once, at mount, so one mounted while this is true would
|
|
948
|
+
* open on nothing and never take them.
|
|
949
|
+
*/
|
|
950
|
+
readonly loading: boolean;
|
|
951
|
+
}
|
|
952
|
+
|
|
691
953
|
/**
|
|
692
954
|
* Edits weekly availability for one visit service type, either as a Schedule's
|
|
693
955
|
* override of the service hours or as the service's own default hours.
|
|
@@ -713,7 +975,7 @@ export declare type ScheduleAvailabilityEditorProps = ScheduleOverrideEditorProp
|
|
|
713
975
|
export declare interface ScheduleCandidate {
|
|
714
976
|
readonly schedule: WithId<Schedule>;
|
|
715
977
|
/** The actor itself, when the search was able to include it. */
|
|
716
|
-
readonly actorResource:
|
|
978
|
+
readonly actorResource: SchedulingActorResource | undefined;
|
|
717
979
|
}
|
|
718
980
|
|
|
719
981
|
/**
|
|
@@ -734,7 +996,15 @@ export declare interface ScheduleOverrideEditorProps extends CommonProps {
|
|
|
734
996
|
*/
|
|
735
997
|
export declare type SchedulingActor = Schedule['actor'][number];
|
|
736
998
|
|
|
737
|
-
|
|
999
|
+
/** A loaded actor resource. */
|
|
1000
|
+
export declare type SchedulingActorResource = WithId<Dereference<SchedulingActor>>;
|
|
1001
|
+
|
|
1002
|
+
export declare type SchedulingActorType = SchedulingActorResource['resourceType'];
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* An actor as a reference, or as the resource when it has already been read.
|
|
1006
|
+
*/
|
|
1007
|
+
export declare type SchedulingActorValue = SchedulingActor | SchedulingActorResource;
|
|
738
1008
|
|
|
739
1009
|
/**
|
|
740
1010
|
* A data-coordination component pairing {@link CalendarsPanel} with {@link MultiCalendar}.
|
|
@@ -746,9 +1016,9 @@ export declare type SchedulingActorType = Dereference<SchedulingActor>['resource
|
|
|
746
1016
|
* The form writes the booking and announces what it wrote, which is what puts the
|
|
747
1017
|
* new appointment on the calendar beside it — a host supplies no data for any of it.
|
|
748
1018
|
* What was written is reported through `onBooked`, for a host that wants to say so.
|
|
749
|
-
* - Shows what is booked: clicking an appointment opens {@link AppointmentDetails} in
|
|
750
|
-
*
|
|
751
|
-
*
|
|
1019
|
+
* - Shows what is booked: clicking an appointment opens {@link AppointmentDetails} in the
|
|
1020
|
+
* same pane the booking form uses, describing the visit and offering to cancel or
|
|
1021
|
+
* reschedule it.
|
|
752
1022
|
* - Highlights the time last chosen, wherever it was chosen: the click that opened the
|
|
753
1023
|
* pane, then whatever the form's time search settles on, and nothing while the form
|
|
754
1024
|
* holds no time. The calendar is never moved to reach it — a highlight off the week
|
|
@@ -767,11 +1037,32 @@ export declare interface SchedulingWorkspaceProps {
|
|
|
767
1037
|
readonly diagnosisBinding?: string;
|
|
768
1038
|
readonly onBooked?: (booking: AppointmentBooking) => void | Promise<void>;
|
|
769
1039
|
readonly onCancelled?: (appointment: WithId<Appointment>) => void | Promise<void>;
|
|
1040
|
+
readonly onRescheduled?: (reschedule: AppointmentReschedule) => void | Promise<void>;
|
|
770
1041
|
/**
|
|
771
1042
|
* Overrides the value set the appointment detail view offers cancellation reasons
|
|
772
1043
|
* from, for a host coding them against its own terminology.
|
|
773
1044
|
*/
|
|
774
1045
|
readonly appointmentCancellationReasonValueSet?: string;
|
|
1046
|
+
/**
|
|
1047
|
+
* Lets the booking form take a typed time and length, placing a visit the scheduling
|
|
1048
|
+
* rules would refuse: over occupied or blocked time, past the configured capacity,
|
|
1049
|
+
* or at a time or length the visit type does not offer.
|
|
1050
|
+
*
|
|
1051
|
+
* Passing it draws the fields; it enforces nothing. Which users get it is the host
|
|
1052
|
+
* application's responsibility.
|
|
1053
|
+
*
|
|
1054
|
+
* Such a booking is sent as a transaction, so the appointment and its Slots commit
|
|
1055
|
+
* together on projects with the `transaction-bundles` feature enabled. Without it they
|
|
1056
|
+
* are applied as a plain batch, where an appointment that failed to write would leave
|
|
1057
|
+
* Slots holding no visit.
|
|
1058
|
+
* @see https://www.medplum.com/docs/fhir-datastore/fhir-batch-requests#batches-vs-transactions
|
|
1059
|
+
*/
|
|
1060
|
+
readonly canBypassSchedulingRules?: boolean;
|
|
1061
|
+
/**
|
|
1062
|
+
* Extensions to put on every appointment booked from this workspace. See
|
|
1063
|
+
* {@link AppointmentProposalFormProps.appointmentExtensions}.
|
|
1064
|
+
*/
|
|
1065
|
+
readonly appointmentExtensions?: readonly Extension[];
|
|
775
1066
|
}
|
|
776
1067
|
|
|
777
1068
|
/**
|
|
@@ -801,6 +1092,20 @@ export declare interface SearchScheduleCandidatesOptions {
|
|
|
801
1092
|
readonly count?: number;
|
|
802
1093
|
}
|
|
803
1094
|
|
|
1095
|
+
/** Why the current selections cannot be searched. */
|
|
1096
|
+
export declare interface SelectionBlocker {
|
|
1097
|
+
/** A whole sentence to show the user. */
|
|
1098
|
+
readonly message: string;
|
|
1099
|
+
readonly severity: SelectionBlockerSeverity;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Whether a blocker is a form that is not finished yet, or answers that cannot work.
|
|
1104
|
+
*
|
|
1105
|
+
* Only `invalid` is the user's to undo, so only it is worth showing as an error.
|
|
1106
|
+
*/
|
|
1107
|
+
export declare type SelectionBlockerSeverity = 'incomplete' | 'invalid';
|
|
1108
|
+
|
|
804
1109
|
/**
|
|
805
1110
|
* Props for editing a service's own default hours, in place of any one calendar's override.
|
|
806
1111
|
* @param schedule - Omitted, which is what selects this mode.
|
|
@@ -816,10 +1121,10 @@ export declare interface ServiceDefaultEditorProps extends CommonProps {
|
|
|
816
1121
|
/**
|
|
817
1122
|
* Immutably gives a Schedule its own hours for a HealthcareService, in place of the service default.
|
|
818
1123
|
* Reads back through `getEffectiveAvailability`; to drop the calendar back to the default, clear the
|
|
819
|
-
* parameter with `
|
|
1124
|
+
* parameter with `clearScheduleSchedulingParameter(schedule, service, 'availability')` from `@medplum/core`.
|
|
820
1125
|
*
|
|
821
1126
|
* Availability is the one parameter with a typed wrapper, because it is the only one that is not a single
|
|
822
|
-
* `value[x]`: `bufferBefore` and the rest go through `
|
|
1127
|
+
* `value[x]`: `bufferBefore` and the rest go through `setScheduleSchedulingParameter` directly, already legible as
|
|
823
1128
|
* `{ url: 'bufferBefore', valueDuration: { value: 10, unit: 'min' } }`. Availability is a repeating nested
|
|
824
1129
|
* structure, so hand-building it at every call site would mean re-deriving the encoding.
|
|
825
1130
|
*
|
|
@@ -852,6 +1157,16 @@ export declare type TimeOfDay = 'any' | 'morning' | 'afternoon';
|
|
|
852
1157
|
*/
|
|
853
1158
|
export declare function toCodings(elements: readonly ValueSetExpansionContains[]): Coding[];
|
|
854
1159
|
|
|
1160
|
+
export declare function toScheduleCandidate(schedule: WithId<Schedule>, service: WithId<HealthcareService> | undefined, actors: Map<string, SchedulingActorResource>): ScheduleCandidate | undefined;
|
|
1161
|
+
|
|
1162
|
+
/** Rows that cannot all be filled at once, and where to say so. */
|
|
1163
|
+
export declare interface UnsatisfiableRows {
|
|
1164
|
+
/** The actor type whose rows have no answer between them. */
|
|
1165
|
+
readonly actorType: BookableActorType;
|
|
1166
|
+
/** What to do about it, to show against those rows. */
|
|
1167
|
+
readonly message: string;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
855
1170
|
/**
|
|
856
1171
|
* Searches for the times an appointment could be held at.
|
|
857
1172
|
*
|
|
@@ -872,6 +1187,14 @@ export declare interface UseProposedAppointmentsOptions {
|
|
|
872
1187
|
readonly range: DateRange;
|
|
873
1188
|
/** Times to ask for per combination. Defaults to 20. */
|
|
874
1189
|
readonly count?: number;
|
|
1190
|
+
/**
|
|
1191
|
+
* An appointment whose own times are not to count as taken.
|
|
1192
|
+
*
|
|
1193
|
+
* For searching on behalf of an appointment that already exists: the times it holds
|
|
1194
|
+
* are the times it is being moved off, and left standing they would block every
|
|
1195
|
+
* search that keeps any of the actors it is held on.
|
|
1196
|
+
*/
|
|
1197
|
+
readonly ignoreAppointment?: Reference<Appointment> | WithId<Appointment>;
|
|
875
1198
|
}
|
|
876
1199
|
|
|
877
1200
|
export declare interface UseProposedAppointmentsResult {
|
|
@@ -888,6 +1211,23 @@ export declare interface UseProposedAppointmentsResult {
|
|
|
888
1211
|
readonly windowError: string | undefined;
|
|
889
1212
|
}
|
|
890
1213
|
|
|
1214
|
+
/**
|
|
1215
|
+
* Reads what an appointment is currently held on, for a form that offers to move it.
|
|
1216
|
+
*
|
|
1217
|
+
* The visit type comes off `Appointment.serviceType`, which carries a reference to the
|
|
1218
|
+
* HealthcareService it was booked under; the actors come off the Slots it holds, which
|
|
1219
|
+
* name the Schedules — the appointment's own participants would not say which of an
|
|
1220
|
+
* actor's schedules is the one being moved off.
|
|
1221
|
+
*
|
|
1222
|
+
* An actor that cannot be read keeps its schedule, shown under the name the schedule
|
|
1223
|
+
* gives it: the move is written against the schedule, not the actor.
|
|
1224
|
+
*
|
|
1225
|
+
* @param appointment - The appointment being moved.
|
|
1226
|
+
* @returns Its visit type and actors, whether they are still being read, who a move
|
|
1227
|
+
* would drop off it, and why it could not be read, where it could not.
|
|
1228
|
+
*/
|
|
1229
|
+
export declare function useRescheduleDefaults(appointment: WithId<Appointment>): RescheduleDefaults;
|
|
1230
|
+
|
|
891
1231
|
/**
|
|
892
1232
|
* Loads the Appointments for a set of schedules within a date range and keeps them live.
|
|
893
1233
|
*
|