@infosoftas/s4-orders-js-sdk 0.0.1-beta1 → 0.0.1-beta1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infosoftas/s4-orders-js-sdk",
3
- "version": "0.0.1-beta1",
3
+ "version": "0.0.1-beta1.0",
4
4
  "scripts": {
5
5
  "build": "rimraf lib && webpack --env mode=production",
6
6
  "release": "release-it"
package/src/App.tsx CHANGED
@@ -255,11 +255,19 @@ const App: FC<ConfigType> = ({
255
255
  setFormType(FormTypeEnum.ORDER);
256
256
  };
257
257
 
258
- const handleInvoiceForm = async () => {
258
+ const updateFormData = (data: OrderFormInputsType) => {
259
+ setOrderFormValues(data);
260
+ setFormType(data.paymentMethod as unknown as FormTypeEnum);
261
+ };
262
+
263
+ const handleInvoiceForm = async (
264
+ _: string | null,
265
+ data?: OrderInfoType | null
266
+ ) => {
259
267
  await messageCallback({
260
- orderId: orderId || '',
268
+ orderId: data?.orderId || orderId || '',
261
269
  agreementId: '',
262
- orderInfo: orderInfo || null,
270
+ orderInfo: data || orderInfo || null,
263
271
  });
264
272
  };
265
273
 
@@ -294,6 +302,20 @@ const App: FC<ConfigType> = ({
294
302
  organizationNumber={
295
303
  orderFormValues?.organizationNumber
296
304
  }
305
+ orderValues={orderFormValues}
306
+ templatePackageId={templatePackageId}
307
+ subscriberId={subscriberId}
308
+ userId={userId}
309
+ identityProviderId={identityProviderId}
310
+ organizationId={organizationId}
311
+ redirectUrl={redirectUrl}
312
+ showIframe={showIframe}
313
+ paymentMethodsOptions={paymentMethodsOptions}
314
+ language={language}
315
+ merchantAgreementUrl={merchantAgreementUrl}
316
+ invoiceAddressSelection={
317
+ invoiceAddressSelection
318
+ }
297
319
  />
298
320
  )}
299
321
  {formType === FormTypeEnum.EHF && (
@@ -308,12 +330,27 @@ const App: FC<ConfigType> = ({
308
330
  organizationNumber={
309
331
  orderFormValues?.organizationNumber
310
332
  }
333
+ orderValues={orderFormValues}
334
+ templatePackageId={templatePackageId}
335
+ subscriberId={subscriberId}
336
+ userId={userId}
337
+ identityProviderId={identityProviderId}
338
+ organizationId={organizationId}
339
+ redirectUrl={redirectUrl}
340
+ showIframe={showIframe}
341
+ paymentMethodsOptions={paymentMethodsOptions}
342
+ language={language}
343
+ merchantAgreementUrl={merchantAgreementUrl}
344
+ invoiceAddressSelection={
345
+ invoiceAddressSelection
346
+ }
311
347
  />
312
348
  )}
313
349
  {formType !== FormTypeEnum.OIO &&
314
350
  formType !== FormTypeEnum.EHF && (
315
351
  <OrderForm
316
352
  callback={handleForm}
353
+ updateFormData={updateFormData}
317
354
  submitStartCallback={submitStartCallback}
318
355
  templatePackageId={templatePackageId}
319
356
  subscriberId={subscriberId}
@@ -1,25 +1,46 @@
1
- import { FC, useState } from 'react';
1
+ import { FC } from 'react';
2
2
  import { FormProvider, useForm, SubmitHandler } from 'react-hook-form';
3
3
 
4
- import { invoiceLookup } from '../../api/InvoiceApi';
5
4
  import Alert from '../Alert/Alert';
6
5
  import Button from '../Button/Button';
7
6
  import InputField from '../FormFields/InputField';
7
+ import { PaymentMethodEnum } from '../../enums/general';
8
8
  import {
9
- prepareErrorMessage,
10
- prepareErrorsArrayMessage,
11
- } from '../../utils/helper';
12
- import { InvoiceLookupNetworkEnum } from '../../enums/general';
13
- import { ErrorsMsg } from '../../types/general';
9
+ OrderFormFiledType,
10
+ PaymentMethodOptionsType,
11
+ } from '../../types/general';
12
+ import { OrderFormInputsType, OrderInfoType } from '../../types/order';
13
+ import { orderInvoiceContactFields } from '../../utils/order.helper';
14
+ import useOrderForm from '../../hooks/useOrderForm';
15
+ import { DEFAULT_ORDER_FORM_FIELDS } from '../FormFields/FormFields.helper';
14
16
 
15
17
  type Props = {
16
- callback: (value: string) => void;
18
+ callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
17
19
  onBack: () => void;
20
+ submitStartCallback?: (id: string) => void;
21
+ className?: string;
18
22
  backButtonText?: string;
19
23
  verifyButtonText?: string;
20
24
  organizationNumberLabel?: string;
21
25
  organizationNumber?: string;
22
- className?: string;
26
+ glnLabel?: string;
27
+ templatePackageId: string;
28
+ subscriberId?: string;
29
+ userId?: string;
30
+ identityProviderId?: string;
31
+ organizationId: string;
32
+ redirectUrl?: string;
33
+ showIframe?: boolean;
34
+ language: string;
35
+ merchantAgreementUrl: string;
36
+ orderValues?: OrderFormInputsType;
37
+ paymentMethodsOptions?: PaymentMethodOptionsType;
38
+ invoiceAddressSelection?: {
39
+ enabled?: boolean;
40
+ label?: string;
41
+ fields?: OrderFormFiledType[];
42
+ paymentMethods?: PaymentMethodEnum[];
43
+ };
23
44
  };
24
45
 
25
46
  type EHFFormInputsType = {
@@ -33,16 +54,25 @@ const initialData = {
33
54
  const EHFForm: FC<Props> = ({
34
55
  callback,
35
56
  onBack,
57
+ submitStartCallback,
58
+ className = '',
36
59
  backButtonText = '',
37
60
  verifyButtonText = '',
38
61
  organizationNumberLabel = '',
39
62
  organizationNumber = '',
40
- className = '',
63
+ templatePackageId,
64
+ subscriberId,
65
+ userId,
66
+ identityProviderId,
67
+ organizationId,
68
+ redirectUrl,
69
+ showIframe,
70
+ language,
71
+ merchantAgreementUrl,
72
+ orderValues,
73
+ paymentMethodsOptions,
74
+ invoiceAddressSelection,
41
75
  }) => {
42
- const [loading, setLoading] = useState<boolean>(false);
43
- const [apiErrorMsg, setApiErrorMsg] = useState<string>('');
44
- const [errorsMsg, setErrorsMsg] = useState<string[]>([]);
45
-
46
76
  const methods = useForm<EHFFormInputsType>({
47
77
  defaultValues: {
48
78
  ...initialData,
@@ -55,32 +85,38 @@ const EHFForm: FC<Props> = ({
55
85
  formState: { errors },
56
86
  } = methods;
57
87
 
88
+ const invoiceOrderFields =
89
+ invoiceAddressSelection?.fields || orderInvoiceContactFields;
90
+
91
+ const orderFields =
92
+ paymentMethodsOptions?.[orderValues?.paymentMethod as PaymentMethodEnum]
93
+ ?.orderFormFields ?? DEFAULT_ORDER_FORM_FIELDS;
94
+
95
+ const { orderSubmit, loading, apiErrorMsg, errorsMsg } = useOrderForm({
96
+ callback,
97
+ submitStartCallback,
98
+ organizationId,
99
+ subscriberId,
100
+ userId,
101
+ identityProviderId,
102
+ orderFields,
103
+ redirectUrl,
104
+ showIframe,
105
+ language,
106
+ merchantAgreementUrl,
107
+ paymentMethodsOptions,
108
+ templatePackageId,
109
+ invoiceAddressToggle: orderValues?.invoiceAddressSelection,
110
+ invoiceOrderFields,
111
+ });
112
+
58
113
  const onSubmit: SubmitHandler<EHFFormInputsType> = async (
59
114
  data
60
115
  ): Promise<void> => {
61
- setApiErrorMsg('');
62
- setErrorsMsg([]);
63
- setLoading(true);
64
- try {
65
- await invoiceLookup({
66
- network: InvoiceLookupNetworkEnum.EHF,
67
- value: data.organizationNumber,
68
- });
69
- callback(data.organizationNumber);
70
- } catch (error) {
71
- setApiErrorMsg(prepareErrorMessage(error as Error));
72
- setErrorsMsg(
73
- prepareErrorsArrayMessage(
74
- (
75
- error as {
76
- errors: ErrorsMsg;
77
- }
78
- )?.errors
79
- )
80
- );
81
- } finally {
82
- setLoading(false);
83
- }
116
+ orderSubmit({
117
+ ...orderValues,
118
+ organizationNumber: data.organizationNumber,
119
+ });
84
120
  };
85
121
 
86
122
  const handleBack = () => {
@@ -27,7 +27,7 @@ const AddressField: FC<Props> = ({
27
27
  const { register } = useFormContext();
28
28
  const id = uuidv4();
29
29
  return (
30
- <div className="field-wrapper" data-testid="sdk-address-field-id">
30
+ <div className="field-wrapper" data-testid={`sdk-${name}-field-id`}>
31
31
  <textarea
32
32
  id={id}
33
33
  autoComplete="address"
@@ -29,7 +29,7 @@ const EmailField: FC<Props> = ({
29
29
  const { register } = useFormContext();
30
30
  const id = uuidv4();
31
31
  return (
32
- <div className="field-wrapper" data-testid="sdk-email-field-id">
32
+ <div className="field-wrapper" data-testid={`sdk-${name}-field-id`}>
33
33
  <input
34
34
  id={id}
35
35
  autoComplete="email"
@@ -27,7 +27,7 @@ const NameField: FC<Props> = ({
27
27
  const { register } = useFormContext();
28
28
  const id = uuidv4();
29
29
  return (
30
- <div className="field-wrapper" data-testid="sdk-name-field-id">
30
+ <div className="field-wrapper" data-testid={`sdk-${name}-field-id`}>
31
31
  <input
32
32
  id={id}
33
33
  autoComplete="name"
@@ -29,7 +29,7 @@ const PhoneFiled: FC<Props> = ({
29
29
  const { register } = useFormContext();
30
30
  const id = uuidv4();
31
31
  return (
32
- <div className="field-wrapper" data-testid="sdk-phone-field-id">
32
+ <div className="field-wrapper" data-testid={`sdk-${name}-field-id`}>
33
33
  <input
34
34
  id={id}
35
35
  autoComplete="tel"
@@ -1,26 +1,47 @@
1
- import { FC, useState } from 'react';
1
+ import { FC } from 'react';
2
2
  import { FormProvider, useForm, SubmitHandler } from 'react-hook-form';
3
3
 
4
- import { invoiceLookup } from '../../api/InvoiceApi';
5
4
  import Alert from '../Alert/Alert';
6
5
  import Button from '../Button/Button';
7
6
  import InputField from '../FormFields/InputField';
7
+ import { DEFAULT_ORDER_FORM_FIELDS } from '../FormFields/FormFields.helper';
8
+
9
+ import { PaymentMethodEnum } from '../../enums/general';
8
10
  import {
9
- prepareErrorMessage,
10
- prepareErrorsArrayMessage,
11
- } from '../../utils/helper';
12
- import { InvoiceLookupNetworkEnum } from '../../enums/general';
13
- import { ErrorsMsg } from '../../types/general';
11
+ OrderFormFiledType,
12
+ PaymentMethodOptionsType,
13
+ } from '../../types/general';
14
+ import useOrderForm from '../../hooks/useOrderForm';
15
+ import { orderInvoiceContactFields } from '../../utils/order.helper';
16
+ import { OrderFormInputsType, OrderInfoType } from '../../types/order';
14
17
 
15
18
  type Props = {
16
- callback: (value: string) => void;
19
+ callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
17
20
  onBack: () => void;
21
+ submitStartCallback?: (id: string) => void;
22
+ className?: string;
18
23
  backButtonText?: string;
19
24
  verifyButtonText?: string;
20
25
  organizationNumberLabel?: string;
21
26
  organizationNumber?: string;
22
27
  glnLabel?: string;
23
- className?: string;
28
+ templatePackageId: string;
29
+ subscriberId?: string;
30
+ userId?: string;
31
+ identityProviderId?: string;
32
+ organizationId: string;
33
+ redirectUrl?: string;
34
+ showIframe?: boolean;
35
+ language: string;
36
+ merchantAgreementUrl: string;
37
+ orderValues?: OrderFormInputsType;
38
+ paymentMethodsOptions?: PaymentMethodOptionsType;
39
+ invoiceAddressSelection?: {
40
+ enabled?: boolean;
41
+ label?: string;
42
+ fields?: OrderFormFiledType[];
43
+ paymentMethods?: PaymentMethodEnum[];
44
+ };
24
45
  };
25
46
 
26
47
  type OIOFormInputsType = {
@@ -36,17 +57,26 @@ const initialData = {
36
57
  const EHFForm: FC<Props> = ({
37
58
  callback,
38
59
  onBack,
60
+ submitStartCallback,
61
+ className = '',
39
62
  backButtonText = '',
40
63
  verifyButtonText = '',
41
64
  organizationNumberLabel = '',
42
65
  organizationNumber = '',
43
66
  glnLabel = '',
44
- className = '',
67
+ templatePackageId,
68
+ subscriberId,
69
+ userId,
70
+ identityProviderId,
71
+ organizationId,
72
+ redirectUrl,
73
+ showIframe,
74
+ language,
75
+ merchantAgreementUrl,
76
+ orderValues,
77
+ paymentMethodsOptions,
78
+ invoiceAddressSelection,
45
79
  }) => {
46
- const [loading, setLoading] = useState<boolean>(false);
47
- const [apiErrorMsg, setApiErrorMsg] = useState<string>('');
48
- const [errorsMsg, setErrorsMsg] = useState<string[]>([]);
49
-
50
80
  const methods = useForm<OIOFormInputsType>({
51
81
  defaultValues: {
52
82
  ...initialData,
@@ -63,34 +93,35 @@ const EHFForm: FC<Props> = ({
63
93
  const cvr = watch('cvr');
64
94
  const gln = watch('gln');
65
95
 
96
+ const invoiceOrderFields =
97
+ invoiceAddressSelection?.fields || orderInvoiceContactFields;
98
+
99
+ const orderFields =
100
+ paymentMethodsOptions?.[orderValues?.paymentMethod as PaymentMethodEnum]
101
+ ?.orderFormFields ?? DEFAULT_ORDER_FORM_FIELDS;
102
+
103
+ const { orderSubmit, loading, apiErrorMsg, errorsMsg } = useOrderForm({
104
+ callback,
105
+ submitStartCallback,
106
+ organizationId,
107
+ subscriberId,
108
+ userId,
109
+ identityProviderId,
110
+ orderFields,
111
+ redirectUrl,
112
+ showIframe,
113
+ language,
114
+ merchantAgreementUrl,
115
+ paymentMethodsOptions,
116
+ templatePackageId,
117
+ invoiceAddressToggle: orderValues?.invoiceAddressSelection,
118
+ invoiceOrderFields,
119
+ });
120
+
66
121
  const onSubmit: SubmitHandler<OIOFormInputsType> = async (
67
122
  data
68
123
  ): Promise<void> => {
69
- setApiErrorMsg('');
70
- setErrorsMsg([]);
71
- setLoading(true);
72
- try {
73
- await invoiceLookup({
74
- network: data.gln
75
- ? InvoiceLookupNetworkEnum.OIO_GLN
76
- : InvoiceLookupNetworkEnum.OIO_Danish_CVR,
77
- value: data.gln || data.cvr,
78
- });
79
- callback(data.gln || data.cvr);
80
- } catch (error) {
81
- setApiErrorMsg(prepareErrorMessage(error as Error));
82
- setErrorsMsg(
83
- prepareErrorsArrayMessage(
84
- (
85
- error as {
86
- errors: ErrorsMsg;
87
- }
88
- )?.errors
89
- )
90
- );
91
- } finally {
92
- setLoading(false);
93
- }
124
+ orderSubmit({ ...orderValues, gln: data.gln, cvr: data.cvr });
94
125
  };
95
126
 
96
127
  const handleBack = () => {
@@ -1,11 +1,8 @@
1
1
  import { FC, ChangeEvent, Suspense, useState, useMemo } from 'react';
2
2
  import { FormProvider, useForm, SubmitHandler } from 'react-hook-form';
3
3
 
4
- import { createSubscriber, mapSubscriberToUser } from '../../api/SubscribeApi';
5
- import { orderStart } from '../../api/OrdersApi';
6
4
  import { PaymentMethodEnum } from '../../enums/general';
7
5
  import {
8
- WRONG_MSG,
9
6
  PAYMENT_METHOD_DEFAULT,
10
7
  INVOICE_ALLOWED_PAYMENT_METHODS,
11
8
  } from '../../constants/index';
@@ -18,23 +15,15 @@ import { OrderFormInputsType, OrderInfoType } from '../../types/order';
18
15
  import {
19
16
  PaymentMethodOptionsType,
20
17
  OrderFormFiledType,
21
- ErrorsMsg,
22
18
  } from '../../types/general';
23
- import {
24
- orderInvoiceContactFields,
25
- prepareAgreementModel,
26
- prepareContactModel,
27
- prepareInvoiceModel,
28
- } from '../../utils/order.helper';
29
- import {
30
- prepareErrorMessage,
31
- prepareErrorsArrayMessage,
32
- } from '../../utils/helper';
19
+ import { orderInvoiceContactFields } from '../../utils/order.helper';
20
+ import useOrderForm from '../../hooks/useOrderForm';
33
21
 
34
22
  import './orderForm.scss';
35
23
 
36
24
  type Props = {
37
25
  callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
26
+ updateFormData: (data: OrderFormInputsType) => void;
38
27
  submitStartCallback?: (id: string) => void;
39
28
  templatePackageId: string;
40
29
  subscriberId?: string;
@@ -78,6 +67,7 @@ const initialData = {
78
67
 
79
68
  const OrderForm: FC<Props> = ({
80
69
  callback,
70
+ updateFormData,
81
71
  submitStartCallback,
82
72
  templatePackageId,
83
73
  subscriberId,
@@ -100,9 +90,6 @@ const OrderForm: FC<Props> = ({
100
90
  errorInvalidEmailMsg = '',
101
91
  errorInvalidPhoneMsg = '',
102
92
  }) => {
103
- const [loading, setLoading] = useState<boolean>(false);
104
- const [apiErrorMsg, setApiErrorMsg] = useState<string>('');
105
- const [errorsMsg, setErrorsMsg] = useState<string[]>([]);
106
93
  const [orderFields, setOrderFields] = useState<OrderFormFiledType[]>(
107
94
  paymentMethodsOptions?.[
108
95
  defaultValues?.paymentMethod || PAYMENT_METHOD_DEFAULT
@@ -135,98 +122,35 @@ const OrderForm: FC<Props> = ({
135
122
  const invoiceAddressToggle = watch('invoiceAddressSelection');
136
123
  const paymentMethodInput = watch('paymentMethod');
137
124
 
125
+ const { orderSubmit, loading, apiErrorMsg, errorsMsg } = useOrderForm({
126
+ callback,
127
+ submitStartCallback,
128
+ organizationId,
129
+ subscriberId,
130
+ userId,
131
+ identityProviderId,
132
+ orderFields,
133
+ redirectUrl,
134
+ showIframe,
135
+ language,
136
+ merchantAgreementUrl,
137
+ paymentMethodsOptions,
138
+ templatePackageId,
139
+ invoiceAddressToggle,
140
+ invoiceOrderFields,
141
+ });
142
+
138
143
  const onSubmit: SubmitHandler<OrderFormInputsType> = async (
139
144
  data
140
145
  ): Promise<void> => {
141
- setApiErrorMsg('');
142
- setErrorsMsg([]);
143
-
144
- setLoading(true);
145
- try {
146
- let id: string | undefined = subscriberId;
147
- const contactModel = prepareContactModel({ data, orderFields });
148
- if (!subscriberId) {
149
- const response = await createSubscriber({
150
- ...contactModel,
151
- });
152
- id = response.id;
153
-
154
- if (userId && identityProviderId) {
155
- await mapSubscriberToUser(id, {
156
- userId: userId,
157
- identityProviderId: identityProviderId,
158
- });
159
- }
160
- }
161
-
162
- submitStartCallback?.(id as string);
163
-
164
- if (id) {
165
- const paymentMethod =
166
- data.paymentMethod || PAYMENT_METHOD_DEFAULT;
167
-
168
- const agreements = prepareAgreementModel({
169
- paymentMethod,
170
- redirectUrl,
171
- showIframe,
172
- phoneNumber: orderFields.find(
173
- (i) => i.name === 'phoneNumber'
174
- )
175
- ? data.phoneNumber?.trim() || undefined
176
- : undefined,
177
- language,
178
- merchantAgreementUrl,
179
- generateSubscriberContact:
180
- paymentMethodsOptions?.[
181
- data.paymentMethod as PaymentMethodEnum
182
- ]?.generateSubscriberContact || false,
183
- accountId:
184
- paymentMethodsOptions?.[
185
- data.paymentMethod as PaymentMethodEnum
186
- ]?.accountId,
187
- });
188
- const responseOrder = await orderStart({
189
- subscriberId: id,
190
- subscriptionPlan: {
191
- organizationId,
192
- templateSubscriptionPlanId: templatePackageId,
193
- },
194
- paymentAgreement: { ...agreements },
195
- invoiceContact: invoiceAddressToggle
196
- ? prepareInvoiceModel({
197
- data,
198
- orderFields: invoiceOrderFields,
199
- })
200
- : undefined,
201
- orderReference: data.orderReference || undefined,
202
- });
203
- callback(responseOrder.terminalRedirectUrl, {
204
- ...(data || {}),
205
- orderId: responseOrder.id,
206
- subscriberId: id,
207
- paymentMethod: paymentMethod,
208
- });
209
- return;
210
- }
211
- callback(null);
212
- setApiErrorMsg(WRONG_MSG);
213
- setErrorsMsg([]);
214
- } catch (error) {
215
- console.error(error);
216
- setApiErrorMsg(prepareErrorMessage(error as Error));
217
- setErrorsMsg(
218
- prepareErrorsArrayMessage(
219
- (
220
- error as {
221
- errors: ErrorsMsg;
222
- }
223
- )?.errors
224
- )
225
- );
226
- callback(null);
227
- } finally {
228
- setLoading(false);
146
+ if (
147
+ paymentMethodInput === PaymentMethodEnum.EHF ||
148
+ paymentMethodInput === PaymentMethodEnum.OIO
149
+ ) {
150
+ updateFormData(data);
151
+ return;
229
152
  }
153
+ await orderSubmit(data);
230
154
  };
231
155
 
232
156
  const handlePaymentChange = (e: ChangeEvent<HTMLInputElement>) => {
@@ -258,6 +182,16 @@ const OrderForm: FC<Props> = ({
258
182
  return false;
259
183
  }, [allowedPaymentMethods, paymentMethodInput]);
260
184
 
185
+ const showInvoiceFields =
186
+ invoiceAddressToggle &&
187
+ invoiceOrderFields?.length > 0 &&
188
+ allowPaymentMethod;
189
+
190
+ const showInvoiceToggle =
191
+ invoiceAddressSelection?.enabled &&
192
+ allowPaymentMethod &&
193
+ invoicePaymentMethods.includes(paymentMethodInput as PaymentMethodEnum);
194
+
261
195
  return (
262
196
  <FormProvider {...methods}>
263
197
  <form
@@ -319,46 +253,35 @@ const OrderForm: FC<Props> = ({
319
253
  })}
320
254
  </Suspense>
321
255
  )}
322
- {invoiceAddressSelection?.enabled &&
323
- allowPaymentMethod &&
324
- invoicePaymentMethods.includes(
325
- paymentMethodInput as PaymentMethodEnum
326
- ) && (
327
- <ToggleField
328
- name="invoiceAddressSelection"
329
- label={
330
- invoiceAddressSelection?.label ??
331
- 'Invoice Address'
332
- }
333
- />
334
- )}
335
- {invoiceAddressToggle &&
336
- invoiceOrderFields?.length > 0 &&
337
- allowPaymentMethod && (
338
- <Suspense fallback={null}>
339
- {invoiceOrderFields.map((field) => {
340
- const Component = formFieldsMapper[field.name];
256
+ {showInvoiceToggle && (
257
+ <ToggleField
258
+ name="invoiceAddressSelection"
259
+ label={
260
+ invoiceAddressSelection?.label ?? 'Invoice Address'
261
+ }
262
+ />
263
+ )}
264
+ {showInvoiceFields && (
265
+ <Suspense fallback={null}>
266
+ {invoiceOrderFields.map((field) => {
267
+ const Component = formFieldsMapper[field.name];
341
268
 
342
- return Component ? (
343
- <Component
344
- key={field.name}
345
- name={field.name}
346
- label={field.label}
347
- required={field.required || false}
348
- readOnly={field.readOnly || false}
349
- errors={errors}
350
- errorReqMsg={errorReqMsg}
351
- errorInvalidEmailMsg={
352
- errorInvalidEmailMsg
353
- }
354
- errorInvalidPhoneMsg={
355
- errorInvalidPhoneMsg
356
- }
357
- />
358
- ) : null;
359
- })}
360
- </Suspense>
361
- )}
269
+ return Component ? (
270
+ <Component
271
+ key={field.name}
272
+ name={field.name}
273
+ label={field.label}
274
+ required={field.required || false}
275
+ readOnly={field.readOnly || false}
276
+ errors={errors}
277
+ errorReqMsg={errorReqMsg}
278
+ errorInvalidEmailMsg={errorInvalidEmailMsg}
279
+ errorInvalidPhoneMsg={errorInvalidPhoneMsg}
280
+ />
281
+ ) : null;
282
+ })}
283
+ </Suspense>
284
+ )}
362
285
  {allowPaymentMethod && (
363
286
  <Button
364
287
  type="submit"
@@ -0,0 +1,184 @@
1
+ import { useState } from 'react';
2
+ import { SubmitHandler } from 'react-hook-form';
3
+
4
+ import { createSubscriber, mapSubscriberToUser } from '../api/SubscribeApi';
5
+ import { orderStart } from '../api/OrdersApi';
6
+ import { invoiceLookup } from '../api/InvoiceApi';
7
+ import { InvoiceLookupNetworkEnum, PaymentMethodEnum } from '../enums/general';
8
+ import { WRONG_MSG, PAYMENT_METHOD_DEFAULT } from '../constants/index';
9
+ import { OrderFormInputsType, OrderInfoType } from '../types/order';
10
+ import {
11
+ ErrorsMsg,
12
+ OrderFormFiledType,
13
+ PaymentMethodOptionsType,
14
+ } from '../types/general';
15
+ import {
16
+ prepareAgreementModel,
17
+ prepareContactModel,
18
+ prepareInvoiceModel,
19
+ } from '../utils/order.helper';
20
+ import {
21
+ prepareErrorMessage,
22
+ prepareErrorsArrayMessage,
23
+ } from '../utils/helper';
24
+
25
+ type Props = {
26
+ callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
27
+ submitStartCallback?: (id: string) => void;
28
+ templatePackageId: string;
29
+ subscriberId?: string;
30
+ userId?: string;
31
+ identityProviderId?: string;
32
+ organizationId: string;
33
+ redirectUrl?: string;
34
+ showIframe?: boolean;
35
+ language: string;
36
+ merchantAgreementUrl: string;
37
+ paymentMethodsOptions?: PaymentMethodOptionsType;
38
+ orderFields: OrderFormFiledType[];
39
+ invoiceAddressToggle?: boolean;
40
+ invoiceOrderFields: OrderFormFiledType[];
41
+ };
42
+
43
+ const useOrderForm = ({
44
+ callback,
45
+ submitStartCallback,
46
+ organizationId,
47
+ subscriberId,
48
+ userId,
49
+ identityProviderId,
50
+ orderFields,
51
+ redirectUrl,
52
+ showIframe,
53
+ language,
54
+ merchantAgreementUrl,
55
+ paymentMethodsOptions,
56
+ templatePackageId,
57
+ invoiceAddressToggle,
58
+ invoiceOrderFields,
59
+ }: Props) => {
60
+ const [loading, setLoading] = useState<boolean>(false);
61
+ const [apiErrorMsg, setApiErrorMsg] = useState<string>('');
62
+ const [errorsMsg, setErrorsMsg] = useState<string[]>([]);
63
+
64
+ const orderSubmit: SubmitHandler<OrderFormInputsType> = async (
65
+ data
66
+ ): Promise<void> => {
67
+ setApiErrorMsg('');
68
+ setErrorsMsg([]);
69
+ setLoading(true);
70
+ try {
71
+ let id: string | undefined = subscriberId;
72
+ const contactModel = prepareContactModel({ data, orderFields });
73
+ if (!subscriberId) {
74
+ const response = await createSubscriber({
75
+ ...contactModel,
76
+ gln: data?.gln,
77
+ organizationNumber:
78
+ data.paymentMethod === PaymentMethodEnum.OIO
79
+ ? data?.cvr
80
+ : data.organizationNumber || undefined,
81
+ });
82
+ id = response.id;
83
+
84
+ if (userId && identityProviderId) {
85
+ await mapSubscriberToUser(id, {
86
+ userId: userId,
87
+ identityProviderId: identityProviderId,
88
+ });
89
+ }
90
+ }
91
+
92
+ submitStartCallback?.(id as string);
93
+
94
+ if (id) {
95
+ const paymentMethod =
96
+ data.paymentMethod || PAYMENT_METHOD_DEFAULT;
97
+
98
+ const agreements = prepareAgreementModel({
99
+ paymentMethod,
100
+ redirectUrl,
101
+ showIframe,
102
+ phoneNumber: orderFields.find(
103
+ (i) => i.name === 'phoneNumber'
104
+ )
105
+ ? data.phoneNumber?.trim() || undefined
106
+ : undefined,
107
+ language,
108
+ merchantAgreementUrl,
109
+ generateSubscriberContact:
110
+ paymentMethodsOptions?.[
111
+ data.paymentMethod as PaymentMethodEnum
112
+ ]?.generateSubscriberContact || false,
113
+ accountId:
114
+ paymentMethodsOptions?.[
115
+ data.paymentMethod as PaymentMethodEnum
116
+ ]?.accountId,
117
+ });
118
+ const responseOrder = await orderStart({
119
+ subscriberId: id,
120
+ subscriptionPlan: {
121
+ organizationId,
122
+ templateSubscriptionPlanId: templatePackageId,
123
+ },
124
+ paymentAgreement: { ...agreements },
125
+ invoiceContact: invoiceAddressToggle
126
+ ? prepareInvoiceModel({
127
+ data,
128
+ orderFields: invoiceOrderFields,
129
+ })
130
+ : undefined,
131
+ orderReference: data.orderReference || undefined,
132
+ });
133
+ if (data.paymentMethod === PaymentMethodEnum.OIO) {
134
+ await invoiceLookup({
135
+ network: data.gln
136
+ ? InvoiceLookupNetworkEnum.OIO_GLN
137
+ : InvoiceLookupNetworkEnum.OIO_Danish_CVR,
138
+ value: data.gln || data.cvr || '',
139
+ });
140
+ }
141
+ if (data.paymentMethod === PaymentMethodEnum.EHF) {
142
+ await invoiceLookup({
143
+ network: InvoiceLookupNetworkEnum.EHF,
144
+ value: data.organizationNumber || '',
145
+ });
146
+ }
147
+ callback(responseOrder.terminalRedirectUrl, {
148
+ ...(data || {}),
149
+ orderId: responseOrder.id,
150
+ subscriberId: id,
151
+ paymentMethod: paymentMethod,
152
+ });
153
+ return;
154
+ }
155
+ callback(null);
156
+ setApiErrorMsg(WRONG_MSG);
157
+ setErrorsMsg([]);
158
+ } catch (error) {
159
+ console.error(error);
160
+ setApiErrorMsg(prepareErrorMessage(error as Error));
161
+ setErrorsMsg(
162
+ prepareErrorsArrayMessage(
163
+ (
164
+ error as {
165
+ errors: ErrorsMsg;
166
+ }
167
+ )?.errors
168
+ )
169
+ );
170
+ callback(null);
171
+ } finally {
172
+ setLoading(false);
173
+ }
174
+ };
175
+
176
+ return {
177
+ orderSubmit,
178
+ loading,
179
+ apiErrorMsg,
180
+ errorsMsg,
181
+ };
182
+ };
183
+
184
+ export default useOrderForm;
package/src/types/api.ts CHANGED
@@ -21,4 +21,6 @@ export type CreateSubscriberRequestType = {
21
21
  zip?: string;
22
22
  careOf?: string;
23
23
  buyerReference?: string;
24
+ gln?: string;
25
+ organizationNumber?: string;
24
26
  };
@@ -22,6 +22,8 @@ export type OrderFormInputsType = {
22
22
  invoiceZip?: string;
23
23
  invoiceCareOf?: string;
24
24
  invoiceBuyerReference?: string;
25
+ gln?: string;
26
+ cvr?: string;
25
27
  };
26
28
 
27
29
  export type VippsMobilePay = {