Add To Cart Button

498

📘

Components:

First, you need to create your AddToCart component which will be responsible for the logic and import withHandlers from recompose.js. It will help us increase rendering speed and avoid memory leaks in the future.
We will also use axios in this example, so let's add it as well.

import { withHandlers } from 'recompose';
import axios from 'axios';

The AddToCartButton component could look like this:

const AddToCartButton = withHandlers({
  onClick: ({ item }) => async (event) => {
    // Prevent clicking item
    event.stopPropagation();
    const item_id = item.get('id');
    const variant_item_id = item.get('selected_variant_id');
    // Send events
    await item.analytics.sendEvent('add-to-cart', { item_id, variant_item_id, quantity: 1, rid: item.meta.toJS().rid });
    await item.analytics.sendEvent('click-item', { item_id, variant_item_id, rid: item.meta.toJS().rid });
    // Your code
    ...
  }
})(({ onClick }) =>
  <button className='YOUR CSS CLASS' onClick={onClick}>
   Add to cart
  </button>
)
const AddToCartButton = withHandlers({
  onClick: ({ item }) => async (event) => {
    // Prevent clicking item
    event.stopPropagation();
    const item_id = item.get('id');
    // Send events
    await item.analytics.sendEvent('add-to-cart', { item_id, quantity: 1, rid: item.meta.toJS().rid });
    await item.analytics.sendEvent('click-item', { item_id, rid: item.meta.toJS().rid });
    window.location.href = `/cart.php?action=add&product_id=${item_id}`;
  }
})(({ onClick }) =>
  <button className='YOUR CSS CLASS' onClick={onClick}>
   Add to cart
  </button>
)
const AddToCartButton = withHandlers({
  onClick: ({ item }) => async (event) => {
    // Prevent clicking item
    event.preventDefault();
    event.stopPropagation();
    const item_id = item.get('id');
    // Send events
    await item.analytics.sendEvent('add-to-cart', { item_id, quantity: 1, rid: item.meta.toJS().rid });
    await item.analytics.sendEvent('click-item', { item_id, rid: item.meta.toJS().rid });
    await axios.post('/cart/add', {
    	quantity: 1,
      id: item.getIn(['variants_ids', 0]) // //SET CORRECT VARIANT ID IF THERE ARE MULTIPLE
    })
  }
})(({ onClick }) =>
  <button className='YOUR CSS CLASS' onClick={onClick}>
   Add to cart
  </button>
)

Result

The final markup of your component could look like this:

/**
 * @module components/Cards/Product
 */

import React from 'react'
import classNames from 'classnames'
import Image from 'components/common/Image'
import Truncate from 'components/common/Truncate'
import Text from 'components/Text'
import Rating from 'components/Cards/Product/Rating';
import Price from 'components/Cards/Product/Price';
import template from 'helpers/template';
import { DiscountSticker, OutOfStockSticker  } from 'components/Cards/Product/Stickers';
import { Map, List } from 'immutable'
import { IProduct, MJSConfiguration, ThemedSFCProps } from 'types';
import { withHandlers } from 'recompose' // <= Import helper
import axios from 'axios' // <= Import axios if you need to send request

const Title: any = ({ text, theme, ...rest }) => (
  <Text display-if={!!text} className={theme.title} {...rest}>{text}</Text>
);

const Description: any = ({ text, theme, ...rest }) => (
  <p
    display-if={!!text}
    className={theme.description}
    {...rest}
  >
    <Truncate>{text}</Truncate>
  </p>
);

export interface IProductCardProps extends ThemedSFCProps {
  item: IProduct;
  config: MJSConfiguration;
}

// Your Button component
const AddToCartButton = withHandlers({
	onClick: ({ item }) => async (event) => {
    // Prevent clicking item
    event.preventDefault();
    event.stopPropagation();
    const item_id = item.get('id');
    const variant_item_id = item.get('selected_variant_id');
    // Send events
    await item.analytics.sendEvent('add-to-cart', { item_id, variant_item_id, quantity: 1, rid: item.meta.toJS().rid });
    await item.analytics.sendEvent('click-item', { item_id, variant_item_id, rid: item.meta.toJS().rid });
    // Your code
    ...
  }
})(({ onClick }) =>
  <button className='YOUR CSS CLASS' onClick={onClick}>
   Add to cart
  </button>
)

const ProductCardView: React.SFC<IProductCardProps> = ({
  item,
  config,
  theme,
}: any) => (
  <a
    onClick={item.onClick}
    href={item.get('product_url')}
    className={classNames(
      theme.root,
      config.get('simple') && theme.simple,
      theme.productCard,
    )}
  >
    <div className={classNames(theme.imageWrap)}>
      <Image
        className={classNames(theme.image)}
        aspectRatio={config.getIn(['product', 'image', 'aspectRatio'], 1)}
        thumbnail={item.get('thumbnail_url')}
        src={item.get('image_url') || item.get('thumbnail_url')}
        alt={item.get('title')}
      />
      <div display-if={config.getIn(['product', 'stickers', 'display'])}>
        <DiscountSticker
          config={config}
          className={theme.discountSticker}
          discount={item.get('discount')}
          display-if={
            config.getIn(['stickers', 'discount']) &&
            config.getIn(['product', 'stickers', 'display']) &&
            item.get('discount', List()).size &&
            item.getIn(['stickers', 'discount'])
          } />
      </div>
    </div>
    <div display-if={config.getIn(['product', 'reviews', 'display']) && !!item.getIn(['reviews', 'count'])} className={theme.rating}>
      <Rating value={item.getIn(['reviews', 'average_score'])} count={item.getIn(['reviews', 'count'])} />
    </div>
    <div
      className={theme.variants}
      display-if={
        config.getIn(['product', 'variants', 'display']) &&
        item.get('variants', List()).size > 1
      }
      >
      {
        template(config.getIn(['product', 'i18n', 'variants'], 'Available in %s variants'))(
          item.get('variants', List()).size
        )
      }
    </div>
    <div className={theme.content}>
      <Title
        theme={theme}
        display-if={config.getIn(['product', 'title', 'display'])}
        text={item.get('title')}
        config={config.getIn(['product', 'title'])} />
      <Description
        theme={theme}
        display-if={config.getIn(['product', 'description', 'display'])}
        text={item.get('description')}
        config={config.getIn(['product', 'description'])} />
      <Price
        className={theme.priceWrapper}
        display-if={config.getIn(['product', 'price', 'display'])}
        price={item.get('price')}
        oldPrice={item.get('compare_at')}
        discount={item.get('discount')}
        currency={config.get('currency').toJS()} />
      <OutOfStockSticker
        display-if={item.getIn(['stickers', 'out-of-stock'])}
        config={config} />
      {
        // Add your component somewhere in the markup
      }
      <AddToCartButton item={item} />
    </div>
  </a>
)

export default ProductCardView;