@timum/booking 0.2.4 → 0.3.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.
@@ -0,0 +1,495 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=0.6" />
7
+ <title>timum single instance example</title>
8
+ </head>
9
+
10
+ <body>
11
+ <div id="bookingjs" style="margin: 15px;"></div>
12
+
13
+
14
+ <script type="text/javascript" src="../build/timum-booking.js"></script>
15
+ <script type="text/javascript">
16
+ timum.init(
17
+ {
18
+ ref: "booking-widget-demo-resource@timum",
19
+ calendarFrontend: 'detailsListView', // either fullCalendar or pureListView or detailsListView
20
+
21
+ // here are various callbacks which allow you to run custom code
22
+ // here is the reference for the RKQ portions: https://redux-toolkit.js.org/rtk-query/usage-with-typescript#type-safe-error-handling
23
+ callbacks: {
24
+ // makeup of timeslot:
25
+ /*
26
+ {
27
+ "start": luxon Datetime object. Internal state. "2023-01-27T09:05:00.000Z",
28
+ "end": luxon Datetime object. Internal state. "2023-01-27T09:35:00.000Z",
29
+ "timeslot_uuid": uuid of the booked timeslot. e.g. "82ec5220-9d55-11ed-8617-e4a7a0ca32e8",
30
+ "product_uuid": uuid of the booked product e.g. "92867f70-4836-11e5-bc04-021a52c25043",
31
+ "product_name": string. e.g. "Meeting",
32
+ "resource_name": string. e.g. "Booking Widget DEMO",
33
+ "capacity": number e.g. 1,
34
+ "capacity_left": number e.g. 1,
35
+ "kind": either "models.Bookable" or "models.LotAppointment",
36
+ "untouchedStart": ISO String e.g: "2023-01-27T09:05:00+01:00" as the server sent it,
37
+ "untouchedEnd": ISO String e.g: "2023-01-27T09:35:00+01:00" as the server sent it
38
+ }
39
+ */
40
+
41
+ // makeup of data. Contains properties named after the 'fields' property placed right after 'callbacks'.
42
+ // e.g if you defined field.creditCard : {title: ..., <...>} then it's input value is stored under "creditCard".
43
+ // the fields you see here are hose present if you use timum's standard configuration.
44
+ //
45
+ // --> this allows you to evaluate the input data of your custom fields in these callbacks and act accordingly.
46
+ /*
47
+ {
48
+ "firstName": "Sebastian",
49
+ "lastName": "Müller",
50
+ "email": "sebastian@timum.de",
51
+ "agbs": true
52
+ }
53
+
54
+ */
55
+ createBookingStarted: ({ timeslot, data }) => { console.log(timeslot); console.log(data) },
56
+ createBookingSuccessful: ({ timeslot, response /* an RTKQ response object */, data }) => { },
57
+ createBookingFailed: ({ timeslot, response/* an RTKQ response object */, data }) => { },
58
+
59
+ cancelationgStarted: ({ timeslot, response /* an RTKQ response object */ }) => { },
60
+ cancelationSuccessful: ({ timeslot, response /* an RTKQ response object */ }) => { },
61
+ cancelationFailed: ({ timeslot, response /* an RTKQ response object */ }) => { },
62
+
63
+ // these are requests collecting the necessary information to
64
+ // display the booking frontend
65
+ fetchingPublicDataSucceeded: (publicData) => { },
66
+ fetchingProductsSucceeded: (products) => { },
67
+ fetchingBookablesSucceeded: (bookables) => { },
68
+
69
+ fetchingPublicDataFailed: (error /* an RTKQ error object */) => { },
70
+ fetchingProductsFailed: (error /* an RTKQ error object */) => { },
71
+ fetchingBookablesFailed: (error /* an RTKQ error object */) => { },
72
+ },
73
+
74
+ // The standard fields displayed for unknown customers.
75
+ // You can customise what information is demanded of your customers prior to booking.
76
+ // timum only ever needs firstName, lastName, email and agbs to function (meaning you can savely remove fields 'mobile' and 'message').
77
+ // But you can also add fields of your own.
78
+ //
79
+ // See 'callbacks' to see how you can process input data of your custom fields.
80
+
81
+
82
+ /*
83
+ How to do custom fields
84
+
85
+ Anatomy of a field
86
+ <fieldName> : {
87
+ title: string or JSXElement
88
+ validation: yup based validation. See https://github.com/jquense/yup. Re-exported and accessible via timum.yup
89
+ type: either 'text' (default), 'phoneNumber', 'textarea', 'checkbox' or 'select'
90
+ }
91
+
92
+ Depending on the type there are additional properties you can/must specify:
93
+ Type 'text':
94
+ -> format: string; the native input fields 'type' (... don't judge ^^). Can be 'email', 'number' etc.
95
+
96
+ Type 'phoneNumber':
97
+ -> does NOT support 'validation'. Phone number validation is hard. So timum does it for you.
98
+ This does mean that field validaion localisation is currently not supported for fields of this type.
99
+ This will be fixed in a future update.
100
+ -> isRequired: boolean; if true, this field must be filled with a valid number
101
+
102
+ Type 'textArea':
103
+ -> limit: number; sets the maximum number of characters customers may enter.
104
+
105
+ Type 'checkbox':
106
+ -> no special properties here
107
+
108
+ Type 'select':
109
+ -> options: array of objects. Structure { title: string, key: string };
110
+ 'title' is displayed. 'key' is what you get in the 'data' object passed into callbacks.
111
+
112
+ */
113
+
114
+ fields: {
115
+ firstName: {
116
+ title: 'fields.firstName',
117
+ validation: timum.yup.string().required('validation.field_required'), // <- compare with key in 'localisation'
118
+ },
119
+ lastName: {
120
+ title: 'fields.lastName',
121
+ validation: timum.yup.string().required('validation.field_required'),
122
+ },
123
+ email: {
124
+ title: 'fields.email',
125
+ format: 'email',
126
+ type: 'text',
127
+ validation: timum.yup
128
+ .string()
129
+ .email('validation.email_field_must_be_valid')
130
+ .required('validation.field_required'),
131
+ },
132
+ mobile: {
133
+ title: 'fields.mobile',
134
+ type: 'phoneNumber',
135
+ isRequired: false,
136
+ // validation: is in built and ignored
137
+ },
138
+ message: {
139
+ title: 'fields.message',
140
+ type: 'textarea',
141
+ validation: timum.yup.string().max(1024),
142
+ limit: 1024,
143
+ },
144
+ agbs: {
145
+ title: 'fields.accept_timum_privacy',
146
+ type: 'checkbox',
147
+ validation: timum.yup
148
+ .boolean()
149
+ .required('validation.field_required')
150
+ .test(
151
+ 'privacyAccepted',
152
+ 'validation.privacy_field_required',
153
+ (value) => value === true
154
+ ),
155
+ },
156
+ },
157
+
158
+ // Here are all localization variables and their standard texts.
159
+ // You may change the texts as you see fit.
160
+ // timum supports de and en out of the box.
161
+ // You can easily expand this with fr or it (or any other language)
162
+ // by adding it to the localization object below and translating all of the variables.
163
+ localization: {
164
+ de: {
165
+ product_selection_headline: 'Terminart wählen',
166
+ booked_successfully_header: 'Termin gebucht',
167
+ booked_successfully_message:
168
+ 'Sie erhalten eine E-Mail mit den Termindetails an {{mail}}',
169
+ requested_successfully_header: 'Termin angefragt',
170
+ requested_successfully_message:
171
+ 'Sie erhalten eine E-Mail mit den Termindetails an {{mail}}. Sie werden unter der gleichen Adresse benachrichtigt, sobald Ihre Anfrage bearbeitet wurde.',
172
+ submit_button_book: 'Buchen',
173
+ submit_button_request: 'Verbindlich Anfragen',
174
+
175
+ noEventsMessage:
176
+ 'Zur Zeit sind leider keine buchbaren Termine verfügbar.',
177
+ appoinment_at_capacity: 'vollständig ausgebucht',
178
+ add_to_calendar_btn: 'Zu Kalender hinzufügen',
179
+ until_reservation_expiration:
180
+ '{{expiration}} bis zum Ablauf der Reservierung',
181
+ reservation_expired: 'Reservierung abgelaufen.',
182
+ identified_customer_hint:
183
+ 'Sie wurden mit persönlichem Link eingeladen und können direkt Ihren Termin buchen.',
184
+ cancellation: {
185
+ cancelation_successfull_message: 'Termin erfolgreich abgesagt',
186
+ cancellable_appointment_highlight: 'Mein Termin',
187
+ submit_button_cancel: 'Absagen',
188
+ cancel_appointment_header: 'Ihr Termin',
189
+ message_label: 'Nachricht zur Terminabsage',
190
+ },
191
+ // if you have additional fields with their own validation texts you can add
192
+ // translation keys here and reference them in your custom fields validation.
193
+ // e.g. If you were to add the key 'valid_credit_card' here, you could reference it in your credit card field with 'validation.valid_credit_card'.
194
+ validation: {
195
+ field_required: 'Notwendig',
196
+ privacy_field_required:
197
+ 'Sie müssen die Datenschutzbestimmungen akzeptieren bevor Sie buchen können.',
198
+ email_field_must_be_valid: 'Geben Sie eine valide E-Mail Adresse ein',
199
+ },
200
+ // Similarly to additional validation texts for your custom fields above,
201
+ // you can also add custom labels for them.
202
+ // e.g. add creditCard here and reference it in your custom field's 'title' with 'fields.creditCard'
203
+ fields: {
204
+ firstName: 'Vorname',
205
+ lastName: 'Nachname',
206
+ name: 'Name',
207
+ email: 'E-Mail',
208
+ mobile: 'Mobil',
209
+ message: 'Ihre Nachricht',
210
+ accept_timum_privacy:
211
+ 'Datenschutzbestimmungen gelesen und akzeptiert',
212
+ },
213
+ },
214
+ // the same for english.
215
+ en: {
216
+ product_selection_headline: 'Choose Product',
217
+ booked_successfully_header: 'Appoinment Booked',
218
+ booked_successfully_message:
219
+ 'You will receive an email with appointment details to {{mail}}',
220
+ requested_successfully_header: 'Appointment Requested',
221
+ requested_successfully_message:
222
+ 'You will receive an email with appointment details to {{mail}}. You will be notified at the same address once your request has been processed.',
223
+ submit_button_book: 'Book',
224
+ submit_button_request: 'Request',
225
+
226
+ noEventsMessage:
227
+ 'Unfortunately, there are no bookable dates available at the moment.',
228
+ appoinment_at_capacity: 'fully booked',
229
+ add_to_calendar_btn: 'Add to Calendar',
230
+ until_reservation_expiration:
231
+ '{{expiration}} until reservation expiration.',
232
+ reservation_expired: 'Reservation expired.',
233
+ identified_customer_hint:
234
+ 'You have been invited with a personal link and can book your appointment directly.',
235
+ cancellation: {
236
+ cancelation_successfull_message: 'Appointment canceled sucessfully.',
237
+ cancellable_appointment_highlight: 'My Appointment',
238
+ submit_button_cancel: 'Cancel',
239
+ cancel_appointment_header: 'Your Appointment',
240
+ message_label: 'You may enter a reason here.',
241
+ },
242
+ validation: {
243
+ field_required: 'Required',
244
+ privacy_field_required:
245
+ 'You must accept the privacy policy prior to booking.',
246
+ email_field_must_be_valid: 'Enter a valid email address',
247
+ },
248
+ fields: {
249
+ firstName: 'First name',
250
+ lastName: 'Last name',
251
+ name: 'name',
252
+ email: 'E-mail',
253
+ mobile: 'Mobile',
254
+ message: 'Your Message',
255
+ accept_timum_privacy: '<0>Privacy policy</0> read and accepted.',
256
+ },
257
+ },
258
+ },
259
+ },
260
+ {
261
+ // This is a mui theme object. Documentation: https://mui.com/material-ui/customization/default-theme/
262
+ // If you are in a professional plan you can customise the look and feel of timum booking to your hearts content.
263
+ // otherwise timum's standard theme is used.
264
+
265
+ // Here is an example which alters some aspects of the standard timum theme.
266
+ // (Based on https://github.com/app-generator/react-berry-dashboard)
267
+ palette: {
268
+ common: {
269
+ black: '#000000'
270
+ },
271
+ primary: {
272
+ light: '#e3f2fd',
273
+ main: '#5e35b1',
274
+ },
275
+ secondary: {
276
+ light: '#ede7f6',
277
+ main: '#673ab7',
278
+ dark: '#5e35b1'
279
+ },
280
+ error: {
281
+ main: '#f44336',
282
+ },
283
+ warning: {
284
+ main: '#ffe57f',
285
+ },
286
+ success: {
287
+ main: '#00e676',
288
+ },
289
+ grey: {
290
+ 50: '#fafafa',
291
+ 100: '#f5f5f5',
292
+ 500: '#9e9e9e',
293
+ 600: '#757575',
294
+ 700: '#616161',
295
+ 900: '#212121'
296
+ },
297
+ text: {
298
+ primary: '#616161',
299
+ secondary: '#9e9e9e',
300
+ dark: '#212121',
301
+ hint: '#f5f5f5'
302
+ },
303
+ },
304
+ typography: {
305
+ fontFamily: "'Inter', sans-serif",
306
+ fontSize: "16px",
307
+ h6: {
308
+ fontWeight: 500,
309
+ color: '#757575',
310
+ fontSize: '0.75rem'
311
+ },
312
+ h5: {
313
+ fontSize: '0.875rem',
314
+ color: '#757575',
315
+ fontWeight: 500
316
+ },
317
+ h4: {
318
+ fontSize: '1rem',
319
+ color: '#757575',
320
+ fontWeight: 600
321
+ },
322
+ h3: {
323
+ fontSize: '1.25rem',
324
+ color: '#757575',
325
+ fontWeight: 600
326
+ },
327
+ h2: {
328
+ fontSize: '1.5rem',
329
+ color: '#757575',
330
+ fontWeight: 700
331
+ },
332
+ h1: {
333
+ fontSize: '2.125rem',
334
+ color: '#757575',
335
+ fontWeight: 700
336
+ },
337
+ subtitle1: {
338
+ fontSize: '0.875rem',
339
+ fontWeight: 500,
340
+ color: '#212121'
341
+ },
342
+ subtitle2: {
343
+ fontSize: '0.75rem',
344
+ fontWeight: 400,
345
+ color: '#9e9e9e'
346
+ },
347
+ caption: {
348
+ fontSize: '0.75rem',
349
+ color: '#9e9e9e',
350
+ fontWeight: 400
351
+ },
352
+ body1: {
353
+ fontSize: '0.875rem',
354
+ fontWeight: 400,
355
+ lineHeight: '1.334'
356
+ },
357
+ body2: {
358
+ fontSize: '0.800rem',
359
+ letterSpacing: '0em',
360
+ fontWeight: 400,
361
+ lineHeight: '1.5',
362
+ color: '#616161'
363
+ },
364
+ },
365
+ components: {
366
+ MuiButton: {
367
+ styleOverrides: {
368
+ root: {
369
+ fontWeight: 500,
370
+ textTransform: 'capitalize',
371
+ borderRadius: '16px'
372
+ }
373
+ }
374
+ },
375
+ MuiPaper: {
376
+ defaultProps: {
377
+ elevation: 0
378
+ },
379
+ styleOverrides: {
380
+ root: {
381
+ backgroundImage: 'none'
382
+ },
383
+ rounded: {
384
+ borderRadius: '16px'
385
+ }
386
+ }
387
+ },
388
+
389
+ MuiCardContent: {
390
+ styleOverrides: {
391
+ root: {
392
+ padding: '12px'
393
+ }
394
+ }
395
+ },
396
+ MuiCardActions: {
397
+ styleOverrides: {
398
+ root: {
399
+ padding: '12px'
400
+ }
401
+ }
402
+ },
403
+ MuiListItem: {
404
+ styleOverrides: {
405
+ root: {
406
+ borderRadius: '16px'
407
+ }
408
+ }
409
+ },
410
+ MuiListItemButton: {
411
+ styleOverrides: {
412
+ root: {
413
+ color: '#616161',
414
+ paddingTop: '10px',
415
+ paddingBottom: '10px',
416
+ borderRadius: '16px',
417
+ '&:hover': {
418
+ backgroundColor: '#ede7f6',
419
+ color: '#ede7f6',
420
+ '& .MuiListItemIcon-root': {
421
+ color: '#5e35b1'
422
+ }
423
+ }
424
+ }
425
+ }
426
+ },
427
+ MuiListItemIcon: {
428
+ styleOverrides: {
429
+ root: {
430
+ color: '#616161',
431
+ minWidth: '36px'
432
+ }
433
+ }
434
+ },
435
+ MuiListItemText: {
436
+ styleOverrides: {
437
+ primary: {
438
+ color: '#212121'
439
+ },
440
+ borderRadius: '16px',
441
+ }
442
+ },
443
+ MuiInputBase: {
444
+ styleOverrides: {
445
+ input: {
446
+ color: '#212121',
447
+ '&::placeholder': {
448
+ color: '#212121',
449
+ fontSize: '0.875rem'
450
+ }
451
+ }
452
+ }
453
+ },
454
+ MuiOutlinedInput: {
455
+ styleOverrides: {
456
+ root: {
457
+ background: '#fafafa',
458
+ borderRadius: '16px',
459
+ '& .MuiOutlinedInput-notchedOutline': {
460
+ borderColor: '#bdbdbd'
461
+ },
462
+ '&:hover $notchedOutline': {
463
+ borderColor: '#e3f2fd'
464
+ },
465
+ '&.MuiInputBase-multiline': {
466
+ padding: 1
467
+ }
468
+ },
469
+ input: {
470
+ fontWeight: 500,
471
+ background: '#fafafa',
472
+ padding: '15.5px 14px',
473
+ borderRadius: '16px',
474
+ '&.MuiInputBase-inputSizeSmall': {
475
+ padding: '10px 14px',
476
+ '&.MuiInputBase-inputAdornedStart': {
477
+ paddingLeft: 0
478
+ }
479
+ }
480
+ },
481
+ inputAdornedStart: {
482
+ paddingLeft: 4
483
+ },
484
+ notchedOutline: {
485
+ borderRadius: '16px'
486
+ }
487
+ }
488
+ },
489
+ }
490
+ }
491
+ );
492
+ </script>
493
+ </body>
494
+
495
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timum/booking",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "license": "CC-BY-ND-4.0",
5
5
  "main": "build/timum-booking.js",
6
6
  "publishConfig": {
@@ -1,31 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
-
4
- <head>
5
- <meta charset="UTF-8" />
6
- <meta name="viewport" content="initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=0.6" />
7
- <title>timum single instance example</title>
8
- </head>
9
-
10
- <body>
11
- <div id="bookingjs"></div>
12
- <script type="text/javascript" src="../build/timum-booking.js"></script>
13
- <script type="text/javascript">
14
- timum.init({
15
- appConfig: {
16
- ref: "booking-widget-demo-resource@timum",
17
- fields: {
18
- // shows
19
- // 1. how to create a custom field
20
- // 2. how to use re-exported yup validation lib to set custom form validation on custom fields
21
- yolo: {
22
- title: 'Yolo',
23
- validation: Timum.getYup().string().required(),
24
- }
25
- },
26
- }
27
- });
28
- </script>
29
- </body>
30
-
31
- </html>