Minimal working multiple crates
Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
63d83b5e10
commit
691e5bbd86
@ -1,101 +1,72 @@
|
||||
import React, {PureComponent} from 'react'
|
||||
import PropTypes from "prop-types";
|
||||
import React from 'react'
|
||||
import {Droppable} from "@hello-pangea/dnd";
|
||||
import {cartStyle, nbrOccupiedSlotsInCrate} from "./utils";
|
||||
import {ProductCartItem} from "./ProductCartItem.jsx";
|
||||
import {FakePlaceholder} from "./FakePlaceholder.jsx";
|
||||
import {FillExtData} from "./options/utils";
|
||||
import {crate_type_to_hp, hp_to_slots, resource_counters} from "./count_resources";
|
||||
|
||||
/**
|
||||
* Component that displays a list of <ProductCartItem>
|
||||
*/
|
||||
export class Cart extends PureComponent {
|
||||
|
||||
static get propTypes() {
|
||||
return {
|
||||
isMobile: PropTypes.bool,
|
||||
isTouch: PropTypes.bool,
|
||||
nbrSlots: PropTypes.number,
|
||||
itemHovered: PropTypes.string,
|
||||
data: PropTypes.object.isRequired,
|
||||
onToggleOverlayRemove: PropTypes.func,
|
||||
onClickRemoveItem: PropTypes.func,
|
||||
onCardUpdate: PropTypes.func,
|
||||
onClickItem: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isMobile,
|
||||
isTouch,
|
||||
nbrSlots,
|
||||
itemHovered,
|
||||
data,
|
||||
onToggleOverlayRemove,
|
||||
onClickRemoveItem,
|
||||
onClickItem,
|
||||
onCardUpdate,
|
||||
} = this.props;
|
||||
|
||||
const nbrOccupied = nbrOccupiedSlotsInCrate(data.items);
|
||||
|
||||
const products = data.items.map((item, index) => {
|
||||
let itemData;
|
||||
let ext_data = FillExtData(data.itemsData, index);
|
||||
if (data.itemsData && index in data.itemsData) {
|
||||
itemData = data.itemsData[index];
|
||||
}
|
||||
return (
|
||||
<ProductCartItem
|
||||
isMobile={isMobile}
|
||||
isTouch={isTouch}
|
||||
hovered={item.id === itemHovered}
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
index={index}
|
||||
first={index === 0}
|
||||
last={index === data.items.length - 1 && nbrOccupied >= nbrSlots}
|
||||
data={itemData}
|
||||
ext_data={ext_data}
|
||||
onToggleOverlayRemove={onToggleOverlayRemove}
|
||||
onClickRemoveItem={onClickRemoveItem}
|
||||
onCardUpdate={onCardUpdate}
|
||||
onClickItem={onClickItem}
|
||||
model={item}>
|
||||
</ProductCartItem>
|
||||
);
|
||||
});
|
||||
export function Cart({isMobile, isTouch, data, onToggleOverlayRemove, onClickRemoveItem, onCardUpdate, onClickItem}) {
|
||||
const nbrOccupied = resource_counters.hp(data.items);
|
||||
const nbrSlots = hp_to_slots(crate_type_to_hp(data.crate_type));
|
||||
|
||||
const products = data.items.map((item, index) => {
|
||||
let itemData;
|
||||
let ext_data = FillExtData(data.items, index);
|
||||
if (data.items && index in data.items) {
|
||||
itemData = data.items[index];
|
||||
}
|
||||
return (
|
||||
<Droppable droppableId={data.id} direction="horizontal">
|
||||
|
||||
{(provided, snapshot) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.droppableProps}
|
||||
style={cartStyle(
|
||||
provided.droppableProps.style,
|
||||
snapshot,
|
||||
)}
|
||||
className="items-cart-list">
|
||||
|
||||
{products}
|
||||
|
||||
{provided.placeholder && (
|
||||
<div style={{ display: 'none' }}>
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<FakePlaceholder
|
||||
nbrSlots={nbrSlots}
|
||||
items={data.items}
|
||||
isDraggingOver={snapshot.isDraggingOver} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
</Droppable>
|
||||
<ProductCartItem
|
||||
isMobile={isMobile}
|
||||
isTouch={isTouch}
|
||||
hovered={item.hovered}
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
index={index}
|
||||
first={index === 0}
|
||||
last={index === data.items.length - 1 && nbrOccupied >= nbrSlots}
|
||||
data={itemData}
|
||||
ext_data={ext_data}
|
||||
onToggleOverlayRemove={onToggleOverlayRemove}
|
||||
onClickRemoveItem={onClickRemoveItem}
|
||||
onCardUpdate={onCardUpdate}
|
||||
onClickItem={onClickItem}
|
||||
model={item}>
|
||||
</ProductCartItem>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Droppable droppableId={data.id} direction="horizontal">
|
||||
|
||||
{(provided, snapshot) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.droppableProps}
|
||||
style={cartStyle(
|
||||
provided.droppableProps.style,
|
||||
snapshot,
|
||||
)}
|
||||
className="items-cart-list">
|
||||
|
||||
{products}
|
||||
|
||||
{provided.placeholder && (
|
||||
<div style={{display: 'none'}}>
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<FakePlaceholder
|
||||
nbrSlots={nbrSlots - nbrOccupied}
|
||||
isDraggingOver={snapshot.isDraggingOver}/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</Droppable>
|
||||
);
|
||||
}
|
@ -1,44 +1,36 @@
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {Cart} from "./Cart.jsx";
|
||||
import {CrateMode} from "./CrateMode.jsx";
|
||||
import {CrateWarnings} from "./CrateWarnings.jsx";
|
||||
|
||||
/**
|
||||
* Component that displays the main crate with reminder rules.
|
||||
* It includes <Cart> and rules
|
||||
*/
|
||||
export class Crate extends PureComponent {
|
||||
export function Crate({data, handleToggleOverlayRemove, handleDeleteItem, handleShowOverlayRemove, handleCardsUpdated, isMobile, isTouch}) {
|
||||
return (
|
||||
<div className="crate">
|
||||
|
||||
static get propTypes() {
|
||||
return {
|
||||
rules: PropTypes.array,
|
||||
cart: PropTypes.element,
|
||||
};
|
||||
}
|
||||
<CrateMode current={data.mode} onChange={null} />
|
||||
|
||||
render() {
|
||||
const {
|
||||
rules,
|
||||
cart,
|
||||
} = this.props;
|
||||
<div className="crate-products">
|
||||
|
||||
return (
|
||||
<div className="crate">
|
||||
|
||||
<div className="crate-products">
|
||||
|
||||
{cart}
|
||||
|
||||
{rules && rules.length > 0 && (
|
||||
<div className="crate-info">
|
||||
{rules.map((rule, index) => (
|
||||
<p key={index} className="rule" style={{'color': rule.color ? rule.color : 'inherit'}}>
|
||||
<img src={`/images${rule.icon}`} /> <i><strong>{rule.name}:</strong> {rule.message}</i>
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Cart
|
||||
data={data}
|
||||
isMobile={isMobile}
|
||||
isTouch={isTouch}
|
||||
onToggleOverlayRemove={handleToggleOverlayRemove}
|
||||
onClickRemoveItem={handleDeleteItem}
|
||||
onClickItem={handleShowOverlayRemove}
|
||||
onCardUpdate={handleCardsUpdated}>
|
||||
</Cart>
|
||||
|
||||
{1||(rules && rules.length > 0) && (
|
||||
<CrateWarnings/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
17
static/js/shop/CrateList.jsx
Normal file
17
static/js/shop/CrateList.jsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react'
|
||||
import {Accordion} from "react-bootstrap";
|
||||
import {Crate} from "./Crate.jsx";
|
||||
|
||||
export function CrateList({crates, isMobile, isTouch}) {
|
||||
return (
|
||||
<Accordion defaultActiveKey="0">
|
||||
{Object.entries(crates).map(([crate_id, crate], index) =>
|
||||
<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}/>
|
||||
</Accordion.Body>
|
||||
</Accordion.Item>
|
||||
)}
|
||||
</Accordion>)
|
||||
}
|
@ -1,48 +1,22 @@
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {data as shared_data} from "./utils";
|
||||
|
||||
/**
|
||||
* Component that displays crate modes
|
||||
*/
|
||||
export class CrateMode extends PureComponent {
|
||||
export function CrateMode({current, onChange}) {
|
||||
return (
|
||||
<div className="crate-mode">
|
||||
{shared_data.crateModeOrder.map(item => (
|
||||
<a
|
||||
key={item}
|
||||
className={current === item ? 'active' : ''}
|
||||
|
||||
static get propTypes() {
|
||||
return {
|
||||
items: PropTypes.array.isRequired,
|
||||
mode: PropTypes.string.isRequired,
|
||||
onClickMode: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleOnClickMode = this.handleOnClickMode.bind(this);
|
||||
}
|
||||
|
||||
handleOnClickMode(mode, e) {
|
||||
if (this.props.onClickMode) {
|
||||
this.props.onClickMode(mode);
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
mode,
|
||||
items,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className="crate-mode">
|
||||
{items.map(item => (
|
||||
<a
|
||||
key={item.id}
|
||||
className={mode == item.id ? 'active' : ''}
|
||||
onClick={this.handleOnClickMode.bind(this, item.id)}
|
||||
href="#"
|
||||
role="button">{item.name}</a>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
href="#"
|
||||
role="button">{shared_data.crateModes[item].name}</a>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
//onClick={onChange(this, item)}
|
13
static/js/shop/CrateWarnings.jsx
Normal file
13
static/js/shop/CrateWarnings.jsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
|
||||
export function CrateWarnings() {
|
||||
return (
|
||||
<div className="crate-info">
|
||||
{rules.map((rule, index) => (
|
||||
<p key={index} className="rule" style={{'color': rule.color ? rule.color : 'inherit'}}>
|
||||
<img src={`/images${rule.icon}`} /> <i><strong>{rule.name}:</strong> {rule.message}</i>
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,47 +1,27 @@
|
||||
import React, {PureComponent} from 'react'
|
||||
import PropTypes from "prop-types";
|
||||
import {nbrOccupiedSlotsInCrate} from "./utils";
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* Component that displays a placeholder inside crate.
|
||||
* Allows to display how it remains space for the current crate.
|
||||
*/
|
||||
export class FakePlaceholder extends PureComponent {
|
||||
export function FakePlaceholder({isDraggingOver, nToDraw}) {
|
||||
const fakePlaceholder = [];
|
||||
|
||||
static get propTypes() {
|
||||
return {
|
||||
isDraggingOver: PropTypes.bool,
|
||||
nbrSlots: PropTypes.number.isRequired,
|
||||
items: PropTypes.array.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isDraggingOver,
|
||||
nbrSlots,
|
||||
items,
|
||||
} = this.props;
|
||||
|
||||
const fakePlaceholder = [];
|
||||
const nbrOccupied = nbrOccupiedSlotsInCrate(items);
|
||||
|
||||
for (var i = (nbrSlots - nbrOccupied); i > 0; i--) {
|
||||
fakePlaceholder.push(
|
||||
<div key={i} style={{
|
||||
display: isDraggingOver ? 'none' : 'block',
|
||||
border: '1px dashed #ccc',
|
||||
width: '45px',
|
||||
marginBottom: '5px',
|
||||
}}></div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{fakePlaceholder}
|
||||
</React.Fragment>
|
||||
for (let i = nToDraw; i > 0; i--) {
|
||||
fakePlaceholder.push(
|
||||
<div key={i} style={{
|
||||
display: isDraggingOver ? 'none' : 'block',
|
||||
border: '1px dashed #ccc',
|
||||
width: '45px',
|
||||
marginBottom: '5px',
|
||||
}}></div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{fakePlaceholder}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
}
|
||||
|
5
static/js/shop/ImportJSON.jsx
Normal file
5
static/js/shop/ImportJSON.jsx
Normal file
@ -0,0 +1,5 @@
|
||||
export function ImportJSON() {
|
||||
return (
|
||||
<div> Import JSON BAOBAO</div>
|
||||
)
|
||||
}
|
@ -11,8 +11,7 @@ export class OrderPanel extends PureComponent {
|
||||
return {
|
||||
title: PropTypes.string,
|
||||
description: PropTypes.element,
|
||||
crateMode: PropTypes.element,
|
||||
crate: PropTypes.element,
|
||||
cratesList: PropTypes.element,
|
||||
summaryPrice: PropTypes.element,
|
||||
form: PropTypes.element,
|
||||
isMobile: PropTypes.bool,
|
||||
@ -25,8 +24,7 @@ export class OrderPanel extends PureComponent {
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
crateMode,
|
||||
crate,
|
||||
cratesList,
|
||||
summaryPrice,
|
||||
form,
|
||||
isMobile,
|
||||
@ -41,8 +39,6 @@ export class OrderPanel extends PureComponent {
|
||||
|
||||
<div className="control">
|
||||
{description}
|
||||
|
||||
{crateMode}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -61,7 +57,7 @@ export class OrderPanel extends PureComponent {
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{crate}
|
||||
{cratesList}
|
||||
|
||||
<section className="summary">
|
||||
{summaryPrice}
|
||||
|
@ -121,7 +121,7 @@ export class OrderSummary extends PureComponent {
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{summary.map((item, index) => {
|
||||
{[].map((item, index) => {
|
||||
let alert, warning, options, options_data;
|
||||
|
||||
if (itemsData[index] && itemsData[index].warnings) {
|
||||
|
@ -4,18 +4,16 @@ import {FilterOptions} from "./options/utils";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import {DragDropContext} from "@hello-pangea/dnd";
|
||||
|
||||
import {copy, itemsUnfoldedList, nbrOccupiedSlotsInCrate, remove, reorder} from "./utils";
|
||||
import {copyFromBacklog, itemsUnfoldedList, nbrOccupiedSlotsInCrate, remove, reorder} from "./utils";
|
||||
|
||||
import {Layout} from "./Layout.jsx";
|
||||
import {Backlog} from "./Backlog.jsx";
|
||||
import {OrderPanel} from "./OrderPanel.jsx";
|
||||
import {CrateMode} from "./CrateMode.jsx";
|
||||
import {Crate} from "./Crate.jsx";
|
||||
import {Cart} from "./Cart.jsx";
|
||||
import {OrderSummary} from "./OrderSummary.jsx";
|
||||
import {OrderForm} from "./OrderForm.jsx";
|
||||
import {TriggerWarnings} from "./warnings";
|
||||
import {FillResources} from "./count_resources";
|
||||
import {CrateList} from "./CrateList.jsx";
|
||||
|
||||
/**
|
||||
* Component that render the entire shop
|
||||
@ -64,14 +62,14 @@ export class Shop extends PureComponent {
|
||||
],
|
||||
};
|
||||
const destination = {
|
||||
droppableId: 'cart',
|
||||
droppableId: 'crate0',
|
||||
index: 0,
|
||||
};
|
||||
|
||||
this.handleOnDragEnd({
|
||||
/*this.handleOnDragEnd({
|
||||
source,
|
||||
destination
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
@ -83,13 +81,15 @@ export class Shop extends PureComponent {
|
||||
* trigger again this function (componentDidUpdate) and thus,
|
||||
* making an infinite loop.
|
||||
*/
|
||||
return;
|
||||
if (
|
||||
(prevState.columns.cart.items !== this.state.columns.cart.items) ||
|
||||
(prevState.columns.crates !== this.state.columns.crates.items) ||
|
||||
(prevState.currentMode !== this.state.currentMode)
|
||||
) {
|
||||
this.checkAlerts(this.state.columns.cart.items);
|
||||
}
|
||||
|
||||
|
||||
if (this.state.newCardJustAdded) {
|
||||
this.timer = setTimeout(() => {
|
||||
this.setState({
|
||||
@ -353,11 +353,20 @@ export class Shop extends PureComponent {
|
||||
})
|
||||
}
|
||||
|
||||
handleOnDragEnd(result, newAdded) {
|
||||
handleOnDragEnd(result) {
|
||||
/**
|
||||
* 4 cases:
|
||||
* - from backlog to one of the crate - add to the correct crate in correct order
|
||||
* - from one crate to another - delete from one crate and put to another in correct order
|
||||
* - within one crate - reorder
|
||||
* - from crate to backlog - delete
|
||||
* */
|
||||
|
||||
const {
|
||||
source,
|
||||
destination,
|
||||
} = result;
|
||||
/* better move to another function
|
||||
let dragged_items = [];
|
||||
if (source.indexes) {
|
||||
source.indexes.forEach((card_index, _) => {
|
||||
@ -365,82 +374,61 @@ export class Shop extends PureComponent {
|
||||
})
|
||||
} else if (source.index >= 0) {
|
||||
dragged_items.push(itemsUnfoldedList[source.index]);
|
||||
}
|
||||
}*/
|
||||
|
||||
console.log('==> result', result);
|
||||
|
||||
// dropped outside the list
|
||||
if (!destination) {
|
||||
if (source.droppableId === 'cart') {
|
||||
this.setState({
|
||||
...this.state,
|
||||
newCardJustAdded: false,
|
||||
columns: {
|
||||
...this.state.columns,
|
||||
[source.droppableId]: {
|
||||
...this.state.columns[source.droppableId],
|
||||
items: remove(
|
||||
this.state.columns[source.droppableId].items,
|
||||
source.index,
|
||||
),
|
||||
itemsData: remove(
|
||||
this.state.columns[source.droppableId].itemsData,
|
||||
source.index,
|
||||
)
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch(source.droppableId) {
|
||||
|
||||
case 'backlog':
|
||||
if (source.droppableId !== destination.droppableId) {
|
||||
this.setState({
|
||||
...this.state,
|
||||
newCardJustAdded: newAdded ? true : false,
|
||||
columns: {
|
||||
...this.state.columns,
|
||||
[destination.droppableId]: {
|
||||
...this.state.columns[destination.droppableId],
|
||||
items: copy(
|
||||
this.state.items,
|
||||
this.state.columns[source.droppableId],
|
||||
this.state.columns[destination.droppableId],
|
||||
dragged_items,
|
||||
destination,
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
switch (source.droppableId) {
|
||||
// TODO add delete functionality
|
||||
case destination.droppableId:
|
||||
this.setState({
|
||||
...this.state,
|
||||
newCardJustAdded: false,
|
||||
columns: {
|
||||
...this.state.columns,
|
||||
[destination.droppableId]: {
|
||||
...this.state.columns[destination.droppableId],
|
||||
items: reorder(
|
||||
this.state.columns[destination.droppableId].items,
|
||||
source.index,
|
||||
destination.index,
|
||||
),
|
||||
itemsData: reorder(
|
||||
this.state.columns[destination.droppableId].itemsData,
|
||||
source.index,
|
||||
destination.index,
|
||||
),
|
||||
},
|
||||
},
|
||||
crates: {
|
||||
...this.state.columns.crates,
|
||||
[destination.droppableId]: {
|
||||
...this.state.columns.crates[destination.droppableId],
|
||||
items: reorder(
|
||||
this.state.columns.crates[source.droppableId].items,
|
||||
source.index,
|
||||
destination.index
|
||||
)}}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'backlog':
|
||||
this.setState({
|
||||
...this.state,
|
||||
columns: {
|
||||
...this.state.columns,
|
||||
crates: {
|
||||
...this.state.columns.crates,
|
||||
[destination.droppableId]: {
|
||||
...this.state.columns.crates[destination.droppableId],
|
||||
items: copyFromBacklog(
|
||||
this.state.items,
|
||||
this.state.columns.crates[destination.droppableId],
|
||||
source,
|
||||
destination
|
||||
)}}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
this.setState({
|
||||
columns: move(
|
||||
this.state.columns[source.droppableId],
|
||||
this.state.columns[destination.droppableId],
|
||||
source,
|
||||
destination
|
||||
)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -460,6 +448,7 @@ export class Shop extends PureComponent {
|
||||
|
||||
checkAlerts(newItems) {
|
||||
console.log('--- START CHECKING CRATE WARNING ---');
|
||||
return;
|
||||
|
||||
const {
|
||||
currentMode,
|
||||
@ -546,7 +535,7 @@ export class Shop extends PureComponent {
|
||||
<Backlog
|
||||
currency={currency}
|
||||
items={items}
|
||||
data={columns['backlog']}
|
||||
data={columns.backlog}
|
||||
onClickAddItem={this.handleClickAddItem}
|
||||
onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
|
||||
isMobile={isMobile}>
|
||||
@ -559,37 +548,17 @@ export class Shop extends PureComponent {
|
||||
isMobile={isMobile}
|
||||
title="Order hardware"
|
||||
description={(<p className="description">Drag and drop the cards you want into the crate below to see how the combination would look like. Setup card's configuration by tapping at the top of the card, most of the options can be modified after shipment. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a>. The price is estimated and must be confirmed by a quote.</p>)}
|
||||
crateMode={
|
||||
<CrateMode
|
||||
items={crateModeItems}
|
||||
mode={currentMode}
|
||||
onClickMode={this.handleCrateModeChange}>
|
||||
</CrateMode>}
|
||||
crate={
|
||||
<Crate
|
||||
cart={
|
||||
<Cart
|
||||
nbrSlots={crateModeSlots[currentMode]}
|
||||
data={columns['cart']}
|
||||
isMobile={isMobile}
|
||||
isTouch={isTouch}
|
||||
itemHovered={currentItemHovered}
|
||||
onToggleOverlayRemove={this.handleToggleOverlayRemove}
|
||||
onClickRemoveItem={this.handleDeleteItem}
|
||||
onClickItem={this.handleShowOverlayRemove}
|
||||
onCardUpdate={this.handleCardsUpdated}>
|
||||
</Cart>
|
||||
}
|
||||
rules={Object.values(rules).filter(rule => rule)}>
|
||||
</Crate>
|
||||
cratesList={
|
||||
<CrateList
|
||||
crates={columns.crates}
|
||||
/>
|
||||
}
|
||||
summaryPrice={
|
||||
<OrderSummary
|
||||
currency={currency}
|
||||
currentMode={currentMode}
|
||||
modes={crateModeItems}
|
||||
summary={columns['cart'].items}
|
||||
itemsData={columns.cart.itemsData}
|
||||
summary={columns.crates}
|
||||
onMouseEnterItem={this.handleMouseEnterItem}
|
||||
onMouseLeaveItem={this.handleMouseLeaveItem}
|
||||
onDeleteItem={this.handleDeleteItem}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import {data as shared_data} from "./utils";
|
||||
|
||||
const count_item_occupied_eem = (item) => {
|
||||
if (!item.options_data
|
||||
@ -45,7 +46,7 @@ function CounterFactory(name) {
|
||||
}
|
||||
}
|
||||
|
||||
const resource_counters = {
|
||||
export const resource_counters = {
|
||||
"eem": CounterFactory("eem"),
|
||||
"clk": CounterFactory("clk"),
|
||||
"idc": CounterFactory("idc"),
|
||||
@ -71,3 +72,11 @@ export function FillResources(data) {
|
||||
return element;
|
||||
})
|
||||
}
|
||||
|
||||
export function hp_to_slots(hp) {
|
||||
return Math.trunc(hp / 4);
|
||||
}
|
||||
|
||||
export function crate_type_to_hp(crate_t) {
|
||||
return shared_data.crateModes[crate_t].hp;
|
||||
}
|
@ -5,7 +5,7 @@ import {v4 as uuidv4} from "uuid";
|
||||
export const data = window.shop_data;
|
||||
export const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat());
|
||||
|
||||
export const copy = (
|
||||
/*export const copy = (
|
||||
model,
|
||||
source,
|
||||
destination,
|
||||
@ -23,7 +23,7 @@ export const copy = (
|
||||
|
||||
return destClone;
|
||||
};
|
||||
|
||||
*/
|
||||
export const reorder = (list, startIndex, endIndex) => {
|
||||
const result = Array.from(list);
|
||||
const [removed] = result.splice(startIndex, 1);
|
||||
@ -38,6 +38,36 @@ export const remove = (list, startIndex) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
export const copyFromBacklog = (source, destination, droppableSource, droppableDestination) => {
|
||||
console.log('==> dest', destination);
|
||||
|
||||
const destClone = Array.from(destination.items);
|
||||
const items = droppableSource.indexes
|
||||
? droppableSource.indexes .map((item, _) => itemsUnfoldedList[item])
|
||||
: [itemsUnfoldedList[droppableSource.index]];
|
||||
|
||||
destClone.splice(droppableDestination.index, 0, ...items.map((item, _) => {
|
||||
return {...source[item], id: uuidv4()}
|
||||
}));
|
||||
return destClone;
|
||||
};
|
||||
|
||||
export const move = (source, destination, droppableSource, droppableDestination) => {
|
||||
console.log('==> move', source, destination);
|
||||
const sourceClone = Array.from(source);
|
||||
const destClone = Array.from(destination);
|
||||
const [removed] = sourceClone.splice(droppableSource.index, 1);
|
||||
|
||||
destClone.splice(droppableDestination.index, 0, removed);
|
||||
|
||||
const result = {columns: {}};
|
||||
result.columns[droppableSource.droppableId] = sourceClone;
|
||||
result.columns[droppableDestination.droppableId] = destClone;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const productStyle = (style, snapshot, removeAnim, hovered, selected, cart=false) => {
|
||||
const custom = {
|
||||
opacity: snapshot.isDragging ? .7 : 1,
|
||||
@ -76,13 +106,6 @@ export const cartStyle = (style, snapshot) => {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export const nbrOccupiedSlotsInCrate = (items) => {
|
||||
return items.reduce((prev, next) => {
|
||||
return prev + (next.hp === 8 ? 2 : 1);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
export function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
|
||||
// https://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-currency-string-in-javascript
|
||||
// changes: return amount if error in order to avoid empty value
|
||||
|
@ -38,6 +38,30 @@ const shop_data = {
|
||||
price: 500,
|
||||
}],
|
||||
|
||||
crateModes: {
|
||||
rack: {
|
||||
id: 'rack',
|
||||
name: 'Rack mountable crate',
|
||||
price: 550,
|
||||
hp: 84
|
||||
},
|
||||
desktop: {
|
||||
id: 'desktop',
|
||||
name: 'Desktop crate',
|
||||
price: 500,
|
||||
hp: 42
|
||||
},
|
||||
no_crate: {
|
||||
id: 'no_crate',
|
||||
name: 'Standalone cards',
|
||||
price: 0,
|
||||
hp: -1
|
||||
}
|
||||
},
|
||||
crateModeOrder: [
|
||||
"rack", "desktop", "no_crate"
|
||||
],
|
||||
|
||||
items: {
|
||||
/* keys are also ids, avoid changing them */
|
||||
'kasli': {
|
||||
@ -1161,12 +1185,12 @@ const shop_data = {
|
||||
],
|
||||
},
|
||||
|
||||
'cart': {
|
||||
id: 'cart',
|
||||
title: 'Cart',
|
||||
items: [],
|
||||
itemsData: [],
|
||||
},
|
||||
"crates": {
|
||||
"crate0": {
|
||||
crate_type: "rack",
|
||||
items: []
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user