Start adding the warnings

Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
Egor Savkin 2023-12-08 17:36:12 +08:00
parent 94f321ecf7
commit 9bdaca2ca9
4 changed files with 69 additions and 31 deletions

View File

@ -2,16 +2,16 @@ 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, onModeChange}) { export function CrateList({crates, active_crate, isMobile, isTouch, onAddCrate, onDeleteCrate, onModeChange, onCrateSelect}) {
const onClickAdd = (_) => { const onClickAdd = (_) => {
onAddCrate("crate" + Object.entries(crates).length); onAddCrate("crate" + Object.entries(crates).length);
} }
return ( return (
<Accordion defaultActiveKey="0"> <Accordion defaultActiveKey={active_crate}>
{Object.entries(crates).map(([crate_id, crate], index) => {Object.entries(crates).map(([crate_id, crate], index) =>
<Accordion.Item eventKey={`${index}`} key={`crate${index}`}> <Accordion.Item eventKey={crate_id} key={`crate${index}`} >
<Accordion.Header>Crate #{`${index}`}</Accordion.Header> <Accordion.Header onClick={() => onCrateSelect(crate_id)}>Crate #{`${index}`}</Accordion.Header>
<Accordion.Body> <Accordion.Body>
<Crate <Crate
data={{id: crate_id, ...crate}} data={{id: crate_id, ...crate}}

View File

@ -11,7 +11,7 @@ import {Backlog} from "./Backlog.jsx";
import {OrderPanel} from "./OrderPanel.jsx"; import {OrderPanel} from "./OrderPanel.jsx";
import {OrderSummary} from "./OrderSummary.jsx"; import {OrderSummary} from "./OrderSummary.jsx";
import {OrderForm} from "./OrderForm.jsx"; import {OrderForm} from "./OrderForm.jsx";
import {TriggerWarnings} from "./warnings"; import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
import {FillResources} from "./count_resources"; import {FillResources} from "./count_resources";
import {CrateList} from "./CrateList.jsx"; import {CrateList} from "./CrateList.jsx";
@ -51,6 +51,7 @@ export class Shop extends PureComponent {
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.onCrateModeChange = this.onCrateModeChange.bind(this);
this.onCrateSelected = this.onCrateSelected.bind(this);
this.timer = null; this.timer = null;
this.timer_remove = null; this.timer_remove = null;
@ -107,6 +108,13 @@ export class Shop extends PureComponent {
clearTimeout(this.timer); clearTimeout(this.timer);
} }
onCrateChanged(crate_id) {
// kinda silly that hover over cards triggers checkAlerts
this.checkAlerts(crate_id)
}
handleCardsUpdated() { handleCardsUpdated() {
this.checkAlerts(this.state.columns.cart.items); this.checkAlerts(this.state.columns.cart.items);
} }
@ -405,6 +413,7 @@ export class Shop extends PureComponent {
)}} )}}
} }
}); });
this.onCrateChanged(destination.droppableId);
break; break;
case 'backlog': case 'backlog':
this.setState({ this.setState({
@ -423,6 +432,7 @@ export class Shop extends PureComponent {
)}} )}}
} }
}); });
this.onCrateChanged(destination.droppableId);
break; break;
default: default:
this.setState({ this.setState({
@ -450,18 +460,12 @@ export class Shop extends PureComponent {
}); });
} }
checkAlerts(newItems) { checkAlerts(crate_id) {
console.log('--- START CHECKING CRATE WARNING ---'); console.log('--- START CHECKING CRATE WARNING ---');
return;
const { let itemsCloned = Array.from(this.state.columns.crates[crate_id].items);
currentMode,
crateModeSlots,
crateRules,
} = this.state;
let itemsCloned = Array.from(newItems); const crate_warnings = TriggerCrateWarnings(this.state.columns.crates[crate_id]);
const rules = {};
itemsCloned.forEach((elem, idx) => { itemsCloned.forEach((elem, idx) => {
if (!(idx in itemsCloned)) itemsCloned[idx] = elem; if (!(idx in itemsCloned)) itemsCloned[idx] = elem;
@ -473,27 +477,20 @@ export class Shop extends PureComponent {
itemsCloned = FillResources(itemsCloned); itemsCloned = FillResources(itemsCloned);
itemsCloned = TriggerWarnings(itemsCloned); itemsCloned = TriggerWarnings(itemsCloned);
// check number of slot in crate
const nbrOccupied = nbrOccupiedSlotsInCrate(newItems);
if (nbrOccupied > crateModeSlots[currentMode]) {
rules[crateRules.maxSlot.type] = {...crateRules.maxSlot};
} else if (crateModeSlots[currentMode] === 21 && nbrOccupied <= 10) {
rules[crateRules.compactSlot.type] = {...crateRules.compactSlot};
}
// update state with rules // update state with rules
this.setState({ this.setState({
...this.state, ...this.state,
columns: { columns: {
...this.state.columns, ...this.state.columns,
cart: { crates: {
...this.state.columns.cart, ...this.state.columns.crates,
itemsData: itemsCloned, [crate_id]: {
...this.state.columns.crates[crate_id],
items: itemsCloned,
warnings: crate_warnings
},
} }
}, }
rules: {
...rules,
},
}); });
} }
@ -525,6 +522,13 @@ export class Shop extends PureComponent {
this.setState(new_state); this.setState(new_state);
} }
onCrateSelected(id) {
console.log(id)
this.setState({
active_crate: id
})
}
onCrateModeChange(crate_id, new_mode) { onCrateModeChange(crate_id, new_mode) {
let new_state = { let new_state = {
...this.state, ...this.state,
@ -604,6 +608,8 @@ export class Shop extends PureComponent {
onAddCrate={this.onAddCrate} onAddCrate={this.onAddCrate}
onDeleteCrate={this.onDeleteCrate} onDeleteCrate={this.onDeleteCrate}
onModeChange={this.onCrateModeChange} onModeChange={this.onCrateModeChange}
onCrateSelect={this.onCrateSelected}
active_crate={this.state.active_crate}
/> />
} }
summaryPrice={ summaryPrice={

View File

@ -5,7 +5,8 @@
* Second - resources indicator should be separate component * Second - resources indicator should be separate component
*/ */
import {item_occupied_counters} from "./count_resources"; import {crate_type_to_hp, item_occupied_counters, resource_counters} from "./count_resources";
import {data as shared_data} from "./utils";
const Levels = { const Levels = {
"reminder": {priority: 1, icon: '/images/shop/icon-reminder.svg'}, "reminder": {priority: 1, icon: '/images/shop/icon-reminder.svg'},
@ -121,3 +122,33 @@ export function MaxLevel(warnings) {
} }
return mx; return mx;
} }
const crate_warnings = {
"overfit": {
message: "You have reached the maximum number of slots allowed for this crate. Consider removing cards.",
level: "warning",
trigger: (crate, occupied) => {
const nbrHP = crate_type_to_hp(crate.crate_type);
return occupied > nbrHP;
}
},
"underfit_rack": {
message: "The selected cards fit in a 42hp desktop crate, consider switching to it for a more compact system",
level: "reminder",
trigger: (crate, occupied) => {
const nbrHPDesktop = shared_data.crateModes.desktop.hp;
return crate.crate_type === shared_data.crateModes.rack.id && occupied < nbrHPDesktop;
}
}
}
export function TriggerCrateWarnings(crate) {
const nbrOccupied = resource_counters.hp(crate.items, -1);
let warnings = [];
Object.entries(crate_warnings).forEach(([id, warning], _) => {
if (warning.trigger(crate, nbrOccupied)) warnings.push({...warning, id: id, trigger: undefined});
})
return warnings;
}

View File

@ -1188,7 +1188,8 @@ const shop_data = {
"crates": { "crates": {
"crate0": { "crate0": {
crate_type: "rack", crate_type: "rack",
items: [] items: [],
warnings: []
} }
} }