Skip to content

Commit 5f48b6f

Browse files
committed
feat(payment): Stripe Shipping Form component migrated to functional
1 parent 0529684 commit 5f48b6f

File tree

1 file changed

+170
-192
lines changed

1 file changed

+170
-192
lines changed
Lines changed: 170 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
import {
2-
type Address,
3-
type CheckoutParams,
4-
type CheckoutSelectors,
5-
type Consignment,
6-
type Country,
7-
type FormField,
8-
type RequestOptions,
9-
type ShippingInitializeOptions,
10-
type ShippingRequestOptions,
2+
type Address,
3+
type CheckoutParams,
4+
type CheckoutSelectors,
5+
type Consignment,
6+
type Country,
7+
type FormField,
8+
type RequestOptions,
9+
type ShippingInitializeOptions,
10+
type ShippingRequestOptions,
1111
} from '@bigcommerce/checkout-sdk';
1212
import { type FormikProps } from 'formik';
1313
import { noop } from 'lodash';
14-
import React, { PureComponent, type ReactNode } from 'react';
14+
import React, { useCallback, useState } from 'react';
1515
import { lazy, object } from 'yup';
16-
1716
import { withLanguage, type WithLanguageProps } from '@bigcommerce/checkout/locale';
18-
import { FormContext } from '@bigcommerce/checkout/ui';
1917

2018
import {
21-
type AddressFormValues,
22-
getAddressFormFieldsValidationSchema,
23-
getTranslateAddressError,
24-
mapAddressToFormValues,
19+
type AddressFormValues,
20+
getAddressFormFieldsValidationSchema,
21+
getTranslateAddressError,
22+
mapAddressToFormValues,
2523
} from '../../address';
24+
2625
import type CheckoutStepStatus from '../../checkout/CheckoutStepStatus';
2726
import { withFormikExtended } from '../../common/form';
2827
import { getCustomFormFieldsValidationSchema } from '../../formFields';
@@ -34,190 +33,169 @@ import ShippingFormFooter from '../ShippingFormFooter';
3433
import StripeShippingAddress from './StripeShippingAddress';
3534

3635
export interface SingleShippingFormProps {
37-
isBillingSameAsShipping: boolean;
38-
cartHasChanged: boolean;
39-
consignments: Consignment[];
40-
countries: Country[];
41-
customerMessage: string;
42-
isLoading: boolean;
43-
isShippingMethodLoading: boolean;
44-
isMultiShippingMode: boolean;
45-
methodId?: string;
46-
shippingAddress?: Address;
47-
shouldShowOrderComments: boolean;
48-
step: CheckoutStepStatus;
49-
isInitialValueLoaded: boolean;
50-
isStripeLoading?(): void;
51-
isStripeAutoStep?(): void;
52-
deinitialize(options: ShippingRequestOptions): Promise<CheckoutSelectors>;
53-
getFields(countryCode?: string): FormField[];
54-
initialize(options: ShippingInitializeOptions): Promise<CheckoutSelectors>;
55-
onSubmit(values: SingleShippingFormValues): void;
56-
onUnhandledError?(error: Error): void;
57-
updateAddress(
58-
address: Partial<Address>,
59-
options?: RequestOptions<CheckoutParams>,
60-
): Promise<CheckoutSelectors>;
36+
isBillingSameAsShipping: boolean;
37+
cartHasChanged: boolean;
38+
consignments: Consignment[];
39+
countries: Country[];
40+
customerMessage: string;
41+
isLoading: boolean;
42+
isShippingMethodLoading: boolean;
43+
isMultiShippingMode: boolean;
44+
methodId?: string;
45+
shippingAddress?: Address;
46+
shouldShowOrderComments: boolean;
47+
step: CheckoutStepStatus;
48+
isInitialValueLoaded: boolean;
49+
isStripeLoading?(): void;
50+
isStripeAutoStep?(): void;
51+
deinitialize(options: ShippingRequestOptions): Promise<CheckoutSelectors>;
52+
getFields(countryCode?: string): FormField[];
53+
initialize(options: ShippingInitializeOptions): Promise<CheckoutSelectors>;
54+
onSubmit(values: SingleShippingFormValues): void;
55+
onUnhandledError?(error: Error): void;
56+
updateAddress(
57+
address: Partial<Address>,
58+
options?: RequestOptions<CheckoutParams>,
59+
): Promise<CheckoutSelectors>;
6160
}
6261

6362
export interface SingleShippingFormValues {
64-
billingSameAsShipping: boolean;
65-
shippingAddress?: AddressFormValues;
66-
orderComment: string;
67-
}
68-
69-
interface SingleShippingFormState {
70-
isUpdatingShippingData: boolean;
63+
billingSameAsShipping: boolean;
64+
shippingAddress?: AddressFormValues;
65+
orderComment: string;
7166
}
7267

73-
class StripeShippingForm extends PureComponent<
74-
SingleShippingFormProps & WithLanguageProps & FormikProps<SingleShippingFormValues>
75-
> {
76-
static contextType = FormContext;
77-
78-
state: SingleShippingFormState = {
79-
isUpdatingShippingData: false,
80-
};
81-
82-
render(): ReactNode {
83-
const {
84-
cartHasChanged,
85-
isInitialValueLoaded,
86-
isLoading,
87-
countries,
88-
isStripeLoading,
89-
shippingAddress,
90-
consignments,
91-
shouldShowOrderComments,
92-
initialize,
93-
isValid,
94-
deinitialize,
95-
onSubmit,
96-
isStripeAutoStep,
97-
step,
98-
isShippingMethodLoading,
99-
} = this.props;
100-
101-
const { isUpdatingShippingData } = this.state;
102-
103-
return (
104-
<Form autoComplete="on">
105-
<Fieldset>
106-
<StripeShippingAddress
107-
consignments={consignments}
108-
countries={countries}
109-
deinitialize={deinitialize}
110-
initialize={initialize}
111-
isShippingMethodLoading={isShippingMethodLoading}
112-
isStripeAutoStep={isStripeAutoStep}
113-
isStripeLoading={isStripeLoading}
114-
onAddressSelect={this.handleAddressSelect}
115-
onSubmit={onSubmit}
116-
shippingAddress={shippingAddress}
117-
shouldDisableSubmit={this.shouldDisableSubmit()}
118-
step={step}
119-
/>
120-
<div className="form-body">
121-
<BillingSameAsShippingField />
122-
</div>
123-
</Fieldset>
124-
125-
<ShippingFormFooter
126-
cartHasChanged={cartHasChanged}
127-
isInitialValueLoaded={isInitialValueLoaded}
128-
isLoading={isLoading || isUpdatingShippingData}
129-
isMultiShippingMode={false}
130-
shouldDisableSubmit={this.shouldDisableSubmit()}
131-
shouldShowOrderComments={shouldShowOrderComments}
132-
shouldShowShippingOptions={isValid}
133-
/>
134-
</Form>
135-
);
68+
const StripeShippingForm: React.FC<SingleShippingFormProps & WithLanguageProps & FormikProps<SingleShippingFormValues>> = (props) => {
69+
const [isUpdatingShippingData] = useState(false);
70+
71+
const {
72+
cartHasChanged,
73+
isInitialValueLoaded,
74+
isLoading,
75+
countries,
76+
isStripeLoading,
77+
shippingAddress,
78+
consignments,
79+
shouldShowOrderComments,
80+
initialize,
81+
isValid,
82+
deinitialize,
83+
onSubmit,
84+
isStripeAutoStep,
85+
step,
86+
isShippingMethodLoading,
87+
updateAddress,
88+
onUnhandledError = noop,
89+
values,
90+
setValues,
91+
getFields,
92+
} = props;
93+
94+
const shouldDisableSubmit = () => {
95+
if (!isValid) {
96+
return false;
13697
}
13798

138-
private shouldDisableSubmit: () => boolean = () => {
139-
const { isLoading, consignments, isValid } = this.props;
140-
141-
const { isUpdatingShippingData } = this.state;
142-
143-
if (!isValid) {
144-
return false;
145-
}
146-
147-
return isLoading || isUpdatingShippingData || !hasSelectedShippingOptions(consignments);
148-
};
149-
150-
private handleAddressSelect: (address: Address) => void = async (address) => {
151-
const { updateAddress, onUnhandledError = noop, values, setValues } = this.props;
152-
153-
try {
154-
await updateAddress(address);
155-
156-
setValues({
157-
...values,
158-
shippingAddress: mapAddressToFormValues(
159-
this.getFields(address.countryCode),
160-
address,
161-
),
162-
});
163-
} catch (error) {
164-
onUnhandledError(error);
165-
}
166-
};
167-
168-
private getFields(countryCode: string | undefined): FormField[] {
169-
const { getFields } = this.props;
170-
171-
return getFields(countryCode);
99+
return isLoading || isUpdatingShippingData || !hasSelectedShippingOptions(consignments);
100+
};
101+
102+
const handleAddressSelect = useCallback(async (address: Address) => {
103+
try {
104+
await updateAddress(address);
105+
106+
setValues({
107+
...values,
108+
shippingAddress: mapAddressToFormValues(
109+
getFields(address.countryCode),
110+
address,
111+
),
112+
});
113+
} catch (error) {
114+
onUnhandledError(error);
172115
}
173-
}
174-
116+
}, [values, setValues, onUnhandledError]);
117+
118+
return (
119+
<Form autoComplete="on">
120+
<Fieldset>
121+
<StripeShippingAddress
122+
consignments={consignments}
123+
countries={countries}
124+
deinitialize={deinitialize}
125+
initialize={initialize}
126+
isShippingMethodLoading={isShippingMethodLoading}
127+
isStripeAutoStep={isStripeAutoStep}
128+
isStripeLoading={isStripeLoading}
129+
onAddressSelect={handleAddressSelect}
130+
onSubmit={onSubmit}
131+
shippingAddress={shippingAddress}
132+
shouldDisableSubmit={shouldDisableSubmit()}
133+
step={step}
134+
/>
135+
136+
<div className="form-body">
137+
<BillingSameAsShippingField />
138+
</div>
139+
</Fieldset>
140+
141+
<ShippingFormFooter
142+
cartHasChanged={cartHasChanged}
143+
isInitialValueLoaded={isInitialValueLoaded}
144+
isLoading={isLoading || isUpdatingShippingData}
145+
isMultiShippingMode={false}
146+
shouldDisableSubmit={shouldDisableSubmit()}
147+
shouldShowOrderComments={shouldShowOrderComments}
148+
shouldShowShippingOptions={isValid}
149+
/>
150+
</Form>
151+
);
152+
};
175153
export default withLanguage(
176-
withFormikExtended<SingleShippingFormProps & WithLanguageProps, SingleShippingFormValues>({
177-
handleSubmit: (values, { props: { onSubmit } }) => {
178-
onSubmit(values);
179-
},
180-
mapPropsToValues: ({
181-
getFields,
182-
shippingAddress,
183-
isBillingSameAsShipping,
184-
customerMessage,
185-
}) => ({
186-
billingSameAsShipping: isBillingSameAsShipping,
187-
orderComment: customerMessage,
188-
shippingAddress: mapAddressToFormValues(
189-
getFields(shippingAddress && shippingAddress.countryCode),
190-
shippingAddress,
191-
),
192-
}),
193-
isInitialValid: ({ shippingAddress, getFields, language }) =>
194-
!!shippingAddress &&
154+
withFormikExtended<SingleShippingFormProps & WithLanguageProps, SingleShippingFormValues>({
155+
handleSubmit: (values, { props: { onSubmit } }) => {
156+
onSubmit(values);
157+
},
158+
mapPropsToValues: ({
159+
getFields,
160+
shippingAddress,
161+
isBillingSameAsShipping,
162+
customerMessage,
163+
}) => ({
164+
billingSameAsShipping: isBillingSameAsShipping,
165+
orderComment: customerMessage,
166+
shippingAddress: mapAddressToFormValues(
167+
getFields(shippingAddress && shippingAddress.countryCode),
168+
shippingAddress,
169+
),
170+
}),
171+
isInitialValid: ({ shippingAddress, getFields, language }) =>
172+
!!shippingAddress &&
173+
getAddressFormFieldsValidationSchema({
174+
language,
175+
formFields: getFields(shippingAddress.countryCode),
176+
}).isValidSync(shippingAddress),
177+
validationSchema: ({
178+
language,
179+
getFields,
180+
methodId,
181+
}: SingleShippingFormProps & WithLanguageProps) =>
182+
methodId
183+
? object({
184+
shippingAddress: lazy<Partial<AddressFormValues>>((formValues) =>
185+
getCustomFormFieldsValidationSchema({
186+
translate: getTranslateAddressError(language),
187+
formFields: getFields(formValues && formValues.countryCode),
188+
}),
189+
),
190+
})
191+
: object({
192+
shippingAddress: lazy<Partial<AddressFormValues>>((formValues) =>
195193
getAddressFormFieldsValidationSchema({
196-
language,
197-
formFields: getFields(shippingAddress.countryCode),
198-
}).isValidSync(shippingAddress),
199-
validationSchema: ({
200-
language,
201-
getFields,
202-
methodId,
203-
}: SingleShippingFormProps & WithLanguageProps) =>
204-
methodId
205-
? object({
206-
shippingAddress: lazy<Partial<AddressFormValues>>((formValues) =>
207-
getCustomFormFieldsValidationSchema({
208-
translate: getTranslateAddressError(language),
209-
formFields: getFields(formValues && formValues.countryCode),
210-
}),
211-
),
212-
})
213-
: object({
214-
shippingAddress: lazy<Partial<AddressFormValues>>((formValues) =>
215-
getAddressFormFieldsValidationSchema({
216-
language,
217-
formFields: getFields(formValues && formValues.countryCode),
218-
}),
219-
),
220-
}),
221-
enableReinitialize: false,
222-
})(StripeShippingForm),
194+
language,
195+
formFields: getFields(formValues && formValues.countryCode),
196+
}),
197+
),
198+
}),
199+
enableReinitialize: false,
200+
})(StripeShippingForm),
223201
);

0 commit comments

Comments
 (0)