web2019/static/js/shop/ProductCartItem.jsx

253 lines
9.7 KiB
JavaScript

import React, {PureComponent} from 'react'
import PropTypes from "prop-types";
import {Draggable} from "@hello-pangea/dnd";
import {OverlayTrigger} from "react-bootstrap";
import {DialogPopup} from "./options/DialogPopup.jsx";
import {nbrClocksStyle, nbrConnectorsStyle, productStyle} from "./utils";
/**
* Component that renders a product.
* Used in the crate
*/
export class ProductCartItem extends PureComponent {
static get propTypes() {
return {
isMobile: PropTypes.bool,
isTouch: PropTypes.bool,
hovered: PropTypes.bool,
first: PropTypes.bool,
last: PropTypes.bool,
index: PropTypes.number.isRequired,
model: PropTypes.object.isRequired,
data: PropTypes.object,
ext_data: PropTypes.object,
onToggleOverlayRemove: PropTypes.func,
onClickRemoveItem: PropTypes.func,
onClickItem: PropTypes.func,
onCardUpdate: PropTypes.func,
};
}
static get defaultProps() {
return {
hovered: false,
};
}
constructor(props) {
super(props);
this.handleOnMouseEnterRemoveItem = this.handleOnMouseEnterRemoveItem.bind(this);
this.handleOnMouseLeaveRemoveItem = this.handleOnMouseLeaveRemoveItem.bind(this);
this.handleOnClickRemoveItem = this.handleOnClickRemoveItem.bind(this);
this.handleOnClickItem = this.handleOnClickItem.bind(this);
}
handleOnMouseEnterRemoveItem(index, e) {
if (this.props.onToggleOverlayRemove && !this.props.isMobile) {
this.props.onToggleOverlayRemove(index, true);
}
e.preventDefault();
}
handleOnMouseLeaveRemoveItem(index, e) {
if (this.props.onToggleOverlayRemove && !this.props.isMobile) {
this.props.onToggleOverlayRemove(index, false);
}
e.preventDefault();
}
handleOnClickItem(index, e) {
if (this.props.onClickItem && this.props.isTouch) {
this.props.onClickItem(index);
}
e.preventDefault();
}
handleOnClickRemoveItem(index, e) {
if (this.props.onClickRemoveItem) {
this.props.onClickRemoveItem(index);
}
}
render() {
const {
hovered,
model,
data,
index,
first,
last,
ext_data,
onCardUpdate,
} = this.props;
let warning, options, options_data;
if (data && data.warnings) {
const warningsKeys = Object.keys(data.warnings);
if (warningsKeys && warningsKeys.length > 0) {
// we display only the first warning
warning = data.warnings[warningsKeys[0]];
}
}
if (data && data.options) {
options = data.options;
if (!data.options_data) data.options_data = {};
options_data = data.options_data;
options_data.ext_data = ext_data;
}
let render_progress;
if (data) {
switch(model.type) {
case 'kasli':
render_progress = [
(<p key={model.type+model.id+"EEM"}>{`${data.nbrCurrentSlot}/${model.nbrSlotMax} EEM connectors used`}</p>),
(<p key={model.type+model.id+"CLK"}>{`${data.nbrCurrentClock}/${model.nbrClockMax} Clock connectors used`}</p>)
];
break;
case 'vhdcicarrier':
render_progress = (<p>{`${data.nbrCurrentSlot}/${model.nbrSlotMax} EEM connectors used`}</p>);
break;
case 'zotino':
case 'hd68':
render_progress = (<p>{`${data.nbrCurrentSlot}/${model.nbrSlotMax} connectors used`}</p>);
break;
case 'clocker':
render_progress = (<p>{`${data.nbrCurrentClock}/${model.nbrClockMax} Clock connectors used`}</p>);
break;
default:
break;
}
}
return (
<Draggable draggableId={model.id} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{ ...productStyle(
provided.draggableProps.style,
snapshot,
true,
!!hovered,
!!model.selected,
true
)}}
onMouseEnter={this.handleOnMouseEnterRemoveItem.bind(this, index)}
onMouseLeave={this.handleOnMouseLeaveRemoveItem.bind(this, index)}
>
{/* warning container */}
<div className="progress-container warning d-flex justify-content-evenly">
{warning &&
(<OverlayTrigger
placement="bottom"
trigger={['click', 'hover', 'focus']}
overlay={
({arrowProps, hasDoneInitialMeasure, show, ...props}) => (
<div className="k-popup-warning" {...props}>
<p className="rule warning">
<i>{warning.message}</i>
</p>
</div>)
}
rootClose
>
<img className="alert-warning" src={`/images${warning.icon}`}/>
</OverlayTrigger>)
}
{options && (
<DialogPopup
options={options}
data={options_data}
options_class={model.options_class}
key={"popover" + index}
id={"popover" + index}
big={model.size === "big"}
first={first}
last={last}
target={{
construct: ((outvar, value) => {
// console.log("construct", outvar, value, options_data);
options_data[outvar] = value;
}),
update: ((outvar, value) => {
// console.log("update", outvar, value, options_data);
if (outvar in options_data) options_data[outvar] = value;
onCardUpdate();
})
}}
/>
)}
</div>
<h6>{model.name_number}</h6>
<div
onMouseEnter={this.handleOnMouseEnterRemoveItem.bind(this, index)}
onClick={this.handleOnClickItem.bind(this, index)}
>
<img
className='item-cart'
src={`/images${model.image}`} />
</div>
{/* remove container */}
<div
style={{'display': model.showOverlayRemove ? 'flex':'none'}}
className="overlayRemove"
onClick={this.handleOnClickRemoveItem.bind(this, index)}>
<img src="/images/shop/icon-remove.svg" alt="rm"/>
<p>Remove</p>
</div>
{/* progression container */}
{render_progress && (
<OverlayTrigger
placement="top"
trigger={['click', 'hover', 'focus']}
overlay={({arrowProps, hasDoneInitialMeasure, show, ...props}) => (<div className="k-popup-connectors" {...props}>{render_progress}</div>)}
rootClose
>
<div className="progress-container">
{model.nbrSlotMax > 0 && (
<div className="nbr-connectors">
<div style={{ ...nbrConnectorsStyle(data)}}></div>
</div>
)}
{model.nbrClockMax > 0 && (
<div className="nbr-clocks">
<div style={{ ...nbrClocksStyle(data)}}></div>
</div>
)}
</div>
</OverlayTrigger>
)}
</div>
)}
</Draggable>
);
}
}