Finished converting all the popups.

This commit is contained in:
Olivier Gagnon 2021-08-30 17:59:11 -04:00
parent 3ba04220e1
commit cf72d72bb0
15 changed files with 585 additions and 615 deletions

@ -47,7 +47,6 @@ import { yesNoBoxCreate,
// UI Related Imports // UI Related Imports
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { CorporationEventHandler } from "./ui/CorporationUIEventHandler";
import { CorporationRoot } from "./ui/Root"; import { CorporationRoot } from "./ui/Root";
import { CorporationRouting } from "./ui/Routing"; import { CorporationRouting } from "./ui/Routing";
@ -1884,7 +1883,6 @@ Corporation.prototype.getStarterGuide = function() {
} }
let corpRouting; let corpRouting;
let eventHandler;
let companyManagementDiv; let companyManagementDiv;
Corporation.prototype.createUI = function() { Corporation.prototype.createUI = function() {
companyManagementDiv = createElement("div", { companyManagementDiv = createElement("div", {
@ -1895,13 +1893,12 @@ Corporation.prototype.createUI = function() {
document.getElementById("entire-game-container").appendChild(companyManagementDiv); document.getElementById("entire-game-container").appendChild(companyManagementDiv);
corpRouting = new CorporationRouting(this); corpRouting = new CorporationRouting(this);
eventHandler = new CorporationEventHandler(this, corpRouting);
this.rerender(); this.rerender();
} }
Corporation.prototype.rerender = function() { Corporation.prototype.rerender = function() {
if (companyManagementDiv == null || corpRouting == null || eventHandler == null) { if (companyManagementDiv == null || corpRouting == null) {
console.warn(`Corporation.rerender() called when companyManagementDiv, corpRouting, or eventHandler is null`); console.warn(`Corporation.rerender() called when companyManagementDiv, corpRouting, or eventHandler is null`);
return; return;
} }
@ -1910,7 +1907,6 @@ Corporation.prototype.rerender = function() {
ReactDOM.render(<CorporationRoot ReactDOM.render(<CorporationRoot
corp={this} corp={this}
routing={corpRouting} routing={corpRouting}
eventHandler={eventHandler}
player={Player} player={Player}
/>, companyManagementDiv); />, companyManagementDiv);
} }

@ -7,7 +7,6 @@ import { createPopup } from "../../ui/React/createPopup";
import { IDivision } from "../IDivision"; import { IDivision } from "../IDivision";
interface IProps { interface IProps {
eventHandler: any;
routing: any; routing: any;
onClicks: {[key: string]: () => void}; onClicks: {[key: string]: () => void};
city: string; // currentCity city: string; // currentCity

@ -1,578 +0,0 @@
// Creates a class for handling UI events, such as clicks and keyboard events
import { CorporationRouting } from "./Routing";
import { Corporation,
Industry,
Warehouse,
DividendMaxPercentage,
IssueNewSharesCooldown } from "../Corporation";
import { OfficeSpace } from "../OfficeSpace";
import { Industries,
IndustryStartingCosts,
IndustryDescriptions,
} from "../IndustryData";
import { MaterialSizes } from "../MaterialSizes";
import { Product } from "../Product";
import { Cities } from "../../Locations/Cities";
import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { getRandomInt } from "../../../utils/helpers/getRandomInt";
import { KEY } from "../../../utils/helpers/keyCodes";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { createPopup } from "../../../utils/uiHelpers/createPopup";
import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
export class CorporationEventHandler {
constructor(corp, routing) {
if (!(corp instanceof Corporation)) {
throw new Error(`CorporationEventHandler constructed without proper Corporation instance`);
}
if (!(routing instanceof CorporationRouting)) {
throw new Error(`CorporationEventHandler constructed without proper CorporationRouting instance`);
}
this.corp = corp;
this.routing = routing;
}
// Create a popup that lets the player use the Market TA research for Products
createProductMarketTaPopup(product, industry) {
const popupId = "cmpy-mgmt-marketta-popup";
const markupLimit = product.rat / product.mku;
const ta1 = createElement("p", {
innerHTML: "<u><strong>Market-TA.I</strong></u><br>" +
"The maximum sale price you can mark this up to is " +
numeralWrapper.formatMoney(product.pCost + markupLimit) +
". This means that if you set the sale price higher than this, " +
"you will begin to experience a loss in number of sales",
});
// Enable using Market-TA1 for automatically setting sale price
const useTa1AutoSaleId = "cmpy-mgmt-marketa1-checkbox";
const useTa1AutoSaleDiv = createElement("div", { display: "block" });
const useTa1AutoSaleLabel = createElement("label", {
color: "white",
for: useTa1AutoSaleId,
innerText: "Use Market-TA.I for Auto-Sale Price",
tooltip: "If this is enabled, then this Product will automatically " +
"be sold at the price identified by Market-TA.I (i.e. the price shown above)",
})
const useTa1AutoSaleCheckbox = createElement("input", {
checked: product.marketTa1,
id: useTa1AutoSaleId,
margin: "3px",
type: "checkbox",
changeListener: (e) => {
product.marketTa1 = e.target.checked;
},
});
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
const closeBtn = createPopupCloseButton(popupId, {
class: "std-button",
display: "block",
innerText: "Close",
});
if (industry.hasResearch("Market-TA.II")) {
let updateTa2Text;
const ta2Text = createElement("p");
const ta2Input = createElement("input", {
marginTop: "4px",
onkeyup: (e) => {
e.preventDefault();
updateTa2Text();
},
type: "number",
value: product.pCost,
});
// Function that updates the text in ta2Text element
updateTa2Text = function() {
const sCost = parseFloat(ta2Input.value);
let markup = 1;
if (sCost > product.pCost) {
if ((sCost - product.pCost) > markupLimit) {
markup = markupLimit / (sCost - product.pCost);
}
}
ta2Text.innerHTML = `<br><u><strong>Market-TA.II</strong></u><br>` +
`If you sell at ${numeralWrapper.formatMoney(sCost)}, ` +
`then you will sell ${numeralWrapper.format(markup, "0.00000")}x as much compared ` +
`to if you sold at market price.`;
}
updateTa2Text();
// Enable using Market-TA2 for automatically setting sale price
const useTa2AutoSaleId = "cmpy-mgmt-marketa2-checkbox";
const useTa2AutoSaleDiv = createElement("div", { display: "block" });
const useTa2AutoSaleLabel = createElement("label", {
color: "white",
for: useTa2AutoSaleId,
innerText: "Use Market-TA.II for Auto-Sale Price",
tooltip: "If this is enabled, then this Product will automatically " +
"be sold at the optimal price such that the amount sold matches the " +
"amount produced. (i.e. the highest possible price, while still ensuring " +
" that all produced materials will be sold)",
})
const useTa2AutoSaleCheckbox = createElement("input", {
checked: product.marketTa2,
id: useTa2AutoSaleId,
margin: "3px",
type: "checkbox",
changeListener: (e) => {
product.marketTa2 = e.target.checked;
},
});
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
const ta2OverridesTa1 = createElement("p", {
innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " +
"both are enabled, then Market-TA.II will take effect, not Market-TA.I",
});
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]);
} else {
// Market-TA.I only
createPopup(popupId, [ta1, useTa1AutoSaleDiv, closeBtn]);
}
}
// Create a popup that lets the player purchase a Material
createPurchaseMaterialPopup(mat, industry, warehouse) {
const corp = this.corp;
const purchasePopupId = "cmpy-mgmt-material-purchase-popup";
const txt = createElement("p", {
innerHTML: "Enter the amount of " + mat.name + " you would like " +
"to purchase per second. This material's cost changes constantly",
});
let confirmBtn;
let input = createElement("input", {
margin: "5px",
placeholder: "Purchase amount",
type: "number",
value: mat.buy ? mat.buy : null,
onkeyup: (e) => {
e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
},
});
confirmBtn = createElement("button", {
innerText: "Confirm", class: "std-button",
clickListener: () => {
if (isNaN(input.value)) {
dialogBoxCreate("Invalid amount");
} else {
mat.buy = parseFloat(input.value);
if (isNaN(mat.buy)) {mat.buy = 0;}
removeElementById(purchasePopupId);
this.rerender();
return false;
}
},
});
const clearButton = createElement("button", {
innerText: "Clear Purchase", class: "std-button",
clickListener: () => {
mat.buy = 0;
removeElementById(purchasePopupId);
this.rerender();
return false;
},
});
const cancelBtn = createPopupCloseButton(purchasePopupId, {
class: "std-button",
innerText: "Cancel",
});
const elems = [txt, input, confirmBtn, clearButton, cancelBtn];
if (industry.hasResearch("Bulk Purchasing")) {
const bulkPurchaseInfo = createElement("p", {
innerText: "Enter the amount of " + mat.name + " you would like " +
"to bulk purchase. This purchases the specified amount instantly " +
"(all at once).",
});
let bulkPurchaseCostTxt = createElement("p");
function updateBulkPurchaseText(amount) {
const parsedAmt = parseFloat(amount);
const cost = parsedAmt * mat.bCost;
const matSize = MaterialSizes[mat.name];
const maxAmount = ((warehouse.size - warehouse.sizeUsed) / matSize);
if (parsedAmt * matSize > maxAmount) {
bulkPurchaseCostTxt.innerText = "Not enough warehouse space to purchase this amount";
} else if (isNaN(cost)) {
bulkPurchaseCostTxt.innerText = "Invalid put for Bulk Purchase amount";
} else {
bulkPurchaseCostTxt.innerText = `Purchasing ${numeralWrapper.format(parsedAmt, "0,0.00")} of ` +
`${mat.name} will cost ${numeralWrapper.formatMoney(cost)}`;
}
}
let bulkPurchaseConfirmBtn;
const bulkPurchaseInput = createElement("input", {
margin: "5px",
placeholder: "Bulk Purchase amount",
type: "number",
onkeyup: (e) => {
e.preventDefault();
updateBulkPurchaseText(e.target.value);
if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();}
},
});
bulkPurchaseConfirmBtn = createElement("button", {
class: "std-button",
innerText: "Confirm Bulk Purchase",
clickListener: () => {
const amount = parseFloat(bulkPurchaseInput.value);
const matSize = MaterialSizes[mat.name];
const maxAmount = ((warehouse.size - warehouse.sizeUsed) / matSize);
if (amount * matSize > maxAmount) {
dialogBoxCreate(`You do not have enough warehouse size to fit this purchase`);
return false;
}
if (isNaN(amount)) {
dialogBoxCreate("Invalid input amount");
} else {
const cost = amount * mat.bCost;
if (corp.funds.gt(cost)) {
corp.funds = corp.funds.minus(cost);
mat.qty += amount;
} else {
dialogBoxCreate(`You cannot afford this purchase.`);
return false;
}
removeElementById(purchasePopupId);
return false;
}
},
})
elems.push(bulkPurchaseInfo);
elems.push(bulkPurchaseCostTxt);
elems.push(bulkPurchaseInput);
elems.push(bulkPurchaseConfirmBtn);
}
createPopup(purchasePopupId, elems);
input.focus();
}
// Create a popup that let the player manage sales of a material
createSellMaterialPopup(mat) {
const sellPopupId = "cmpy-mgmt-material-sell-popup";
const txt = createElement("p", {
innerHTML: "Enter the maximum amount of " + mat.name + " you would like " +
"to sell per second, as well as the price at which you would " +
"like to sell at.<br><br>" +
"If the sell amount is set to 0, then the material will not be sold. If the sell price " +
"if set to 0, then the material will be discarded<br><br>" +
"Setting the sell amount to 'MAX' will result in you always selling the " +
"maximum possible amount of the material.<br><br>" +
"When setting the sell amount, you can use the 'PROD' variable to designate a dynamically " +
"changing amount that depends on your production. For example, if you set the sell amount " +
"to 'PROD-5' then you will always sell 5 less of the material than you produce.<br><br>" +
"When setting the sell price, you can use the 'MP' variable to designate a dynamically " +
"changing price that depends on the market price. For example, if you set the sell price " +
"to 'MP+10' then it will always be sold at $10 above the market price.",
});
const br = createElement("br");
let confirmBtn;
const inputQty = createElement("input", {
type: "text", marginTop: "4px",
value: mat.sllman[1] ? mat.sllman[1] : null,
placeholder: "Sell amount",
onkeyup: (e) => {
e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
},
});
let inputButtonInitValue = mat.sCost ? mat.sCost : null;
if (mat.marketTa2) {
inputButtonInitValue += " (Market-TA.II)";
} else if (mat.marketTa1) {
inputButtonInitValue += " (Market-TA.I)";
}
const inputPx = createElement("input", {
type: "text", marginTop: "4px",
value: inputButtonInitValue,
placeholder: "Sell price",
onkeyup: (e) => {
e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
},
});
confirmBtn = createElement("button", {
class: "std-button",
innerText: "Confirm",
clickListener: () => {
//Parse price
let cost = inputPx.value.replace(/\s+/g, '');
cost = cost.replace(/[^-()\d/*+.MP]/g, ''); //Sanitize cost
let temp = cost.replace(/MP/g, mat.bCost);
try {
temp = eval(temp);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell price field: " + e);
return false;
}
if (temp == null || isNaN(temp)) {
dialogBoxCreate("Invalid value or expression for sell price field");
return false;
}
if (cost.includes("MP")) {
mat.sCost = cost; //Dynamically evaluated
} else {
mat.sCost = temp;
}
//Parse quantity
if (inputQty.value.includes("MAX") || inputQty.value.includes("PROD")) {
let qty = inputQty.value.replace(/\s+/g, '');
qty = qty.replace(/[^-()\d/*+.MAXPROD]/g, '');
let tempQty = qty.replace(/MAX/g, 1);
tempQty = tempQty.replace(/PROD/g, 1);
try {
tempQty = eval(tempQty);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell price field: " + e);
return false;
}
if (tempQty == null || isNaN(tempQty)) {
dialogBoxCreate("Invalid value or expression for sell price field");
return false;
}
mat.sllman[0] = true;
mat.sllman[1] = qty; //Use sanitized input
} else if (isNaN(inputQty.value)) {
dialogBoxCreate("Invalid value for sell quantity field! Must be numeric or 'MAX'");
return false;
} else {
var qty = parseFloat(inputQty.value);
if (isNaN(qty)) {qty = 0;}
if (qty === 0) {
mat.sllman[0] = false;
mat.sllman[1] = 0;
} else {
mat.sllman[0] = true;
mat.sllman[1] = qty;
}
}
removeElementById(sellPopupId);
this.rerender();
return false;
},
});
const cancelBtn = createPopupCloseButton(sellPopupId, {
class: "std-button",
innerText: "Cancel",
});
createPopup(sellPopupId, [txt, br, inputQty, inputPx, confirmBtn, cancelBtn]);
inputQty.focus();
}
// Create a popup that lets the player manage sales of the product
createSellProductPopup(product, city) {
const popupId = "cmpy-mgmt-sell-product-popup";
const txt = createElement("p", {
innerHTML:"Enter the maximum amount of " + product.name + " you would like " +
"to sell per second, as well as the price at which you would like to " +
"sell it at.<br><br>" +
"If the sell amount is set to 0, then the product will not be sold. If the " +
"sell price is set to 0, then the product will be discarded.<br><br>" +
"Setting the sell amount to 'MAX' will result in you always selling the " +
"maximum possible amount of the material.<br><br>" +
"When setting the sell amount, you can use the 'PROD' variable to designate a " +
"dynamically changing amount that depends on your production. For example, " +
"if you set the sell amount to 'PROD-1' then you will always sell 1 less of " +
"the material than you produce.<br><br>" +
"When setting the sell price, you can use the 'MP' variable to set a " +
"dynamically changing price that depends on the Product's estimated " +
"market price. For example, if you set it to 'MP*5' then it " +
"will always be sold at five times the estimated market price.",
});
let confirmBtn;
const inputQty = createElement("input", {
margin: "5px 0px 5px 0px",
placeholder: "Sell amount",
type: "text",
value: product.sllman[city][1] ? product.sllman[city][1] : null,
onkeyup: (e) => {
e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
},
});
let inputButtonInitValue = product.sCost ? product.sCost : null;
if (product.marketTa2) {
inputButtonInitValue += " (Market-TA.II)";
} else if (product.marketTa1) {
inputButtonInitValue += " (Market-TA.I)";
}
const inputPx = createElement("input", {
margin: "5px 0px 5px 0px",
placeholder: "Sell price",
type: "text",
value: inputButtonInitValue,
onkeyup: (e) => {
e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
},
});
const checkboxDiv = createElement("div", {
border: "1px solid white",
display: "inline-block",
})
const checkboxLabel = createElement("label", {
for: popupId + "-checkbox",
innerText: "Use same 'Sell Amount' for all cities",
});
const checkbox = createElement("input", {
checked: true,
id: popupId + "-checkbox",
margin: "2px",
type: "checkbox",
});
checkboxDiv.appendChild(checkboxLabel);
checkboxDiv.appendChild(checkbox);
confirmBtn = createElement("button", {
class: "std-button",
innerText: "Confirm",
clickListener: () => {
//Parse price
if (inputPx.value.includes("MP")) {
//Dynamically evaluated quantity. First test to make sure its valid
//Sanitize input, then replace dynamic variables with arbitrary numbers
var price = inputPx.value.replace(/\s+/g, '');
price = price.replace(/[^-()\d/*+.MP]/g, '');
var temp = price.replace(/MP/g, 1);
try {
temp = eval(temp);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell quantity field: " + e);
return false;
}
if (temp == null || isNaN(temp)) {
dialogBoxCreate("Invalid value or expression for sell quantity field.");
return false;
}
product.sCost = price; //Use sanitized price
} else {
var cost = parseFloat(inputPx.value);
if (isNaN(cost)) {
dialogBoxCreate("Invalid value for sell price field");
return false;
}
product.sCost = cost;
}
// Array of all cities. Used later
const cities = Object.keys(Cities);
// Parse quantity
if (inputQty.value.includes("MAX") || inputQty.value.includes("PROD")) {
//Dynamically evaluated quantity. First test to make sure its valid
var qty = inputQty.value.replace(/\s+/g, '');
qty = qty.replace(/[^-()\d/*+.MAXPROD]/g, '');
var temp = qty.replace(/MAX/g, 1);
temp = temp.replace(/PROD/g, 1);
try {
temp = eval(temp);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell price field: " + e);
return false;
}
if (temp == null || isNaN(temp)) {
dialogBoxCreate("Invalid value or expression for sell price field");
return false;
}
if (checkbox.checked) {
for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i];
product.sllman[tempCity][0] = true;
product.sllman[tempCity][1] = qty; //Use sanitized input
}
} else {
product.sllman[city][0] = true;
product.sllman[city][1] = qty; //Use sanitized input
}
} else if (isNaN(inputQty.value)) {
dialogBoxCreate("Invalid value for sell quantity field! Must be numeric");
return false;
} else {
var qty = parseFloat(inputQty.value);
if (isNaN(qty)) {qty = 0;}
if (qty === 0) {
if (checkbox.checked) {
for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i];
product.sllman[tempCity][0] = false;
}
} else {
product.sllman[city][0] = false;
}
} else {
if (checkbox.checked) {
for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i];
product.sllman[tempCity][0] = true;
product.sllman[tempCity][1] = qty;
}
} else {
product.sllman[city][0] = true;
product.sllman[city][1] = qty;
}
}
}
removeElementById(popupId);
this.rerender();
return false;
},
});
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" });
const linebreak1 = createElement("br");
createPopup(popupId, [txt, inputQty, inputPx, confirmBtn, cancelBtn, linebreak1,
checkboxDiv]);
inputQty.focus();
}
rerender() {
this.corp.rerender();
}
}

@ -9,7 +9,6 @@ import { createPopup } from "../../ui/React/createPopup";
interface IProps { interface IProps {
corp: any; corp: any;
eventHandler: any;
routing: any; routing: any;
} }

@ -8,7 +8,6 @@ import { IndustryWarehouse } from "./IndustryWarehouse";
interface IProps { interface IProps {
routing: any; routing: any;
eventHandler: any;
corp: any; corp: any;
currentCity: string; currentCity: string;
} }
@ -19,12 +18,10 @@ export function Industry(props: IProps): React.ReactElement {
<div className={"cmpy-mgmt-industry-left-panel"}> <div className={"cmpy-mgmt-industry-left-panel"}>
<IndustryOverview <IndustryOverview
routing={props.routing} routing={props.routing}
eventHandler={props.eventHandler}
corp={props.corp} corp={props.corp}
currentCity={props.currentCity} /> currentCity={props.currentCity} />
<IndustryOffice <IndustryOffice
routing={props.routing} routing={props.routing}
eventHandler={props.eventHandler}
corp={props.corp} corp={props.corp}
currentCity={props.currentCity} /> currentCity={props.currentCity} />
</div> </div>
@ -32,8 +29,7 @@ export function Industry(props: IProps): React.ReactElement {
<IndustryWarehouse <IndustryWarehouse
corp={props.corp} corp={props.corp}
routing={props.routing} routing={props.routing}
currentCity={props.currentCity} currentCity={props.currentCity} />
eventHandler={props.eventHandler} />
</div> </div>
</div> </div>
) )

@ -15,7 +15,6 @@ import { ThrowPartyPopup } from "./ThrowPartyPopup";
interface IProps { interface IProps {
routing: any; routing: any;
eventHandler: any;
corp: any; corp: any;
currentCity: string; currentCity: string;
} }

@ -13,7 +13,6 @@ import { createPopup } from "../../ui/React/createPopup";
interface IProps { interface IProps {
routing: any; routing: any;
eventHandler: any;
corp: any; corp: any;
currentCity: string; currentCity: string;
} }

@ -11,6 +11,10 @@ import { DiscontinueProductPopup } from "./DiscontinueProductPopup";
import { ExportPopup } from "./ExportPopup"; import { ExportPopup } from "./ExportPopup";
import { LimitProductProductionPopup } from "./LimitProductProductionPopup"; import { LimitProductProductionPopup } from "./LimitProductProductionPopup";
import { MaterialMarketTaPopup } from "./MaterialMarketTaPopup"; import { MaterialMarketTaPopup } from "./MaterialMarketTaPopup";
import { SellMaterialPopup } from "./SellMaterialPopup";
import { SellProductPopup } from "./SellProductPopup";
import { PurchaseMaterialPopup } from "./PurchaseMaterialPopup";
import { ProductMarketTaPopup } from "./ProductMarketTaPopup";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
@ -23,7 +27,6 @@ interface IProductProps {
division: any; division: any;
city: string; city: string;
product: any; product: any;
eventHandler: any;
} }
// Creates the UI for a single Product type // Creates the UI for a single Product type
@ -32,7 +35,6 @@ function ProductComponent(props: IProductProps): React.ReactElement {
const division = props.division; const division = props.division;
const city = props.city; const city = props.city;
const product = props.product; const product = props.product;
const eventHandler = props.eventHandler;
// Numeraljs formatters // Numeraljs formatters
const nf = "0.000"; const nf = "0.000";
@ -67,7 +69,15 @@ function ProductComponent(props: IProductProps): React.ReactElement {
sellButtonText += (" @ " + numeralWrapper.format(product.sCost, "$0.000a")); sellButtonText += (" @ " + numeralWrapper.format(product.sCost, "$0.000a"));
} }
} }
const sellButtonOnClick = eventHandler.createSellProductPopup.bind(eventHandler, product, city);
function openSellProductPopup(): void {
const popupId = "cmpy-mgmt-limit-product-production-popup";
createPopup(popupId, SellProductPopup, {
product: product,
city: city,
popupId: popupId,
});
}
// Limit Production button // Limit Production button
let limitProductionButtonText = "Limit Production"; let limitProductionButtonText = "Limit Production";
@ -94,8 +104,14 @@ function ProductComponent(props: IProductProps): React.ReactElement {
}); });
} }
// Market TA button function openProductMarketTaPopup(): void {
const marketTaButtonOnClick = eventHandler.createProductMarketTaPopup.bind(eventHandler, product, division); const popupId = "cmpy-mgmt-marketta-popup";
createPopup(popupId, ProductMarketTaPopup, {
product: product,
industry: division,
popupId: popupId,
});
}
// Unfinished Product // Unfinished Product
if (!product.fin) { if (!product.fin) {
@ -107,7 +123,7 @@ function ProductComponent(props: IProductProps): React.ReactElement {
<br /> <br />
<div> <div>
<button className={"std-button"} onClick={sellButtonOnClick}> <button className={"std-button"} onClick={openSellProductPopup}>
{sellButtonText} {sellButtonText}
</button><br /> </button><br />
<button className={"std-button"} onClick={openLimitProductProdutionPopup}> <button className={"std-button"} onClick={openLimitProductProdutionPopup}>
@ -118,7 +134,7 @@ function ProductComponent(props: IProductProps): React.ReactElement {
</button> </button>
{ {
division.hasResearch("Market-TA.I") && division.hasResearch("Market-TA.I") &&
<button className={"std-button"} onClick={marketTaButtonOnClick}> <button className={"std-button"} onClick={openProductMarketTaPopup}>
Market-TA Market-TA
</button> </button>
} }
@ -187,7 +203,7 @@ function ProductComponent(props: IProductProps): React.ReactElement {
</p> </p>
<div> <div>
<button className={"std-button"} onClick={sellButtonOnClick}> <button className={"std-button"} onClick={openSellProductPopup}>
{sellButtonText} {sellButtonText}
</button><br /> </button><br />
<button className={"std-button"} onClick={openLimitProductProdutionPopup}> <button className={"std-button"} onClick={openLimitProductProdutionPopup}>
@ -198,7 +214,7 @@ function ProductComponent(props: IProductProps): React.ReactElement {
</button> </button>
{ {
division.hasResearch("Market-TA.I") && division.hasResearch("Market-TA.I") &&
<button className={"std-button"} onClick={marketTaButtonOnClick}> <button className={"std-button"} onClick={openProductMarketTaPopup}>
Market-TA Market-TA
</button> </button>
} }
@ -213,7 +229,6 @@ interface IMaterialProps {
warehouse: any; warehouse: any;
city: string; city: string;
mat: any; mat: any;
eventHandler: any;
} }
// Creates the UI for a single Material type // Creates the UI for a single Material type
@ -223,7 +238,6 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
const warehouse = props.warehouse; const warehouse = props.warehouse;
const city = props.city; const city = props.city;
const mat = props.mat; const mat = props.mat;
const eventHandler = props.eventHandler;
const markupLimit = mat.getMarkupLimit(); const markupLimit = mat.getMarkupLimit();
const office = division.offices[city]; const office = division.offices[city];
if (!(office instanceof OfficeSpace)) { if (!(office instanceof OfficeSpace)) {
@ -245,7 +259,17 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
// Purchase material button // Purchase material button
const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nfB)})`; const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nfB)})`;
const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button"; const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button";
const purchaseButtonOnClick = eventHandler.createPurchaseMaterialPopup.bind(eventHandler, mat, division, warehouse);
function openPurchaseMaterialPopup() {
const popupId = "cmpy-mgmt-material-purchase-popup";
createPopup(popupId, PurchaseMaterialPopup, {
mat: mat,
industry: division,
warehouse: warehouse,
corp: props.corp,
popupId: popupId,
});
}
function openExportPopup() { function openExportPopup() {
const popupId = "cmpy-mgmt-export-popup"; const popupId = "cmpy-mgmt-export-popup";
@ -280,7 +304,15 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
} else { } else {
sellButtonText = "Sell (0.000/0.000)"; sellButtonText = "Sell (0.000/0.000)";
} }
const sellButtonOnClick = eventHandler.createSellMaterialPopup.bind(eventHandler, mat);
function openSellMaterialPopup(): void {
const popupId = "cmpy-mgmt-material-sell-popup";
createPopup(popupId, SellMaterialPopup, {
mat: mat,
corp: props.corp,
popupId: popupId,
});
}
function openMaterialMarketTaPopup(): void { function openMaterialMarketTaPopup(): void {
const popupId = "cmpy-mgmt-export-popup"; const popupId = "cmpy-mgmt-export-popup";
@ -334,7 +366,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
</div> </div>
<div style={{display: "inline-block"}}> <div style={{display: "inline-block"}}>
<button className={purchaseButtonClass} onClick={purchaseButtonOnClick}> <button className={purchaseButtonClass} onClick={openPurchaseMaterialPopup}>
{purchaseButtonText} {purchaseButtonText}
{ {
tutorial && tutorial &&
@ -352,7 +384,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
} }
<br /> <br />
<button className={"std-button"} onClick={sellButtonOnClick}> <button className={"std-button"} onClick={openSellMaterialPopup}>
{sellButtonText} {sellButtonText}
</button> </button>
@ -372,7 +404,6 @@ interface IProps {
corp: any; corp: any;
routing: any; routing: any;
currentCity: string; currentCity: string;
eventHandler: any;
} }
export function IndustryWarehouse(props: IProps): React.ReactElement { export function IndustryWarehouse(props: IProps): React.ReactElement {
@ -485,7 +516,6 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
city={props.currentCity} city={props.currentCity}
corp={corp} corp={corp}
division={division} division={division}
eventHandler={props.eventHandler}
key={matName} key={matName}
mat={warehouse.materials[matName]} mat={warehouse.materials[matName]}
warehouse={warehouse} />); warehouse={warehouse} />);
@ -502,7 +532,6 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
city={props.currentCity} city={props.currentCity}
corp={corp} corp={corp}
division={division} division={division}
eventHandler={props.eventHandler}
key={productName} key={productName}
product={division.products[productName]} product={division.products[productName]}
/>); />);

@ -14,7 +14,6 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
interface IProps { interface IProps {
corp: any; corp: any;
eventHandler: any;
routing: any; routing: any;
player: IPlayer; player: IPlayer;
} }

@ -20,7 +20,6 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
interface IProps { interface IProps {
corp: any; corp: any;
eventHandler: any;
player: IPlayer; player: IPlayer;
} }

@ -0,0 +1,105 @@
import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { numeralWrapper } from "../../ui/numeralFormat";
interface IProps {
product: any;
industry: any;
popupId: string;
}
function MarketTA2(props: IProps): React.ReactElement {
const markupLimit = props.product.rat / props.product.mku;
const [value, setValue] = useState(props.product.pCost);
const setRerender = useState(false)[1];
function rerender(): void {
setRerender(old => !old);
}
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
setValue(event.target.value);
}
function onCheckedChange(event: React.ChangeEvent<HTMLInputElement>): void {
props.product.marketTa2 = event.target.checked;
rerender();
}
const sCost = parseFloat(value);
let markup = 1;
if (sCost > props.product.pCost) {
if ((sCost - props.product.pCost) > markupLimit) {
markup = markupLimit / (sCost - props.product.pCost);
}
}
return (<>
<p>
<br /><u><strong>Market-TA.II</strong></u><br />
If you sell at {numeralWrapper.formatMoney(sCost)},
then you will sell {numeralWrapper.format(markup, "0.00000")}x as much compared
to if you sold at market price.
</p>
<input className="text-input" onChange={onChange} value={value} type="number" style={{marginTop: "4px"}} />
<div style={{display: 'block'}}>
<label className="tooltip" htmlFor="cmpy-mgmt-marketa2-checkbox" style={{color: "white"}}>
Use Market-TA.II for Auto-Sale Price
<span className="tooltiptext">
If this is enabled, then this Product will automatically
be sold at the optimal price such that the amount sold matches the
amount produced. (i.e. the highest possible price, while still ensuring
that all produced materials will be sold).
</span>
</label>
<input className="text-input" onChange={onCheckedChange} id="cmpy-mgmt-marketa2-checkbox" style={{margin: "3px"}} type="checkbox" checked={props.product.marketTa2} />
</div>
<p>
Note that Market-TA.II overrides Market-TA.I. This means that if
both are enabled, then Market-TA.II will take effect, not Market-TA.I
</p>
</>);
}
// Create a popup that lets the player use the Market TA research for Products
export function ProductMarketTaPopup(props: IProps): React.ReactElement {
const markupLimit = props.product.rat / props.product.mku;
const setRerender = useState(false)[1];
function rerender(): void {
setRerender(old => !old);
}
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
props.product.marketTa1 = event.target.checked;
rerender();
}
return (<>
<p>
<u><strong>Market-TA.I</strong></u><br />
The maximum sale price you can mark this up to
is {numeralWrapper.formatMoney(props.product.pCost + markupLimit)}.
This means that if you set the sale price higher than this,
you will begin to experience a loss in number of sales.
</p>
<div style={{display: 'block'}}>
<label className="tooltip" htmlFor="cmpy-mgmt-marketa1-checkbox" style={{color: "white"}}>
Use Market-TA.I for Auto-Sale Price
<span className="tooltiptext">
If this is enabled, then this Product will automatically
be sold at the price identified by Market-TA.I
(i.e. the price shown above).
</span>
</label>
<input onChange={onChange} className="text-input" id="cmpy-mgmt-marketa1-checkbox" style={{margin: "3px"}} type="checkbox" checked={props.product.marketTa1} />
</div>
{props.industry.hasResearch("Market-TA.II") && <MarketTA2 product={props.product} industry={props.industry} popupId={props.popupId} />}
</>);
}

@ -0,0 +1,130 @@
import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { MaterialSizes } from "../MaterialSizes";
import { numeralWrapper } from "../../ui/numeralFormat";
interface IBulkPurchaseTextProps {
warehouse: any;
mat: any;
amount: string;
}
function BulkPurchaseText(props: IBulkPurchaseTextProps): React.ReactElement {
const parsedAmt = parseFloat(props.amount);
const cost = parsedAmt * props.mat.bCost;
const matSize = MaterialSizes[props.mat.name];
const maxAmount = ((props.warehouse.size - props.warehouse.sizeUsed) / matSize);
if (parsedAmt * matSize > maxAmount) {
return (<>Not enough warehouse space to purchase this amount</>);
} else if (isNaN(cost)) {
return (<>Invalid put for Bulk Purchase amount</>);
} else {
return (<>Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of
{props.mat.name} will cost {numeralWrapper.formatMoney(cost)}</>);
}
}
interface IProps {
mat: any;
industry: any;
warehouse: any;
corp: any;
popupId: string;
}
function BulkPurchase(props: IProps): React.ReactElement {
const [buyAmt, setBuyAmt] = useState('');
function bulkPurchase(): void {
const amount = parseFloat(buyAmt);
const matSize = MaterialSizes[props.mat.name];
const maxAmount = ((props.warehouse.size - props.warehouse.sizeUsed) / matSize);
if (amount * matSize > maxAmount) {
dialogBoxCreate(`You do not have enough warehouse size to fit this purchase`);
return;
}
if (isNaN(amount)) {
dialogBoxCreate("Invalid input amount");
} else {
const cost = amount * props.mat.bCost;
if (props.corp.funds.gt(cost)) {
props.corp.funds = props.corp.funds.minus(cost);
props.mat.qty += amount;
} else {
dialogBoxCreate(`You cannot afford this purchase.`);
return;
}
removePopup(props.popupId);
}
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (event.keyCode === 13) bulkPurchase();
}
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
setBuyAmt(event.target.value);
}
return (<>
<p>
Enter the amount of {props.mat.name} you would like
to bulk purchase. This purchases the specified amount instantly
(all at once).
</p>
<BulkPurchaseText warehouse={props.warehouse} mat={props.mat} amount={buyAmt} />
<input onChange={onChange} type="number" placeholder="Bulk Purchase amount" style={{margin: "5px"}} />
<button className="std-button">Confirm Bulk Purchase</button>
</>);
}
// Create a popup that lets the player purchase a Material
export function PurchaseMaterialPopup(props: IProps): React.ReactElement {
const [buyAmt, setBuyAmt] = useState(props.mat.buy ? props.mat.buy : null);
function purchaseMaterial(): void {
if (isNaN(parseFloat(buyAmt))) {
dialogBoxCreate("Invalid amount");
} else {
props.mat.buy = parseFloat(buyAmt);
if (isNaN(props.mat.buy)) props.mat.buy = 0;
removePopup(props.popupId);
}
}
function clearPurchase(): void {
props.mat.buy = 0;
removePopup(props.popupId);
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (event.keyCode === 13) purchaseMaterial();
}
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
setBuyAmt(event.target.value);
}
return (<>
<p>
Enter the amount of {props.mat.name} you would like
to purchase per second. This material's cost changes constantly.
</p>
<input onChange={onChange} className="text-input" autoFocus={true} placeholder="Purchase amount" type="number" style={{margin: "5px"}} onKeyDown={onKeyDown} />
<button onClick={purchaseMaterial} className="std-button">Confirm</button>
<button onClick={clearPurchase} className="std-button">Clear Purchase</button>
{props.industry.hasResearch("Bulk Purchasing") && <BulkPurchase corp={props.corp} mat={props.mat} industry={props.industry} warehouse={props.warehouse} popupId={props.popupId} />}
</>);
}

@ -7,7 +7,6 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
interface IProps { interface IProps {
corp: any; corp: any;
eventHandler: any;
routing: any; routing: any;
player: IPlayer; player: IPlayer;
} }
@ -15,8 +14,8 @@ interface IProps {
export function CorporationRoot(props: IProps): React.ReactElement { export function CorporationRoot(props: IProps): React.ReactElement {
return ( return (
<div> <div>
<HeaderTabs corp={props.corp} eventHandler={props.eventHandler} routing={props.routing} /> <HeaderTabs corp={props.corp} routing={props.routing} />
<MainPanel corp={props.corp} eventHandler={props.eventHandler} routing={props.routing} player={props.player} /> <MainPanel corp={props.corp} routing={props.routing} player={props.player} />
</div> </div>
) )
} }

@ -0,0 +1,129 @@
import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
function initialPrice(mat: any): string {
let val = mat.sCost ? mat.sCost : '';
if (mat.marketTa2) {
val += " (Market-TA.II)";
} else if (mat.marketTa1) {
val += " (Market-TA.I)";
}
return val;
}
interface IProps {
mat: any;
corp: any;
popupId: string;
}
// Create a popup that let the player manage sales of a material
export function SellMaterialPopup(props: IProps): React.ReactElement {
const [amt, setAmt] = useState<string>(props.mat.sllman[1] ? props.mat.sllman[1] : '');
const [price, setPrice] = useState<string>(initialPrice(props.mat));
function sellMaterial(): void {
let p = price;
let qty = amt;
if(p === '') p = '0';
if(qty === '') qty = '0';
let cost = p.replace(/\s+/g, '');
cost = cost.replace(/[^-()\d/*+.MP]/g, ''); //Sanitize cost
let temp = cost.replace(/MP/g, props.mat.bCost);
try {
temp = eval(temp);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell price field: " + e);
return;
}
if (temp == null || isNaN(parseFloat(temp))) {
dialogBoxCreate("Invalid value or expression for sell price field");
return;
}
if (cost.includes("MP")) {
props.mat.sCost = cost; //Dynamically evaluated
} else {
props.mat.sCost = temp;
}
//Parse quantity
if (qty.includes("MAX") || qty.includes("PROD")) {
let q = qty.replace(/\s+/g, '');
q = q.replace(/[^-()\d/*+.MAXPROD]/g, '');
let tempQty = q.replace(/MAX/g, '1');
tempQty = tempQty.replace(/PROD/g, '1');
try {
tempQty = eval(tempQty);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell price field: " + e);
return;
}
if (tempQty == null || isNaN(parseFloat(tempQty))) {
dialogBoxCreate("Invalid value or expression for sell price field");
return;
}
props.mat.sllman[0] = true;
props.mat.sllman[1] = q; //Use sanitized input
} else if (isNaN(parseFloat(qty))) {
dialogBoxCreate("Invalid value for sell quantity field! Must be numeric or 'MAX'");
return;
} else {
let q = parseFloat(qty);
if (isNaN(q)) {q = 0;}
if (q === 0) {
props.mat.sllman[0] = false;
props.mat.sllman[1] = 0;
} else {
props.mat.sllman[0] = true;
props.mat.sllman[1] = q;
}
}
removePopup(props.popupId);
}
function onAmtChange(event: React.ChangeEvent<HTMLInputElement>): void {
setAmt(event.target.value);
}
function onPriceChange(event: React.ChangeEvent<HTMLInputElement>): void {
setPrice(event.target.value);
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (event.keyCode === 13) sellMaterial();
}
return (<>
<p>
Enter the maximum amount of {props.mat.name} you would like
to sell per second, as well as the price at which you would
like to sell at.<br /><br />
If the sell amount is set to 0, then the material will not be sold. If the sell price
if set to 0, then the material will be discarded<br /><br />
Setting the sell amount to 'MAX' will result in you always selling the
maximum possible amount of the material.<br /><br />
When setting the sell amount, you can use the 'PROD' variable to designate a dynamically
changing amount that depends on your production. For example, if you set the sell amount
to 'PROD-5' then you will always sell 5 less of the material than you produce.<br /><br />
When setting the sell price, you can use the 'MP' variable to designate a dynamically
changing price that depends on the market price. For example, if you set the sell price
to 'MP+10' then it will always be sold at $10 above the market price.
</p>
<br />
<input className="text-input" value={amt} autoFocus={true} type="text" placeholder="Sell amount" style={{marginTop: "4px"}} onChange={onAmtChange} onKeyDown={onKeyDown} />
<input className="text-input" value={price} type="text" placeholder="Sell price" style={{marginTop: "4px"}} onChange={onPriceChange} onKeyDown={onKeyDown} />
<button className="std-button" onClick={sellMaterial}>Confirm</button>
</>);
}

@ -0,0 +1,170 @@
import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { Cities } from "../../Locations/Cities";
function initialPrice(product: any): string {
let val = product.sCost ? product.sCost : '';
if (product.marketTa2) {
val += " (Market-TA.II)";
} else if (product.marketTa1) {
val += " (Market-TA.I)";
}
return val;
}
interface IProps {
product: any;
city: string;
popupId: string;
}
// Create a popup that let the player manage sales of a material
export function SellProductPopup(props: IProps): React.ReactElement {
const [checked, setChecked] = useState(true);
const [iQty, setQty] = useState<string>(props.product.sllman[props.city][1] ? props.product.sllman[props.city][1] : '');
const [px, setPx] = useState<string>(initialPrice(props.product));
function onCheckedChange(event: React.ChangeEvent<HTMLInputElement>): void {
setChecked(event.target.checked);
}
function sellProduct(): void {
//Parse price
if (px.includes("MP")) {
//Dynamically evaluated quantity. First test to make sure its valid
//Sanitize input, then replace dynamic variables with arbitrary numbers
var price = px.replace(/\s+/g, '');
price = price.replace(/[^-()\d/*+.MP]/g, '');
var temp = price.replace(/MP/g, '1');
try {
temp = eval(temp);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell quantity field: " + e);
return;
}
if (temp == null || isNaN(parseFloat(temp))) {
dialogBoxCreate("Invalid value or expression for sell quantity field.");
return;
}
props.product.sCost = price; //Use sanitized price
} else {
var cost = parseFloat(px);
if (isNaN(cost)) {
dialogBoxCreate("Invalid value for sell price field");
return;
}
props.product.sCost = cost;
}
// Array of all cities. Used later
const cities = Object.keys(Cities);
// Parse quantity
if (iQty.includes("MAX") || iQty.includes("PROD")) {
//Dynamically evaluated quantity. First test to make sure its valid
var qty = iQty.replace(/\s+/g, '');
qty = qty.replace(/[^-()\d/*+.MAXPROD]/g, '');
var temp = qty.replace(/MAX/g, '1');
temp = temp.replace(/PROD/g, '1');
try {
temp = eval(temp);
} catch(e) {
dialogBoxCreate("Invalid value or expression for sell price field: " + e);
return;
}
if (temp == null || isNaN(parseFloat(temp))) {
dialogBoxCreate("Invalid value or expression for sell price field");
return;
}
if (checked) {
for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i];
props.product.sllman[tempCity][0] = true;
props.product.sllman[tempCity][1] = qty; //Use sanitized input
}
} else {
props.product.sllman[props.city][0] = true;
props.product.sllman[props.city][1] = qty; //Use sanitized input
}
} else if (isNaN(parseFloat(iQty))) {
dialogBoxCreate("Invalid value for sell quantity field! Must be numeric");
return;
} else {
let qty = parseFloat(iQty);
if (isNaN(qty)) {qty = 0;}
if (qty === 0) {
if (checked) {
for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i];
props.product.sllman[tempCity][0] = false;
props.product.sllman[tempCity][1] = '';
}
} else {
props.product.sllman[props.city][0] = false;
props.product.sllman[props.city][1] = '';
}
} else {
if (checked) {
for (let i = 0; i < cities.length; ++i) {
const tempCity = cities[i];
props.product.sllman[tempCity][0] = true;
props.product.sllman[tempCity][1] = qty;
}
} else {
props.product.sllman[props.city][0] = true;
props.product.sllman[props.city][1] = qty;
}
}
}
removePopup(props.popupId);
}
function onAmtChange(event: React.ChangeEvent<HTMLInputElement>): void {
setQty(event.target.value);
}
function onPriceChange(event: React.ChangeEvent<HTMLInputElement>): void {
setPx(event.target.value);
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (event.keyCode === 13) sellProduct();
}
return (<>
<p>
Enter the maximum amount of {props.product.name} you would like
to sell per second, as well as the price at which you would like to
sell it at.<br /><br />
If the sell amount is set to 0, then the product will not be sold. If the
sell price is set to 0, then the product will be discarded.<br /><br />
Setting the sell amount to 'MAX' will result in you always selling the
maximum possible amount of the material.<br /><br />
When setting the sell amount, you can use the 'PROD' variable to designate a
dynamically changing amount that depends on your production. For example,
if you set the sell amount to 'PROD-1' then you will always sell 1 less of
the material than you produce.<br /><br />
When setting the sell price, you can use the 'MP' variable to set a
dynamically changing price that depends on the Product's estimated
market price. For example, if you set it to 'MP*5' then it
will always be sold at five times the estimated market price.
</p>
<br />
<input className="text-input" value={iQty} autoFocus={true} type="text" placeholder="Sell amount" style={{marginTop: "4px"}} onChange={onAmtChange} onKeyDown={onKeyDown} />
<input className="text-input" value={px} type="text" placeholder="Sell price" style={{marginTop: "4px"}} onChange={onPriceChange} onKeyDown={onKeyDown} />
<button className="std-button" onClick={sellProduct}>Confirm</button>
<div style={{border: "1px solid white", display: "inline-block"}}>
<label htmlFor={props.popupId+'-checkbox'}>Use same 'Sell Amount' for all cities</label>
<input checked={checked} onChange={onCheckedChange} id={props.popupId + "-checkbox"} style={{margin:"2px"}} type="checkbox" />
</div>
</>);
}