From a88cb7d3bdb4836a52a3f51b8bdbae0c53645995 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Tue, 14 Jan 2020 18:10:43 +0100 Subject: [PATCH 01/19] Add isShippingRequired to checkout in context object --- package-lock.json | 12 ++++++------ package.json | 4 ++-- src/@sdk/fragments/checkout.ts | 1 + src/@sdk/fragments/types/Checkout.ts | 4 ++++ src/@sdk/mutations/types/CreateCheckout.ts | 4 ++++ .../mutations/types/UpdateCheckoutBillingAddress.ts | 4 ++++ .../mutations/types/UpdateCheckoutShippingAddress.ts | 8 ++++++++ src/@sdk/queries/types/CheckoutDetails.ts | 4 ++++ src/@sdk/queries/types/UserCheckoutDetails.ts | 4 ++++ src/checkout/queries.ts | 3 ++- src/checkout/types/Checkout.ts | 4 ++++ src/checkout/types/createCheckout.ts | 4 ++++ src/checkout/types/getCheckout.ts | 4 ++++ src/checkout/types/getUserCheckout.ts | 4 ++++ .../Billing/types/updateCheckoutBillingAddress.ts | 4 ++++ src/checkout/views/CheckoutDispatcher.tsx | 2 +- .../Shipping/types/updateCheckoutShippingAddress.ts | 8 ++++++++ .../types/updateCheckoutShippingOptions.ts | 4 ++++ 18 files changed, 72 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 078da1fcbc..4c8ca5027e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16901,9 +16901,9 @@ "dev": true }, "graphql": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", - "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", + "version": "14.5.8", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.5.8.tgz", + "integrity": "sha512-MMwmi0zlVLQKLdGiMfWkgQD7dY/TUKt4L+zgJ/aR0Howebod3aNgP5JkgvAULiR2HPVZaP2VEElqtdidHweLkg==", "requires": { "iterall": "^1.2.2" } @@ -18937,9 +18937,9 @@ } }, "iterall": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", - "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" }, "java-properties": { "version": "1.0.2", diff --git a/package.json b/package.json index ba22f9d10e..397867e1ee 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,8 @@ "dompurify": "^2.0.7", "draftjs-to-html": "^0.8.4", "formik": "^1.5.7", - "graphql": "^14.0.2", - "graphql-tag": "^2.9.2", + "graphql": "^14.5.8", + "graphql-tag": "^2.10.1", "history": "^4.7.2", "isomorphic-fetch": "^2.2.1", "js-base64": "^2.4.8", diff --git a/src/@sdk/fragments/checkout.ts b/src/@sdk/fragments/checkout.ts index 17dc52fa84..7df077ab81 100644 --- a/src/@sdk/fragments/checkout.ts +++ b/src/@sdk/fragments/checkout.ts @@ -136,5 +136,6 @@ export const checkoutFragment = gql` lines { ...CheckoutLine } + isShippingRequired } `; diff --git a/src/@sdk/fragments/types/Checkout.ts b/src/@sdk/fragments/types/Checkout.ts index 3e41f702c4..95164a96c8 100644 --- a/src/@sdk/fragments/types/Checkout.ts +++ b/src/@sdk/fragments/types/Checkout.ts @@ -557,4 +557,8 @@ export interface Checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (Checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } diff --git a/src/@sdk/mutations/types/CreateCheckout.ts b/src/@sdk/mutations/types/CreateCheckout.ts index d74f885523..88e435b0c6 100644 --- a/src/@sdk/mutations/types/CreateCheckout.ts +++ b/src/@sdk/mutations/types/CreateCheckout.ts @@ -572,6 +572,10 @@ export interface CreateCheckout_checkoutCreate_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (CreateCheckout_checkoutCreate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface CreateCheckout_checkoutCreate { diff --git a/src/@sdk/mutations/types/UpdateCheckoutBillingAddress.ts b/src/@sdk/mutations/types/UpdateCheckoutBillingAddress.ts index 078637906a..63754aa5b8 100644 --- a/src/@sdk/mutations/types/UpdateCheckoutBillingAddress.ts +++ b/src/@sdk/mutations/types/UpdateCheckoutBillingAddress.ts @@ -572,6 +572,10 @@ export interface UpdateCheckoutBillingAddress_checkoutBillingAddressUpdate_check * A list of checkout lines, each containing information about an item in the checkout. */ lines: (UpdateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface UpdateCheckoutBillingAddress_checkoutBillingAddressUpdate { diff --git a/src/@sdk/mutations/types/UpdateCheckoutShippingAddress.ts b/src/@sdk/mutations/types/UpdateCheckoutShippingAddress.ts index 59daf72680..5194ed0ef6 100644 --- a/src/@sdk/mutations/types/UpdateCheckoutShippingAddress.ts +++ b/src/@sdk/mutations/types/UpdateCheckoutShippingAddress.ts @@ -572,6 +572,10 @@ export interface UpdateCheckoutShippingAddress_checkoutShippingAddressUpdate_che * A list of checkout lines, each containing information about an item in the checkout. */ lines: (UpdateCheckoutShippingAddress_checkoutShippingAddressUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface UpdateCheckoutShippingAddress_checkoutShippingAddressUpdate { @@ -1137,6 +1141,10 @@ export interface UpdateCheckoutShippingAddress_checkoutEmailUpdate_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (UpdateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface UpdateCheckoutShippingAddress_checkoutEmailUpdate_errors { diff --git a/src/@sdk/queries/types/CheckoutDetails.ts b/src/@sdk/queries/types/CheckoutDetails.ts index 90c31b518f..a64c8934e1 100644 --- a/src/@sdk/queries/types/CheckoutDetails.ts +++ b/src/@sdk/queries/types/CheckoutDetails.ts @@ -557,6 +557,10 @@ export interface CheckoutDetails_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (CheckoutDetails_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface CheckoutDetails { diff --git a/src/@sdk/queries/types/UserCheckoutDetails.ts b/src/@sdk/queries/types/UserCheckoutDetails.ts index abfed62303..1771768ca0 100644 --- a/src/@sdk/queries/types/UserCheckoutDetails.ts +++ b/src/@sdk/queries/types/UserCheckoutDetails.ts @@ -557,6 +557,10 @@ export interface UserCheckoutDetails_me_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (UserCheckoutDetails_me_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface UserCheckoutDetails_me { diff --git a/src/checkout/queries.ts b/src/checkout/queries.ts index ffefbf3e82..7f2dddcd31 100644 --- a/src/checkout/queries.ts +++ b/src/checkout/queries.ts @@ -4,7 +4,7 @@ import { TypedMutation } from "../core/mutations"; import { TypedQuery } from "../core/queries"; import { createCheckout, - createCheckoutVariables + createCheckoutVariables, } from "./types/createCheckout"; import { getCheckout, getCheckoutVariables } from "./types/getCheckout"; import { getUserCheckout } from "./types/getUserCheckout"; @@ -142,6 +142,7 @@ export const checkoutFragment = gql` lines { ...CheckoutLine } + isShippingRequired } `; diff --git a/src/checkout/types/Checkout.ts b/src/checkout/types/Checkout.ts index 6ea1180f15..1b3028c719 100644 --- a/src/checkout/types/Checkout.ts +++ b/src/checkout/types/Checkout.ts @@ -541,4 +541,8 @@ export interface Checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (Checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } diff --git a/src/checkout/types/createCheckout.ts b/src/checkout/types/createCheckout.ts index 8237183515..68999d2576 100644 --- a/src/checkout/types/createCheckout.ts +++ b/src/checkout/types/createCheckout.ts @@ -556,6 +556,10 @@ export interface createCheckout_checkoutCreate_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (createCheckout_checkoutCreate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface createCheckout_checkoutCreate { diff --git a/src/checkout/types/getCheckout.ts b/src/checkout/types/getCheckout.ts index e787ce18c3..d27e186c1c 100644 --- a/src/checkout/types/getCheckout.ts +++ b/src/checkout/types/getCheckout.ts @@ -541,6 +541,10 @@ export interface getCheckout_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (getCheckout_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface getCheckout { diff --git a/src/checkout/types/getUserCheckout.ts b/src/checkout/types/getUserCheckout.ts index a6bc9bb545..a807d57830 100644 --- a/src/checkout/types/getUserCheckout.ts +++ b/src/checkout/types/getUserCheckout.ts @@ -541,6 +541,10 @@ export interface getUserCheckout_me_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (getUserCheckout_me_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface getUserCheckout_me { diff --git a/src/checkout/views/Billing/types/updateCheckoutBillingAddress.ts b/src/checkout/views/Billing/types/updateCheckoutBillingAddress.ts index d1dc5a05f7..1c10f280c2 100644 --- a/src/checkout/views/Billing/types/updateCheckoutBillingAddress.ts +++ b/src/checkout/views/Billing/types/updateCheckoutBillingAddress.ts @@ -556,6 +556,10 @@ export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate_check * A list of checkout lines, each containing information about an item in the checkout. */ lines: (updateCheckoutBillingAddress_checkoutBillingAddressUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface updateCheckoutBillingAddress_checkoutBillingAddressUpdate { diff --git a/src/checkout/views/CheckoutDispatcher.tsx b/src/checkout/views/CheckoutDispatcher.tsx index d054ade11c..12c23a144b 100644 --- a/src/checkout/views/CheckoutDispatcher.tsx +++ b/src/checkout/views/CheckoutDispatcher.tsx @@ -8,7 +8,7 @@ import { paymentUrl, reviewUrl, shippingAddressUrl, - shippingOptionsUrl + shippingOptionsUrl, } from "../routes"; const getRedirectUrl = (token: string, step: CheckoutStep): string => { diff --git a/src/checkout/views/Shipping/types/updateCheckoutShippingAddress.ts b/src/checkout/views/Shipping/types/updateCheckoutShippingAddress.ts index 41ec2621d2..52256138db 100644 --- a/src/checkout/views/Shipping/types/updateCheckoutShippingAddress.ts +++ b/src/checkout/views/Shipping/types/updateCheckoutShippingAddress.ts @@ -556,6 +556,10 @@ export interface updateCheckoutShippingAddress_checkoutShippingAddressUpdate_che * A list of checkout lines, each containing information about an item in the checkout. */ lines: (updateCheckoutShippingAddress_checkoutShippingAddressUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface updateCheckoutShippingAddress_checkoutShippingAddressUpdate { @@ -1105,6 +1109,10 @@ export interface updateCheckoutShippingAddress_checkoutEmailUpdate_checkout { * A list of checkout lines, each containing information about an item in the checkout. */ lines: (updateCheckoutShippingAddress_checkoutEmailUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface updateCheckoutShippingAddress_checkoutEmailUpdate_errors { diff --git a/src/checkout/views/ShippingOptions/types/updateCheckoutShippingOptions.ts b/src/checkout/views/ShippingOptions/types/updateCheckoutShippingOptions.ts index a837b20c7d..ac2d1e0aba 100644 --- a/src/checkout/views/ShippingOptions/types/updateCheckoutShippingOptions.ts +++ b/src/checkout/views/ShippingOptions/types/updateCheckoutShippingOptions.ts @@ -554,6 +554,10 @@ export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate_chec * A list of checkout lines, each containing information about an item in the checkout. */ lines: (updateCheckoutShippingOptions_checkoutShippingMethodUpdate_checkout_lines | null)[] | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface updateCheckoutShippingOptions_checkoutShippingMethodUpdate { From de35a389e0287129be6d3d6fd4df65602ac8e325 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Wed, 15 Jan 2020 15:47:01 +0100 Subject: [PATCH 02/19] Hide shipping in checkout when products not require shipping --- src/@sdk/mutations/checkout.ts | 3 +- .../mutations/types/UpdateCheckoutLine.ts | 4 + src/checkout/CheckoutProvider.tsx | 5 +- src/checkout/components/Steps.tsx | 8 +- src/checkout/queries.ts | 1 + src/checkout/types/updateCheckoutLine.ts | 4 + src/checkout/views/Billing/Page.tsx | 39 ++++---- src/checkout/views/Review/Summary.tsx | 26 +++--- src/checkout/views/Review/View.tsx | 6 +- src/components/AddressSummary/index.tsx | 88 +++++++++++-------- src/components/CartProvider/index.tsx | 5 +- src/index.tsx | 4 +- 12 files changed, 115 insertions(+), 78 deletions(-) diff --git a/src/@sdk/mutations/checkout.ts b/src/@sdk/mutations/checkout.ts index 9c52b810fa..7f53cd23ba 100644 --- a/src/@sdk/mutations/checkout.ts +++ b/src/@sdk/mutations/checkout.ts @@ -3,7 +3,7 @@ import gql from "graphql-tag"; import { checkoutFragment, checkoutLineFragment, - checkoutPriceFragment + checkoutPriceFragment, } from "../fragments/checkout"; export const updateCheckoutLineQuery = gql` @@ -19,6 +19,7 @@ export const updateCheckoutLineQuery = gql` subtotalPrice { ...Price } + isShippingRequired } errors { field diff --git a/src/@sdk/mutations/types/UpdateCheckoutLine.ts b/src/@sdk/mutations/types/UpdateCheckoutLine.ts index 69e83f5530..71e4fc1106 100644 --- a/src/@sdk/mutations/types/UpdateCheckoutLine.ts +++ b/src/@sdk/mutations/types/UpdateCheckoutLine.ts @@ -283,6 +283,10 @@ export interface UpdateCheckoutLine_checkoutLinesUpdate_checkout { * The price of the checkout before shipping, with taxes included. */ subtotalPrice: UpdateCheckoutLine_checkoutLinesUpdate_checkout_subtotalPrice | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface UpdateCheckoutLine_checkoutLinesUpdate_errors { diff --git a/src/checkout/CheckoutProvider.tsx b/src/checkout/CheckoutProvider.tsx index 0bcf9aa075..dc95a9bd9c 100644 --- a/src/checkout/CheckoutProvider.tsx +++ b/src/checkout/CheckoutProvider.tsx @@ -6,7 +6,7 @@ import { useAuth, useCheckoutDetails, useUserCheckout } from "@sdk/react"; import { CheckoutContext, CheckoutContextInterface, - CheckoutStep + CheckoutStep, } from "./context"; interface ProviderProps { @@ -63,7 +63,8 @@ export const CheckoutProvider: React.FC = ({ state.checkout.availableShippingMethods.length && !!state.checkout.shippingAddress; const isBillingStep = - isShippingOptionStep && !!state.checkout.shippingMethod; + (isShippingOptionStep && !!state.checkout.shippingMethod) || + !state.checkout.isShippingRequired; const isPaymentStep = isBillingStep && !!state.checkout.billingAddress; const isReviewStep = isPaymentStep && !!(state.cardData || state.dummyStatus); diff --git a/src/checkout/components/Steps.tsx b/src/checkout/components/Steps.tsx index 16e3829a87..04d0bb3c44 100644 --- a/src/checkout/components/Steps.tsx +++ b/src/checkout/components/Steps.tsx @@ -50,11 +50,13 @@ const Steps: React.FC<{ { header: "Shipping Address", path: shippingAddressUrl, + shippingContent: true, step: CheckoutStep.ShippingAddress, }, { header: "Shipping Method", path: shippingOptionsUrl, + shippingContent: true, step: CheckoutStep.ShippingOption, }, { @@ -67,11 +69,15 @@ const Steps: React.FC<{ step: CheckoutStep.Payment, }, ]; + const availableSteps = + checkout && checkout.isShippingRequired + ? steps + : steps.filter(({ shippingContent }) => !shippingContent); const currentStepIndex = steps.findIndex(({ step }) => step === currentStep); return ( <> - {steps.map(({ header, step, path }, index) => ( + {availableSteps.map(({ header, step, path }, index) => ( {currentStepIndex > index ? ( <> diff --git a/src/checkout/queries.ts b/src/checkout/queries.ts index 7f2dddcd31..f77df65c29 100644 --- a/src/checkout/queries.ts +++ b/src/checkout/queries.ts @@ -173,6 +173,7 @@ export const updateCheckoutLineQuery = gql` subtotalPrice { ...Price } + isShippingRequired } errors { field diff --git a/src/checkout/types/updateCheckoutLine.ts b/src/checkout/types/updateCheckoutLine.ts index 9c0e6a3752..49737d93af 100644 --- a/src/checkout/types/updateCheckoutLine.ts +++ b/src/checkout/types/updateCheckoutLine.ts @@ -283,6 +283,10 @@ export interface updateCheckoutLine_checkoutLinesUpdate_checkout { * The price of the checkout before shipping, with taxes included. */ subtotalPrice: updateCheckoutLine_checkoutLinesUpdate_checkout_subtotalPrice | null; + /** + * Returns True, if checkout requires shipping. + */ + isShippingRequired: boolean; } export interface updateCheckoutLine_checkoutLinesUpdate_errors { diff --git a/src/checkout/views/Billing/Page.tsx b/src/checkout/views/Billing/Page.tsx index b6248553b3..0d2eca4e52 100644 --- a/src/checkout/views/Billing/Page.tsx +++ b/src/checkout/views/Billing/Page.tsx @@ -10,7 +10,7 @@ import { GuestAddressForm, StepCheck, Steps, - UserAddressSelector + UserAddressSelector, } from "../../components"; import { CheckoutStep } from "../../context"; import { paymentUrl } from "../../routes"; @@ -33,7 +33,10 @@ const computeMutationVariables = ( return { billingAddress: { city: data.city, - country: maybe(() => data.country.value, data.country.code) as CountryCode, + country: maybe( + () => data.country.value, + data.country.code + ) as CountryCode, countryArea: data.countryArea, firstName: data.firstName, lastName: data.lastName, @@ -113,21 +116,23 @@ const View: React.FC = ({ checkout={checkout} > <> -
- -
+ {checkout.isShippingRequired && ( +
+ +
+ )} {user ? ( @@ -62,17 +62,19 @@ class Summary extends React.PureComponent<{ paragraphRef={this.billingAddressRef} /> -
-

- Shipping method - -

-

{checkout.shippingMethod.name}

-
+ {checkout.isShippingRequired && ( +
+

+ Shipping method + +

+

{checkout.shippingMethod.name}

+
+ )}

Payment method diff --git a/src/checkout/views/Review/View.tsx b/src/checkout/views/Review/View.tsx index 60e188ecea..1475cbbba8 100644 --- a/src/checkout/views/Review/View.tsx +++ b/src/checkout/views/Review/View.tsx @@ -84,7 +84,7 @@ const View: React.FC> = ({
- 5 + {checkout.isShippingRequired ? "5" : "3"}

Review your order

@@ -92,7 +92,9 @@ const View: React.FC> = ({
diff --git a/src/components/AddressSummary/index.tsx b/src/components/AddressSummary/index.tsx index e17f368aee..11238fbeed 100644 --- a/src/components/AddressSummary/index.tsx +++ b/src/components/AddressSummary/index.tsx @@ -5,46 +5,56 @@ import * as React from "react"; import { FormAddressType } from "../ShippingAddressForm/types"; const AddressSummary: React.FC<{ - address: FormAddressType; + address?: FormAddressType; email?: string; paragraphRef?: React.RefObject; -}> = ({ address, email, paragraphRef }) => - address ? ( -

- {`${address.firstName} ${address.lastName}`} -
- {address.companyName && ( - <> - {address.companyName}
- - )} - {address.streetAddress1} -
- {address.streetAddress2 && ( - <> - {address.streetAddress2}
- - )} - {address.city}, {address.postalCode} -
- {address.countryArea && ( - <> - {address.countryArea}
- - )} - {address.country.country} -
- {address.phone && ( - <> - Phone number: {address.phone}
- - )} - {email && ( - <> - {email}
- - )} -

- ) : null; +}> = ({ address, email, paragraphRef }) => { + if (address) { + return ( +

+ {`${address.firstName} ${address.lastName}`} +
+ {address.companyName && ( + <> + {address.companyName}
+ + )} + {address.streetAddress1} +
+ {address.streetAddress2 && ( + <> + {address.streetAddress2}
+ + )} + {address.city}, {address.postalCode} +
+ {address.countryArea && ( + <> + {address.countryArea}
+ + )} + {address.country.country} +
+ {address.phone && ( + <> + Phone number: {address.phone}
+ + )} + {email && ( + <> + {email}
+ + )} +

+ ); + } else if (email) { + return ( +

+ {email} +

+ ); + } + return null; +}; export default AddressSummary; diff --git a/src/components/CartProvider/index.tsx b/src/components/CartProvider/index.tsx index af1961a9dc..bd24d51d51 100644 --- a/src/components/CartProvider/index.tsx +++ b/src/components/CartProvider/index.tsx @@ -6,14 +6,14 @@ import { CheckoutContextInterface } from "../../checkout/context"; import { updateCheckoutLineQuery } from "../../checkout/queries"; import { updateCheckoutLine, - updateCheckoutLineVariables + updateCheckoutLineVariables, } from "../../checkout/types/updateCheckoutLine"; import { maybe } from "../../core/utils"; import { CartContext, CartInterface, CartLine, - CartLineInterface + CartLineInterface, } from "./context"; enum LocalStorageKeys { @@ -123,6 +123,7 @@ export default class CartProvider extends React.Component< checkout.update({ checkout: { ...checkout.checkout, + isShippingRequired: updatedCheckout.isShippingRequired, lines: updatedCheckout.lines, subtotalPrice: updatedCheckout.subtotalPrice, }, diff --git a/src/index.tsx b/src/index.tsx index d757e9f997..610ead4895 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,7 +5,7 @@ import { NotificationTemplate } from "@components/atoms"; import { I18nLoader, ServiceWorkerContext, - ServiceWorkerProvider + ServiceWorkerProvider, } from "@components/containers"; import { SaleorProvider, useAuth, useUserDetails } from "@sdk/react"; import { defaultTheme, GlobalStyle } from "@styles"; @@ -38,7 +38,7 @@ import ShopProvider from "./components/ShopProvider"; import { authLink, - invalidTokenLinkWithTokenHandlerComponent + invalidTokenLinkWithTokenHandlerComponent, } from "./core/auth"; import { languages } from "./languages"; From ffc9f0edd66f4ec8bbd1a5ae5c8d93d3fbf40f04 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Wed, 15 Jan 2020 17:54:19 +0100 Subject: [PATCH 03/19] Query variants products --- src/checkout/queries.ts | 27 ++++++++++++ src/checkout/types/getVariantsProducts.ts | 54 +++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/checkout/types/getVariantsProducts.ts diff --git a/src/checkout/queries.ts b/src/checkout/queries.ts index f77df65c29..02700c28e2 100644 --- a/src/checkout/queries.ts +++ b/src/checkout/queries.ts @@ -8,6 +8,10 @@ import { } from "./types/createCheckout"; import { getCheckout, getCheckoutVariables } from "./types/getCheckout"; import { getUserCheckout } from "./types/getUserCheckout"; +import { + getVariantsProducts, + getVariantsProductsVariables, +} from "./types/getVariantsProducts"; export const checkoutAddressFragment = gql` fragment Address on Address { @@ -217,3 +221,26 @@ const getUserCheckoutQuery = gql` export const TypedGetUserCheckoutQuery = TypedQuery( getUserCheckoutQuery ); + +export const getVariantsProductsQuery = gql` + query getVariantsProducts($ids: [ID]) { + productVariants(ids: $ids, first: 100) { + edges { + node { + id + product { + id + productType { + isShippingRequired + } + } + } + } + } + } +`; + +export const TypedGetVariantsProductsQuery = TypedQuery< + getVariantsProducts, + getVariantsProductsVariables +>(getUserCheckoutQuery); diff --git a/src/checkout/types/getVariantsProducts.ts b/src/checkout/types/getVariantsProducts.ts new file mode 100644 index 0000000000..360814016e --- /dev/null +++ b/src/checkout/types/getVariantsProducts.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: getVariantsProducts +// ==================================================== + +export interface getVariantsProducts_productVariants_edges_node_product_productType { + __typename: "ProductType"; + isShippingRequired: boolean; +} + +export interface getVariantsProducts_productVariants_edges_node_product { + __typename: "Product"; + /** + * The ID of the object. + */ + id: string; + productType: getVariantsProducts_productVariants_edges_node_product_productType; +} + +export interface getVariantsProducts_productVariants_edges_node { + __typename: "ProductVariant"; + /** + * The ID of the object. + */ + id: string; + product: getVariantsProducts_productVariants_edges_node_product; +} + +export interface getVariantsProducts_productVariants_edges { + __typename: "ProductVariantCountableEdge"; + /** + * The item at the end of the edge. + */ + node: getVariantsProducts_productVariants_edges_node; +} + +export interface getVariantsProducts_productVariants { + __typename: "ProductVariantCountableConnection"; + edges: getVariantsProducts_productVariants_edges[]; +} + +export interface getVariantsProducts { + /** + * List of product variants. + */ + productVariants: getVariantsProducts_productVariants | null; +} + +export interface getVariantsProductsVariables { + ids?: (string | null)[] | null; +} From 80e1669f9996cf02c3cdfa38d30b173c3e9af2d0 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Thu, 16 Jan 2020 13:55:39 +0100 Subject: [PATCH 04/19] VariantsProduct hook --- package-lock.json | 6 +-- src/@sdk/index.ts | 9 +++- src/@sdk/queries/index.ts | 23 +++++++-- src/@sdk/queries/products.ts | 18 ++++++++ src/@sdk/queries/types/VariantsProducts.ts | 54 ++++++++++++++++++++++ src/@sdk/react/queries.ts | 4 ++ src/checkout/CheckoutProvider.tsx | 20 +++++++- 7 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 src/@sdk/queries/types/VariantsProducts.ts diff --git a/package-lock.json b/package-lock.json index 4c8ca5027e..fbec30798a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16909,9 +16909,9 @@ } }, "graphql-tag": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.0.tgz", - "integrity": "sha512-9FD6cw976TLLf9WYIUPCaaTpniawIjHWZSwIRZSjrfufJamcXbVVYfN2TWvJYbw0Xf2JjYbl1/f2+wDnBVw3/w==" + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.1.tgz", + "integrity": "sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg==" }, "growly": { "version": "1.3.0", diff --git a/src/@sdk/index.ts b/src/@sdk/index.ts index 5610d29b97..415be9758c 100644 --- a/src/@sdk/index.ts +++ b/src/@sdk/index.ts @@ -16,13 +16,13 @@ import { MapFn, QueryShape, WatchMapFn, - WatchQueryData + WatchQueryData, } from "./types"; import { getErrorsFromData, getMappedData, isDataEmpty, - mergeEdges + mergeEdges, } from "./utils"; import { UserDetails } from "./queries/types/UserDetails"; @@ -88,6 +88,11 @@ export class SaleorAPI { data.me ? data.me.checkout : null ); + getVariantsProducts = this.watchQuery( + QUERIES.VariantsProducts, + data => data.productVariants + ); + setUserDefaultAddress = this.fireQuery( MUTATIONS.AddressTypeUpdate, data => data!.accountSetDefaultAddress diff --git a/src/@sdk/queries/index.ts b/src/@sdk/queries/index.ts index dec5ba6fb2..22d73d843c 100644 --- a/src/@sdk/queries/index.ts +++ b/src/@sdk/queries/index.ts @@ -1,7 +1,7 @@ import { ApolloClient, ObservableQuery, - QueryOptions as ApolloQueryOptions + QueryOptions as ApolloQueryOptions, } from "apollo-client"; import gql from "graphql-tag"; @@ -14,26 +14,31 @@ import * as Product from "./products"; import { CheckoutDetails, - CheckoutDetailsVariables + CheckoutDetailsVariables, } from "./types/CheckoutDetails"; import { OrderByToken, OrderByTokenVariables } from "./types/OrderByToken"; import { Attributes, AttributesVariables } from "./types/Attributes"; import { ProductDetails, - ProductDetailsVariables + ProductDetailsVariables, } from "./types/ProductDetails"; import { ProductList, ProductListVariables } from "./types/ProductList"; import { CategoryDetails, - CategoryDetailsVariables + CategoryDetailsVariables, } from "./types/CategoryDetails"; import { OrdersByUser, OrdersByUserVariables } from "./types/OrdersByUser"; import { UserCheckoutDetails } from "./types/UserCheckoutDetails"; import { UserDetails } from "./types/UserDetails"; +import { + VariantsProducts, + VariantsProductsVariables, +} from "./types/VariantsProducts"; + import * as User from "./user"; type QueryOptions = T extends { [n: string]: never } @@ -132,6 +137,16 @@ export const QUERIES = { `, ...options, }), + VariantsProducts: ( + client: ApolloClient, + options: QueryOptions + ): ObservableQuery => + client.watchQuery({ + query: gql` + ${Product.variantsProducts} + `, + ...options, + }), }; export type QUERIES = typeof QUERIES; diff --git a/src/@sdk/queries/products.ts b/src/@sdk/queries/products.ts index bfc9f4d321..bdbe394c54 100644 --- a/src/@sdk/queries/products.ts +++ b/src/@sdk/queries/products.ts @@ -115,3 +115,21 @@ export const productDetails = gql` } } `; + +export const variantsProducts = gql` + query VariantsProducts($ids: [ID]) { + productVariants(ids: $ids, first: 100) { + edges { + node { + id + product { + id + productType { + isShippingRequired + } + } + } + } + } + } +`; diff --git a/src/@sdk/queries/types/VariantsProducts.ts b/src/@sdk/queries/types/VariantsProducts.ts new file mode 100644 index 0000000000..955798f700 --- /dev/null +++ b/src/@sdk/queries/types/VariantsProducts.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: VariantsProducts +// ==================================================== + +export interface VariantsProducts_productVariants_edges_node_product_productType { + __typename: "ProductType"; + isShippingRequired: boolean; +} + +export interface VariantsProducts_productVariants_edges_node_product { + __typename: "Product"; + /** + * The ID of the object. + */ + id: string; + productType: VariantsProducts_productVariants_edges_node_product_productType; +} + +export interface VariantsProducts_productVariants_edges_node { + __typename: "ProductVariant"; + /** + * The ID of the object. + */ + id: string; + product: VariantsProducts_productVariants_edges_node_product; +} + +export interface VariantsProducts_productVariants_edges { + __typename: "ProductVariantCountableEdge"; + /** + * The item at the end of the edge. + */ + node: VariantsProducts_productVariants_edges_node; +} + +export interface VariantsProducts_productVariants { + __typename: "ProductVariantCountableConnection"; + edges: VariantsProducts_productVariants_edges[]; +} + +export interface VariantsProducts { + /** + * List of product variants. + */ + productVariants: VariantsProducts_productVariants | null; +} + +export interface VariantsProductsVariables { + ids?: (string | null)[] | null; +} diff --git a/src/@sdk/react/queries.ts b/src/@sdk/react/queries.ts index 5ca2986444..3b3cfb1501 100644 --- a/src/@sdk/react/queries.ts +++ b/src/@sdk/react/queries.ts @@ -19,3 +19,7 @@ export const useCategoryDetails = queryWithVariablesFactory( ); export const useAtrributes = queryWithVariablesFactory("getAttributes"); + +export const useVariantsProducts = queryWithVariablesFactory( + "getVariantsProducts" +); diff --git a/src/checkout/CheckoutProvider.tsx b/src/checkout/CheckoutProvider.tsx index dc95a9bd9c..d61bb20e29 100644 --- a/src/checkout/CheckoutProvider.tsx +++ b/src/checkout/CheckoutProvider.tsx @@ -1,7 +1,12 @@ import * as React from "react"; import { useLocalStorage } from "@hooks"; -import { useAuth, useCheckoutDetails, useUserCheckout } from "@sdk/react"; +import { + useAuth, + useCheckoutDetails, + useUserCheckout, + useVariantsProducts, +} from "@sdk/react"; import { CheckoutContext, @@ -54,6 +59,19 @@ export const CheckoutProvider: React.FC = ({ } }, [user.data]); + const { + data: variantsProducts, + loading: variantsProductsLoading, + } = useVariantsProducts({ + ids: state.checkout + ? state.checkout.lines.map(({ variant }) => variant.id) + : [], + }); + + // TODO: Something is wrong, it takes too much products! + // tslint:disable-next-line:no-console + console.log(variantsProducts); + const getCurrentStep = () => { if (!state.checkout) { return CheckoutStep.ShippingAddress; From dd05041f2cb5ea71dfab3fc43d353e1aa97a2c2d Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Thu, 16 Jan 2020 16:24:05 +0100 Subject: [PATCH 05/19] Workaround to check if products requires shipping for guest user --- src/checkout/CheckoutProvider.tsx | 20 +---------------- src/checkout/components/Steps.tsx | 37 ++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/checkout/CheckoutProvider.tsx b/src/checkout/CheckoutProvider.tsx index d61bb20e29..dc95a9bd9c 100644 --- a/src/checkout/CheckoutProvider.tsx +++ b/src/checkout/CheckoutProvider.tsx @@ -1,12 +1,7 @@ import * as React from "react"; import { useLocalStorage } from "@hooks"; -import { - useAuth, - useCheckoutDetails, - useUserCheckout, - useVariantsProducts, -} from "@sdk/react"; +import { useAuth, useCheckoutDetails, useUserCheckout } from "@sdk/react"; import { CheckoutContext, @@ -59,19 +54,6 @@ export const CheckoutProvider: React.FC = ({ } }, [user.data]); - const { - data: variantsProducts, - loading: variantsProductsLoading, - } = useVariantsProducts({ - ids: state.checkout - ? state.checkout.lines.map(({ variant }) => variant.id) - : [], - }); - - // TODO: Something is wrong, it takes too much products! - // tslint:disable-next-line:no-console - console.log(variantsProducts); - const getCurrentStep = () => { if (!state.checkout) { return CheckoutStep.ShippingAddress; diff --git a/src/checkout/components/Steps.tsx b/src/checkout/components/Steps.tsx index 04d0bb3c44..16c255a568 100644 --- a/src/checkout/components/Steps.tsx +++ b/src/checkout/components/Steps.tsx @@ -1,6 +1,9 @@ import * as React from "react"; import { generatePath, Link } from "react-router-dom"; +import { useVariantsProducts } from "@sdk/react"; + +import { CartContext } from "@temp/components/CartProvider/context"; import { ShippingOptionSummary } from "."; import { AddressSummary } from "../../components"; import { CheckoutStep } from "../context"; @@ -46,6 +49,14 @@ const Steps: React.FC<{ token?: string; checkout?: Checkout; }> = ({ checkout, step: currentStep, token, children }) => { + const { lines: cardLines } = React.useContext(CartContext); + const { + data: variantsProducts, + loading: variantsProductsLoading, + } = useVariantsProducts({ + ids: cardLines ? cardLines.map(line => line.variantId) : [], + }); + const steps = [ { header: "Shipping Address", @@ -69,15 +80,31 @@ const Steps: React.FC<{ step: CheckoutStep.Payment, }, ]; - const availableSteps = - checkout && checkout.isShippingRequired - ? steps - : steps.filter(({ shippingContent }) => !shippingContent); + + const availableSteps = () => { + if (checkout && checkout.isShippingRequired) { + return steps; + } else if (checkout) { + return steps.filter(({ shippingContent }) => !shippingContent); + } else if (variantsProducts) { + const isShippingRequired = + variantsProducts.edges && + variantsProducts.edges.some( + ({ node }) => node.product.productType.isShippingRequired + ); + if (isShippingRequired) { + return steps; + } + return steps.filter(({ shippingContent }) => !shippingContent); + } + return steps; + }; + const currentStepIndex = steps.findIndex(({ step }) => step === currentStep); return ( <> - {availableSteps.map(({ header, step, path }, index) => ( + {availableSteps().map(({ header, step, path }, index) => ( {currentStepIndex > index ? ( <> From db758cecb8080ad36117a22d4d96b663a65aac26 Mon Sep 17 00:00:00 2001 From: Dawid Tarasiuk Date: Thu, 16 Jan 2020 21:30:59 +0100 Subject: [PATCH 06/19] Redirect to billing if not user logged in and products exists --- src/checkout/components/StepCheck.tsx | 2 +- src/checkout/components/Steps.tsx | 4 +- src/checkout/index.tsx | 95 ++++++++++++++++----------- src/checkout/views/Billing/Page.tsx | 5 +- src/checkout/views/Billing/View.tsx | 81 ++++++++++++++++------- src/checkout/views/Billing/types.ts | 3 +- src/checkout/views/Shipping/Page.tsx | 2 +- src/checkout/views/Shipping/View.tsx | 2 +- src/checkout/views/Shipping/types.ts | 4 +- 9 files changed, 126 insertions(+), 72 deletions(-) diff --git a/src/checkout/components/StepCheck.tsx b/src/checkout/components/StepCheck.tsx index 8398f9a0c0..e96faf77e3 100644 --- a/src/checkout/components/StepCheck.tsx +++ b/src/checkout/components/StepCheck.tsx @@ -8,7 +8,7 @@ import { paymentUrl, reviewUrl, shippingAddressUrl, - shippingOptionsUrl + shippingOptionsUrl, } from "../routes"; import { Checkout } from "../types/Checkout"; diff --git a/src/checkout/components/Steps.tsx b/src/checkout/components/Steps.tsx index 16c255a568..dcd6540bc0 100644 --- a/src/checkout/components/Steps.tsx +++ b/src/checkout/components/Steps.tsx @@ -3,9 +3,9 @@ import { generatePath, Link } from "react-router-dom"; import { useVariantsProducts } from "@sdk/react"; -import { CartContext } from "@temp/components/CartProvider/context"; import { ShippingOptionSummary } from "."; import { AddressSummary } from "../../components"; +import { CartContext } from "../../components/CartProvider/context"; import { CheckoutStep } from "../context"; import { billingUrl, shippingAddressUrl, shippingOptionsUrl } from "../routes"; import { Checkout } from "../types/Checkout"; @@ -118,7 +118,7 @@ const Steps: React.FC<{

{header}

- {getSummary(step, checkout)} + {checkout && getSummary(step, checkout)} ) : (
diff --git a/src/checkout/index.tsx b/src/checkout/index.tsx index 95b46beed7..ad21016dfe 100644 --- a/src/checkout/index.tsx +++ b/src/checkout/index.tsx @@ -1,58 +1,79 @@ import "./scss/index.scss"; import * as React from "react"; -import { Redirect } from "react-router"; +import { generatePath, Redirect, withRouter } from "react-router"; import { Link } from "react-router-dom"; import ReactSVG from "react-svg"; +import { useVariantsProducts } from "@sdk/react"; + import { Loader, Offline, OfflinePlaceholder, Online, - OverlayManager + OverlayManager, } from "../components"; import { CartContext } from "../components/CartProvider/context"; import { BASE_URL } from "../core/config"; import { CheckoutContext } from "./context"; -import { Routes } from "./routes"; +import { billingUrl, Routes } from "./routes"; import logoImg from "../images/logo.svg"; -const CheckoutApp: React.FC = () => ( -
-
-
- +const CheckoutApp: React.FC<{ location: any }> = ({ location }) => { + const { lines: cartLines } = React.useContext(CartContext); + const { + data: variantsProducts, + loading: variantsProductsLoading, + } = useVariantsProducts({ + ids: cartLines ? cartLines.map(line => line.variantId) : [], + }); + const [initialStepRequired, setInitialStepRequired] = React.useState(true); + + return ( +
+
+
+ +
+ Return to shopping
- Return to shopping -
-
- - - {cart => ( - - {({ loading }) => { - if (!cart.lines.length) { - return ; - } - - if (loading) { - return ; - } - - return ; - }} - - )} - - - - - +
+ + + {cart => ( + + {({ loading, checkout }) => { + if (!cartLines.length) { + return ; + } + + if (loading) { + return ; + } + + if ( + !checkout && + variantsProducts && + location.pathname !== generatePath(billingUrl) + ) { + return ; + } + + return ; + }} + + )} + + + + + +
+
- -
-); + ); +}; -export default CheckoutApp; +export default withRouter(CheckoutApp); diff --git a/src/checkout/views/Billing/Page.tsx b/src/checkout/views/Billing/Page.tsx index 0d2eca4e52..2ce2c41d5f 100644 --- a/src/checkout/views/Billing/Page.tsx +++ b/src/checkout/views/Billing/Page.tsx @@ -58,6 +58,7 @@ const View: React.FC = ({ step, update, updateCheckoutBillingAddress, + isShippingRequired, }) => { const [saveBillingAddress, { loading, error }] = updateCheckoutBillingAddress; const errors = maybe(() => error.extraInfo.userInputErrors, []); @@ -101,7 +102,7 @@ const View: React.FC = ({ const { data: user } = useUserDetails(); - return validateStep ? ( + return !validateStep ? ( = ({ checkout={checkout} > <> - {checkout.isShippingRequired && ( + {isShippingRequired && (