@rocketsofawesome/mirage
Version:
[Live Demo of the Pattern Library](https://rocketsofawesome.github.io/mirage/)
217 lines (186 loc) • 5 kB
JavaScript
import React from 'react'
import PropTypes from 'prop-types'
import accounting from 'accounting'
import styled from 'styled-components'
import { XIcon } from 'SRC'
import cloudinary from 'services/cloudinary'
const shotTypeSortOrder = [
'front',
'back',
'detail',
'other',
'on_model'
]
const sortShots = (shots) => {
return shots.sort((shot1, shot2) => {
return shotTypeSortOrder.indexOf(shot1.shot_type) < shotTypeSortOrder.indexOf(shot2.shot_type) ? -1 : 1
})
}
const Select = styled.select`
margin-left: 10px;
`
const Thumbnail = styled.div`
flex: 0 0 auto;
img {
max-width: 110px;
}
`
const ImageLink = styled(({ renderLink, children, ...props }) => {
delete props.light
delete props.uppercase
delete props.underline
delete props.fontFamily
delete props.fontSize
delete props.fontWeight
if (renderLink) {
return renderLink({...props, children: children})
} else {
return (<a {...props}>{children}</a>)
}
})`
cursor: pointer;
`
const ItemName = styled.h4`
max-width: 150px;
margin-top: 0;
margin-bottom: 5px;
font-family: ${props => props.theme.fonts.headerFont};
font-size: 20px;
font-weight: 500;
line-height: 1.1;
letter-spacing: 0.5px;
color: ${props => props.theme.colors.navy};
text-transform: uppercase;
`
const Attribute = styled.div`
margin-bottom: 4px;
font-size: 14px;
font-weight: normal;
font-family: ${props => props.theme.fonts.primaryFont};
color: ${props => props.theme.colors.navy};
em {
margin-left: 6px;
font-style: normal;
color: #707070;
}
`
const Remove = styled(XIcon)`
height: 12px;
margin-left: 10px;
margin-right: 20px;
margin-top: 5px;
width: 12px;
cursor: pointer;
`
class BaseProduct extends React.Component {
constructor (props) {
super(props)
this.quantities = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
_onUpdateQuantity = ({ target: { value } }) => {
const { item } = this.props
this.props.onUpdateQuantity(item.id, parseInt(value, 10))
}
_onRemoveItem = () => {
const { item } = this.props
this.props.onRemoveItem(item.id)
}
_renderQuantityPicker = () => {
return (
<Select
value={this.props.item.quantity || ''}
onChange={this._onUpdateQuantity}>
{this.quantities.map((i) =>
<option key={`quantity-${i}`} value={i}>{i}</option>)
}
</Select>
)
}
_showRemoveItem = () => {
const { loading } = this.props
return !loading && !this._isOutOfStock()
}
_getNotEnoughQuantityError = () => {
const { item: { quantity } } = this.props
if (quantity === 0) return 'Out of stock.'
return `Only ${quantity} ${(quantity === 1) ? 'item' : 'items'} left`
}
_isOutOfStock = () => {
const { item } = this.props
return item.quantity <= 0
}
_getVariantShot = () => {
const { item } = this.props
const shot = item.shots
? (sortShots(item.shots))[0].cloudinary_key
: item.shot.cloudinary_key
return cloudinary.url(shot, { transformation: 'order-history' })
}
render () {
const { item, hideCartSidebar, className, renderLink } = this.props
const isOutOfStock = this._isOutOfStock()
return (
<div className={className}>
<Thumbnail>
<ImageLink renderLink={renderLink} target={`/products/${item.slug}-${item.colorway_slug}`} onClick={hideCartSidebar}>
<img alt={item.description} src={this._getVariantShot()} />
</ImageLink>
</Thumbnail>
<div>
<ItemName>
{item.name}
<span>
<br />
{accounting.formatMoney(item.price)}
</span>
</ItemName>
<Attribute>
Color<em>{item.color}</em>
</Attribute>
<Attribute>
Size<em>{item.size}</em>
</Attribute>
{!isOutOfStock &&
<Attribute>
Qty
{this._renderQuantityPicker()}
</Attribute>
}
{(item.not_enough_quantity_error || isOutOfStock) &&
<Attribute>
{this._getNotEnoughQuantityError()}
</Attribute>
}
</div>
{this._showRemoveItem() && <Remove onClick={this._onRemoveItem} />}
</div>
)
}
}
const renderLink = (inProps) => {
const {target, children, ...props } = inProps
return (<a href={target} {...props}>{children}</a>)
}
const Product = styled(BaseProduct)`
padding-top: 20px;
padding-bottom: 20px;
display: flex;
flex-direction: row;
justify-content: space-between;
border-bottom: 1px solid #d5d5d5;
select {
font-size: 16px;
}
`
BaseProduct.propTypes = {
item: PropTypes.object,
onUpdateQuantity: PropTypes.func,
onRemoveItem: PropTypes.func,
hideCartSidebar: PropTypes.func,
className: PropTypes.string,
renderLink: PropTypes.func
}
BaseProduct.defaultProps = {
renderLink: renderLink
}
export default Product