From 35a0560bf06ea3ba919ba117b71af36f9828a272 Mon Sep 17 00:00:00 2001 From: David Chin Date: Tue, 20 Aug 2019 15:34:42 +1000 Subject: [PATCH] perf(checkout): CHECKOUT-4338 Only load cart and order summary drawer when in mobile view --- jest-setup.ts | 2 + package-lock.json | 25 +++++- package.json | 1 + src/app/checkout/Checkout.tsx | 36 +++++--- src/app/order/OrderConfirmation.spec.tsx | 2 - src/app/order/OrderConfirmation.tsx | 85 +++++++++++-------- src/app/ui/responsive/MobileView.tsx | 14 +++ src/app/ui/responsive/breakpoints.ts | 2 + src/app/ui/responsive/index.ts | 4 + src/app/ui/responsive/isMobileView.ts | 9 ++ .../checkout/cartDrawer/_cartDrawer.scss | 4 - 11 files changed, 130 insertions(+), 54 deletions(-) create mode 100644 src/app/ui/responsive/MobileView.tsx create mode 100644 src/app/ui/responsive/breakpoints.ts create mode 100644 src/app/ui/responsive/index.ts create mode 100644 src/app/ui/responsive/isMobileView.ts diff --git a/jest-setup.ts b/jest-setup.ts index 1a4578b22c..bed2e0902f 100644 --- a/jest-setup.ts +++ b/jest-setup.ts @@ -18,7 +18,9 @@ if (window.document) { window.matchMedia = jest.fn(() => ({ matches: false, + addListener: noop, addEventListener: noop, + removeListener: noop, removeEventListener: noop, } as MediaQueryList)); diff --git a/package-lock.json b/package-lock.json index 3ae9b55ddd..ed2f7bd8b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8990,7 +8990,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -10395,6 +10394,14 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=", + "requires": { + "string-convert": "^0.2.0" + } + }, "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", @@ -12681,6 +12688,17 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-media": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/react-media/-/react-media-1.9.2.tgz", + "integrity": "sha512-JUYECMcJIm0V61LSVKd1e+II4ZTYO0GuR7xtlvKETlmThZ416BqZjZdJ1uGqgmMAGFeJ3TG4TX/3Kg4qbR3EJw==", + "requires": { + "@babel/runtime": "^7.2.0", + "invariant": "^2.2.2", + "json2mq": "^0.2.0", + "prop-types": "^15.5.10" + } + }, "react-modal": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.9.1.tgz", @@ -14218,6 +14236,11 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=" + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", diff --git a/package.json b/package.json index a321a6f0f1..b0ef95c172 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "react": "^16.8.0", "react-datepicker": "^2.7.0", "react-dom": "^16.8.0", + "react-media": "^1.9.2", "react-modal": "^3.8.1", "react-popper": "^1.3.2", "react-transition-group": "^2.5.3", diff --git a/src/app/checkout/Checkout.tsx b/src/app/checkout/Checkout.tsx index 90de884076..dabbcf800a 100644 --- a/src/app/checkout/Checkout.tsx +++ b/src/app/checkout/Checkout.tsx @@ -14,6 +14,7 @@ import { PromotionBannerList } from '../promotion'; import { isUsingMultiShipping, StaticConsignment } from '../shipping'; import { FlashMessage } from '../ui/alert'; import { LoadingNotification, LoadingOverlay, LoadingSpinner } from '../ui/loading'; +import { MobileView } from '../ui/responsive'; import mapToCheckoutProps from './mapToCheckoutProps'; import navigateToOrderConfirmation from './navigateToOrderConfirmation'; @@ -172,7 +173,6 @@ class Checkout extends Component - - - }> - - + { this.renderCartSummary() } ); } @@ -388,6 +379,29 @@ class Checkout extends Component + { matched => { + if (matched) { + return }> + + ; + } + + return ; + } } + + ); + } + private navigateToStep(type: CheckoutStepType, options?: { isDefault?: boolean }): void { const { clearError, error, steps } = this.props; const step = find(steps, { type }); diff --git a/src/app/order/OrderConfirmation.spec.tsx b/src/app/order/OrderConfirmation.spec.tsx index d5ac9dd81f..7329416318 100644 --- a/src/app/order/OrderConfirmation.spec.tsx +++ b/src/app/order/OrderConfirmation.spec.tsx @@ -14,7 +14,6 @@ import { getOrder } from './orders.mock'; import OrderConfirmation, { OrderConfirmationProps } from './OrderConfirmation'; import OrderStatus from './OrderStatus'; import OrderSummary from './OrderSummary'; -import OrderSummaryDrawer from './OrderSummaryDrawer'; import ThankYouHeader from './ThankYouHeader'; describe('OrderConfirmation', () => { @@ -128,7 +127,6 @@ describe('OrderConfirmation', () => { expect(orderConfirmation.find('.orderConfirmation').length).toEqual(1); expect(orderConfirmation.find(OrderStatus).length).toEqual(1); expect(orderConfirmation.find(ThankYouHeader).length).toEqual(1); - expect(orderConfirmation.find(OrderSummaryDrawer).length).toEqual(1); expect(orderConfirmation.find(OrderSummary).length).toEqual(1); expect(orderConfirmation.find('[data-test="payment-instructions"]')).toMatchSnapshot(); }); diff --git a/src/app/order/OrderConfirmation.tsx b/src/app/order/OrderConfirmation.tsx index 39cfd4cfea..a74c0d608a 100644 --- a/src/app/order/OrderConfirmation.tsx +++ b/src/app/order/OrderConfirmation.tsx @@ -1,4 +1,4 @@ -import { CheckoutSelectors, EmbeddedCheckoutMessenger, EmbeddedCheckoutMessengerOptions, Order, ShopperConfig, ShopperCurrency, StoreConfig, StoreCurrency } from '@bigcommerce/checkout-sdk'; +import { CheckoutSelectors, EmbeddedCheckoutMessenger, EmbeddedCheckoutMessengerOptions, Order, ShopperConfig, StoreConfig } from '@bigcommerce/checkout-sdk'; import classNames from 'classnames'; import DOMPurify from 'dompurify'; import React, { lazy, Component, Fragment, ReactNode, Suspense } from 'react'; @@ -12,6 +12,7 @@ import { AccountCreationFailedError, AccountCreationRequirementsError } from '.. import { TranslatedString } from '../locale'; import { Button, ButtonVariant } from '../ui/button'; import { LoadingSpinner } from '../ui/loading'; +import { MobileView } from '../ui/responsive'; import getPaymentInstructions from './getPaymentInstructions'; import mapToOrderSummarySubtotalsProps from './mapToOrderSummarySubtotalsProps'; @@ -103,8 +104,6 @@ class OrderConfirmation extends Component< orderEmail, storePhoneNumber, }, - currency, - shopperCurrency, shopperConfig, links: { siteLink, @@ -150,7 +149,7 @@ class OrderConfirmation extends Component< - { this.renderOrderSummary({ order, currency, shopperCurrency }) } + { this.renderOrderSummary() } { this.renderErrorModal() } ); @@ -176,38 +175,52 @@ class OrderConfirmation extends Component< ; } - private renderOrderSummary({ order, currency, shopperCurrency }: { - order: Order; - currency: StoreCurrency; - shopperCurrency: ShopperCurrency; - }): ReactNode { - return ( - - - - }> - } - lineItems={ order.lineItems } - total={ order.orderAmount } - storeCurrency={ currency } - shopperCurrency={ shopperCurrency } - /> - - - ); + private renderOrderSummary(): ReactNode { + const { + order, + config, + } = this.props; + + if (!order || !config) { + return null; + } + + const { + currency, + shopperCurrency, + } = config; + + return <> + + { matched => { + if (matched) { + return }> + } + lineItems={ order.lineItems } + total={ order.orderAmount } + storeCurrency={ currency } + shopperCurrency={ shopperCurrency } + /> + ; + } + + return ; + } } + + ; } private renderErrorModal(): ReactNode { diff --git a/src/app/ui/responsive/MobileView.tsx b/src/app/ui/responsive/MobileView.tsx new file mode 100644 index 0000000000..b82d5f6829 --- /dev/null +++ b/src/app/ui/responsive/MobileView.tsx @@ -0,0 +1,14 @@ +import React, { FunctionComponent } from 'react'; +import Media, { MediaProps } from 'react-media'; + +import { MOBILE_MAX_WIDTH } from './breakpoints'; + +const MobileView: FunctionComponent> = ({ children }) => { + return ( + + { children } + + ); +}; + +export default MobileView; diff --git a/src/app/ui/responsive/breakpoints.ts b/src/app/ui/responsive/breakpoints.ts new file mode 100644 index 0000000000..341820c1a3 --- /dev/null +++ b/src/app/ui/responsive/breakpoints.ts @@ -0,0 +1,2 @@ +// These values have to match with screensizes.scss +export const MOBILE_MAX_WIDTH = 968; diff --git a/src/app/ui/responsive/index.ts b/src/app/ui/responsive/index.ts new file mode 100644 index 0000000000..95255a78ad --- /dev/null +++ b/src/app/ui/responsive/index.ts @@ -0,0 +1,4 @@ +export * from './breakpoints'; + +export { default as MobileView } from './MobileView'; +export { default as isMobileView } from './isMobileView'; diff --git a/src/app/ui/responsive/isMobileView.ts b/src/app/ui/responsive/isMobileView.ts new file mode 100644 index 0000000000..d012b6da44 --- /dev/null +++ b/src/app/ui/responsive/isMobileView.ts @@ -0,0 +1,9 @@ +import { MOBILE_MAX_WIDTH } from './breakpoints'; + +let query: MediaQueryList; + +export default function isMobileView() { + query = query || window.matchMedia(`(max-width: ${MOBILE_MAX_WIDTH}px)`); + + return query.matches; +} diff --git a/src/scss/components/checkout/cartDrawer/_cartDrawer.scss b/src/scss/components/checkout/cartDrawer/_cartDrawer.scss index cf7af8f801..c7a364b41e 100644 --- a/src/scss/components/checkout/cartDrawer/_cartDrawer.scss +++ b/src/scss/components/checkout/cartDrawer/_cartDrawer.scss @@ -17,10 +17,6 @@ right: 0; z-index: zIndex("low"); - @include breakpoint("large") { - display: none; - } - // Making the cartDrawer static when the height of the screen is really small @media (max-height: remCalc($cartDrawer-min-height)) { position: static;