@infosoftas/s4-orders-js-sdk 0.1.19 → 0.1.21-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 +471 -426
- package/build/postcss-scope-tailwind.cjs +66 -0
- package/components.json +21 -0
- package/package.json +59 -43
- package/src/App.css +409 -0
- package/src/App.tsx +639 -569
- package/src/api/OrdersApi.ts +2 -2
- package/src/components/Alert/Alert.tsx +23 -22
- package/src/components/Button/Button.tsx +18 -22
- package/src/components/EHFForm/EHFForm.tsx +253 -235
- package/src/components/FormFields/AddressField.tsx +55 -62
- package/src/components/FormFields/EmailField.tsx +53 -58
- package/src/components/FormFields/InputField.tsx +52 -53
- package/src/components/FormFields/NameField.tsx +52 -53
- package/src/components/FormFields/PhoneField.tsx +53 -58
- package/src/components/FormFields/TermsCheckbox.tsx +70 -58
- package/src/components/FormFields/ToggleFiled.tsx +52 -63
- package/src/components/FormFields/fieldValidators.ts +71 -0
- package/src/components/OIOForm/OIOForm.tsx +132 -71
- package/src/components/OrderDenialModal/OrderDenialModal.tsx +102 -89
- package/src/components/OrderForm/ContactDetailsSection.tsx +71 -0
- package/src/components/OrderForm/OrderForm.tsx +177 -224
- package/src/components/OrderForm/PaymentMethodContent.tsx +62 -0
- package/src/components/OrderForm/PaymentMethodSection.tsx +79 -0
- package/src/components/OrderForm/SubmitConfirmationDialog.tsx +55 -0
- package/src/components/OrderForm/orderFormState.ts +171 -0
- package/src/components/OrderForm/useSlotElement.tsx +89 -0
- package/src/components/ui/alert-dialog.tsx +185 -0
- package/src/components/ui/alert.tsx +75 -0
- package/src/components/ui/button.tsx +55 -0
- package/src/components/ui/card.tsx +99 -0
- package/src/components/ui/checkbox.tsx +28 -0
- package/src/components/ui/field.tsx +238 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/radio-group.tsx +37 -0
- package/src/components/ui/separator.tsx +24 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/spinner.tsx +10 -0
- package/src/components/ui/switch.tsx +29 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/constants/index.ts +0 -2
- package/src/custom.d.ts +4 -4
- package/src/enums/general.ts +1 -0
- package/src/hooks/useMessageEvent.tsx +54 -3
- package/src/hooks/useOrderForm.tsx +9 -2
- package/src/index.tsx +2 -0
- package/src/lib/utils.ts +1 -0
- package/src/types/general.ts +136 -111
- package/src/types/order.ts +8 -0
- package/src/utils/order.helper.ts +14 -3
- package/tsconfig.json +37 -38
- package/src/App.scss +0 -23
- package/src/assets/styles/forms.scss +0 -164
- package/src/assets/styles/general.scss +0 -46
- package/src/assets/styles/variables.scss +0 -29
- package/src/components/Alert/alert.scss +0 -21
- package/src/components/Button/button.scss +0 -48
- package/src/components/Loader/Loader.tsx +0 -22
- package/src/components/Loader/loader.scss +0 -37
- package/src/components/OrderDenialModal/orderDenialModal.scss +0 -42
- package/src/components/OrderForm/orderForm.scss +0 -10
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FC,
|
|
3
|
-
|
|
3
|
+
KeyboardEvent,
|
|
4
4
|
ReactNode,
|
|
5
|
-
Suspense,
|
|
6
|
-
useState,
|
|
7
|
-
useMemo,
|
|
8
5
|
useEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
9
8
|
} from 'react';
|
|
10
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
FormProvider,
|
|
11
|
+
useForm,
|
|
12
|
+
Resolver,
|
|
13
|
+
SubmitHandler,
|
|
14
|
+
} from 'react-hook-form';
|
|
15
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
11
16
|
|
|
12
17
|
import { PaymentMethodEnum, UserActionEnum } from '../../enums/general';
|
|
13
|
-
import {
|
|
14
|
-
PAYMENT_METHOD_DEFAULT,
|
|
15
|
-
INVOICE_ALLOWED_PAYMENT_METHODS,
|
|
16
|
-
} from '../../constants/index';
|
|
18
|
+
import { PAYMENT_METHOD_DEFAULT } from '../../constants/index';
|
|
17
19
|
import Alert from '../Alert/Alert';
|
|
18
20
|
import Button from '../Button/Button';
|
|
19
21
|
import OrderDenialModal from '../OrderDenialModal/OrderDenialModal';
|
|
20
|
-
import
|
|
21
|
-
import formFieldsMapper from '../FormFields/FormFieldsMapper';
|
|
22
|
-
import { DEFAULT_ORDER_FORM_FIELDS } from '../FormFields/FormFields.helper';
|
|
22
|
+
import TermsCheckbox from '../FormFields/TermsCheckbox';
|
|
23
23
|
import { OrderFormInputsType, OrderInfoType } from '../../types/order';
|
|
24
24
|
import {
|
|
25
|
-
|
|
25
|
+
PaymentMethodSettingsType,
|
|
26
|
+
PaymentMethodOptionType,
|
|
26
27
|
OrderFormFieldType,
|
|
27
28
|
ContactRequestType,
|
|
28
29
|
OrderDenialFallbackOfferType,
|
|
30
|
+
SubmitConfirmationType,
|
|
29
31
|
} from '../../types/general';
|
|
30
|
-
import { orderInvoiceContactFields } from '../../utils/order.helper';
|
|
31
32
|
import useOrderForm from '../../hooks/useOrderForm';
|
|
32
|
-
|
|
33
|
-
import
|
|
34
|
-
|
|
33
|
+
import { useSlotElement, renderInSlot } from './useSlotElement';
|
|
34
|
+
import {
|
|
35
|
+
deriveOrderFormState,
|
|
36
|
+
buildOrderFormSchema,
|
|
37
|
+
OrderFormConfig,
|
|
38
|
+
} from './orderFormState';
|
|
39
|
+
import PaymentMethodSection from './PaymentMethodSection';
|
|
40
|
+
import ContactDetailsSection from './ContactDetailsSection';
|
|
41
|
+
import SubmitConfirmationDialog from './SubmitConfirmationDialog';
|
|
35
42
|
|
|
36
43
|
type Props = {
|
|
37
44
|
callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
|
|
@@ -51,18 +58,22 @@ type Props = {
|
|
|
51
58
|
showIframe?: boolean;
|
|
52
59
|
language: string;
|
|
53
60
|
merchantAgreementUrl: string;
|
|
54
|
-
paymentMethodsOptions?:
|
|
61
|
+
paymentMethodsOptions?: PaymentMethodSettingsType;
|
|
55
62
|
defaultValues?: OrderFormInputsType;
|
|
56
|
-
paymentMethods?:
|
|
63
|
+
paymentMethods?: PaymentMethodOptionType[];
|
|
57
64
|
allowedPaymentMethods?: PaymentMethodEnum[];
|
|
58
65
|
submitButtonText?: string;
|
|
59
66
|
orderDenialCloseButtonText?: string;
|
|
60
67
|
orderDenialContinueButtonText?: string;
|
|
61
68
|
paymentMethodLabel?: string;
|
|
69
|
+
contactDetailsLabel?: string;
|
|
70
|
+
paymentMethodElementId?: string;
|
|
71
|
+
contactDetailsElementId?: string;
|
|
62
72
|
paymentMethodNotAllowedMsg?: string;
|
|
63
73
|
errorReqMsg?: string;
|
|
64
74
|
errorInvalidEmailMsg?: string;
|
|
65
75
|
errorInvalidPhoneMsg?: string;
|
|
76
|
+
errorTermsMsg?: string;
|
|
66
77
|
invoiceAddressSelection?: {
|
|
67
78
|
enabled?: boolean;
|
|
68
79
|
label?: string;
|
|
@@ -80,6 +91,7 @@ type Props = {
|
|
|
80
91
|
organizationId: string
|
|
81
92
|
) => Promise<OrderDenialFallbackOfferType | undefined>;
|
|
82
93
|
termsAndConditionsText?: string | ReactNode;
|
|
94
|
+
submitConfirmation?: SubmitConfirmationType;
|
|
83
95
|
};
|
|
84
96
|
|
|
85
97
|
const initialData = {
|
|
@@ -118,11 +130,15 @@ const OrderForm: FC<Props> = ({
|
|
|
118
130
|
submitButtonText = 'Start',
|
|
119
131
|
orderDenialCloseButtonText = 'Close',
|
|
120
132
|
orderDenialContinueButtonText = 'Continue',
|
|
121
|
-
paymentMethodLabel = 'Select
|
|
133
|
+
paymentMethodLabel = 'Select payment method',
|
|
134
|
+
contactDetailsLabel,
|
|
135
|
+
paymentMethodElementId,
|
|
136
|
+
contactDetailsElementId,
|
|
122
137
|
paymentMethodNotAllowedMsg = 'This payment method not allowed!',
|
|
123
138
|
errorReqMsg = '',
|
|
124
139
|
errorInvalidEmailMsg = '',
|
|
125
140
|
errorInvalidPhoneMsg = '',
|
|
141
|
+
errorTermsMsg = '',
|
|
126
142
|
errorValidationTitleMsg,
|
|
127
143
|
errorValidationDenialOrderBlockingMsg,
|
|
128
144
|
errorValidationBlockingOffersMsg,
|
|
@@ -132,52 +148,68 @@ const OrderForm: FC<Props> = ({
|
|
|
132
148
|
fetchDenialFallbackOffer,
|
|
133
149
|
requireTermsAcceptance,
|
|
134
150
|
termsAndConditionsText,
|
|
151
|
+
submitConfirmation,
|
|
135
152
|
}) => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
153
|
+
const subscriberIdValue =
|
|
154
|
+
subscriberId || sessionStorage.getItem('subscriberId') || undefined;
|
|
139
155
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (!templatePackageId)
|
|
158
|
+
console.error('"templatePackageId" should be set');
|
|
159
|
+
if (!organizationId) console.error('"organizationId" should be set');
|
|
160
|
+
if (!userId) console.error('"userId" should be set');
|
|
161
|
+
if (!identityProviderId)
|
|
162
|
+
console.error('"identityProviderId" should be set');
|
|
163
|
+
}, [templatePackageId, organizationId, userId, identityProviderId]);
|
|
143
164
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
165
|
+
const config: OrderFormConfig = {
|
|
166
|
+
paymentMethods,
|
|
167
|
+
paymentMethodsOptions,
|
|
168
|
+
allowedPaymentMethods,
|
|
169
|
+
invoiceAddressSelection,
|
|
170
|
+
};
|
|
150
171
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
const messages = {
|
|
173
|
+
errorReqMsg,
|
|
174
|
+
errorInvalidEmailMsg,
|
|
175
|
+
errorInvalidPhoneMsg,
|
|
176
|
+
errorTermsMsg,
|
|
177
|
+
};
|
|
154
178
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
179
|
+
const configuredPaymentMethods = paymentMethods.map((m) => m.value);
|
|
180
|
+
const initialPaymentMethod = configuredPaymentMethods.length
|
|
181
|
+
? ([defaultValues?.paymentMethod, PAYMENT_METHOD_DEFAULT].find(
|
|
182
|
+
(m) => m && configuredPaymentMethods.includes(m)
|
|
183
|
+
) ?? configuredPaymentMethods[0])
|
|
184
|
+
: defaultValues?.paymentMethod || PAYMENT_METHOD_DEFAULT;
|
|
158
185
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
186
|
+
const resolver: Resolver<OrderFormInputsType> = (values, ctx, options) => {
|
|
187
|
+
const schema = buildOrderFormSchema(
|
|
188
|
+
deriveOrderFormState(values, config),
|
|
189
|
+
requireTermsAcceptance,
|
|
190
|
+
messages
|
|
191
|
+
);
|
|
192
|
+
return zodResolver(schema)(values, ctx, options);
|
|
193
|
+
};
|
|
164
194
|
|
|
165
195
|
const methods = useForm<OrderFormInputsType>({
|
|
196
|
+
resolver,
|
|
166
197
|
defaultValues: {
|
|
167
198
|
...initialData,
|
|
168
199
|
...(defaultValues ?? {}),
|
|
169
|
-
paymentMethod:
|
|
170
|
-
defaultValues?.paymentMethod || PAYMENT_METHOD_DEFAULT,
|
|
200
|
+
paymentMethod: initialPaymentMethod,
|
|
171
201
|
},
|
|
172
202
|
});
|
|
173
203
|
|
|
174
|
-
const {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
204
|
+
const { control, handleSubmit, setValue, watch } = methods;
|
|
205
|
+
|
|
206
|
+
const derived = deriveOrderFormState(
|
|
207
|
+
{
|
|
208
|
+
paymentMethod: watch('paymentMethod'),
|
|
209
|
+
invoiceAddressSelection: watch('invoiceAddressSelection'),
|
|
210
|
+
},
|
|
211
|
+
config
|
|
212
|
+
);
|
|
181
213
|
|
|
182
214
|
useEffect(() => {
|
|
183
215
|
userActionCallback?.(UserActionEnum.SELECT_PAYMENT_METHOD, {
|
|
@@ -185,20 +217,6 @@ const OrderForm: FC<Props> = ({
|
|
|
185
217
|
});
|
|
186
218
|
}, []);
|
|
187
219
|
|
|
188
|
-
const invoiceAddressToggle = watch('invoiceAddressSelection');
|
|
189
|
-
const paymentMethodInput = watch('paymentMethod');
|
|
190
|
-
const isTermsAccepted = watch('termsAccept', false);
|
|
191
|
-
|
|
192
|
-
const invoiceOrderFields =
|
|
193
|
-
paymentMethodsOptions?.[paymentMethodInput || PAYMENT_METHOD_DEFAULT]
|
|
194
|
-
?.paymentInvoiceFields ||
|
|
195
|
-
invoiceAddressSelection?.fields ||
|
|
196
|
-
orderInvoiceContactFields;
|
|
197
|
-
|
|
198
|
-
const invoicePaymentMethods =
|
|
199
|
-
invoiceAddressSelection?.paymentMethods ||
|
|
200
|
-
INVOICE_ALLOWED_PAYMENT_METHODS;
|
|
201
|
-
|
|
202
220
|
const {
|
|
203
221
|
orderSubmit,
|
|
204
222
|
continueWithFallbackOffer,
|
|
@@ -215,18 +233,18 @@ const OrderForm: FC<Props> = ({
|
|
|
215
233
|
userActionCallback,
|
|
216
234
|
setContactCallback,
|
|
217
235
|
organizationId,
|
|
218
|
-
subscriberId,
|
|
236
|
+
subscriberId: subscriberIdValue,
|
|
219
237
|
userId,
|
|
220
238
|
identityProviderId,
|
|
221
|
-
orderFields,
|
|
239
|
+
orderFields: derived.orderFields,
|
|
222
240
|
redirectUrl,
|
|
223
241
|
showIframe,
|
|
224
242
|
language,
|
|
225
243
|
merchantAgreementUrl,
|
|
226
244
|
paymentMethodsOptions,
|
|
227
245
|
templatePackageId,
|
|
228
|
-
invoiceAddressToggle,
|
|
229
|
-
invoiceOrderFields,
|
|
246
|
+
invoiceAddressToggle: watch('invoiceAddressSelection'),
|
|
247
|
+
invoiceOrderFields: derived.invoiceOrderFields,
|
|
230
248
|
errorValidationTitleMsg,
|
|
231
249
|
errorValidationDenialOrderBlockingMsg,
|
|
232
250
|
errorValidationBlockingOffersMsg,
|
|
@@ -236,210 +254,145 @@ const OrderForm: FC<Props> = ({
|
|
|
236
254
|
fetchDenialFallbackOffer,
|
|
237
255
|
});
|
|
238
256
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
257
|
+
const [pendingSubmit, setPendingSubmit] =
|
|
258
|
+
useState<OrderFormInputsType | null>(null);
|
|
259
|
+
|
|
260
|
+
const submitOrder = async (data: OrderFormInputsType): Promise<void> => {
|
|
242
261
|
if (
|
|
243
|
-
|
|
244
|
-
|
|
262
|
+
derived.paymentMethod === PaymentMethodEnum.EHF ||
|
|
263
|
+
derived.paymentMethod === PaymentMethodEnum.OIO
|
|
245
264
|
) {
|
|
246
|
-
updateFormData(data);
|
|
265
|
+
updateFormData?.(data);
|
|
247
266
|
return;
|
|
248
267
|
}
|
|
249
268
|
await orderSubmit(data);
|
|
250
269
|
};
|
|
251
270
|
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
271
|
+
const onSubmit: SubmitHandler<OrderFormInputsType> = async (data) => {
|
|
272
|
+
if (submitConfirmation) {
|
|
273
|
+
setPendingSubmit(data);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
await submitOrder(data);
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const confirmSubmit = () => {
|
|
280
|
+
const data = pendingSubmit;
|
|
281
|
+
setPendingSubmit(null);
|
|
282
|
+
if (data) submitOrder(data);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const handlePaymentChange = (paymentMethod: PaymentMethodEnum) => {
|
|
286
|
+
setValue('paymentMethod', paymentMethod, { shouldValidate: true });
|
|
287
|
+
if (!derived.invoicePaymentMethods.includes(paymentMethod)) {
|
|
261
288
|
setValue('invoiceAddressSelection', false);
|
|
262
289
|
}
|
|
263
290
|
|
|
264
291
|
userActionCallback?.(UserActionEnum.SELECT_PAYMENT_METHOD, {
|
|
265
|
-
paymentMethod
|
|
292
|
+
paymentMethod,
|
|
266
293
|
});
|
|
267
294
|
};
|
|
268
295
|
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
296
|
+
const paymentMethodSlot = useSlotElement(paymentMethodElementId);
|
|
297
|
+
const contactDetailsSlot = useSlotElement(contactDetailsElementId);
|
|
298
|
+
const formRef = useRef<HTMLFormElement>(null);
|
|
273
299
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
)
|
|
278
|
-
) {
|
|
279
|
-
return true;
|
|
280
|
-
}
|
|
300
|
+
const handleSlotKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
|
|
301
|
+
if (event.key !== 'Enter' || event.defaultPrevented) return;
|
|
302
|
+
if (!derived.allowPaymentMethod || loading) return;
|
|
281
303
|
|
|
282
|
-
|
|
283
|
-
|
|
304
|
+
const target = event.target as HTMLElement;
|
|
305
|
+
if (target.tagName !== 'INPUT') return;
|
|
284
306
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
invoiceOrderFields?.length > 0 &&
|
|
288
|
-
allowPaymentMethod;
|
|
307
|
+
const { type } = target as HTMLInputElement;
|
|
308
|
+
if (type === 'button' || type === 'submit' || type === 'reset') return;
|
|
289
309
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
310
|
+
event.preventDefault();
|
|
311
|
+
formRef.current?.requestSubmit();
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const paymentMethodSection = derived.showPaymentMethodSelection ? (
|
|
315
|
+
<PaymentMethodSection
|
|
316
|
+
control={control}
|
|
317
|
+
paymentMethods={paymentMethods}
|
|
318
|
+
label={paymentMethodLabel}
|
|
319
|
+
onChange={handlePaymentChange}
|
|
320
|
+
/>
|
|
321
|
+
) : null;
|
|
294
322
|
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
323
|
+
const contactDetailsSection = derived.showContactDetails ? (
|
|
324
|
+
<ContactDetailsSection
|
|
325
|
+
label={contactDetailsLabel}
|
|
326
|
+
orderFields={derived.orderFields}
|
|
327
|
+
invoiceOrderFields={derived.invoiceOrderFields}
|
|
328
|
+
showOrderFields={derived.showOrderFields}
|
|
329
|
+
showInvoiceToggle={derived.showInvoiceToggle}
|
|
330
|
+
showInvoiceFields={derived.showInvoiceFields}
|
|
331
|
+
invoiceToggleLabel={invoiceAddressSelection?.label}
|
|
332
|
+
onInvoiceToggle={(value) =>
|
|
333
|
+
userActionCallback?.(UserActionEnum.TOGGLE_INVOICE_ADDRESS, {
|
|
334
|
+
value,
|
|
335
|
+
})
|
|
336
|
+
}
|
|
337
|
+
/>
|
|
338
|
+
) : null;
|
|
298
339
|
|
|
299
340
|
return (
|
|
300
341
|
<FormProvider {...methods}>
|
|
301
342
|
<form
|
|
302
|
-
|
|
343
|
+
ref={formRef}
|
|
344
|
+
className="sdk-order-form flex w-full flex-col gap-6"
|
|
345
|
+
noValidate
|
|
303
346
|
onSubmit={handleSubmit(onSubmit)}
|
|
304
347
|
data-testid="sdk-order-form-id"
|
|
305
348
|
>
|
|
306
|
-
{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
{paymentMethodLabel}
|
|
311
|
-
</div>
|
|
312
|
-
{paymentMethods.map((item) => (
|
|
313
|
-
<div
|
|
314
|
-
className="radio-button-control"
|
|
315
|
-
key={item.value}
|
|
316
|
-
>
|
|
317
|
-
<label className="radio-badge">
|
|
318
|
-
<input
|
|
319
|
-
{...register('paymentMethod', {
|
|
320
|
-
required: true,
|
|
321
|
-
})}
|
|
322
|
-
onChange={handlePaymentChange}
|
|
323
|
-
type="radio"
|
|
324
|
-
value={item.value}
|
|
325
|
-
/>
|
|
326
|
-
<span className="value-block">
|
|
327
|
-
<span className="prefix-icon"></span>
|
|
328
|
-
<span className="text-block">
|
|
329
|
-
{item.label}
|
|
330
|
-
</span>
|
|
331
|
-
</span>
|
|
332
|
-
</label>
|
|
333
|
-
</div>
|
|
334
|
-
))}
|
|
335
|
-
{errors.paymentMethod && (
|
|
336
|
-
<div className="text-error caption">
|
|
337
|
-
{errors.paymentMethod.message}
|
|
338
|
-
</div>
|
|
339
|
-
)}
|
|
340
|
-
</div>
|
|
341
|
-
</div>
|
|
349
|
+
{renderInSlot(
|
|
350
|
+
paymentMethodSection,
|
|
351
|
+
paymentMethodSlot,
|
|
352
|
+
handleSlotKeyDown
|
|
342
353
|
)}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return Component ? (
|
|
350
|
-
<Component
|
|
351
|
-
key={field.name}
|
|
352
|
-
name={field.name}
|
|
353
|
-
label={field.label}
|
|
354
|
-
required={field.required || false}
|
|
355
|
-
readOnly={field.readOnly || false}
|
|
356
|
-
errors={errors}
|
|
357
|
-
errorReqMsg={errorReqMsg}
|
|
358
|
-
errorInvalidEmailMsg={
|
|
359
|
-
errorInvalidEmailMsg
|
|
360
|
-
}
|
|
361
|
-
errorInvalidPhoneMsg={
|
|
362
|
-
errorInvalidPhoneMsg
|
|
363
|
-
}
|
|
364
|
-
/>
|
|
365
|
-
) : null;
|
|
366
|
-
})}
|
|
367
|
-
</Suspense>
|
|
368
|
-
)}
|
|
369
|
-
{showInvoiceToggle && (
|
|
370
|
-
<ToggleField
|
|
371
|
-
name="invoiceAddressSelection"
|
|
372
|
-
label={
|
|
373
|
-
invoiceAddressSelection?.label ??
|
|
374
|
-
'Invoice Address'
|
|
375
|
-
}
|
|
376
|
-
toggleCallback={(e) =>
|
|
377
|
-
userActionCallback?.(
|
|
378
|
-
UserActionEnum.TOGGLE_INVOICE_ADDRESS,
|
|
379
|
-
{ value: e }
|
|
380
|
-
)
|
|
381
|
-
}
|
|
382
|
-
/>
|
|
383
|
-
)}
|
|
384
|
-
{showInvoiceFields && (
|
|
385
|
-
<Suspense fallback={null}>
|
|
386
|
-
{invoiceOrderFields.map((field) => {
|
|
387
|
-
const Component = formFieldsMapper[field.name];
|
|
388
|
-
|
|
389
|
-
return Component ? (
|
|
390
|
-
<Component
|
|
391
|
-
key={field.name}
|
|
392
|
-
name={field.name}
|
|
393
|
-
label={field.label}
|
|
394
|
-
required={field.required || false}
|
|
395
|
-
readOnly={field.readOnly || false}
|
|
396
|
-
errors={errors}
|
|
397
|
-
errorReqMsg={errorReqMsg}
|
|
398
|
-
errorInvalidEmailMsg={
|
|
399
|
-
errorInvalidEmailMsg
|
|
400
|
-
}
|
|
401
|
-
errorInvalidPhoneMsg={
|
|
402
|
-
errorInvalidPhoneMsg
|
|
403
|
-
}
|
|
404
|
-
/>
|
|
405
|
-
) : null;
|
|
406
|
-
})}
|
|
407
|
-
</Suspense>
|
|
408
|
-
)}
|
|
354
|
+
{renderInSlot(
|
|
355
|
+
contactDetailsSection,
|
|
356
|
+
contactDetailsSlot,
|
|
357
|
+
handleSlotKeyDown
|
|
358
|
+
)}
|
|
359
|
+
<div className="sdk-order-actions-section flex flex-col gap-4">
|
|
409
360
|
{requireTermsAcceptance && (
|
|
410
361
|
<TermsCheckbox
|
|
411
362
|
name="termsAccept"
|
|
412
363
|
label={termsAndConditionsText}
|
|
413
364
|
required
|
|
414
|
-
errors={errors}
|
|
415
365
|
/>
|
|
416
366
|
)}
|
|
417
|
-
{allowPaymentMethod && (
|
|
367
|
+
{derived.allowPaymentMethod && (
|
|
418
368
|
<Button
|
|
419
369
|
type="submit"
|
|
420
370
|
loading={loading}
|
|
421
371
|
buttonText={submitButtonText}
|
|
422
|
-
|
|
372
|
+
className="w-full"
|
|
423
373
|
/>
|
|
424
374
|
)}
|
|
425
375
|
<Alert
|
|
426
|
-
className="mt-2"
|
|
427
376
|
msg={
|
|
428
|
-
allowPaymentMethod
|
|
377
|
+
derived.allowPaymentMethod
|
|
429
378
|
? apiErrorMsg
|
|
430
379
|
: paymentMethodNotAllowedMsg
|
|
431
380
|
}
|
|
432
381
|
/>
|
|
433
382
|
{errorsMsg?.length > 0 &&
|
|
434
|
-
allowPaymentMethod &&
|
|
383
|
+
derived.allowPaymentMethod &&
|
|
435
384
|
errorsMsg.map((i, index) => (
|
|
436
|
-
<Alert
|
|
437
|
-
key={`${i}-${index}`}
|
|
438
|
-
className="mt-2"
|
|
439
|
-
msg={i}
|
|
440
|
-
/>
|
|
385
|
+
<Alert key={`${i}-${index}`} msg={i} />
|
|
441
386
|
))}
|
|
442
387
|
</div>
|
|
388
|
+
{submitConfirmation && (
|
|
389
|
+
<SubmitConfirmationDialog
|
|
390
|
+
isOpen={!!pendingSubmit}
|
|
391
|
+
confirmation={submitConfirmation}
|
|
392
|
+
onConfirm={confirmSubmit}
|
|
393
|
+
onCancel={() => setPendingSubmit(null)}
|
|
394
|
+
/>
|
|
395
|
+
)}
|
|
443
396
|
<OrderDenialModal
|
|
444
397
|
isOpen={!!orderDenialType}
|
|
445
398
|
message={orderDenialMessage}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { cn } from 'cn';
|
|
3
|
+
|
|
4
|
+
import { PaymentMethodOptionType } from '../../types/general';
|
|
5
|
+
import { FieldDescription, FieldTitle } from '../ui/field';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
method: PaymentMethodOptionType;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const PaymentMethodContent: FC<Props> = ({ method }) => {
|
|
12
|
+
const hasIcons = !!method.icons?.length;
|
|
13
|
+
|
|
14
|
+
if (!hasIcons) {
|
|
15
|
+
return (
|
|
16
|
+
<div className="flex flex-1 flex-col gap-0.5">
|
|
17
|
+
<FieldTitle className="sdk-payment-method-label">
|
|
18
|
+
{method.label}
|
|
19
|
+
</FieldTitle>
|
|
20
|
+
{method.description && (
|
|
21
|
+
<FieldDescription className="sdk-payment-method-description">
|
|
22
|
+
{method.description}
|
|
23
|
+
</FieldDescription>
|
|
24
|
+
)}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className="flex flex-1 flex-col gap-0.5">
|
|
31
|
+
<FieldTitle className="sdk-payment-method-icons min-h-5 flex-wrap items-center gap-1.5">
|
|
32
|
+
{method.description && (
|
|
33
|
+
<span className="sdk-payment-method-label sr-only">
|
|
34
|
+
{method.label}
|
|
35
|
+
</span>
|
|
36
|
+
)}
|
|
37
|
+
{method.icons?.map((icon) => (
|
|
38
|
+
<img
|
|
39
|
+
key={icon.src}
|
|
40
|
+
src={icon.src}
|
|
41
|
+
alt={icon.alt ?? ''}
|
|
42
|
+
className={cn(
|
|
43
|
+
'h-5 w-auto object-contain',
|
|
44
|
+
icon.className
|
|
45
|
+
)}
|
|
46
|
+
/>
|
|
47
|
+
))}
|
|
48
|
+
</FieldTitle>
|
|
49
|
+
{method.description ? (
|
|
50
|
+
<FieldDescription className="sdk-payment-method-description">
|
|
51
|
+
{method.description}
|
|
52
|
+
</FieldDescription>
|
|
53
|
+
) : (
|
|
54
|
+
<FieldDescription className="sdk-payment-method-label">
|
|
55
|
+
{method.label}
|
|
56
|
+
</FieldDescription>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default PaymentMethodContent;
|