forked from M-Labs/web2019
Minimal summary and crate mode
Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
e6df70b96a
commit
94f321ecf7
|
@ -10,8 +10,9 @@ import {crate_type_to_hp, hp_to_slots, resource_counters} from "./count_resource
|
|||
* Component that displays a list of <ProductCartItem>
|
||||
*/
|
||||
export function Cart({isMobile, isTouch, data, onToggleOverlayRemove, onClickRemoveItem, onCardUpdate, onClickItem}) {
|
||||
const nbrOccupied = resource_counters.hp(data.items);
|
||||
const nbrOccupied = hp_to_slots(resource_counters.hp(data.items, -1));
|
||||
const nbrSlots = hp_to_slots(crate_type_to_hp(data.crate_type));
|
||||
console.log(nbrOccupied, nbrSlots);
|
||||
|
||||
const products = data.items.map((item, index) => {
|
||||
let itemData;
|
||||
|
@ -62,7 +63,7 @@ export function Cart({isMobile, isTouch, data, onToggleOverlayRemove, onClickRem
|
|||
)}
|
||||
|
||||
<FakePlaceholder
|
||||
nbrSlots={nbrSlots - nbrOccupied}
|
||||
nToDraw={nbrSlots - nbrOccupied}
|
||||
isDraggingOver={snapshot.isDraggingOver}/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -7,16 +7,26 @@ import {CrateWarnings} from "./CrateWarnings.jsx";
|
|||
* Component that displays the main crate with reminder rules.
|
||||
* It includes <Cart> and rules
|
||||
*/
|
||||
export function Crate({data, handleToggleOverlayRemove, handleDeleteItem, handleShowOverlayRemove, handleCardsUpdated, isMobile, isTouch, onDelete}) {
|
||||
export function Crate({
|
||||
data,
|
||||
handleToggleOverlayRemove,
|
||||
handleDeleteItem,
|
||||
handleShowOverlayRemove,
|
||||
handleCardsUpdated,
|
||||
isMobile,
|
||||
isTouch,
|
||||
onDelete,
|
||||
onModeChange
|
||||
}) {
|
||||
return (
|
||||
<div className="crate">
|
||||
|
||||
<CrateMode current={data.mode} onChange={null} />
|
||||
<CrateMode current={data.mode} onChange={onModeChange}/>
|
||||
|
||||
<div>
|
||||
Delete crate
|
||||
<button style={{width: "32px"}} onClick={() => onDelete(data.id)}>
|
||||
<img src="/images/shop/icon-remove.svg" alt="remove" />
|
||||
<img src="/images/shop/icon-remove.svg" alt="remove"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -32,7 +42,7 @@ export function Crate({data, handleToggleOverlayRemove, handleDeleteItem, handle
|
|||
onCardUpdate={handleCardsUpdated}>
|
||||
</Cart>
|
||||
|
||||
{1||(rules && rules.length > 0) && (
|
||||
{1 || (rules && rules.length > 0) && (
|
||||
<CrateWarnings/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import {Accordion} from "react-bootstrap";
|
||||
import {Crate} from "./Crate.jsx";
|
||||
|
||||
export function CrateList({crates, isMobile, isTouch, onAddCrate, onDeleteCrate}) {
|
||||
export function CrateList({crates, isMobile, isTouch, onAddCrate, onDeleteCrate, onModeChange}) {
|
||||
const onClickAdd = (_) => {
|
||||
onAddCrate("crate" + Object.entries(crates).length);
|
||||
}
|
||||
|
@ -13,7 +13,13 @@ export function CrateList({crates, isMobile, isTouch, onAddCrate, onDeleteCrate}
|
|||
<Accordion.Item eventKey={`${index}`} key={`crate${index}`}>
|
||||
<Accordion.Header>Crate #{`${index}`}</Accordion.Header>
|
||||
<Accordion.Body>
|
||||
<Crate data={{id: crate_id, ...crate}} isTouch={isTouch} isMobile={isMobile} onDelete={onDeleteCrate}/>
|
||||
<Crate
|
||||
data={{id: crate_id, ...crate}}
|
||||
isTouch={isTouch}
|
||||
isMobile={isMobile}
|
||||
onDelete={onDeleteCrate}
|
||||
onModeChange={(new_mode) => onModeChange(crate_id, new_mode)}
|
||||
/>
|
||||
</Accordion.Body>
|
||||
</Accordion.Item>
|
||||
)}
|
||||
|
|
|
@ -11,12 +11,10 @@ export function CrateMode({current, onChange}) {
|
|||
<a
|
||||
key={item}
|
||||
className={current === item ? 'active' : ''}
|
||||
|
||||
onClick={() => onChange(item)}
|
||||
href="#"
|
||||
role="button">{shared_data.crateModes[item].name}</a>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
//onClick={onChange(this, item)}
|
|
@ -3,7 +3,8 @@ import PropTypes from "prop-types";
|
|||
import {SummaryPopup} from "./options/SummaryPopup.jsx";
|
||||
import {formatMoney} from "./utils";
|
||||
import {WarningIndicator} from "./CardWarnings.jsx";
|
||||
|
||||
import {total_order_price} from "./count_resources";
|
||||
import {data as shared_data} from "./utils";
|
||||
|
||||
/**
|
||||
* Components that displays the list of card that are used in the crate.
|
||||
|
@ -14,10 +15,7 @@ export class OrderSummary extends PureComponent {
|
|||
static get propTypes() {
|
||||
return {
|
||||
currency: PropTypes.string,
|
||||
modes: PropTypes.array,
|
||||
currentMode: PropTypes.string,
|
||||
summary: PropTypes.array,
|
||||
itemsData: PropTypes.array,
|
||||
crates: PropTypes.object,
|
||||
onDeleteItem: PropTypes.func,
|
||||
onDeleteAllItems: PropTypes.func,
|
||||
onMouseEnterItem: PropTypes.func,
|
||||
|
@ -75,13 +73,10 @@ export class OrderSummary extends PureComponent {
|
|||
render() {
|
||||
const {
|
||||
currency,
|
||||
modes,
|
||||
currentMode,
|
||||
summary,
|
||||
itemsData,
|
||||
crates
|
||||
} = this.props;
|
||||
|
||||
const mode = modes.find(elem => elem.id === currentMode);
|
||||
const total_price = total_order_price(crates);
|
||||
|
||||
return (
|
||||
<div className="summary-price">
|
||||
|
@ -98,102 +93,82 @@ export class OrderSummary extends PureComponent {
|
|||
</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>
|
||||
{[].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;
|
||||
|
||||
{Object.entries(crates).map(([crate_id, crate], _i) => {
|
||||
let crate_type = shared_data.crateModes[crate.crate_type];
|
||||
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>
|
||||
|
||||
<tbody key={"summary_crate_body"+crate_id}>
|
||||
<tr key={"summary_crate_"+crate_id}>
|
||||
<td className="item-card-name">{crate_type.name}</td>
|
||||
<td className="price">
|
||||
<div className="d-inline-flex align-content-center">
|
||||
{`${currency} ${formatMoney(item.price)}`}
|
||||
<div>
|
||||
{`${currency} ${formatMoney(crate_type.price)}`}
|
||||
|
||||
<button onClick={this.handleOnDeleteItem.bind(this, index)}>
|
||||
<button style={{'opacity': '0', 'cursor': 'initial'}}>
|
||||
<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>
|
||||
|
||||
<span style={{
|
||||
'display': 'inline-block',
|
||||
'width': '30px',
|
||||
}}> </span>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</tr>
|
||||
{crate.items.map((item, index) => {
|
||||
let options = item && item.options;
|
||||
let options_data = item && item.options_data;
|
||||
const warnings = item && item.show_warnings;
|
||||
|
||||
return (<tr key={"summary_crate_" + crate_id+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)}`
|
||||
)}
|
||||
|
||||
${currency} ${formatMoney(total_price)}
|
||||
<button style={{'opacity': '0', 'cursor': 'initial'}}>
|
||||
<img src="/images/shop/icon-remove.svg" alt="icon remove"/>
|
||||
</button>
|
||||
|
|
|
@ -50,6 +50,7 @@ export class Shop extends PureComponent {
|
|||
this.handleCardsUpdated = this.handleCardsUpdated.bind(this);
|
||||
this.onAddCrate = this.onAddCrate.bind(this);
|
||||
this.onDeleteCrate = this.onDeleteCrate.bind(this);
|
||||
this.onCrateModeChange = this.onCrateModeChange.bind(this);
|
||||
|
||||
this.timer = null;
|
||||
this.timer_remove = null;
|
||||
|
@ -68,10 +69,10 @@ export class Shop extends PureComponent {
|
|||
index: 0,
|
||||
};
|
||||
|
||||
/*this.handleOnDragEnd({
|
||||
this.handleOnDragEnd({
|
||||
source,
|
||||
destination
|
||||
});*/
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
|
@ -524,6 +525,22 @@ export class Shop extends PureComponent {
|
|||
this.setState(new_state);
|
||||
}
|
||||
|
||||
onCrateModeChange(crate_id, new_mode) {
|
||||
let new_state = {
|
||||
...this.state,
|
||||
columns: {
|
||||
...this.state.columns,
|
||||
crates: {
|
||||
...this.state.columns.crates,
|
||||
[crate_id]: {
|
||||
...this.state.columns.crates[crate_id],
|
||||
crate_type: new_mode
|
||||
}
|
||||
}
|
||||
}};
|
||||
this.setState(new_state);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const {
|
||||
|
@ -586,14 +603,13 @@ export class Shop extends PureComponent {
|
|||
isMobile={isMobile}
|
||||
onAddCrate={this.onAddCrate}
|
||||
onDeleteCrate={this.onDeleteCrate}
|
||||
onModeChange={this.onCrateModeChange}
|
||||
/>
|
||||
}
|
||||
summaryPrice={
|
||||
<OrderSummary
|
||||
currency={currency}
|
||||
currentMode={currentMode}
|
||||
modes={crateModeItems}
|
||||
summary={columns.crates}
|
||||
crates={columns.crates}
|
||||
onMouseEnterItem={this.handleMouseEnterItem}
|
||||
onMouseLeaveItem={this.handleMouseLeaveItem}
|
||||
onDeleteItem={this.handleDeleteItem}
|
||||
|
|
|
@ -80,3 +80,14 @@ export function hp_to_slots(hp) {
|
|||
export function crate_type_to_hp(crate_t) {
|
||||
return shared_data.crateModes[crate_t].hp;
|
||||
}
|
||||
|
||||
export function total_order_price(crates) {
|
||||
let sum = 0;
|
||||
Object.entries(crates).forEach( ([key, crate], _i) => {
|
||||
sum += shared_data.crateModes[crate.crate_type].price;
|
||||
crate.items.forEach((item, _) => {
|
||||
sum += item.price;
|
||||
});
|
||||
});
|
||||
return sum;
|
||||
}
|
Loading…
Reference in New Issue