@timum/booking 0.6.2 → 0.7.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/README.md +613 -1
- package/build/timum-booking.js +12735 -12706
- package/build/timum-booking.umd.cjs +79 -79
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1 +1,613 @@
|
|
|
1
|
-
|
|
1
|
+
# timum booking
|
|
2
|
+
|
|
3
|
+
## Content
|
|
4
|
+
|
|
5
|
+
- [Basic Usage](#basicUsage)
|
|
6
|
+
- [In a Script Tag](#inAScriptTag)
|
|
7
|
+
- [As ESM import](#asEsmImport)
|
|
8
|
+
- [Advanced Usage](#advancedUsage)
|
|
9
|
+
- [muiTheme](#muiTheme)
|
|
10
|
+
- [fcConfig](#fullCalendar)
|
|
11
|
+
- [appConfig](#appConfig)
|
|
12
|
+
- [How to use Callbacks](#howToUseCallbacks)
|
|
13
|
+
- [Booking Related](#bookingRelated)
|
|
14
|
+
- [Cancelation Related](#cancelationRelated)
|
|
15
|
+
- [Data Fetching Related](#dataFetchingRelated)
|
|
16
|
+
- [Localisation](#localisation)
|
|
17
|
+
- [How to Define Fields](#howToDefineFields)
|
|
18
|
+
- [Anatomy of a Field](#anatomyOfAField)
|
|
19
|
+
- [An Example](#anExample)
|
|
20
|
+
- [The Scenario](#theScenario)
|
|
21
|
+
- [The Implementation](#theImplementation)
|
|
22
|
+
|
|
23
|
+
### Basic Usage {#basicUsage}
|
|
24
|
+
|
|
25
|
+
#### In a Script Tag {#inAScriptTag}
|
|
26
|
+
|
|
27
|
+
Add the following code to your webpage:
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<div id="bookingjs" style="margin: 32px"></div>
|
|
31
|
+
<script type="module">
|
|
32
|
+
import * as timum from 'https://cdn.jsdelivr.net/npm/@timum/booking@0.6.3/build/timum-booking.js';
|
|
33
|
+
|
|
34
|
+
timum.init({ ref: 'booking-widget-demo-resource@timum' });
|
|
35
|
+
</script>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
A working fiddle can be found [here](https://jsfiddle.net/timum/3swq1tdy/).
|
|
39
|
+
|
|
40
|
+
Alternatively, you can add `ref` to your url as a parameter. This allows you to omit `ref` in the javascript portion. Like this:
|
|
41
|
+
|
|
42
|
+
`https://your.website.nic?ref=<enter resource reference here>`
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<div id="bookingjs" style="margin: 32px"></div>
|
|
46
|
+
<script type="module">
|
|
47
|
+
import * as timum from 'https://cdn.jsdelivr.net/npm/@timum/booking@0.6.3/build/timum-booking.js';
|
|
48
|
+
|
|
49
|
+
timum.init(); //<- no need for the reference here
|
|
50
|
+
</script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### As ESM import {#asEsmImport}
|
|
54
|
+
|
|
55
|
+
1. Add timum-booking to your project with
|
|
56
|
+
`yarn add @timum/booking`
|
|
57
|
+
or use npm with
|
|
58
|
+
`npm install @timum/booking`
|
|
59
|
+
<br>
|
|
60
|
+
2. Add `<div id="bookingjs" style="margin: 32px"></div>` where you want timum to be displayed (the margin is just a sggestion, not mandatory).
|
|
61
|
+
<br>
|
|
62
|
+
3. Add the following code to one of your .js files:
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
import { init } from '@timum/booking';
|
|
66
|
+
|
|
67
|
+
init({ ref: 'booking-widget-demo-resource@timum' });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
A example project can be found [here](https://stackblitz.com/edit/react-8q6r8b?file=src/index.js)
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### Advanced usage {#advancedUsage}
|
|
75
|
+
|
|
76
|
+
timum booking has a lot of customisation options.
|
|
77
|
+
|
|
78
|
+
The init accepts the following arguements in the order listed here.
|
|
79
|
+
The following table gives a rough overview over each.
|
|
80
|
+
|
|
81
|
+
| Arguments | Description |
|
|
82
|
+
| --------- | -------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| appConfig | object, containing various options like callbacks, localiation, input fields etc. |
|
|
84
|
+
| muiTheme | object, mui theme allowing you to change the look and feel of timum. Requires a professional plan. |
|
|
85
|
+
| fcConfig | object, only used if you use full calendar as a booking frontend (settable in appConfig). |
|
|
86
|
+
|
|
87
|
+
#### muiTheme {#muiTheme}
|
|
88
|
+
|
|
89
|
+
timum uses mui components for all frontends. The muiTheme object allows global design changes.
|
|
90
|
+
See [here](https://mui.com/) for a general overview. <br> See [here](https://mui.com/material-ui/customization/default-theme/) for theme related documentation.
|
|
91
|
+
|
|
92
|
+
When you open the file `config.js` in [this](https://stackblitz.com/edit/react-8q6r8b?file=src/index.js) example, you can find an elaborate custom configuration which includes a redesign of the standard timum theme.
|
|
93
|
+
|
|
94
|
+
#### fcConfig {#fullCalendar}
|
|
95
|
+
|
|
96
|
+
FullCalendar can be set as one of the frontends in appConfig.
|
|
97
|
+
See [here](https://fullcalendar.io/docs#toc) for a full list of configuration options.
|
|
98
|
+
|
|
99
|
+
> Note that since fullCalendar isn't mui based, it does not consider the muiTheme object.
|
|
100
|
+
|
|
101
|
+
#### appConfig {#appConfig}
|
|
102
|
+
|
|
103
|
+
This object's options directly affect timum's behaviour or allow you to react to it.
|
|
104
|
+
|
|
105
|
+
<table>
|
|
106
|
+
<tr>
|
|
107
|
+
<th>Property</th>
|
|
108
|
+
<th>Description</th>
|
|
109
|
+
</tr>
|
|
110
|
+
<tr>
|
|
111
|
+
<td>ref</td>
|
|
112
|
+
<td>string, Reference of the resource to show the appointments of. <br><em> This is the only prop that is mandatory.</em><br> Everything else is optional. <br>Can also be a url parameter.</td>
|
|
113
|
+
</tr>
|
|
114
|
+
<tr>
|
|
115
|
+
<td>height</td>
|
|
116
|
+
<td> string, Height of timum on your page. `500px` is standard.</td>
|
|
117
|
+
</tr>
|
|
118
|
+
<tr>
|
|
119
|
+
<td>channelKey</td>
|
|
120
|
+
<td>string, timum has, as of now, 4 different channels through which you can share your resource's appointments. <br> You can find them in the timum frontend under <resource name> -> Calendar Sharing (Terminbuchung freigeben). <br> Every channel has its own settings allowing you to control whom of your customers can see certain appointments, whether they book directly or create a request first and other settings. <br> Valid values for this attribute are: <br>
|
|
121
|
+
- RESOURCE_PUBLIC <br> referring to "Public Booking Link" (Öffentlicher Buchungs-Link) <br>
|
|
122
|
+
- RESOURCE_EXCLUSIVE <br> referring to "Exclusive Booking Access" (Exklusiver Buchungs-Zugang) <br>
|
|
123
|
+
- RESOURCE_REFERENCE <br> referring to "Embedded booking calendars" (Eingebettete Buchungskalender) <br>
|
|
124
|
+
- CALENDAR_PUBLIC <br> referring to "In all Website Plugin Views and your General Calendar" (In Website-Plugin Ansichten sowie Ihrem Gesamtkalender) <br>RESOURCE_PUBLIC is the default, used if you specify nothing else. <br><br>Can also be a url parameter. </td>
|
|
125
|
+
</tr>
|
|
126
|
+
<tr>
|
|
127
|
+
<td>calendarFrontend</td>
|
|
128
|
+
<td>string, one of `fullCalendar` (that's what `init`'s 3rd parameter is for), `pureListView` or `detailsListView`</td>
|
|
129
|
+
</tr>
|
|
130
|
+
<tr>
|
|
131
|
+
<td>culture</td>
|
|
132
|
+
<td>string, The localisation to use. If not specified the browser language is used. Can also be a url parameter.</td>
|
|
133
|
+
</tr>
|
|
134
|
+
<tr>
|
|
135
|
+
<td>pData</td>
|
|
136
|
+
<td>object, <br> Data indentifying the customer, so that they don't have to input their data again. <br> Works in conjunction with timum and select, supported plaforms like OnOffice, Immosolve etc. <br> Properties: <br>
|
|
137
|
+
<code>{ platform: string, personId: string }</code>
|
|
138
|
+
<br> Can also be a url parameter. -> the params are named differently though: pDataPlatform, pDataId</td>
|
|
139
|
+
</tr>
|
|
140
|
+
<tr>
|
|
141
|
+
<td>callbacks</td>
|
|
142
|
+
<td>object, may contain various functions which allow to to run custom code in reaction to certain events. See below for a guide on how to do this. </td>
|
|
143
|
+
</tr>
|
|
144
|
+
<tr>
|
|
145
|
+
<td>fields</td>
|
|
146
|
+
<td>object, You can customise what information is demanded of your customers prior to booking. timum requires certain fields to work and has some optional fields it can parse. Fields other than those supported by timum can be evaluated in a callback (see the callback guide below for further info). All fields (yours too!) support localization and input validation. </td>
|
|
147
|
+
</tr>
|
|
148
|
+
<tr>
|
|
149
|
+
<td>localization</td>
|
|
150
|
+
<td>object. Contains all localization variables and their standard texts. timum nativly supports English and German. Use this to override the standard text and/or add translations for your custom field labels and input validations (see the localisation guide for mor info.)</td>
|
|
151
|
+
</tr>
|
|
152
|
+
</table>
|
|
153
|
+
|
|
154
|
+
##### How to use callbacks {#howToUseCallbacks}
|
|
155
|
+
|
|
156
|
+
The callbacks object may contain any of the following functions.
|
|
157
|
+
|
|
158
|
+
###### Booking related {#bookingRelated}
|
|
159
|
+
|
|
160
|
+
- `createBookingStarted`
|
|
161
|
+
- `createBookingSuccessfull`
|
|
162
|
+
- `createBookingFailed`
|
|
163
|
+
|
|
164
|
+
All Booking related callbacks receive a <em>single obejct</em> as argument containing the following properties:
|
|
165
|
+
|
|
166
|
+
- a `timeslot` looking like this:
|
|
167
|
+
```
|
|
168
|
+
{
|
|
169
|
+
start: luxon Datetime object. Internal state. "2023-01-27T09:05:00.000Z",
|
|
170
|
+
end: luxon Datetime object. Internal state. "2023-01-27T09:35:00.000Z",
|
|
171
|
+
timeslot_uuid: uuid of the booked timeslot. e.g. "82ec5220-9d55-11ed-8617-e4a7a0ca32e8",
|
|
172
|
+
product_uuid: uuid of the booked product e.g. "92867f70-4836-11e5-bc04-021a52c25043",
|
|
173
|
+
product_name: string. e.g. "Meeting",
|
|
174
|
+
resource_name: string. e.g. "Booking Widget DEMO",
|
|
175
|
+
capacity: number e.g. 1,
|
|
176
|
+
capacity_left: number e.g. 1,
|
|
177
|
+
kind: either "models.Bookable" or "models.LotAppointment",
|
|
178
|
+
untouchedStart: ISO String e.g: "2023-01-27T09:05:00+01:00" as the server sent it,
|
|
179
|
+
untouchedEnd: ISO String e.g: "2023-01-27T09:35:00+01:00" as the server sent it
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
- a `data` looking like this:
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
{
|
|
186
|
+
firstName: 'string',
|
|
187
|
+
lastName: 'string',
|
|
188
|
+
email: 'string',
|
|
189
|
+
agbs: 'bool'
|
|
190
|
+
|
|
191
|
+
// plus whatever optional and/or custom fields you yourself has defined.
|
|
192
|
+
// -> so the makeup of this object changes depending on your settings.
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Additionally, `createBookingFailed` and `createBookingSuccessfull` also have a RTKQ `response` object in their respecive argument. See [here](https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling) for a reference.
|
|
198
|
+
|
|
199
|
+
###### Cancelation Related {#cancelationRelated}
|
|
200
|
+
|
|
201
|
+
- `cancelationStarted`
|
|
202
|
+
- `cancelationSuccessful`
|
|
203
|
+
- `cancelationFailed`
|
|
204
|
+
|
|
205
|
+
All cancelation related callbacks receive a single obejct as argument containing the same properties as described in [Booking related](#bookingRelated)
|
|
206
|
+
|
|
207
|
+
Additionally, `cancelationSuccessful` and `cancelationFailed` also have a RTKQ response object in their respecive argument. See here for a reference.
|
|
208
|
+
|
|
209
|
+
###### Data Fetching Related {#dataFetchingRelated}
|
|
210
|
+
|
|
211
|
+
In order to display public appointments, resource and calendar information timum sends several requests.
|
|
212
|
+
|
|
213
|
+
- `fetchingPublicDataSucceeded`
|
|
214
|
+
Gets passed in a single object looking like this:
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
{
|
|
218
|
+
contact: {
|
|
219
|
+
name: 'string',
|
|
220
|
+
email: 'string',
|
|
221
|
+
mobile: 'string',
|
|
222
|
+
phone: 'string',
|
|
223
|
+
},
|
|
224
|
+
resource: {
|
|
225
|
+
name: 'string', //<- 80 chars, max length of names in timum
|
|
226
|
+
description: 'string',
|
|
227
|
+
msgHelpText: 'string',
|
|
228
|
+
},
|
|
229
|
+
provider: {
|
|
230
|
+
name: 'string',
|
|
231
|
+
description: 'string',
|
|
232
|
+
isBrandingAllowed: 'boolean',
|
|
233
|
+
},
|
|
234
|
+
channel: {
|
|
235
|
+
bookingProcess: 'string' // One of 'IMMEDIATE' or 'REQUESTED',
|
|
236
|
+
},
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
- `fetchingPublicDataFailed`
|
|
241
|
+
receives a single RTKQ error object. See [here](https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling) for a reference.
|
|
242
|
+
<br>
|
|
243
|
+
- `fetchingProductsSucceeded`
|
|
244
|
+
Gets passed in a single object looking like this:
|
|
245
|
+
```javascript
|
|
246
|
+
{
|
|
247
|
+
products: [
|
|
248
|
+
{
|
|
249
|
+
description: string,
|
|
250
|
+
minDuration: number,
|
|
251
|
+
name: string,
|
|
252
|
+
uuid
|
|
253
|
+
}
|
|
254
|
+
//...
|
|
255
|
+
];
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
- `fetchingProductsFailed`
|
|
259
|
+
receives a single RTKQ error object. See [here](https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling) for a reference.
|
|
260
|
+
<br>
|
|
261
|
+
- `fetchingBookablesSucceeded`
|
|
262
|
+
Gets passed in a single object looking like this:
|
|
263
|
+
```javascript
|
|
264
|
+
{
|
|
265
|
+
2023-02-06: [ //<- this obviously changes depending on when appointments are available.
|
|
266
|
+
0: {
|
|
267
|
+
timeslot_uuid: uuid of the booked timeslot,
|
|
268
|
+
product_uuid: uuid of the booked product,
|
|
269
|
+
product_name: string,
|
|
270
|
+
resource_name: string,
|
|
271
|
+
capacity: number,
|
|
272
|
+
capacity_left: number,
|
|
273
|
+
kind: one of "models.Bookable" or "models.LotAppointment",
|
|
274
|
+
start: ISO String e.g: "2023-02-06T09:05:00+01:00",
|
|
275
|
+
end: ISO String e.g: "2023-02-06T09:35:00+01:00"
|
|
276
|
+
},
|
|
277
|
+
//... more appointments ...
|
|
278
|
+
],
|
|
279
|
+
//... more dates ...
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
- `fetchingBookablesFailed`
|
|
283
|
+
receives a single RTKQ error object. See [here](https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling) for a reference.
|
|
284
|
+
<br>
|
|
285
|
+
|
|
286
|
+
##### Localisation {#localisation}
|
|
287
|
+
|
|
288
|
+
timum booking has the ability to change all of its text. It comes with English and German pre-installed, but you can add additional translations as well. You can also change the text for these languages to your preference. You don't have to redefine the entire localization object; you can just add or change the specific texts you want. Any missing texts will be taken from the default.
|
|
289
|
+
The code snippet provided shows the complete localization object and the standard text for both English and German. For each language, it includes text for different parts of the booking process such as product selection, appointment booking, appointment request, appointment cancellation, form fields, and more.
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
localization: {
|
|
293
|
+
de: {
|
|
294
|
+
product_selection_headline: 'Terminart wählen',
|
|
295
|
+
booked_successfully_header: 'Termin gebucht',
|
|
296
|
+
booked_successfully_message:
|
|
297
|
+
'Sie erhalten eine E-Mail mit den Termindetails an {{mail}}',
|
|
298
|
+
requested_successfully_header: 'Termin angefragt',
|
|
299
|
+
requested_successfully_message:
|
|
300
|
+
'Sie erhalten eine E-Mail mit den Termindetails an {{mail}}. Sie werden unter der gleichen Adresse benachrichtigt, sobald Ihre Anfrage bearbeitet wurde.',
|
|
301
|
+
submit_button_book: 'Buchen',
|
|
302
|
+
submit_button_request: 'Verbindlich Anfragen',
|
|
303
|
+
|
|
304
|
+
noEventsMessage:
|
|
305
|
+
'Zur Zeit sind leider keine buchbaren Termine verfügbar.',
|
|
306
|
+
appoinment_at_capacity: 'vollständig ausgebucht',
|
|
307
|
+
add_to_calendar_btn: 'Zu Kalender hinzufügen',
|
|
308
|
+
until_reservation_expiration:
|
|
309
|
+
'{{expiration}} bis zum Ablauf der Reservierung',
|
|
310
|
+
reservation_expired: 'Reservierung abgelaufen.',
|
|
311
|
+
identified_customer_hint:
|
|
312
|
+
'Sie wurden mit persönlichem Link eingeladen und können direkt Ihren Termin buchen.',
|
|
313
|
+
reservation_failed: {
|
|
314
|
+
title: 'Hohe Nachfrage',
|
|
315
|
+
mesage:
|
|
316
|
+
'Dieser Termin wurde gerade durch jemanden reserviert. Bitte wählen' +
|
|
317
|
+
'Sie einen anderen Termin. Oder schauen Sie später noch einmal, ob' +
|
|
318
|
+
'ein Termin frei wird.',
|
|
319
|
+
},
|
|
320
|
+
cancellation: {
|
|
321
|
+
cancelation_successfull_message: 'Termin erfolgreich abgesagt',
|
|
322
|
+
cancellable_appointment_highlight: 'Mein Termin',
|
|
323
|
+
submit_button_cancel: 'Absagen',
|
|
324
|
+
cancel_appointment_header: 'Ihr Termin',
|
|
325
|
+
message_label: 'Nachricht zur Terminabsage',
|
|
326
|
+
},
|
|
327
|
+
validation: {
|
|
328
|
+
field_required: 'Notwendig',
|
|
329
|
+
privacy_field_required:
|
|
330
|
+
'Sie müssen die Datenschutzbestimmungen akzeptieren bevor Sie buchen können.',
|
|
331
|
+
email_field_must_be_valid: 'Geben Sie eine valide E-Mail Adresse ein',
|
|
332
|
+
},
|
|
333
|
+
fields: {
|
|
334
|
+
firstName: 'Vorname',
|
|
335
|
+
lastName: 'Nachname',
|
|
336
|
+
name: 'Name',
|
|
337
|
+
email: 'E-Mail',
|
|
338
|
+
mobile: 'Mobil',
|
|
339
|
+
message: 'Ihre Nachricht',
|
|
340
|
+
accept_timum_privacy:
|
|
341
|
+
'Datenschutzbestimmungen gelesen und akzeptiert',
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
// the same for english.
|
|
345
|
+
en: {
|
|
346
|
+
product_selection_headline: 'Choose Product',
|
|
347
|
+
booked_successfully_header: 'Appoinment Booked',
|
|
348
|
+
booked_successfully_message:
|
|
349
|
+
'You will receive an email with appointment details to {{mail}}',
|
|
350
|
+
requested_successfully_header: 'Appointment Requested',
|
|
351
|
+
requested_successfully_message:
|
|
352
|
+
'You will receive an email with appointment details to {{mail}}. You will be notified at the same address once your request has been processed.',
|
|
353
|
+
submit_button_book: 'Book',
|
|
354
|
+
submit_button_request: 'Request',
|
|
355
|
+
|
|
356
|
+
noEventsMessage:
|
|
357
|
+
'Unfortunately, there are no bookable dates available at the moment.',
|
|
358
|
+
appoinment_at_capacity: 'fully booked',
|
|
359
|
+
add_to_calendar_btn: 'Add to Calendar',
|
|
360
|
+
until_reservation_expiration:
|
|
361
|
+
'{{expiration}} until reservation expiration.',
|
|
362
|
+
reservation_expired: 'Reservation expired.',
|
|
363
|
+
identified_customer_hint:
|
|
364
|
+
'You have been invited with a personal link and can book your appointment directly.',
|
|
365
|
+
reservation_failed: {
|
|
366
|
+
title: 'High Demand',
|
|
367
|
+
mesage:
|
|
368
|
+
'This appointment has just been reserved by someone. Please choose another appointment. Or check back later to see if an appointment becomes available.',
|
|
369
|
+
},
|
|
370
|
+
cancellation: {
|
|
371
|
+
cancelation_successfull_message: 'Appointment canceled sucessfully.',
|
|
372
|
+
cancellable_appointment_highlight: 'My Appointment',
|
|
373
|
+
submit_button_cancel: 'Cancel',
|
|
374
|
+
cancel_appointment_header: 'Your Appointment',
|
|
375
|
+
message_label: 'You may enter a reason here.',
|
|
376
|
+
},
|
|
377
|
+
validation: {
|
|
378
|
+
field_required: 'Required',
|
|
379
|
+
privacy_field_required:
|
|
380
|
+
'You must accept the privacy policy prior to booking.',
|
|
381
|
+
email_field_must_be_valid: 'Enter a valid email address',
|
|
382
|
+
},
|
|
383
|
+
fields: {
|
|
384
|
+
firstName: 'First name',
|
|
385
|
+
lastName: 'Last name',
|
|
386
|
+
name: 'name',
|
|
387
|
+
email: 'E-mail',
|
|
388
|
+
mobile: 'Mobile',
|
|
389
|
+
message: 'Your Message',
|
|
390
|
+
accept_timum_privacy: '<0>Privacy policy</0> read and accepted.',
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
##### How to define fields {#howToDefineFields}
|
|
397
|
+
|
|
398
|
+
You can customize the information required from customers before booking by defining fields. The minimum required fields for timum are firstName, lastName, email, and agbs. By default, timum also requests mobile and message fields, but you can add your own fields as well.
|
|
399
|
+
|
|
400
|
+
Fields, including custom ones, support validation and localization.
|
|
401
|
+
Validation is realized using the yup library, which is included with timum. You can import it using the following code:
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
import { yup } from '@timum/booking';
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Localization is achieved by using the title property in the field definition. You can specify a translation key and add the corresponding translation to the localization object. The same process can be applied to custom field validations.
|
|
408
|
+
|
|
409
|
+
The standard configuration can be overridden except for the aforementioned fields. The following is the standard configuration:
|
|
410
|
+
|
|
411
|
+
```javascript
|
|
412
|
+
fields: {
|
|
413
|
+
firstName: {
|
|
414
|
+
title: 'fields.firstName',
|
|
415
|
+
validation: yup.string().required('validation.field_required'), // <- compare with key in 'localization'
|
|
416
|
+
},
|
|
417
|
+
lastName: {
|
|
418
|
+
title: 'fields.lastName',
|
|
419
|
+
validation: yup.string().required('validation.field_required'),
|
|
420
|
+
},
|
|
421
|
+
email: {
|
|
422
|
+
title: 'fields.email',
|
|
423
|
+
format: 'email',
|
|
424
|
+
type: 'text',
|
|
425
|
+
validation: yup
|
|
426
|
+
.string()
|
|
427
|
+
.email('validation.email_field_must_be_valid')
|
|
428
|
+
.required('validation.field_required'),
|
|
429
|
+
},
|
|
430
|
+
mobile: {
|
|
431
|
+
title: 'fields.mobile',
|
|
432
|
+
type: 'phoneNumber',
|
|
433
|
+
isRequired: false,
|
|
434
|
+
// validation: is in built and ignored
|
|
435
|
+
},
|
|
436
|
+
message: {
|
|
437
|
+
title: 'fields.message',
|
|
438
|
+
type: 'textarea',
|
|
439
|
+
validation: yup.string().max(1024),
|
|
440
|
+
limit: 1024,
|
|
441
|
+
},
|
|
442
|
+
agbs: {
|
|
443
|
+
title: 'fields.accept_timum_privacy',
|
|
444
|
+
type: 'checkbox',
|
|
445
|
+
validation: yup
|
|
446
|
+
.boolean()
|
|
447
|
+
.required('validation.field_required')
|
|
448
|
+
.test(
|
|
449
|
+
'privacyAccepted',
|
|
450
|
+
'validation.privacy_field_required',
|
|
451
|
+
(value) => value === true
|
|
452
|
+
),
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
###### Anatomy of a field {#anatomyOfAField}
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
<fieldName> : {
|
|
461
|
+
title: string or JSXElement;
|
|
462
|
+
validation: yup based validation. See https://github.com/jquense/yup. Re-exported and accessible via timum.yup
|
|
463
|
+
type: string; either 'text' (default), 'phoneNumber', 'textarea', 'checkbox' or 'select',
|
|
464
|
+
prefilled: string; value a fiels is initiated with. Not that for fields of type 'select' you must use the 'key' of on of it's options.
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Depending on the type there are additional properties you can/must specify:
|
|
469
|
+
|
|
470
|
+
- Type `text`:
|
|
471
|
+
|
|
472
|
+
- `format`: string; the native input field's 'type' (e.g. 'email', 'number', etc.).
|
|
473
|
+
|
|
474
|
+
- Type `phoneNumber`:
|
|
475
|
+
|
|
476
|
+
- does NOT support `validation`. Phone number validation is complex, so timum handles it for you.
|
|
477
|
+
This does mean that field validation localisation is currently not supported for fields of this type.
|
|
478
|
+
This will be fixed in a future update.
|
|
479
|
+
- isRequired: boolean; if true, this field must be filled with a valid number
|
|
480
|
+
|
|
481
|
+
- Type `textArea`:
|
|
482
|
+
|
|
483
|
+
- limit: number; sets the maximum number of characters customers can enter.
|
|
484
|
+
|
|
485
|
+
- Type `checkbox`:
|
|
486
|
+
- no special properties.
|
|
487
|
+
|
|
488
|
+
Type `select`:
|
|
489
|
+
|
|
490
|
+
- options: array of objects with structure { title: string, key: string }. The title is displayed and the key is passed in the data object to callbacks.
|
|
491
|
+
|
|
492
|
+
#### An Example {#anExample}
|
|
493
|
+
|
|
494
|
+
Here is an example Tying all of the aforementioned concepts together.
|
|
495
|
+
|
|
496
|
+
##### The Scenario {#theScenario}
|
|
497
|
+
|
|
498
|
+
For whatever reason it is important to know the gender of customers.
|
|
499
|
+
On the other side the optional fields `mobile` and `message` aren't important for you and you wish to remove them.
|
|
500
|
+
This new gender field must be filled, therefore a validation is required.
|
|
501
|
+
Both the title of the field and it's validations must be localized.
|
|
502
|
+
|
|
503
|
+
##### The Implementation {#theImplementation}
|
|
504
|
+
|
|
505
|
+
This is the base configuration. As it is it uses the standard field configuration shown in [How to define fields](#howToDefineFields).
|
|
506
|
+
|
|
507
|
+
```html
|
|
508
|
+
<div id="bookingjs" style="margin: 32px"></div>
|
|
509
|
+
<script type="module">
|
|
510
|
+
import * as timum from 'https://cdn.jsdelivr.net/npm/@timum/booking@0.6.3/build/timum-booking.js';
|
|
511
|
+
|
|
512
|
+
timum.init({ ref: 'booking-widget-demo-resource@timum' });
|
|
513
|
+
</script>
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Let's add the necessary changes:
|
|
517
|
+
|
|
518
|
+
```html
|
|
519
|
+
<div id="bookingjs" style="margin: 32px"></div>
|
|
520
|
+
<script type="module">
|
|
521
|
+
import * as timum from 'https://cdn.jsdelivr.net/npm/@timum/booking@0.6.3/build/timum-booking.js';
|
|
522
|
+
|
|
523
|
+
timum.init(
|
|
524
|
+
{
|
|
525
|
+
ref: 'booking-widget-demo-resource@timum',
|
|
526
|
+
fields: {
|
|
527
|
+
// set these fields to undefined explicitly in order to remove them
|
|
528
|
+
message: undefined,
|
|
529
|
+
mobile: undefined,
|
|
530
|
+
firstName: {
|
|
531
|
+
// index defines the order in which the fields get displayed
|
|
532
|
+
index: 0,
|
|
533
|
+
title: 'fields.firstName',
|
|
534
|
+
validation: yup.string().required('validation.field_required'), // <- compare with key in localisation
|
|
535
|
+
},
|
|
536
|
+
lastName: {
|
|
537
|
+
index: 1,
|
|
538
|
+
title: 'fields.lastName',
|
|
539
|
+
validation: yup.string().required('validation.field_required'),
|
|
540
|
+
},
|
|
541
|
+
email: {
|
|
542
|
+
index: 2,
|
|
543
|
+
title: 'fields.email',
|
|
544
|
+
format: 'email',
|
|
545
|
+
type: 'text',
|
|
546
|
+
validation: yup
|
|
547
|
+
.string()
|
|
548
|
+
.email('validation.email_field_must_be_valid')
|
|
549
|
+
.required('validation.field_required'),
|
|
550
|
+
},
|
|
551
|
+
gender: {
|
|
552
|
+
index: 3,
|
|
553
|
+
// new language key
|
|
554
|
+
title: 'fields.gender.title',
|
|
555
|
+
// best for a limited number of predefined choices
|
|
556
|
+
type: 'select',
|
|
557
|
+
// could use 'validation.field_required' but
|
|
558
|
+
// for this example let's create a new key
|
|
559
|
+
validation: yup.string().required('validation.gender_field_required'),
|
|
560
|
+
options: [
|
|
561
|
+
{ key: 'm', title: 'fields.gender.male' },
|
|
562
|
+
{ key: 'w', title: 'fields.gender.female' },
|
|
563
|
+
{ key: 'd', title: 'fields.gender.other' },
|
|
564
|
+
],
|
|
565
|
+
},
|
|
566
|
+
agbs: {
|
|
567
|
+
index: 4,
|
|
568
|
+
title: 'Datenschutzbestimmungen gelesen und akzeptiert.',
|
|
569
|
+
type: 'checkbox',
|
|
570
|
+
validation: yup
|
|
571
|
+
.boolean()
|
|
572
|
+
.required('validation.field_required')
|
|
573
|
+
.test(
|
|
574
|
+
'privacyAccepted',
|
|
575
|
+
'validation.privacy_field_required',
|
|
576
|
+
(value) => value === true
|
|
577
|
+
),
|
|
578
|
+
},
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// now we need to add the new translation keys and their translations.
|
|
582
|
+
|
|
583
|
+
localization: {
|
|
584
|
+
de: {
|
|
585
|
+
validation: {
|
|
586
|
+
gender_field_required: 'Bitte wählen.'
|
|
587
|
+
},
|
|
588
|
+
fields: {
|
|
589
|
+
gender: {
|
|
590
|
+
title: 'Geschlecht',
|
|
591
|
+
male: 'Männlich',
|
|
592
|
+
female: 'Weiblich',
|
|
593
|
+
other: 'Divers'
|
|
594
|
+
},
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
en: {
|
|
598
|
+
validation: {
|
|
599
|
+
gender_field_required: 'Please select an option.'
|
|
600
|
+
},
|
|
601
|
+
fields: {
|
|
602
|
+
gender: {
|
|
603
|
+
title: 'Gender',
|
|
604
|
+
male: 'Male',
|
|
605
|
+
female: 'Female',
|
|
606
|
+
other: 'Others'
|
|
607
|
+
},
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
</script>
|
|
613
|
+
```
|