Cart and Checkout

The Cart

👍

Heads up

  • If you are using Starter Kit, there's no need need to manually create the Sections and Components below.
  • All the code examples below are just an implementation suggestions. For brevity, the styles are omitted.
  • For this guide, we will be creating Sections and Components locally. Make sure you have your Local Development Environment ready.

👉 Remember to commit and push newly created Sections and Components to your remote repository to sync the changes with Shogun Frontend.

It’s common to have a cart open as a drawer, sliding from right to left to indicate a product was added to the cart. This allows the customer to edit the quantity without navigating away from their current page.

This section will cover the cart drawer and normal cart page. The cart page isn't a necessity, but it can serve as a landing page for the customer if they navigate back from the Shopify checkout page.

For both scenarios, we need specific data points:
-a list of products in the cart
-the total price of the products
-a link to redirect us to checkout itself.

Luckily, the frontend-checkout package provides all of this information via the useCartState hook.

This guide will cover creating:
-CartItem: responsible for rendering a single row of a product in the cart.
-CartItems: shows a list of CartItems.
-CartDrawer: a section that will act as a wrapper and will handle the drawer itself.

Creating CartItem

The CartItem component accepts a product as a prop coming from frontend-checkout's useCartState hook, which we will cover in the next step.

// CartItem component
import * as React from 'react'
import { useCartActions } from 'frontend-checkout'
import { IconButton } from '@chakra-ui/react
import Link from 'frontend-link'
import NumberInput from 'Components/NumberInput'

const CartItem = ({ product }) => {
  const { id, quantity, title: name, variant } = product
  const { image, price, product: variantProduct, title: variantTitle } = variant
  const { src } = image
  const { handle: slug } = variantProduct
  const { removeItems, updateItems } = useCartActions()

  const onChangeItemQuantity = (_, quantityAsNumber) => {
    updateItems({ id, quantity: quantityAsNumber })
  }

  return (
    <div>
      <div>
        <Link to={`/products/${slug}`}>
          <div>
            <img alt="" src={src} height="120px" width="180px" sizes="120px" />
          </div>
          <div>
            <h3>
              {name}
            </h3>
            {variantTitle && (
              <p>
                {variantTitle}
              </p>
            )}
          </div>
        </Link>
      </div>
      <p>
        ${price}
      </p>
      <div>
        <NumberInput
          defaultValue={quantity}
          onChange={onChangeItemQuantity}
          inputProps={{
            'aria-label': 'Product quantity',
            size: 'xs',
          }}
          buttonProps={{
            size: 'xs',
          }}
        />
      </div>
      <p>
        ${Number(price) * quantity}
      </p>
      <div>
        <IconButton
          icon={<Icon icon="CloseIcon" />}
          aria-label={`Remove ${name} from cart`}
          border="0"
          borderRadius="0"
          size="xs"
          variant="outline"
          _hover={{ color: 'gray.700' }}
          onClick={() => removeItems(id)}
        />
      </div>
    </div>
  )
}

export default CartItem

Creating CartItems

The useCartState hook will give us access to all products a customer may have in their cart, the subtotalprice, and the checkoutUrl.

// CartItems component
import * as React from 'react'
import { useCartState } from 'frontend-checkout'
import Link from 'frontend-link'
import CartItem from 'Components/CartItem'

const CartItems = () => {
  const { checkoutUrl, items, subtotalPrice } = useCartState()

  return (
    <div>
      <p>
        Shopping cart ({items.length})
      </p>
      {items.length ? (
        <React.Fragment>
          {items.map(product => (
            <div key={product.id}>
              <CartItem product={product} />
              <hr />
            </div>
          ))}
          <div>
            <div>
              <strong>Subtotal:</strong>
              <p>${subtotalPrice}</p>
            </div>
            <div>
              <Link to="/">
                Continue shopping
              </Link>
              <Link to={checkoutUrl}target="_self">
                Checkout
              </Link>
            </div>
          </div>
        </React.Fragment>
      ) : (
        <React.Fragment>
          <p>Your cart is currently empty.</p>
          <Link to="/">
            Start shopping
          </Link>
        </React.Fragment>
      )}
    </div>
  )
}

export default CartItems

Creating CartDrawer

This step will assemble everything in the CartDrawer section. We will use hideCart from useCartActions and isCartShown from the useCartState hook and have the showCart function to display the CartDrawer when a product is successfully added to the cart.

// CartDrawer section
import * as React from 'react'
import { useCartActions, useCartState } from 'frontend-checkout'
import CartItems from 'Components/CartItems'
import Drawer from 'Components/Drawer'

const CartDrawer = () => {
  const { hideCart } = useCartActions()
  const { isCartShown } = useCartState()

  return (
    <Drawer isOpen={isCartShown} onClose={hideCart} size="md">
      <CartItems />
    </Drawer>
  )
}

export default CartDrawer

The CartDrawer section will live inside the App component. If you are using the Starter Kit, an App component already exists and you will just need to import the CartDrawer into it:

import React from 'react'
import { ChakraProvider } from '@chakra-ui/react'
import { theme } from 'Components/Theme'
import CartDrawer from 'Components/CartDrawer'

const App = props => {
  const { children } = props

  return (
    <ChakraProvider theme={theme}>
      <CartDrawer />
      {children}
    </ChakraProvider>
  )
}

export default App

You will now be able to see the CartDrawer if you add a product to the cart.

The Cart Page

Similar to the CartDrawer, the Cart page will also show a list of the products and will use CartItems.

As a wrapper to the CartItems, we will create a section called CartPage and call the CartItems:

import * as React from 'react'
import CartItems from 'Components/CartItems'
import Container from 'Components/Container'

const CartPage = () => (
  <Container>
    <CartItems />
  </Container>
)

export default CartPage

Next, create a page called Cart, making sure to use /cart for the path, and add the CartPage section to the Cart page. Reference Adding a section in the Homepage Guide if an example is needed.

The cart page is now complete and your customers can now add products to their cart and checkout!


What’s Next