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');
// 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;
Updated over 4 years ago