Maropost Add to Cart

Add Maropost Add to Cart with quantity picker integration

First, you need to create your AddToCart component which will be responsible for the logic and import compose, withStateHandlers, withHandlers, from recompose.js. It will help us increase rendering speed and avoid memory leaks in the future.
import {compose, withStateHandlers, withHandlers} from 'recompose'

import React from 'react';
import Branch from 'components/common/Branch';
import {compose, withStateHandlers, withHandlers, withProps} from 'recompose';

const withAddToCart = compose(
  withStateHandlers(
    ({ qty }) => ({ 
      qty: 1,
    }),
    {
      changeQty: () => (qty) => ({ qty: qty }),
    }
  ),
  withHandlers({
    handleAddToCart: () => async (event, item, qty) => {
      event.preventDefault();
      event.stopPropagation();
      await item.analytics.sendEvent('click-item',
        { 
          rid: item.meta.get('rid'), 
          item_id: item.get('id') 
        },
        false
      );
      await item.analytics.sendEvent('add-to-cart', { item_id: item.get('id') , quantity: qty, rid: item.meta.get('rid') });
    }
  })
)


const AddToCart = ({ item, handleAddToCart, changeQty, qty, isAvailable }) => (
<div className='findify-add-to-cart-button-wrapper'>
  <form class="form-inline buying-options">
    <input type="hidden" id={`sku${item.get('id')}`} name={`sku${item.get('id')}`} value={item.get('id')}></input>
    <input type="hidden" id={`model${item.get('id')}`} name={`model${item.get('id')}`} value={item.get('title')}></input>
    <input type="hidden" id={`thumb${item.get('id')}`} name={`thumb${item.get('id')}`} value={item.get('thumbnail_url')}></input>
    <div className="findify-cart-buttons-wrapper">
      <input 
        type="text" 
        min="1" 
        id={`qty${item.get('id')}`}
        name={`qty${item.get('id')}`}
        value={qty}
        onInput={e => changeQty(e.target.value)}
        className="findify-qty"
      />
      <button 
        type="button" 
        title="Add to Cart" 
        className="addtocart btn-primary btn btn-block btn-loads" 
        rel={item.get('id')} 
        data-loading-text="<i class='fa fa-spinner fa-spin' style='font-size: 14px'></i>"
      >
        Add to Cart
      </button>
    </div>
  </form>
</div>
)


export default withAddToCart(AddToCart)

Result

You need to transfer AddToCart component outside the tag a to not have problems with adding to cart and relocation to the PDP page.

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 { List } from 'immutable'
import { IProduct, MJSConfiguration, ThemedSFCProps } from 'types/index';
import BundleAction from 'components/Cards/Product/BundleAction';
import AddToCart from 'AddToCart';

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;
}

const ProductCardView: React.SFC<IProductCardProps> = ({
  item,
  config,
  theme,
}: any) => (
<div 
  className={classNames(
    theme.root,
    config.get('simple') && theme.simple,
    theme.productCard,
  )}
>
  <a
    onClick={item.onClick}
    href={item.get('product_url')}
  >
    <div className={classNames(theme.imageWrap)}>
      <BundleAction display-if={config.get('bundle')} item={item} />
      <Image
        className={classNames(theme.image)}
        aspectRatio={config.getIn(['product', 'image', 'aspectRatio'], 1)}
        thumbnail={item.get('thumbnail_url')}
        src={item.get('image_url') ? item.get('image_url').replace('full','thumb') : 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
      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}>
      <Price
        className={theme.priceWrapper}
        display-if={config.getIn(['product', 'price', 'display'])}
        price={item.get('price')}
        oldPrice={item.getIn(['custom_fields','rrp',0]) || item.get('compare_at')}
        discount={item.get('discount')}
        currency={config.get('currency_config').toJS()} 
      />
      <div className={theme.rating}>
        <div display-if={item.getIn(['reviews', 'average_score'])}>
          <Rating
            value={item.getIn(['reviews', 'average_score'])}
            count={item.getIn(['reviews', 'count']) || item.getIn(['reviews', 'total_reviews'])} 
          />
        </div>
      </div>
      <div display-if={item.get('sku')} className="findify-product-sku">SKU:{item.getIn(['sku',0])}</div>
      <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'])} />
      <OutOfStockSticker
        display-if={item.getIn(['stickers', 'out-of-stock'])}
        config={config} />
    </div>
  </a>
  <AddToCart item={item} isAvailable={item.get('availability')}/>
</div>
)

export default ProductCardView;