215 lines
8.5 KiB
JavaScript
215 lines
8.5 KiB
JavaScript
import React, {PureComponent} from 'react';
|
|
import PropTypes from "prop-types";
|
|
import {SummaryPopup} from "./options/SummaryPopup.jsx";
|
|
import {formatMoney} from "./utils";
|
|
import {WarningIndicator} from "./CardWarnings.jsx";
|
|
|
|
|
|
/**
|
|
* Components that displays the list of card that are used in the crate.
|
|
* It is a summary of purchase
|
|
*/
|
|
export class OrderSummary extends PureComponent {
|
|
|
|
static get propTypes() {
|
|
return {
|
|
currency: PropTypes.string,
|
|
modes: PropTypes.array,
|
|
currentMode: PropTypes.string,
|
|
summary: PropTypes.array,
|
|
itemsData: PropTypes.array,
|
|
onDeleteItem: PropTypes.func,
|
|
onDeleteAllItems: PropTypes.func,
|
|
onMouseEnterItem: PropTypes.func,
|
|
onMouseLeaveItem: PropTypes.func,
|
|
onClickSelectItem: PropTypes.func,
|
|
};
|
|
}
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.handleOnDeleteItem = this.handleOnDeleteItem.bind(this);
|
|
this.handleOnDeleteAllItems = this.handleOnDeleteAllItems.bind(this);
|
|
this.handleOnMouseEnterItem = this.handleOnMouseEnterItem.bind(this);
|
|
this.handleOnMouseLeaveItem = this.handleOnMouseLeaveItem.bind(this);
|
|
this.handleOnClickSelectItem = this.handleOnClickSelectItem.bind(this);
|
|
}
|
|
|
|
handleOnDeleteItem(index, e) {
|
|
if (this.props.onDeleteItem) {
|
|
this.props.onDeleteItem(index);
|
|
}
|
|
e.preventDefault();
|
|
}
|
|
|
|
handleOnDeleteAllItems(e) {
|
|
if (this.props.onDeleteAllItems) {
|
|
this.props.onDeleteAllItems();
|
|
}
|
|
e.preventDefault();
|
|
}
|
|
|
|
handleOnMouseEnterItem(id, e) {
|
|
if (this.props.onMouseEnterItem) {
|
|
this.props.onMouseEnterItem(id);
|
|
}
|
|
e.preventDefault();
|
|
}
|
|
|
|
handleOnMouseLeaveItem(e) {
|
|
if (this.props.onMouseLeaveItem) {
|
|
this.props.onMouseLeaveItem();
|
|
}
|
|
e.preventDefault();
|
|
}
|
|
|
|
handleOnClickSelectItem(index, e) {
|
|
if (e.target.tagName !== 'IMG') {
|
|
if (this.props.onClickSelectItem) {
|
|
this.props.onClickSelectItem(index);
|
|
}
|
|
}
|
|
return e.preventDefault();
|
|
}
|
|
|
|
render() {
|
|
const {
|
|
currency,
|
|
modes,
|
|
currentMode,
|
|
summary,
|
|
itemsData,
|
|
} = this.props;
|
|
|
|
const mode = modes.find(elem => elem.id === currentMode);
|
|
|
|
return (
|
|
<div className="summary-price">
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
<tr>
|
|
<td colSpan="2" className="summary-remove-all">
|
|
<span className="item-card-name">Remove all cards</span>
|
|
|
|
<button onClick={this.handleOnDeleteAllItems}>
|
|
<img src="/images/shop/icon-remove.svg" />
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
|
|
{mode && (
|
|
<tr>
|
|
<td className="item-card-name">{mode.name}</td>
|
|
<td className="price">
|
|
<div>
|
|
{`${currency} ${formatMoney(mode.price)}`}
|
|
|
|
<button style={{'opacity': '0', 'cursor': 'initial'}}>
|
|
<img src="/images/shop/icon-remove.svg" />
|
|
</button>
|
|
</div>
|
|
|
|
<span style={{
|
|
'display': 'inline-block',
|
|
'width': '30px',
|
|
}}> </span>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</thead>
|
|
|
|
<tbody>
|
|
{summary.map((item, index) => {
|
|
let alert, warning, options, options_data;
|
|
|
|
if (itemsData[index] && itemsData[index].warnings) {
|
|
alert = itemsData[index];
|
|
const warningsKeys = Object.keys(alert.warnings);
|
|
if (warningsKeys && warningsKeys.length > 0) {
|
|
warning = alert.warnings[warningsKeys[0]];
|
|
}
|
|
}
|
|
options = itemsData[index] && itemsData[index].options;
|
|
options_data = itemsData[index] && itemsData[index].options_data;
|
|
const warnings = itemsData[index] && itemsData[index].show_warnings;
|
|
|
|
return (
|
|
<tr key={item.id}
|
|
className={`hoverable ${item.selected ? 'selected' : ''}`}
|
|
onClick={this.handleOnClickSelectItem.bind(this, index)}
|
|
onMouseEnter={this.handleOnMouseEnterItem.bind(this, item.id)}
|
|
onMouseLeave={this.handleOnMouseLeaveItem}>
|
|
|
|
<td className="item-card-name">
|
|
<div>{`${item.name_number} ${item.name} ${item.name_codename}`}</div>
|
|
</td>
|
|
|
|
<td className="price">
|
|
<div className="d-inline-flex align-content-center">
|
|
{`${currency} ${formatMoney(item.price)}`}
|
|
|
|
<button onClick={this.handleOnDeleteItem.bind(this, index)}>
|
|
<img src="/images/shop/icon-remove.svg" />
|
|
</button>
|
|
|
|
<div style={{'width': '45px', 'height': '20px'}} className="d-inline-flex align-content-center align-self-center justify-content-evenly">
|
|
{(warnings && warnings.length > 0 ? (
|
|
<WarningIndicator warnings={warnings}/>
|
|
) : (
|
|
<span style={{
|
|
'display': 'inline-block',
|
|
'width': '20px',
|
|
}}> </span>
|
|
))}
|
|
{((options && options_data) ? (
|
|
<SummaryPopup id={item.id + "options"} options={options} data={options_data} />
|
|
) : (
|
|
<span style={{
|
|
'display': 'inline-block',
|
|
'width': '20px',
|
|
}}> </span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
);
|
|
})}
|
|
</tbody>
|
|
|
|
<tfoot>
|
|
<tr>
|
|
<td className="item-card-name">Price estimate</td>
|
|
<td className="price">
|
|
<div>
|
|
{summary.length ? (
|
|
`${currency} ${formatMoney(summary.reduce(
|
|
(prev, next) => {
|
|
return prev + next.price;
|
|
}, 0
|
|
) + mode.price)}`
|
|
) : (
|
|
`${currency} ${formatMoney(mode.price)}`
|
|
)}
|
|
|
|
<button style={{'opacity': '0', 'cursor': 'initial'}}>
|
|
<img src="/images/shop/icon-remove.svg" alt="icon remove"/>
|
|
</button>
|
|
</div>
|
|
|
|
<span style={{
|
|
'display': 'inline-block',
|
|
'width': '30px',
|
|
}}> </span>
|
|
</td>
|
|
</tr>
|
|
</tfoot>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
);
|
|
}
|
|
} |