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