Skip to content

Commit

Permalink
perf(checkout): CHECKOUT-4338 Only load cart and order summary drawer…
Browse files Browse the repository at this point in the history
… when in mobile view
  • Loading branch information
davidchin committed Aug 20, 2019
1 parent 42522ab commit 35a0560
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 54 deletions.
2 changes: 2 additions & 0 deletions jest-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ if (window.document) {

window.matchMedia = jest.fn(() => ({
matches: false,
addListener: noop,
addEventListener: noop,
removeListener: noop,
removeEventListener: noop,
} as MediaQueryList));

Expand Down
25 changes: 24 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
36 changes: 25 additions & 11 deletions src/app/checkout/Checkout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -172,15 +173,13 @@ class Checkout extends Component<CheckoutProps & WithCheckoutProps & WithLanguag
loginUrl,
promotions = [],
steps,
usableStoreCredit,
} = this.props;

const {
activeStepType,
defaultStepType,
isCartEmpty,
isRedirecting,
useStoreCredit,
} = this.state;

if (isCartEmpty) {
Expand Down Expand Up @@ -212,15 +211,7 @@ class Checkout extends Component<CheckoutProps & WithCheckoutProps & WithLanguag
</ol>
</div>

<aside className="layout-cart">
<Suspense fallback={ <LoadingSpinner isLoading /> }>
<CartSummary storeCreditAmount={ useStoreCredit ? usableStoreCredit : 0 } />
</Suspense>
</aside>

<Suspense fallback={ <LoadingSpinner isLoading /> }>
<CartSummaryDrawer storeCreditAmount={ useStoreCredit ? usableStoreCredit : 0 } />
</Suspense>
{ this.renderCartSummary() }
</LoadingOverlay>
);
}
Expand Down Expand Up @@ -388,6 +379,29 @@ class Checkout extends Component<CheckoutProps & WithCheckoutProps & WithLanguag
);
}

private renderCartSummary(): ReactNode {
const { usableStoreCredit } = this.props;
const { useStoreCredit } = this.state;

return (
<MobileView>
{ matched => {
if (matched) {
return <Suspense fallback={ <LoadingSpinner isLoading /> }>
<CartSummaryDrawer storeCreditAmount={ useStoreCredit ? usableStoreCredit : 0 } />
</Suspense>;
}

return <aside className="layout-cart">
<Suspense fallback={ <LoadingSpinner isLoading /> }>
<CartSummary storeCreditAmount={ useStoreCredit ? usableStoreCredit : 0 } />
</Suspense>
</aside>;
} }
</MobileView>
);
}

private navigateToStep(type: CheckoutStepType, options?: { isDefault?: boolean }): void {
const { clearError, error, steps } = this.props;
const step = find(steps, { type });
Expand Down
2 changes: 0 additions & 2 deletions src/app/order/OrderConfirmation.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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();
});
Expand Down
85 changes: 49 additions & 36 deletions src/app/order/OrderConfirmation.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -103,8 +104,6 @@ class OrderConfirmation extends Component<
orderEmail,
storePhoneNumber,
},
currency,
shopperCurrency,
shopperConfig,
links: {
siteLink,
Expand Down Expand Up @@ -150,7 +149,7 @@ class OrderConfirmation extends Component<
</div>
</div>

{ this.renderOrderSummary({ order, currency, shopperCurrency }) }
{ this.renderOrderSummary() }
{ this.renderErrorModal() }
</div>
);
Expand All @@ -176,38 +175,52 @@ class OrderConfirmation extends Component<
</Fragment>;
}

private renderOrderSummary({ order, currency, shopperCurrency }: {
order: Order;
currency: StoreCurrency;
shopperCurrency: ShopperCurrency;
}): ReactNode {
return (
<Fragment>
<aside className="layout-cart">
<Suspense fallback={ <LoadingSpinner isLoading /> }>
<OrderSummary
headerLink={ <PrintLink /> }
{ ...mapToOrderSummarySubtotalsProps(order) }
lineItems={ order.lineItems }
total={ order.orderAmount }
storeCurrency={ currency }
shopperCurrency={ shopperCurrency }
/>
</Suspense>
</aside>

<Suspense fallback={ <LoadingSpinner isLoading /> }>
<OrderSummaryDrawer
{ ...mapToOrderSummarySubtotalsProps(order) }
headerLink={ <PrintLink className="modal-header-link cart-modal-link" /> }
lineItems={ order.lineItems }
total={ order.orderAmount }
storeCurrency={ currency }
shopperCurrency={ shopperCurrency }
/>
</Suspense>
</Fragment>
);
private renderOrderSummary(): ReactNode {
const {
order,
config,
} = this.props;

if (!order || !config) {
return null;
}

const {
currency,
shopperCurrency,
} = config;

return <>
<MobileView>
{ matched => {
if (matched) {
return <Suspense fallback={ <LoadingSpinner isLoading /> }>
<OrderSummaryDrawer
{ ...mapToOrderSummarySubtotalsProps(order) }
headerLink={ <PrintLink className="modal-header-link cart-modal-link" /> }
lineItems={ order.lineItems }
total={ order.orderAmount }
storeCurrency={ currency }
shopperCurrency={ shopperCurrency }
/>
</Suspense>;
}

return <aside className="layout-cart">
<Suspense fallback={ <LoadingSpinner isLoading /> }>
<OrderSummary
headerLink={ <PrintLink /> }
{ ...mapToOrderSummarySubtotalsProps(order) }
lineItems={ order.lineItems }
total={ order.orderAmount }
storeCurrency={ currency }
shopperCurrency={ shopperCurrency }
/>
</Suspense>
</aside>;
} }
</MobileView>
</>;
}

private renderErrorModal(): ReactNode {
Expand Down
14 changes: 14 additions & 0 deletions src/app/ui/responsive/MobileView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React, { FunctionComponent } from 'react';
import Media, { MediaProps } from 'react-media';

import { MOBILE_MAX_WIDTH } from './breakpoints';

const MobileView: FunctionComponent<Pick<MediaProps, 'children'>> = ({ children }) => {
return (
<Media query={ `(max-width: ${MOBILE_MAX_WIDTH}px)` }>
{ children }
</Media>
);
};

export default MobileView;
2 changes: 2 additions & 0 deletions src/app/ui/responsive/breakpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// These values have to match with screensizes.scss
export const MOBILE_MAX_WIDTH = 968;
4 changes: 4 additions & 0 deletions src/app/ui/responsive/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './breakpoints';

export { default as MobileView } from './MobileView';
export { default as isMobileView } from './isMobileView';
9 changes: 9 additions & 0 deletions src/app/ui/responsive/isMobileView.ts
Original file line number Diff line number Diff line change
@@ -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;
}
4 changes: 0 additions & 4 deletions src/scss/components/checkout/cartDrawer/_cartDrawer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 35a0560

Please sign in to comment.