Minimal summary and crate mode

Signed-off-by: Egor Savkin <es@m-labs.hk>
pull/113/head
Egor Savkin 2023-12-08 16:39:28 +08:00
parent e6df70b96a
commit 94f321ecf7
7 changed files with 124 additions and 107 deletions

View File

@ -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>
)}

View File

@ -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>

View File

@ -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>
)}

View File

@ -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)}

View File

@ -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',
}}>&nbsp;</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',
}}>&nbsp;</span>
))}
{((options && options_data) ? (
<SummaryPopup id={item.id + "options"} options={options} data={options_data} />
) : (
<span style={{
'display': 'inline-block',
'width': '20px',
}}>&nbsp;</span>
))}
</div>
</div>
<span style={{
'display': 'inline-block',
'width': '30px',
}}>&nbsp;</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',
}}>&nbsp;</span>
))}
{((options && options_data) ? (
<SummaryPopup id={item.id + "options"} options={options} data={options_data} />
) : (
<span style={{
'display': 'inline-block',
'width': '20px',
}}>&nbsp;</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>

View File

@ -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}

View File

@ -79,4 +79,15 @@ 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;
}