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