@infosoftas/s4-orders-js-sdk 0.1.11 → 0.1.13-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 CHANGED
@@ -39,17 +39,19 @@ enum PaymentMethodEnum {
39
39
  OIO = 'OIO',
40
40
  }
41
41
 
42
- type OrderFormFiledType = {
42
+ type OrderFormFieldType = {
43
43
  name: string;
44
44
  required?: boolean;
45
+ readOnly?: boolean;
46
+ label?: string;
45
47
  };
46
48
 
47
49
  type PaymentMethodOptionsType = {
48
50
  [key in PaymentMethodEnum]: {
49
51
  generateSubscriberContact?: boolean;
50
52
  accountId?: string;
51
- orderFormFields?: OrderFormFiledType[] | never[];
52
- paymentInvoiceFields?: OrderFormFiledType[] | never[] | null;
53
+ orderFormFields: OrderFormFieldType[];
54
+ paymentInvoiceFields?: OrderFormFieldType[] | never[] | null;
53
55
  };
54
56
  }
55
57
 
@@ -75,9 +77,10 @@ type ConfigType = {
75
77
  moduleTitle?: string;
76
78
  submitStartCallback?: (subscriberId: string) => void;
77
79
  userActionCallback?: (action: UserActionEnum, args: object | null | undefined) => void;
78
- setContactCallback?: (contactInfo: contactRequestType) => void;
79
- apiKey: string;
80
- apiUrl: string;
80
+ setContactCallback?: (contactInfo: ContactRequestType) => void;
81
+ cancelVippsCallback?: () => void;
82
+ apiKey?: string;
83
+ apiUrl?: string;
81
84
  templatePackageId: string;
82
85
  subscriberId: string;
83
86
  userId: string;
@@ -85,14 +88,31 @@ type ConfigType = {
85
88
  organizationId: string;
86
89
  redirectUrl?: string;
87
90
  showIframe?: boolean;
91
+ /**
92
+ * The full list of payment methods displayed in the UI, each with a display label and value.
93
+ * Controls what the user sees in the payment method selector.
94
+ * @example [{ label: 'Credit Card', value: 'SwedbankPay' }, { label: 'Invoice', value: 'Invoice' }]
95
+ */
88
96
  availablePaymentMethods?: { label: string; value: PaymentMethodEnum }[];
97
+ /**
98
+ * Whitelist of payment methods the subscriber is permitted to use.
99
+ * If a method is in availablePaymentMethods but not here, it will be shown but blocked.
100
+ * @example ['SwedbankPay', 'Invoice']
101
+ */
102
+ allowedPaymentMethods?: PaymentMethodEnum[];
103
+ /**
104
+ * Per-payment-method form field configuration.
105
+ * Controls which input fields are shown in the order form for each payment method.
106
+ * Use accountId on SwedbankPay to set your Swedbank Pay account ID.
107
+ */
89
108
  paymentMethodsOptions?: PaymentMethodOptionsType;
109
+ requireTermsAcceptance?: boolean;
90
110
  language?: string;
91
111
  merchantAgreementUrl?: string;
92
112
  invoiceAddressSelection?: {
93
113
  enabled?: boolean;
94
114
  label?: string;
95
- fields?: OrderFormFiledType[] | never[];
115
+ fields?: OrderFormFieldType[];
96
116
  };
97
117
  settings?: {
98
118
  successText?: string;
@@ -101,6 +121,7 @@ type ConfigType = {
101
121
  backButtonText?: string;
102
122
  verifyButtonText?: string;
103
123
  organizationNumberLabel?: string;
124
+ cvrLabel?: string;
104
125
  glnLabel?: string;
105
126
  orderDefaultValues?: OrderFormInputsType;
106
127
  paymentMethodLabel?: string;
@@ -110,6 +131,9 @@ type ConfigType = {
110
131
  errorValidationTitleMsg?: string;
111
132
  errorValidationDenialOrderBlockingMsg?: string;
112
133
  errorValidationBlockingOffersMsg?: string;
134
+ paymentMethodNotAllowedMsg?: string;
135
+ invoiceLookupNotFoundText?: string;
136
+ termsAndConditionsText?: string;
113
137
  };
114
138
  }
115
139
  ```
@@ -388,8 +412,11 @@ export default OrderPlace;
388
412
  | redirectUrl | window.location.href | redirect url |
389
413
  | showIframe | false | show credit card in iframe |
390
414
  | userActionCallback | undefined | function for tracking user actions |
391
- | paymentMethodsOptions | orderFormFields: [{name: 'phone, required: false, readOnly: false, label: ''}] | default form fields |
392
- | availablePaymentMethods | [] | available payment methods |
415
+ | cancelVippsCallback | undefined | callback invoked when a Vipps/MobilePay payment is cancelled |
416
+ | paymentMethodsOptions | orderFormFields: [{name: 'phoneNumber', required: false, readOnly: false, label: ''}] | default form fields |
417
+ | availablePaymentMethods | [] | available payment methods to display |
418
+ | allowedPaymentMethods | [] | list of payment methods the subscriber is allowed to use |
419
+ | requireTermsAcceptance | false | when true, the user must accept terms and conditions before submitting |
393
420
  | language | 'en-US' | language |
394
421
  | merchantAgreementUrl | '' | vipps and MobilePay property |
395
- | settings | {successText: 'Order successful completed!',failureText: 'Something went wrong!',submitButtonText: 'Start',backButtonText: 'Back',verifyButtonText: 'Verify',organizationNumberLabel: 'CVR',glnLabel: 'GLN',paymentMethodLabel:'Select Payment Method', orderDefaultValues: 'Default order form values', paymentMethodNotAllowedMsg: 'This payment method not allowed!', invoiceLookupNotFoundText: 'There was no recipient found for the given information' } | label and text properties |
422
+ | settings | {successText: 'Order completed successfully!', failureText: 'Something went wrong!', submitButtonText: 'Start', backButtonText: 'Back', verifyButtonText: 'Verify', organizationNumberLabel: 'Organization Number', cvrLabel: 'CVR', glnLabel: 'GLN', paymentMethodLabel: 'Select Payment Method', orderDefaultValues: 'Default order form values', errorReqMsg: '', errorInvalidEmailMsg: '', errorInvalidPhoneMsg: '', errorValidationTitleMsg: 'One or more validation errors occurred.', errorValidationDenialOrderBlockingMsg: '...', errorValidationBlockingOffersMsg: '...', paymentMethodNotAllowedMsg: 'This payment method not allowed!', invoiceLookupNotFoundText: 'There was no recipient found for the given information', termsAndConditionsText: '' } | label and text properties |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infosoftas/s4-orders-js-sdk",
3
- "version": "0.1.11",
3
+ "version": "0.1.13-0",
4
4
  "scripts": {
5
5
  "build": "rimraf lib && webpack --mode production",
6
6
  "release": "release-it"
package/src/App.tsx CHANGED
@@ -30,6 +30,7 @@ const App: FC<ConfigType> = ({
30
30
  submitStartCallback,
31
31
  userActionCallback,
32
32
  setContactCallback,
33
+ cancelVippsCallback,
33
34
  moduleTitle,
34
35
  apiKey,
35
36
  apiUrl,
@@ -44,6 +45,7 @@ const App: FC<ConfigType> = ({
44
45
  invoiceAddressSelection,
45
46
  availablePaymentMethods = [],
46
47
  allowedPaymentMethods,
48
+ requireTermsAcceptance,
47
49
  language = 'en-US',
48
50
  merchantAgreementUrl = '',
49
51
  settings = {
@@ -69,6 +71,7 @@ const App: FC<ConfigType> = ({
69
71
  paymentMethodNotAllowedMsg: '',
70
72
  invoiceLookupNotFoundText:
71
73
  'There was no recipient found for the given information',
74
+ termsAndConditionsText: '',
72
75
  },
73
76
  }) => {
74
77
  const [loading, setLoading] = useState<boolean>(false);
@@ -140,6 +143,7 @@ const App: FC<ConfigType> = ({
140
143
  (data.paymentMethod === PaymentMethodEnum.Vipps ||
141
144
  data.paymentMethod === PaymentMethodEnum.MobilePay)
142
145
  ) {
146
+ cancelVippsCallback?.();
143
147
  handleOrderDelete(orderId || data.orderId);
144
148
  return;
145
149
  }
@@ -471,6 +475,12 @@ const App: FC<ConfigType> = ({
471
475
  errorValidationBlockingOffersMsg={
472
476
  settings?.errorValidationBlockingOffersMsg
473
477
  }
478
+ termsAndConditionsText={
479
+ settings?.termsAndConditionsText
480
+ }
481
+ requireTermsAcceptance={
482
+ requireTermsAcceptance
483
+ }
474
484
  />
475
485
  )}
476
486
  </>
@@ -6,7 +6,7 @@ import Button from '../Button/Button';
6
6
  import InputField from '../FormFields/InputField';
7
7
  import { PaymentMethodEnum, UserActionEnum } from '../../enums/general';
8
8
  import {
9
- OrderFormFiledType,
9
+ OrderFormFieldType,
10
10
  PaymentMethodOptionsType,
11
11
  ContactRequestType,
12
12
  } from '../../types/general';
@@ -44,7 +44,7 @@ type Props = {
44
44
  invoiceAddressSelection?: {
45
45
  enabled?: boolean;
46
46
  label?: string;
47
- fields?: OrderFormFiledType[];
47
+ fields?: OrderFormFieldType[];
48
48
  paymentMethods?: PaymentMethodEnum[];
49
49
  };
50
50
  invoiceLookupNotFoundText?: string;
@@ -1,4 +1,4 @@
1
- import { OrderFormFiledType } from '../../types/general';
1
+ import { OrderFormFieldType } from '../../types/general';
2
2
 
3
3
  export const FIELD_TYPES = {
4
4
  PHONE: 'phoneNumber',
@@ -21,9 +21,10 @@ export const FIELD_TYPES = {
21
21
  INVOICE_EMAIL: 'invoiceEmail',
22
22
  INVOICE_CARE_OF: 'invoiceCareOf',
23
23
  INVOICE_BUYER_REFERENCE: 'invoiceBuyerReference',
24
+ TERMS_CHECKBOX: 'termsCheckbox',
24
25
  };
25
26
 
26
- export const DEFAULT_ORDER_FORM_FIELDS: OrderFormFiledType[] = [
27
+ export const DEFAULT_ORDER_FORM_FIELDS: OrderFormFieldType[] = [
27
28
  {
28
29
  name: FIELD_TYPES.PHONE,
29
30
  required: false,
@@ -3,6 +3,7 @@ import PhoneField from './PhoneField';
3
3
  import NameField from './NameField';
4
4
  import AddressField from './AddressField';
5
5
  import InputField from './InputField';
6
+ import TermsCheckbox from './TermsCheckbox';
6
7
 
7
8
  import { FIELD_TYPES } from './FormFields.helper';
8
9
 
@@ -27,6 +28,7 @@ const formFieldsMapper = {
27
28
  [FIELD_TYPES.INVOICE_ZIP]: InputField,
28
29
  [FIELD_TYPES.INVOICE_CARE_OF]: InputField,
29
30
  [FIELD_TYPES.INVOICE_BUYER_REFERENCE]: InputField,
31
+ [FIELD_TYPES.TERMS_CHECKBOX]: TermsCheckbox,
30
32
  };
31
33
 
32
34
  export default formFieldsMapper;
@@ -0,0 +1,58 @@
1
+ import { FC, ReactNode } from 'react';
2
+ import { useFormContext } from 'react-hook-form';
3
+
4
+ import { uuidv4 } from '../../utils/helper';
5
+
6
+ type Props = {
7
+ name: string;
8
+ required: boolean;
9
+ disabled?: boolean;
10
+ label?: string | ReactNode;
11
+ errorReqMsg?: string;
12
+ errors?: {
13
+ [key: string]: {
14
+ message?: string;
15
+ };
16
+ };
17
+ };
18
+
19
+ const TermsCheckbox: FC<Props> = ({
20
+ name,
21
+ required = true,
22
+ disabled = false,
23
+ label = 'I accept the terms and conditions',
24
+ errorReqMsg = 'You must accept the terms and conditions to proceed.',
25
+ errors,
26
+ }) => {
27
+ const { register } = useFormContext();
28
+ const id = uuidv4();
29
+
30
+ return (
31
+ <div className="checkbox-wrapper" data-testid={`sdk-${name}-field-id`}>
32
+ <>
33
+ <input
34
+ id={id}
35
+ type="checkbox"
36
+ disabled={disabled}
37
+ className={`checkbox-control ${disabled ? 'disabled' : ''}`}
38
+ {...register(name, {
39
+ required: required ? errorReqMsg : false,
40
+ })}
41
+ />
42
+ <label
43
+ className="checkbox-label"
44
+ htmlFor={id}
45
+ style={{ cursor: disabled ? 'not-allowed' : 'pointer' }}
46
+ >
47
+ {label} {required && <span className="text-error">*</span>}
48
+ </label>
49
+ </>
50
+
51
+ {errors && errors[name] && (
52
+ <div className="text-error caption">{errors[name].message}</div>
53
+ )}
54
+ </div>
55
+ );
56
+ };
57
+
58
+ export default TermsCheckbox;
@@ -8,7 +8,7 @@ import { DEFAULT_ORDER_FORM_FIELDS } from '../FormFields/FormFields.helper';
8
8
 
9
9
  import { PaymentMethodEnum, UserActionEnum } from '../../enums/general';
10
10
  import {
11
- OrderFormFiledType,
11
+ OrderFormFieldType,
12
12
  PaymentMethodOptionsType,
13
13
  ContactRequestType,
14
14
  } from '../../types/general';
@@ -45,7 +45,7 @@ type Props = {
45
45
  invoiceAddressSelection?: {
46
46
  enabled?: boolean;
47
47
  label?: string;
48
- fields?: OrderFormFiledType[];
48
+ fields?: OrderFormFieldType[];
49
49
  paymentMethods?: PaymentMethodEnum[];
50
50
  };
51
51
  invoiceLookupNotFoundText?: string;
@@ -14,13 +14,14 @@ import { DEFAULT_ORDER_FORM_FIELDS } from '../FormFields/FormFields.helper';
14
14
  import { OrderFormInputsType, OrderInfoType } from '../../types/order';
15
15
  import {
16
16
  PaymentMethodOptionsType,
17
- OrderFormFiledType,
17
+ OrderFormFieldType,
18
18
  ContactRequestType,
19
19
  } from '../../types/general';
20
20
  import { orderInvoiceContactFields } from '../../utils/order.helper';
21
21
  import useOrderForm from '../../hooks/useOrderForm';
22
22
 
23
23
  import './orderForm.scss';
24
+ import TermsCheckbox from '../FormFields/TermsCheckbox';
24
25
 
25
26
  type Props = {
26
27
  callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
@@ -53,12 +54,14 @@ type Props = {
53
54
  invoiceAddressSelection?: {
54
55
  enabled?: boolean;
55
56
  label?: string;
56
- fields?: OrderFormFiledType[];
57
+ fields?: OrderFormFieldType[];
57
58
  paymentMethods?: PaymentMethodEnum[];
58
59
  };
60
+ requireTermsAcceptance?: boolean;
59
61
  errorValidationTitleMsg?: string;
60
62
  errorValidationDenialOrderBlockingMsg?: string;
61
63
  errorValidationBlockingOffersMsg?: string;
64
+ termsAndConditionsText?: string;
62
65
  };
63
66
 
64
67
  const initialData = {
@@ -103,6 +106,8 @@ const OrderForm: FC<Props> = ({
103
106
  errorValidationTitleMsg,
104
107
  errorValidationDenialOrderBlockingMsg,
105
108
  errorValidationBlockingOffersMsg,
109
+ requireTermsAcceptance,
110
+ termsAndConditionsText,
106
111
  }) => {
107
112
  if (!templatePackageId) {
108
113
  console.error('"templatePackageId" should be set');
@@ -127,7 +132,7 @@ const OrderForm: FC<Props> = ({
127
132
  console.error('"identityProviderId" should be set');
128
133
  }
129
134
 
130
- const [orderFields, setOrderFields] = useState<OrderFormFiledType[]>(
135
+ const [orderFields, setOrderFields] = useState<OrderFormFieldType[]>(
131
136
  paymentMethodsOptions?.[
132
137
  defaultValues?.paymentMethod || PAYMENT_METHOD_DEFAULT
133
138
  ]?.orderFormFields ?? DEFAULT_ORDER_FORM_FIELDS
@@ -158,6 +163,7 @@ const OrderForm: FC<Props> = ({
158
163
 
159
164
  const invoiceAddressToggle = watch('invoiceAddressSelection');
160
165
  const paymentMethodInput = watch('paymentMethod');
166
+ const isTermsAccepted = watch('termsAccept', false);
161
167
 
162
168
  const invoiceOrderFields =
163
169
  paymentMethodsOptions?.[paymentMethodInput || PAYMENT_METHOD_DEFAULT]
@@ -248,6 +254,10 @@ const OrderForm: FC<Props> = ({
248
254
  allowPaymentMethod &&
249
255
  invoicePaymentMethods.includes(paymentMethodInput as PaymentMethodEnum);
250
256
 
257
+ const isSubmitButtonDisabled = requireTermsAcceptance
258
+ ? !isTermsAccepted
259
+ : false;
260
+
251
261
  return (
252
262
  <FormProvider {...methods}>
253
263
  <form
@@ -344,11 +354,20 @@ const OrderForm: FC<Props> = ({
344
354
  })}
345
355
  </Suspense>
346
356
  )}
357
+ {requireTermsAcceptance && (
358
+ <TermsCheckbox
359
+ name="termsAccept"
360
+ label={termsAndConditionsText}
361
+ required
362
+ errors={errors}
363
+ />
364
+ )}
347
365
  {allowPaymentMethod && (
348
366
  <Button
349
367
  type="submit"
350
368
  loading={loading}
351
369
  buttonText={submitButtonText}
370
+ disable={isSubmitButtonDisabled}
352
371
  />
353
372
  )}
354
373
  <Alert
@@ -13,7 +13,7 @@ import { WRONG_MSG, PAYMENT_METHOD_DEFAULT } from '../constants/index';
13
13
  import { OrderFormInputsType, OrderInfoType } from '../types/order';
14
14
  import {
15
15
  ErrorsMsg,
16
- OrderFormFiledType,
16
+ OrderFormFieldType,
17
17
  PaymentMethodOptionsType,
18
18
  ContactRequestType,
19
19
  } from '../types/general';
@@ -35,7 +35,9 @@ type Props = {
35
35
  action: UserActionEnum,
36
36
  args: object | null | undefined
37
37
  ) => void;
38
- setContactCallback?: (contactInfo: ContactRequestType) => void;
38
+ setContactCallback?: (
39
+ contactInfo: ContactRequestType
40
+ ) => void;
39
41
  templatePackageId: string;
40
42
  subscriberId?: string;
41
43
  userId?: string;
@@ -46,9 +48,9 @@ type Props = {
46
48
  language: string;
47
49
  merchantAgreementUrl: string;
48
50
  paymentMethodsOptions?: PaymentMethodOptionsType;
49
- orderFields: OrderFormFiledType[];
51
+ orderFields: OrderFormFieldType[];
50
52
  invoiceAddressToggle?: boolean;
51
- invoiceOrderFields: OrderFormFiledType[];
53
+ invoiceOrderFields: OrderFormFieldType[];
52
54
  invoiceLookupNotFoundText?: string;
53
55
  errorValidationTitleMsg?: string;
54
56
  errorValidationDenialOrderBlockingMsg?: string;
@@ -7,7 +7,7 @@ declare global {
7
7
  }
8
8
  }
9
9
 
10
- export type OrderFormFiledType = {
10
+ export type OrderFormFieldType = {
11
11
  name: string;
12
12
  required?: boolean;
13
13
  readOnly?: boolean;
@@ -18,8 +18,8 @@ export type PaymentMethodOptionsType = {
18
18
  [key in PaymentMethodEnum]: {
19
19
  generateSubscriberContact?: boolean;
20
20
  accountId?: string;
21
- orderFormFields: OrderFormFiledType[];
22
- paymentInvoiceFields?: OrderFormFiledType[] | never[] | null;
21
+ orderFormFields?: OrderFormFieldType[];
22
+ paymentInvoiceFields?: OrderFormFieldType[] | never[] | null;
23
23
  };
24
24
  };
25
25
 
@@ -41,6 +41,7 @@ export type ConfigType = {
41
41
  args: object | null | undefined
42
42
  ) => void;
43
43
  setContactCallback?: (contactInfo: ContactRequestType) => void;
44
+ cancelVippsCallback?: () => void;
44
45
  domElementId: string;
45
46
  moduleTitle?: string;
46
47
  templatePackageId: string;
@@ -55,12 +56,13 @@ export type ConfigType = {
55
56
  availablePaymentMethods?: { label: string; value: PaymentMethodEnum }[];
56
57
  allowedPaymentMethods?: PaymentMethodEnum[];
57
58
  paymentMethodsOptions?: PaymentMethodOptionsType;
59
+ requireTermsAcceptance?: boolean;
58
60
  language?: string;
59
61
  merchantAgreementUrl?: string;
60
62
  invoiceAddressSelection?: {
61
63
  enabled?: boolean;
62
64
  label?: string;
63
- fields?: OrderFormFiledType[];
65
+ fields?: OrderFormFieldType[];
64
66
  };
65
67
  settings?: {
66
68
  successText?: string;
@@ -81,6 +83,7 @@ export type ConfigType = {
81
83
  errorValidationTitleMsg?: string;
82
84
  errorValidationDenialOrderBlockingMsg?: string;
83
85
  errorValidationBlockingOffersMsg?: string;
86
+ termsAndConditionsText?: string;
84
87
  };
85
88
  };
86
89
 
@@ -24,6 +24,7 @@ export type OrderFormInputsType = {
24
24
  invoiceBuyerReference?: string;
25
25
  gln?: string;
26
26
  cvr?: string;
27
+ termsAccept?: boolean;
27
28
  };
28
29
 
29
30
  export type VippsMobilePay = {
@@ -1,6 +1,6 @@
1
1
  import { MessageEventTypeEnum, PaymentMethodEnum } from '../enums/general';
2
2
  import { AgreementsType, OrderFormInputsType } from '../types/order';
3
- import { OrderFormFiledType } from '../types/general';
3
+ import { OrderFormFieldType } from '../types/general';
4
4
  import { FIELD_TYPES } from '../components/FormFields/FormFields.helper';
5
5
 
6
6
  type AgreementModelType = {
@@ -105,7 +105,7 @@ export const prepareAgreementModel = ({
105
105
 
106
106
  type ContactModelType = {
107
107
  data: OrderFormInputsType;
108
- orderFields: OrderFormFiledType[];
108
+ orderFields: OrderFormFieldType[];
109
109
  };
110
110
 
111
111
  export const prepareContactModel = ({