Add Neto 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;
Updated over 4 years ago