@timum/timum_pdk 2.0.7 → 2.0.9

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,348 @@
1
+ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
2
+
3
+ import failsaveStorage from "./util/failSafeLocalStorage";
4
+
5
+ let host = undefined;
6
+ export const setTimumApiHost = (url) => {
7
+ host = url;
8
+ };
9
+
10
+ export const getTimumApiHost = () => {
11
+ if (host) {
12
+ return host;
13
+ } else {
14
+ return failsaveStorage.get("timumApiHost", "https://www.timum.de");
15
+ }
16
+ };
17
+
18
+ // we do it this way so that the base url can be determined dynamically
19
+ export const getBaseUrl = () => {
20
+ return getTimumApiHost() + "/rest/1";
21
+ };
22
+
23
+ export const constructUrl = (url, props, plain) => {
24
+ if (props.params) {
25
+ for (const [paramName, paramValue] of Object.entries(props.params)) {
26
+ if (Array.isArray(paramValue)) {
27
+ for (let el of paramValue) {
28
+ if (!url.includes("?")) {
29
+ url = `${url}?${paramName}=${el}`;
30
+ } else {
31
+ url = `${url}&${paramName}=${el}`;
32
+ }
33
+ }
34
+
35
+ } else {
36
+ if (!url.includes("?")) {
37
+ url = `${url}?${paramName}=${paramValue}`;
38
+ } else {
39
+ url = `${url}&${paramName}=${paramValue}`;
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ if (!url.includes("?")) {
46
+ url = `${url}?X-DISABLE-COOKIES=true`;
47
+ } else {
48
+ url = `${url}&X-DISABLE-COOKIES=true`;
49
+ }
50
+
51
+ if (plain) {
52
+ return `${getTimumApiHost()}${url}`;
53
+ } else {
54
+ return `${getBaseUrl()}${url}`;
55
+ }
56
+ };
57
+
58
+ export const timumApiSlice = createApi({
59
+ reducerPath: "timumApi",
60
+ baseQuery: fetchBaseQuery({
61
+ baseUrl: undefined,
62
+ credentials: "include",
63
+ }),
64
+ tagTypes: [
65
+ "Timeslot",
66
+ "Product",
67
+ "Account",
68
+ "Provider",
69
+ "User",
70
+ "IdentifiedCustomer",
71
+ ],
72
+ endpoints: (builder) => ({
73
+ // ##########################################
74
+ // # ConsumerAPI v2
75
+ // ##########################################
76
+
77
+ upcomingBookables: builder.query({
78
+ query: (props) => ({
79
+ url: constructUrl(
80
+ `/resources/${props.channelOrResourceId}/upcoming_bookables`,
81
+ props
82
+ ),
83
+ headers: props.headers,
84
+ }),
85
+ providesTags: (/* result = [], error, arg */) => ["Timeslot"],
86
+ }),
87
+
88
+ activeProducts: builder.query({
89
+ query: (props) => ({
90
+ url: constructUrl(
91
+ `/resources/${props.channelOrResourceId}/active_products`,
92
+ props
93
+ ),
94
+ headers: props.headers,
95
+ }),
96
+ providesTags: (/* result = [], error, arg */) => ["Product"],
97
+ }),
98
+
99
+ createAppointmentWithConsumer: builder.mutation({
100
+ query: (props) => ({
101
+ url: constructUrl(
102
+ `/resources/${props.channelOrResourceId}/create_appointment_with_consumer`,
103
+ props
104
+ ),
105
+ method: "post",
106
+ body: props.body,
107
+ headers: props.headers,
108
+ }),
109
+ invalidatesTags: (result, error, arg) => {
110
+ const invalidatedTags = [{ type: "Timeslot" }];
111
+
112
+ if (arg.shouldInvalidateCustomerIdentification) {
113
+ invalidatedTags.push({ type: "IdentifiedCustomer" });
114
+ }
115
+
116
+ return invalidatedTags;
117
+ },
118
+ }),
119
+
120
+ removeCustomerFromAppointment: builder.mutation({
121
+ query: (props) => ({
122
+ url: constructUrl(
123
+ `/customers/${props.customersId}/appointments/${props.appointmentId}`,
124
+ props
125
+ ),
126
+ method: "delete",
127
+ headers: props.headers,
128
+ }),
129
+ invalidatesTags: (/* result, error, arg */) => [{ type: "Timeslot" }],
130
+ }),
131
+
132
+ authenticate: builder.query({
133
+ query: (props) => {
134
+ return {
135
+ url: constructUrl(`/auth/cookieless/login`, props, true),
136
+ headers: props.headers,
137
+ method: "post",
138
+ body: props.body,
139
+ };
140
+ },
141
+ }),
142
+
143
+ /**
144
+ * Returns an object with the following makeup:
145
+ * {
146
+ * contact: {
147
+ * name,
148
+ * email,
149
+ * mobile,
150
+ * phone
151
+ * },
152
+ * resource: {
153
+ * name,
154
+ * description,
155
+ * msgHelpText
156
+ * },
157
+ * provider: {
158
+ * name
159
+ * }
160
+ * }
161
+ */
162
+ publicData: builder.query({
163
+ query: (props) => ({
164
+ url: constructUrl(
165
+ `/resources/${props.channelOrResourceId}/public_data`,
166
+ props
167
+ ),
168
+ headers: props.headers,
169
+ }),
170
+ }),
171
+
172
+ identifyCustomer: builder.query({
173
+ query: (props) => ({
174
+ url: constructUrl(
175
+ `/crms/${props.crmSlug}/resources/${props.channelOrResourceId}/customers/${props.personId}/identify`,
176
+ props
177
+ ),
178
+ headers: props.headers,
179
+ }),
180
+ providesTags: "IdentifiedCustomer", //
181
+ keepUnusedDataFor: 9999999, // once identified it's not going to change
182
+ }),
183
+
184
+ /**
185
+ * body contain:
186
+ * resource_id*,
187
+ * product_id*,
188
+ * provider_id,
189
+ * timeslotUuid (if available)
190
+ * from* (ISO format),
191
+ * to* (ISO format)
192
+ * -> * marks those which are required.
193
+ */
194
+ reserveAppoinment: builder.mutation({
195
+ query: (props) => ({
196
+ url: constructUrl(
197
+ `/resources/${props.channelOrResourceId}/reserve_appointment`,
198
+ props
199
+ ),
200
+ method: "post",
201
+ body: props.body,
202
+ headers: props.headers,
203
+ }),
204
+ }),
205
+
206
+ /**
207
+ * body must contain:
208
+ * placeholder_id (id created for ephemeral customer during call to),
209
+ * appointment_id
210
+ */
211
+ revokeAppointmentReservation: builder.mutation({
212
+ query: (props) => ({
213
+ url: constructUrl(
214
+ `/resources/${props.channelOrResourceId}/revoke_reservation`,
215
+ props
216
+ ),
217
+ method: "post",
218
+ body: props.body,
219
+ headers: props.headers,
220
+ }),
221
+ }),
222
+
223
+ // ##########################################
224
+ // # CRM API requests (general api)
225
+ // ##########################################
226
+
227
+ getAccount: builder.query({
228
+ query: (props) => ({
229
+ url: constructUrl(
230
+ `/crms/${props.platform}/account/${props.accountReference}`,
231
+ props
232
+ ),
233
+ }),
234
+ providesTags: (/* result = [], error, arg */) => ["Account"],
235
+ }),
236
+
237
+ createAccount: builder.mutation({
238
+ query: (props) => {
239
+ return {
240
+ url: constructUrl(`/crms/${props.platform}/account`, props),
241
+ method: "post",
242
+ body: JSON.stringify(props.accountData),
243
+ };
244
+ },
245
+ invalidatesTags: (/* result, error, arg */) => [{ type: "Account" }],
246
+ }),
247
+
248
+ getProviders: builder.query({
249
+ query: (props) => ({
250
+ url: constructUrl(
251
+ `/crms/${props.platform}/account/${props.accountReference}/providers`,
252
+ props
253
+ ),
254
+ }),
255
+ providesTags: (/* result = [], error, arg */) => ["Product"],
256
+ }),
257
+
258
+ getProvider: builder.query({
259
+ query: (props) => ({
260
+ url: constructUrl(
261
+ `/crms/${props.platform}/provider/${props.providerReference}`,
262
+ props
263
+ ),
264
+ }),
265
+ }),
266
+
267
+ createProvider: builder.mutation({
268
+ query: (props) => ({
269
+ url: constructUrl(`/crms/${props.platform}/provider`, props),
270
+ method: "post",
271
+ body: JSON.stringify(
272
+ (() => ({
273
+ user: props.userData ?? {},
274
+ provider: props.providerData ?? {},
275
+ address: props.addressData ?? null,
276
+ account: props.account ?? null,
277
+ sendEmail: props.sendEmail ?? false,
278
+ }))()
279
+ ),
280
+ }),
281
+ invalidatesTags: (/* result, error, arg */) => [{ type: "Provider" }],
282
+ }),
283
+
284
+ // loginUserViaApi: builder.query({
285
+ // query: (props) => ({
286
+ // url: constructUrl(`/crms/${props.platform}/user/loginWithJwt`),
287
+ // }),
288
+ // async onQueryStarted(props, { dispatch, queryFulfilled }) {
289
+ // const { data /* , meta */ } = await queryFulfilled;
290
+ // if (data) {
291
+ // dispatch(timumClientAuthorised({ auth2: data.auth2 }));
292
+ // }
293
+ // },
294
+ // }),
295
+ getUser: builder.query({
296
+ query: (props) => ({
297
+ url: constructUrl(
298
+ `/crms/${props.platform}/user/${props.userReference}`,
299
+ props
300
+ ),
301
+ }),
302
+ }),
303
+
304
+ createUser: builder.mutation({
305
+ query: (props) => ({
306
+ url: constructUrl(`/crms/${props.platform}/user`, props),
307
+ method: "post",
308
+ body: JSON.stringify(props.userData),
309
+ }),
310
+ invalidatesTags: (/* result, error, arg */) => [{ type: "User" }],
311
+ }),
312
+ }),
313
+ });
314
+
315
+ export const {
316
+ // ##########################################
317
+ // # ConsumerAPI v2
318
+ // ##########################################
319
+
320
+ useUpcomingBookablesQuery,
321
+ useLazyUpcomingBookablesQuery,
322
+ useActiveProductsQuery,
323
+ useLazyActiveProductsQuery,
324
+ useCreateAppointmentWithConsumerMutation,
325
+ useIdentifyCustomerQuery,
326
+ useLazyIdentifyCustomerQuery,
327
+ usePublicDataQuery,
328
+ useLazyPublicDataQuery,
329
+ useReserveAppoinmentMutation,
330
+ useRevokeAppointmentReservationMutation,
331
+ useRemoveCustomerFromAppointmentMutation,
332
+ useAuthenticateQuery,
333
+ useLazyAuthenticateQuery,
334
+
335
+ // ##########################################
336
+ // # CRM API requests (general api)
337
+ // ##########################################
338
+ useCreateAccountMutation,
339
+ useGetAccountQuery,
340
+ useLazyGetAccountQuery,
341
+ useGetProvidersQuery,
342
+ useLazyGetProvidersQuery,
343
+ useCreateProviderMutation,
344
+ // useLoginUserViaApiQuery,
345
+ useCreateUserMutation,
346
+ useGetUserQuery,
347
+ useLazyGetUserQuery,
348
+ } = timumApiSlice;
@@ -0,0 +1,50 @@
1
+ import { reactLocalStorage } from "reactjs-localstorage";
2
+
3
+ function get(key, defaultValue = undefined, silent = true) {
4
+ if (isLocalStorageAvailable()) {
5
+ return reactLocalStorage.get(key, defaultValue, silent);
6
+ } else {
7
+ return undefined;
8
+ }
9
+ }
10
+
11
+ function set(key, value) {
12
+ if (isLocalStorageAvailable()) {
13
+ reactLocalStorage.set(key, value);
14
+ }
15
+ }
16
+
17
+ function getObject(key, defaultValue = {}, silent = true) {
18
+ if (isLocalStorageAvailable()) {
19
+ return reactLocalStorage.getObject(key, defaultValue, silent);
20
+ } else {
21
+ return undefined;
22
+ }
23
+ }
24
+
25
+ function setObject(key, object) {
26
+ if (isLocalStorageAvailable()) {
27
+ return reactLocalStorage.setObject(key, object);
28
+ }
29
+ return undefined;
30
+ }
31
+
32
+ function isLocalStorageAvailable() {
33
+ var test = "test";
34
+ try {
35
+ localStorage.setItem(test, test);
36
+ localStorage.removeItem(test);
37
+ return true;
38
+ } catch (e) {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ const failsaveStorage = {
44
+ get,
45
+ set,
46
+ getObject,
47
+ setObject,
48
+ };
49
+
50
+ export default failsaveStorage;