Add To Cart Button

📘

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');
    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 });
    window.location.href = `/cart.php?action=add&product_id=${item_id}`;
  }
})(({ onClick }) =>
  <button className='YOUR CSS CLASS' onClick={onClick}>
   Add to cart
  </button>
)
import axios from 'axios';

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

Add to Cart custom functionality

Since Findify is a third-party application, we have no connection to the Cart components of your store. This means that in order to integrate your Add to Cart solution with the subsequent frontend actions on your store (adding the product to the Cart through API, opening the mini-carts, showing messages once the product is added etc), you need to setup a function that can then be utilized in Findify customizations.
Requirements: We suggest to come up with the simplest functions available in the global (window) scope across all possible pages where Findify widgets are present:

window.addToCart('some variant/product id', 1);

Where the first parameter is either a variant or a product id of the product and the second one is the quantity of product that needs to be added to the cart.
The first argument has to be a variant id in case you have some kind of variant selectors implementation.