forked from M-Labs/web2019
120 lines
3.8 KiB
React
120 lines
3.8 KiB
React
|
import React, {PureComponent} from 'react';
|
||
|
import PropTypes from "prop-types";
|
||
|
import {Draggable} from "react-beautiful-dnd";
|
||
|
import {formatMoney, productStyle} from "./utils";
|
||
|
|
||
|
/**
|
||
|
* Component that renders a product.
|
||
|
* Used in the aside (e.g backlog of product)
|
||
|
*/
|
||
|
export class ProductItem extends PureComponent {
|
||
|
|
||
|
static get propTypes() {
|
||
|
return {
|
||
|
id: PropTypes.string.isRequired,
|
||
|
index: PropTypes.number.isRequired,
|
||
|
name: PropTypes.string.isRequired,
|
||
|
name_codename: PropTypes.string,
|
||
|
price: PropTypes.number.isRequired,
|
||
|
currency: PropTypes.string.isRequired,
|
||
|
image: PropTypes.string.isRequired,
|
||
|
specs: PropTypes.array,
|
||
|
datasheet_file: PropTypes.string,
|
||
|
datasheet_name: PropTypes.string,
|
||
|
onClickAddItem: PropTypes.func,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
constructor(props) {
|
||
|
super(props);
|
||
|
this.handleOnClickAddItem = this.handleOnClickAddItem.bind(this);
|
||
|
}
|
||
|
|
||
|
handleOnClickAddItem(id, tap, e) {
|
||
|
if (this.props.onClickAddItem) {
|
||
|
this.props.onClickAddItem(id, tap);
|
||
|
}
|
||
|
e.preventDefault();
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
const {
|
||
|
id,
|
||
|
index,
|
||
|
name,
|
||
|
name_codename,
|
||
|
price,
|
||
|
currency,
|
||
|
image,
|
||
|
specs,
|
||
|
datasheet_file,
|
||
|
datasheet_name,
|
||
|
} = this.props;
|
||
|
|
||
|
const render_specs = (specs && specs.length > 0 && (
|
||
|
<ul>
|
||
|
{specs.map((spec, index) =>
|
||
|
<li key={index}>{spec}</li>
|
||
|
)}
|
||
|
</ul>
|
||
|
));
|
||
|
|
||
|
const render_datasheet_link = (datasheet_file && datasheet_name && (
|
||
|
<div className="ds">
|
||
|
<span className='doc-icon'></span>
|
||
|
<a href={datasheet_file} target="_blank" rel="noopener noreferrer">
|
||
|
{datasheet_name}
|
||
|
</a>
|
||
|
</div>
|
||
|
));
|
||
|
|
||
|
return (
|
||
|
<section className="productItem">
|
||
|
|
||
|
<div className="content">
|
||
|
<h3 style={{ 'marginBottom': name_codename ? '5px' : '20px'}}>{name}</h3>
|
||
|
{name_codename ? (
|
||
|
<p>{name_codename}</p>
|
||
|
) : null }
|
||
|
|
||
|
<div className="price">{`${currency} ${formatMoney(price)}`}</div>
|
||
|
|
||
|
{render_specs}
|
||
|
|
||
|
{render_datasheet_link}
|
||
|
</div>
|
||
|
|
||
|
<div className="content">
|
||
|
|
||
|
<button onClick={this.handleOnClickAddItem.bind(this, index, true)}>
|
||
|
<img src="/images/shop/icon-add.svg" alt="add" />
|
||
|
</button>
|
||
|
|
||
|
<Draggable draggableId={id} index={index}>
|
||
|
{(provided, snapshot) => (
|
||
|
<React.Fragment>
|
||
|
<img
|
||
|
ref={provided.innerRef}
|
||
|
{...provided.draggableProps}
|
||
|
{...provided.dragHandleProps}
|
||
|
style={productStyle(
|
||
|
provided.draggableProps.style,
|
||
|
snapshot,
|
||
|
true, // hack: remove weird animation after a drop
|
||
|
)}
|
||
|
src={image} />
|
||
|
|
||
|
{/* Allows to simulate a clone */}
|
||
|
{snapshot.isDragging && (
|
||
|
<img className="simclone" src={image} />
|
||
|
)}
|
||
|
</React.Fragment>
|
||
|
)}
|
||
|
</Draggable>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
</section>
|
||
|
);
|
||
|
}
|
||
|
}
|