From 6baed9f484662e1523cc450b0e8dea82cf4f4793 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Mon, 3 Aug 2020 13:32:38 +0200 Subject: [PATCH 1/3] Hoist payment gateways for the whole checkout in DOM --- .../CheckoutPayment/CheckoutPayment.tsx | 16 --- .../__snapshots__/stories.storyshot | 99 +------------------ .../organisms/CheckoutPayment/test.tsx | 4 +- .../organisms/CheckoutPayment/types.ts | 13 --- .../templates/Checkout/Checkout.tsx | 5 + .../Checkout/__snapshots__/stories.storyshot | 90 ++++++++++++++--- .../components/templates/Checkout/stories.tsx | 22 ++++- .../components/templates/Checkout/styles.ts | 9 +- .../components/templates/Checkout/types.ts | 2 + src/@next/pages/CheckoutPage/CheckoutPage.tsx | 29 +++++- .../subpages/CheckoutPaymentSubpage.tsx | 28 ++---- 11 files changed, 153 insertions(+), 164 deletions(-) diff --git a/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx b/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx index 3fedd18ab7..868dda2110 100755 --- a/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx +++ b/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx @@ -6,7 +6,6 @@ import { checkoutMessages } from "@temp/intl"; import { DiscountForm } from "../DiscountForm"; import { IDiscountFormData } from "../DiscountForm/types"; -import { PaymentGatewaysList } from "../PaymentGatewaysList"; import * as S from "./styles"; import { IProps } from "./types"; @@ -24,11 +23,7 @@ const CheckoutPayment: React.FC = ({ addPromoCode, removeVoucherCode, submitUnchangedDiscount, - selectedPaymentGateway, - selectedPaymentGatewayToken, selectPaymentGateway, - gatewayFormRef, - gatewayFormId, processPayment, onGatewayError, }: IProps) => { @@ -86,17 +81,6 @@ const CheckoutPayment: React.FC = ({ )} - ); diff --git a/src/@next/components/organisms/CheckoutPayment/__snapshots__/stories.storyshot b/src/@next/components/organisms/CheckoutPayment/__snapshots__/stories.storyshot index 2dabfa004d..f64d10165e 100644 --- a/src/@next/components/organisms/CheckoutPayment/__snapshots__/stories.storyshot +++ b/src/@next/components/organisms/CheckoutPayment/__snapshots__/stories.storyshot @@ -6,7 +6,7 @@ exports[`Storyshots @components/organisms/CheckoutPayment default 1`] = ` margin: 20px; } -.c9 { +.c6 { position: absolute; width: 100%; height: 100%; @@ -105,39 +105,6 @@ exports[`Storyshots @components/organisms/CheckoutPayment default 1`] = ` background-color: rgb(33,18,94); } -.c8 { - cursor: pointer; -} - -.c8 input[type="radio"] { - opacity: 0; - position: fixed; - width: 0; -} - -.c8 > div { - display: inline-block; - width: 1em; - height: 1em; - margin: 0.25em 1em 0.25em 0.25em; - border: 0.1em solid #21125e; - border-radius: 0.5em; - background: #ffffff; - vertical-align: bottom; -} - -.c6 { - display: grid; - grid-gap: 20px; -} - -.c7 { - display: block; - background-color: #f1f5f5; - padding: 20px; - cursor: pointer; -} - .c5 { width: 100%; border-bottom: 1px solid rgba(50,50,50,0.1); @@ -189,72 +156,10 @@ exports[`Storyshots @components/organisms/CheckoutPayment default 1`] = `
-
-
- -
-
- -
-
`; diff --git a/src/@next/components/organisms/CheckoutPayment/test.tsx b/src/@next/components/organisms/CheckoutPayment/test.tsx index d5b04877d9..7cfdf8ee02 100644 --- a/src/@next/components/organisms/CheckoutPayment/test.tsx +++ b/src/@next/components/organisms/CheckoutPayment/test.tsx @@ -28,8 +28,6 @@ describe("", () => { ); - const wrapperText = wrapper.text(); - expect(wrapperText).toContain(PROPS.paymentGateways[0].name); - expect(wrapperText).toContain(PROPS.paymentGateways[1].name); + expect(wrapper.exists()).toEqual(true); }); }); diff --git a/src/@next/components/organisms/CheckoutPayment/types.ts b/src/@next/components/organisms/CheckoutPayment/types.ts index 7ab75dcd65..b964fc7ff2 100755 --- a/src/@next/components/organisms/CheckoutPayment/types.ts +++ b/src/@next/components/organisms/CheckoutPayment/types.ts @@ -14,23 +14,10 @@ export interface IProps { addPromoCode: (promoCode: string) => void; removeVoucherCode: (voucherCode: string) => void; submitUnchangedDiscount: () => void; - /** - * Selected payment gateway. - */ - selectedPaymentGateway?: string; - /** - * Selected payment gateway token. - */ - selectedPaymentGatewayToken?: string; /** * Called when selected payment gateway is changed. */ selectPaymentGateway: (paymentGateway: string) => void; - /** - * Gateway form reference on which payment might be submitted. - */ - gatewayFormRef?: React.RefObject; - gatewayFormId?: string; /** * Method called after the form is submitted. Passed gateway id and token attribute will be used to create payment. */ diff --git a/src/@next/components/templates/Checkout/Checkout.tsx b/src/@next/components/templates/Checkout/Checkout.tsx index b8d45924db..b5de1193f9 100755 --- a/src/@next/components/templates/Checkout/Checkout.tsx +++ b/src/@next/components/templates/Checkout/Checkout.tsx @@ -14,6 +14,8 @@ const Checkout: React.FC = ({ loading, navigation, checkout, + paymentGateways, + hidePaymentGateways = false, cartSummary, button, }: IProps) => { @@ -27,6 +29,9 @@ const Checkout: React.FC = ({ {navigation} {checkout} + + {paymentGateways} + {cartSummary} {button} diff --git a/src/@next/components/templates/Checkout/__snapshots__/stories.storyshot b/src/@next/components/templates/Checkout/__snapshots__/stories.storyshot index 0e61fa8fe5..c71f61b33f 100644 --- a/src/@next/components/templates/Checkout/__snapshots__/stories.storyshot +++ b/src/@next/components/templates/Checkout/__snapshots__/stories.storyshot @@ -6,7 +6,7 @@ exports[`Storyshots @components/templates/Checkout default 1`] = ` margin: 20px; } -.c7 { +.c8 { position: absolute; width: 100%; height: 100%; @@ -30,7 +30,7 @@ exports[`Storyshots @components/templates/Checkout default 1`] = ` grid-template-columns: 8fr 4fr; grid-template-rows: 85px auto auto; grid-column-gap: 30px; - grid-template-areas: "navigation cartSummary" "checkout cartSummary" "button cartSummary"; + grid-template-areas: "navigation cartSummary" "checkout cartSummary" "paymentGateways cartSummary" "button cartSummary"; } .c3 { @@ -42,15 +42,20 @@ exports[`Storyshots @components/templates/Checkout default 1`] = ` .c4 { grid-area: checkout; - padding: 3rem 0; + padding: 3rem 0 0 0; } .c5 { - grid-area: cartSummary; + grid-area: paymentGateways; } .c6 { + grid-area: cartSummary; +} + +.c7 { grid-area: button; + margin: 3rem 0 0 0; } @media (max-width:992px) { @@ -62,12 +67,12 @@ exports[`Storyshots @components/templates/Checkout default 1`] = ` @media (max-width:720px) { .c2 { grid-template-columns: 1fr; - grid-template-areas: "navigation" "checkout" "button"; + grid-template-areas: "navigation" "checkout" "paymentGateways" "button"; } } @media (max-width:720px) { - .c5 { + .c6 { position: fixed; bottom: 0; } @@ -84,20 +89,83 @@ exports[`Storyshots @components/templates/Checkout default 1`] = ` >
+ > +
+ Navigation +
+
+ > +
+ Checkout +
+
+ > +
+ Payment gateways +
+
+ > +
+ Cart summary +
+
+
+ +
`; diff --git a/src/@next/components/templates/Checkout/stories.tsx b/src/@next/components/templates/Checkout/stories.tsx index c82e0f8b5f..35cf3cc207 100644 --- a/src/@next/components/templates/Checkout/stories.tsx +++ b/src/@next/components/templates/Checkout/stories.tsx @@ -3,6 +3,26 @@ import React from "react"; import { Checkout } from "."; +const style = { + backgroundColor: "#ccc", + border: "1px solid black", + padding: "10px", +}; + +const navigation =
Navigation
; +const checkout =
Checkout
; +const paymentGateways =
Payment gateways
; +const cartSummary =
Cart summary
; +const button = ; + storiesOf("@components/templates/Checkout", module) .addParameters({ component: Checkout }) - .add("default", () => ); + .add("default", () => ( + + )); diff --git a/src/@next/components/templates/Checkout/styles.ts b/src/@next/components/templates/Checkout/styles.ts index 6f5cfb1aba..42b3bdb00a 100755 --- a/src/@next/components/templates/Checkout/styles.ts +++ b/src/@next/components/templates/Checkout/styles.ts @@ -20,6 +20,7 @@ export const Wrapper = styled.div` grid-template-areas: "navigation cartSummary" "checkout cartSummary" + "paymentGateways cartSummary" "button cartSummary"; ${media.mediumScreen` @@ -27,6 +28,7 @@ export const Wrapper = styled.div` grid-template-areas: "navigation" "checkout" + "paymentGateways" "button"; `} `; @@ -40,7 +42,11 @@ export const Navigation = styled.div` `; export const Checkout = styled.div` grid-area: checkout; - padding: 3rem 0; + padding: 3rem 0 0 0; +`; +export const PaymentGateways = styled.div<{ hide: boolean }>` + ${props => props.hide && "display: none;"} + grid-area: paymentGateways; `; export const CartSummary = styled.div` grid-area: cartSummary; @@ -52,4 +58,5 @@ export const CartSummary = styled.div` `; export const Button = styled.div` grid-area: button; + margin: 3rem 0 0 0; `; diff --git a/src/@next/components/templates/Checkout/types.ts b/src/@next/components/templates/Checkout/types.ts index a2867d79b7..182734c1d6 100755 --- a/src/@next/components/templates/Checkout/types.ts +++ b/src/@next/components/templates/Checkout/types.ts @@ -2,6 +2,8 @@ export interface IProps { loading?: boolean; navigation?: React.ReactNode; checkout?: React.ReactNode; + paymentGateways?: React.ReactNode; + hidePaymentGateways?: boolean; cartSummary?: React.ReactNode; button?: React.ReactNode; } diff --git a/src/@next/pages/CheckoutPage/CheckoutPage.tsx b/src/@next/pages/CheckoutPage/CheckoutPage.tsx index 3ad86f8b71..c649078b51 100755 --- a/src/@next/pages/CheckoutPage/CheckoutPage.tsx +++ b/src/@next/pages/CheckoutPage/CheckoutPage.tsx @@ -4,7 +4,7 @@ import { Redirect, useLocation, useHistory } from "react-router-dom"; import { Button, Loader } from "@components/atoms"; import { CheckoutProgressBar } from "@components/molecules"; -import { CartSummary } from "@components/organisms"; +import { CartSummary, PaymentGatewaysList } from "@components/organisms"; import { Checkout } from "@components/templates"; import { useCart, useCheckout } from "@saleor/sdk"; import { IItems } from "@saleor/sdk/lib/api/Cart/types"; @@ -101,7 +101,12 @@ const CheckoutPage: React.FC = ({}: IProps) => { totalPrice, items, } = useCart(); - const { loaded: checkoutLoaded, checkout, payment } = useCheckout(); + const { + loaded: checkoutLoaded, + checkout, + payment, + availablePaymentGateways, + } = useCheckout(); const intl = useIntl(); if (cartLoaded && (!items || !items?.length)) { @@ -151,6 +156,8 @@ const CheckoutPage: React.FC = ({}: IProps) => { null ); const checkoutReviewSubpageRef = useRef(null); + const checkoutGatewayFormId = "gateway-form"; + const checkoutGatewayFormRef = useRef(null); const handleNextStepClick = () => { // Some magic above and below ensures that the activeStepIndex will always @@ -227,8 +234,6 @@ const CheckoutPage: React.FC = ({}: IProps) => { renderPayment={props => ( = ({}: IProps) => { ); + // TODO: handle payment gateways callbacks + const paymentGatewaysView = availablePaymentGateways && ( + undefined} + formId={checkoutGatewayFormId} + formRef={checkoutGatewayFormRef} + selectedPaymentGateway={selectedPaymentGateway} + selectedPaymentGatewayToken={selectedPaymentGatewayToken} + selectPaymentGateway={() => undefined} + onError={() => undefined} + /> + ); + let buttonText = activeStep.nextActionName; /* eslint-disable default-case */ switch (activeStep.nextActionName) { @@ -282,6 +301,8 @@ const CheckoutPage: React.FC = ({}: IProps) => { items )} checkout={checkoutView} + paymentGateways={paymentGatewaysView} + hidePaymentGateways={steps[activeStepIndex].name !== "Payment"} button={getButton(buttonText.toUpperCase(), handleNextStepClick)} /> ); diff --git a/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx b/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx index 5c55d5875d..d4c2939f11 100644 --- a/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx +++ b/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx @@ -17,8 +17,7 @@ export interface ICheckoutPaymentSubpageHandles { submitPayment: () => void; } interface IProps extends RouteComponentProps { - selectedPaymentGateway?: string; - selectedPaymentGatewayToken?: string; + paymentGatewayFormRef?: React.RefObject; selectPaymentGateway: (paymentGateway: string) => void; changeSubmitProgress: (submitInProgress: boolean) => void; onSubmitSuccess: () => void; @@ -29,8 +28,7 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< IProps > = ( { - selectedPaymentGateway, - selectedPaymentGatewayToken, + paymentGatewayFormRef, changeSubmitProgress, selectPaymentGateway, onSubmitSuccess, @@ -51,8 +49,6 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< const paymentGateways = availablePaymentGateways || []; - const checkoutGatewayFormId = "gateway-form"; - const checkoutGatewayFormRef = useRef(null); const promoCodeDiscountFormId = "discount-form"; const promoCodeDiscountFormRef = useRef(null); const intl = useIntl(); @@ -63,8 +59,8 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< promoCodeDiscountFormRef.current?.dispatchEvent( new Event("submit", { cancelable: true }) ); - } else if (checkoutGatewayFormRef.current) { - checkoutGatewayFormRef.current.dispatchEvent( + } else if (paymentGatewayFormRef?.current) { + paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { @@ -102,8 +98,8 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< setPromoCodeErrors(errors); } else { setPromoCodeErrors([]); - if (checkoutGatewayFormRef.current) { - checkoutGatewayFormRef.current.dispatchEvent( + if (paymentGatewayFormRef?.current) { + paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { @@ -122,8 +118,8 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< setPromoCodeErrors(errors); } else { setPromoCodeErrors([]); - if (checkoutGatewayFormRef.current) { - checkoutGatewayFormRef.current.dispatchEvent( + if (paymentGatewayFormRef?.current) { + paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { @@ -135,8 +131,8 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< } }; const handleSubmitUnchangedDiscount = () => { - if (checkoutGatewayFormRef.current) { - checkoutGatewayFormRef.current.dispatchEvent( + if (paymentGatewayFormRef?.current) { + paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { @@ -152,8 +148,6 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< {...props} gatewayErrors={gatewayErrors} paymentGateways={paymentGateways} - selectedPaymentGateway={selectedPaymentGateway} - selectedPaymentGatewayToken={selectedPaymentGatewayToken} selectPaymentGateway={selectPaymentGateway} promoCodeDiscountFormId={promoCodeDiscountFormId} promoCodeDiscountFormRef={promoCodeDiscountFormRef} @@ -164,8 +158,6 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< removeVoucherCode={handleRemovePromoCode} submitUnchangedDiscount={handleSubmitUnchangedDiscount} promoCodeErrors={promoCodeErrors} - gatewayFormId={checkoutGatewayFormId} - gatewayFormRef={checkoutGatewayFormRef} processPayment={handleProcessPayment} onGatewayError={handlePaymentGatewayError} /> From 9400ce156b2eba2bc083f0a70d8587dbef8521f9 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Mon, 3 Aug 2020 18:59:39 +0200 Subject: [PATCH 2/3] Handle payment gateways callbacks --- .../CheckoutPayment/CheckoutPayment.tsx | 5 -- .../organisms/CheckoutPayment/stories.tsx | 6 -- .../organisms/CheckoutPayment/test.tsx | 6 -- .../organisms/CheckoutPayment/types.ts | 20 +------ src/@next/pages/CheckoutPage/CheckoutPage.tsx | 38 +++++++++--- .../subpages/CheckoutPaymentSubpage.tsx | 58 +++++-------------- 6 files changed, 45 insertions(+), 88 deletions(-) diff --git a/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx b/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx index 868dda2110..c5a01de04b 100755 --- a/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx +++ b/src/@next/components/organisms/CheckoutPayment/CheckoutPayment.tsx @@ -14,18 +14,13 @@ import { IProps } from "./types"; * Payment options used in checkout. */ const CheckoutPayment: React.FC = ({ - gatewayErrors, promoCodeErrors, - paymentGateways, promoCodeDiscountFormId, promoCodeDiscountFormRef, promoCodeDiscount, addPromoCode, removeVoucherCode, submitUnchangedDiscount, - selectPaymentGateway, - processPayment, - onGatewayError, }: IProps) => { const [showPromoCodeForm, setShowPromoCodeForm] = useState( !!promoCodeDiscount?.voucherCode diff --git a/src/@next/components/organisms/CheckoutPayment/stories.tsx b/src/@next/components/organisms/CheckoutPayment/stories.tsx index 61f02c6cae..279d96bb79 100644 --- a/src/@next/components/organisms/CheckoutPayment/stories.tsx +++ b/src/@next/components/organisms/CheckoutPayment/stories.tsx @@ -18,9 +18,6 @@ const removeVoucherCode = action("removeVoucherCode has been called"); const submitUnchangedDiscount = action( "submitUnchangedDiscount has been called" ); -const selectPaymentGateway = action("selectPaymentGateway has been called"); -const processPayment = action("processPayment has been called"); -const onGatewayError = action("onGatewayError has been called"); storiesOf("@components/organisms/CheckoutPayment", module) .addParameters({ component: CheckoutPayment }) @@ -31,9 +28,6 @@ storiesOf("@components/organisms/CheckoutPayment", module) addPromoCode={addPromoCode} removeVoucherCode={removeVoucherCode} submitUnchangedDiscount={submitUnchangedDiscount} - selectPaymentGateway={selectPaymentGateway} - processPayment={processPayment} - onGatewayError={onGatewayError} /> )); diff --git a/src/@next/components/organisms/CheckoutPayment/test.tsx b/src/@next/components/organisms/CheckoutPayment/test.tsx index 7cfdf8ee02..9a5c3a5164 100644 --- a/src/@next/components/organisms/CheckoutPayment/test.tsx +++ b/src/@next/components/organisms/CheckoutPayment/test.tsx @@ -11,9 +11,6 @@ describe("", () => { const addPromoCode = jest.fn(); const removeVoucherCode = jest.fn(); const submitUnchangedDiscount = jest.fn(); - const selectPaymentGateway = jest.fn(); - const processPayment = jest.fn(); - const onGatewayError = jest.fn(); const wrapper = mount( ", () => { addPromoCode={addPromoCode} removeVoucherCode={removeVoucherCode} submitUnchangedDiscount={submitUnchangedDiscount} - selectPaymentGateway={selectPaymentGateway} - processPayment={processPayment} - onGatewayError={onGatewayError} /> ); diff --git a/src/@next/components/organisms/CheckoutPayment/types.ts b/src/@next/components/organisms/CheckoutPayment/types.ts index b964fc7ff2..b73c525115 100755 --- a/src/@next/components/organisms/CheckoutPayment/types.ts +++ b/src/@next/components/organisms/CheckoutPayment/types.ts @@ -1,33 +1,15 @@ -import { ICardData, IFormError, IPaymentGateway } from "@types"; +import { IFormError } from "@types"; export interface IPromoCodeDiscount { voucherCode?: string | null; } export interface IProps { - gatewayErrors?: IFormError[]; promoCodeErrors?: IFormError[]; - paymentGateways: IPaymentGateway[]; promoCodeDiscount?: IPromoCodeDiscount; promoCodeDiscountFormRef?: React.RefObject; promoCodeDiscountFormId?: string; addPromoCode: (promoCode: string) => void; removeVoucherCode: (voucherCode: string) => void; submitUnchangedDiscount: () => void; - /** - * Called when selected payment gateway is changed. - */ - selectPaymentGateway: (paymentGateway: string) => void; - /** - * Method called after the form is submitted. Passed gateway id and token attribute will be used to create payment. - */ - processPayment: ( - gateway: string, - token: string, - cardData?: ICardData - ) => void; - /** - * Method called when gateway error occured. - */ - onGatewayError: (errors: IFormError[]) => void; } diff --git a/src/@next/pages/CheckoutPage/CheckoutPage.tsx b/src/@next/pages/CheckoutPage/CheckoutPage.tsx index c649078b51..881f5acc02 100755 --- a/src/@next/pages/CheckoutPage/CheckoutPage.tsx +++ b/src/@next/pages/CheckoutPage/CheckoutPage.tsx @@ -10,7 +10,7 @@ import { useCart, useCheckout } from "@saleor/sdk"; import { IItems } from "@saleor/sdk/lib/api/Cart/types"; import { CHECKOUT_STEPS } from "@temp/core/config"; import { checkoutMessages } from "@temp/intl"; -import { ITaxedMoney, ICheckoutStep } from "@types"; +import { ITaxedMoney, ICheckoutStep, ICardData, IFormError } from "@types"; import { CheckoutRouter } from "./CheckoutRouter"; import { @@ -106,6 +106,7 @@ const CheckoutPage: React.FC = ({}: IProps) => { checkout, payment, availablePaymentGateways, + createPayment, } = useCheckout(); const intl = useIntl(); @@ -122,6 +123,9 @@ const CheckoutPage: React.FC = ({}: IProps) => { selectedPaymentGatewayToken, setSelectedPaymentGatewayToken, ] = useState(payment?.token); + const [paymentGatewayErrors, setPaymentGatewayErrors] = useState< + IFormError[] + >([]); useEffect(() => { setSelectedPaymentGateway(payment?.gateway); @@ -163,7 +167,7 @@ const CheckoutPage: React.FC = ({}: IProps) => { // Some magic above and below ensures that the activeStepIndex will always // be in 0-3 range /* eslint-disable default-case */ - switch (steps[activeStepIndex].index) { + switch (activeStep.index) { case 0: if (checkoutAddressSubpageRef.current?.submitAddress) { checkoutAddressSubpageRef.current?.submitAddress(); @@ -234,9 +238,10 @@ const CheckoutPage: React.FC = ({}: IProps) => { renderPayment={props => ( )} @@ -254,17 +259,36 @@ const CheckoutPage: React.FC = ({}: IProps) => { ); - // TODO: handle payment gateways callbacks + const handleProcessPayment = async ( + gateway: string, + token: string, + cardData?: ICardData + ) => { + const { dataError } = await createPayment(gateway, token, cardData); + const errors = dataError?.error; + setSubmitInProgress(false); + if (errors) { + setPaymentGatewayErrors(errors); + } else { + setPaymentGatewayErrors([]); + handleStepSubmitSuccess(); + } + }; + const handlePaymentGatewayError = () => { + setSubmitInProgress(false); + }; + const paymentGatewaysView = availablePaymentGateways && ( undefined} + processPayment={handleProcessPayment} formId={checkoutGatewayFormId} formRef={checkoutGatewayFormRef} selectedPaymentGateway={selectedPaymentGateway} selectedPaymentGatewayToken={selectedPaymentGatewayToken} - selectPaymentGateway={() => undefined} - onError={() => undefined} + selectPaymentGateway={setSelectedPaymentGateway} + onError={handlePaymentGatewayError} + errors={paymentGatewayErrors} /> ); diff --git a/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx b/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx index d4c2939f11..361030b623 100644 --- a/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx +++ b/src/@next/pages/CheckoutPage/subpages/CheckoutPaymentSubpage.tsx @@ -11,16 +11,16 @@ import { RouteComponentProps } from "react-router"; import { CheckoutPayment } from "@components/organisms"; import { useCheckout } from "@saleor/sdk"; import { commonMessages } from "@temp/intl"; -import { ICardData, IFormError } from "@types"; +import { IFormError } from "@types"; export interface ICheckoutPaymentSubpageHandles { submitPayment: () => void; } interface IProps extends RouteComponentProps { - paymentGatewayFormRef?: React.RefObject; - selectPaymentGateway: (paymentGateway: string) => void; + paymentGatewayFormRef: React.RefObject; changeSubmitProgress: (submitInProgress: boolean) => void; onSubmitSuccess: () => void; + onPaymentGatewayError: (errors: IFormError[]) => void; } const CheckoutPaymentSubpageWithRef: RefForwardingComponent< @@ -30,25 +30,16 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< { paymentGatewayFormRef, changeSubmitProgress, - selectPaymentGateway, onSubmitSuccess, + onPaymentGatewayError, ...props }: IProps, ref ) => { - const { - availablePaymentGateways, - promoCodeDiscount, - addPromoCode, - removePromoCode, - createPayment, - } = useCheckout(); + const { promoCodeDiscount, addPromoCode, removePromoCode } = useCheckout(); - const [gatewayErrors, setGatewayErrors] = useState([]); const [promoCodeErrors, setPromoCodeErrors] = useState([]); - const paymentGateways = availablePaymentGateways || []; - const promoCodeDiscountFormId = "discount-form"; const promoCodeDiscountFormRef = useRef(null); const intl = useIntl(); @@ -59,37 +50,19 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< promoCodeDiscountFormRef.current?.dispatchEvent( new Event("submit", { cancelable: true }) ); - } else if (paymentGatewayFormRef?.current) { + } else if (paymentGatewayFormRef.current) { paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { changeSubmitProgress(false); - setGatewayErrors([ + onPaymentGatewayError([ { message: intl.formatMessage(commonMessages.choosePaymentMethod) }, ]); } }, })); - const handleProcessPayment = async ( - gateway: string, - token: string, - cardData?: ICardData - ) => { - const { dataError } = await createPayment(gateway, token, cardData); - const errors = dataError?.error; - changeSubmitProgress(false); - if (errors) { - setGatewayErrors(errors); - } else { - setGatewayErrors([]); - onSubmitSuccess(); - } - }; - const handlePaymentGatewayError = () => { - changeSubmitProgress(false); - }; const handleAddPromoCode = async (promoCode: string) => { const { dataError } = await addPromoCode(promoCode); const errors = dataError?.error; @@ -98,13 +71,13 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< setPromoCodeErrors(errors); } else { setPromoCodeErrors([]); - if (paymentGatewayFormRef?.current) { + if (paymentGatewayFormRef.current) { paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { changeSubmitProgress(false); - setGatewayErrors([ + onPaymentGatewayError([ { message: intl.formatMessage(commonMessages.choosePaymentMethod) }, ]); } @@ -118,26 +91,26 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< setPromoCodeErrors(errors); } else { setPromoCodeErrors([]); - if (paymentGatewayFormRef?.current) { + if (paymentGatewayFormRef.current) { paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { changeSubmitProgress(false); - setGatewayErrors([ + onPaymentGatewayError([ { message: intl.formatMessage(commonMessages.choosePaymentMethod) }, ]); } } }; const handleSubmitUnchangedDiscount = () => { - if (paymentGatewayFormRef?.current) { + if (paymentGatewayFormRef.current) { paymentGatewayFormRef.current.dispatchEvent( new Event("submit", { cancelable: true }) ); } else { changeSubmitProgress(false); - setGatewayErrors([ + onPaymentGatewayError([ { message: intl.formatMessage(commonMessages.choosePaymentMethod) }, ]); } @@ -146,9 +119,6 @@ const CheckoutPaymentSubpageWithRef: RefForwardingComponent< return ( ); }; From 9eabcfbe1bab4d20340c473ee2132aaa73bc579d Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Thu, 6 Aug 2020 11:48:13 +0300 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d922a46e21..50f1ebbfe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable, unreleased changes to this project will be documented in this file. - Do not throw error if unsupported payment gateway found - #819 by @dominik-zeglen - Fix tsconfig aliases - #824 by @orzechdev - Set billing address in first checkout step - #822 by @orzechdev +- Persist payment gateways for the whole checkout - #828 by @orzechdev ## 2.10.4