convert some corp to mui

This commit is contained in:
Olivier Gagnon 2021-09-30 13:51:55 -04:00
parent 5cce1c255c
commit 510fcedf90
12 changed files with 691 additions and 656 deletions

@ -385,9 +385,6 @@ export class Industry implements IIndustry {
const prod = this.products[prodName]; const prod = this.products[prodName];
if (prod === undefined) continue; if (prod === undefined) continue;
warehouse.sizeUsed += prod.data[warehouse.loc][0] * prod.siz; warehouse.sizeUsed += prod.data[warehouse.loc][0] * prod.siz;
if (prod.data[warehouse.loc][0] > 0) {
warehouse.breakdown += prodName + ": " + formatNumber(prod.data[warehouse.loc][0] * prod.siz, 0) + "<br>";
}
} }
} }
} }

@ -15,10 +15,6 @@ interface IConstructorParams {
} }
export class Warehouse { export class Warehouse {
// Text that describes how the space in this Warehouse is being used
// Used to create a tooltip in the UI
breakdown = "";
// Warehouse's level, which affects its maximum size // Warehouse's level, which affects its maximum size
level = 1; level = 1;
@ -90,14 +86,10 @@ export class Warehouse {
// Re-calculate how much space is being used by this Warehouse // Re-calculate how much space is being used by this Warehouse
updateMaterialSizeUsed(): void { updateMaterialSizeUsed(): void {
this.sizeUsed = 0; this.sizeUsed = 0;
this.breakdown = "";
for (const matName in this.materials) { for (const matName in this.materials) {
const mat = this.materials[matName]; const mat = this.materials[matName];
if (MaterialSizes.hasOwnProperty(matName)) { if (MaterialSizes.hasOwnProperty(matName)) {
this.sizeUsed += mat.qty * MaterialSizes[matName]; this.sizeUsed += mat.qty * MaterialSizes[matName];
if (mat.qty > 0) {
this.breakdown += matName + ": " + numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0") + "<br>";
}
} }
} }
if (this.sizeUsed > this.size) { if (this.sizeUsed > this.size) {

@ -9,6 +9,7 @@ import { Warehouse } from "../Warehouse";
import { OfficeSpace } from "../OfficeSpace"; import { OfficeSpace } from "../OfficeSpace";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
import { useCorporation, useDivision } from "./Context"; import { useCorporation, useDivision } from "./Context";
import Box from "@mui/material/Box";
interface IProps { interface IProps {
city: string; city: string;
@ -22,12 +23,12 @@ export function Industry(props: IProps): React.ReactElement {
const corp = useCorporation(); const corp = useCorporation();
const division = useDivision(); const division = useDivision();
return ( return (
<div> <Box display="flex">
<div className={"cmpy-mgmt-industry-left-panel"}> <Box sx={{ width: "50%" }}>
<IndustryOverview rerender={props.rerender} currentCity={props.city} office={props.office} /> <IndustryOverview rerender={props.rerender} currentCity={props.city} office={props.office} />
<IndustryOffice rerender={props.rerender} office={props.office} /> <IndustryOffice rerender={props.rerender} office={props.office} />
</div> </Box>
<div className={"cmpy-mgmt-industry-right-panel"}> <Box sx={{ width: "50%" }}>
<IndustryWarehouse <IndustryWarehouse
rerender={props.rerender} rerender={props.rerender}
player={player} player={player}
@ -36,7 +37,7 @@ export function Industry(props: IProps): React.ReactElement {
division={division} division={division}
warehouse={props.warehouse} warehouse={props.warehouse}
/> />
</div> </Box>
</div> </Box>
); );
} }

@ -432,7 +432,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
<Tooltip title={<Typography>Automatically hires an employee and gives him/her a random name</Typography>}> <Tooltip title={<Typography>Automatically hires an employee and gives him/her a random name</Typography>}>
<span> <span>
<Button disabled={props.office.atCapacity()} onClick={autohireEmployeeButtonOnClick}> <Button disabled={props.office.atCapacity()} onClick={autohireEmployeeButtonOnClick}>
Autohire Employee Hire Employee
</Button> </Button>
</span> </span>
</Tooltip> </Tooltip>

@ -1,101 +1,74 @@
// React Component for displaying an Industry's overview information // React Component for displaying an Industry's overview information
// (top-left panel in the Industry UI) // (top-left panel in the Industry UI)
import React from "react"; import React, { useState } from "react";
import { OfficeSpace } from "../OfficeSpace"; import { OfficeSpace } from "../OfficeSpace";
import { Industries } from "../IndustryData"; import { Industries } from "../IndustryData";
import { IndustryUpgrades } from "../IndustryUpgrades"; import { IndustryUpgrades } from "../IndustryUpgrades";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { MakeProductPopup } from "./MakeProductPopup"; import { MakeProductModal } from "./MakeProductModal";
import { ResearchPopup } from "./ResearchPopup"; import { ResearchPopup } from "./ResearchPopup";
import { createPopup } from "../../ui/React/createPopup"; import { createPopup } from "../../ui/React/createPopup";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { MoneyRate } from "../../ui/React/MoneyRate";
import { StatsTable } from "../../ui/React/StatsTable";
import { StaticModal } from "../../ui/React/StaticModal";
import { MoneyCost } from "./MoneyCost"; import { MoneyCost } from "./MoneyCost";
import { useCorporation, useDivision } from "./Context"; import { useCorporation, useDivision } from "./Context";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip"; import Tooltip from "@mui/material/Tooltip";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
import IconButton from "@mui/material/IconButton";
import HelpIcon from "@mui/icons-material/Help";
import Box from "@mui/material/Box";
interface IProps { function MakeProductButton(): React.ReactElement {
currentCity: string;
office: OfficeSpace;
rerender: () => void;
}
export function IndustryOverview(props: IProps): React.ReactElement {
const corp = useCorporation(); const corp = useCorporation();
const division = useDivision(); const division = useDivision();
function renderMakeProductButton(): React.ReactElement { const [makeOpen, setMakeOpen] = useState(false);
let createProductButtonText = "";
let createProductPopupText = "";
switch (division.type) {
case Industries.Food:
createProductButtonText = "Build Restaurant";
createProductPopupText = "Build and manage a new restaurant!";
break;
case Industries.Tobacco:
createProductButtonText = "Create Product";
createProductPopupText = "Create a new tobacco product!";
break;
case Industries.Pharmaceutical:
createProductButtonText = "Create Drug";
createProductPopupText = "Design and develop a new pharmaceutical drug!";
break;
case Industries.Computer:
case "Computer":
createProductButtonText = "Create Product";
createProductPopupText = "Design and manufacture a new computer hardware product!";
break;
case Industries.Robotics:
createProductButtonText = "Design Robot";
createProductPopupText = "Design and create a new robot or robotic system!";
break;
case Industries.Software:
createProductButtonText = "Develop Software";
createProductPopupText = "Develop a new piece of software!";
break;
case Industries.Healthcare:
createProductButtonText = "Build Hospital";
createProductPopupText = "Build and manage a new hospital!";
break;
case Industries.RealEstate:
createProductButtonText = "Develop Property";
createProductPopupText = "Develop a new piece of real estate property!";
break;
default:
createProductButtonText = "Create Product";
createProductPopupText = "Create a new product!";
return <></>;
}
createProductPopupText +=
"<br><br>To begin developing a product, " +
"first choose the city in which it will be designed. The stats of your employees " +
"in the selected city affect the properties of the finished product, such as its " +
"quality, performance, and durability.<br><br>" +
"You can also choose to invest money in the design and marketing of " +
"the product. Investing money in its design will result in a superior product. " +
"Investing money in marketing the product will help the product's sales.";
const hasMaxProducts = division.hasMaximumNumberProducts(); const hasMaxProducts = division.hasMaximumNumberProducts();
function openMakeProductPopup(): void { function shouldFlash(): boolean {
const popupId = "cmpy-mgmt-create-product-popup"; return Object.keys(division.products).length === 0;
createPopup(popupId, MakeProductPopup, { }
popupText: createProductPopupText,
division: division,
corp: corp,
popupId: popupId,
});
}
function shouldFlash(): boolean { let createProductButtonText = "";
return Object.keys(division.products).length === 0; switch (division.type) {
} case Industries.Food:
createProductButtonText = "Build Restaurant";
break;
case Industries.Tobacco:
createProductButtonText = "Create Product";
break;
case Industries.Pharmaceutical:
createProductButtonText = "Create Drug";
break;
case Industries.Computer:
case "Computer":
createProductButtonText = "Create Product";
break;
case Industries.Robotics:
createProductButtonText = "Design Robot";
break;
case Industries.Software:
createProductButtonText = "Develop Software";
break;
case Industries.Healthcare:
createProductButtonText = "Build Hospital";
break;
case Industries.RealEstate:
createProductButtonText = "Develop Property";
break;
default:
createProductButtonText = "Create Product";
return <></>;
}
return ( return (
<>
<Tooltip <Tooltip
title={ title={
hasMaxProducts ? ( hasMaxProducts ? (
@ -107,225 +80,212 @@ export function IndustryOverview(props: IProps): React.ReactElement {
) )
} }
> >
<Button color={shouldFlash() ? "error" : "primary"} onClick={openMakeProductPopup} disabled={corp.funds.lt(0)}> <Button
color={shouldFlash() ? "error" : "primary"}
onClick={() => setMakeOpen(true)}
disabled={corp.funds.lt(0)}
>
{createProductButtonText} {createProductButtonText}
</Button> </Button>
</Tooltip> </Tooltip>
); <MakeProductModal open={makeOpen} onClose={() => setMakeOpen(false)} />
</>
);
}
function Text(): React.ReactElement {
const corp = useCorporation();
const division = useDivision();
const [helpOpen, setHelpOpen] = useState(false);
const vechain = corp.unlockUpgrades[4] === 1;
const profit = division.lastCycleRevenue.minus(division.lastCycleExpenses).toNumber();
let advertisingInfo = false;
const advertisingFactors = division.getAdvertisingFactors();
const awarenessFac = advertisingFactors[1];
const popularityFac = advertisingFactors[2];
const ratioFac = advertisingFactors[3];
const totalAdvertisingFac = advertisingFactors[0];
if (vechain) {
advertisingInfo = true;
} }
function renderText(): React.ReactElement { function convertEffectFacToGraphic(fac: number): string {
const vechain = corp.unlockUpgrades[4] === 1; return createProgressBarText({
const profit = division.lastCycleRevenue.minus(division.lastCycleExpenses).toNumber(); progress: fac,
totalTicks: 20,
let advertisingInfo = false; });
const advertisingFactors = division.getAdvertisingFactors();
const awarenessFac = advertisingFactors[1];
const popularityFac = advertisingFactors[2];
const ratioFac = advertisingFactors[3];
const totalAdvertisingFac = advertisingFactors[0];
if (vechain) {
advertisingInfo = true;
}
function productionMultHelpTipOnClick(): void {
// Wrapper for createProgressBarText()
// Converts the industry's "effectiveness factors"
// into a graphic (string) depicting how high that effectiveness is
function convertEffectFacToGraphic(fac: number): string {
return createProgressBarText({
progress: fac,
totalTicks: 20,
});
}
dialogBoxCreate(
"Owning Hardware, Robots, AI Cores, and Real Estate " +
"can boost your Industry's production. The effect these " +
"materials have on your production varies between Industries. " +
"For example, Real Estate may be very effective for some Industries, " +
"but ineffective for others.<br><br>" +
"This division's production multiplier is calculated by summing " +
"the individual production multiplier of each of its office locations. " +
"This production multiplier is applied to each office. Therefore, it is " +
"beneficial to expand into new cities as this can greatly increase the " +
"production multiplier of your entire Division.<br><br>" +
"Below are approximations for how effective each material is at boosting " +
"this industry's production multiplier (Bigger bars = more effective):<br><br>" +
`Hardware:&nbsp;&nbsp;&nbsp; ${convertEffectFacToGraphic(division.hwFac)}<br>` +
`Robots:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ${convertEffectFacToGraphic(division.robFac)}<br>` +
`AI Cores:&nbsp;&nbsp;&nbsp; ${convertEffectFacToGraphic(division.aiFac)}<br>` +
`Real Estate: ${convertEffectFacToGraphic(division.reFac)}`,
);
}
function openResearchPopup(): void {
const popupId = "corporation-research-popup-box";
createPopup(popupId, ResearchPopup, {
industry: division,
popupId: popupId,
});
}
return (
<div>
<Typography>
Industry: {division.type} (Corp Funds: <Money money={corp.funds.toNumber()} />)
<br /> <br />
Awareness: {numeralWrapper.format(division.awareness, "0.000")} <br />
Popularity: {numeralWrapper.format(division.popularity, "0.000")} <br />
{advertisingInfo !== false && (
<p className={"tooltip"}>
Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")}
<span className={"tooltiptext cmpy-mgmt-advertising-info"}>
Total multiplier for this industrys sales due to its awareness and popularity
<br />
Awareness Bonus: x{numeralWrapper.format(Math.pow(awarenessFac, 0.85), "0.000")}
<br />
Popularity Bonus: x{numeralWrapper.format(Math.pow(popularityFac, 0.85), "0.000")}
<br />
Ratio Multiplier: x{numeralWrapper.format(Math.pow(ratioFac, 0.85), "0.000")}
</span>
</p>
)}
{advertisingInfo}
</Typography>
<br />
<br />
<table>
<tbody>
<tr>
<td>
<p>Revenue: </p>
</td>
<td>
<p>
<Money money={division.lastCycleRevenue.toNumber()} /> / s
</p>
</td>
</tr>
<tr>
<td>
<p>Expenses: </p>
</td>
<td>
<p>
<Money money={division.lastCycleExpenses.toNumber()} /> / s
</p>
</td>
</tr>
<tr>
<td>
<p>Profit: </p>
</td>
<td>
<p>
<Money money={profit} /> / s
</p>
</td>
</tr>
</tbody>
</table>
<br />
<p className={"tooltip"}>
Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")}
<span className={"tooltiptext"}>
Production gain from owning production-boosting materials such as hardware, Robots, AI Cores, and Real
Estate
</span>
</p>
<div className={"help-tip"} onClick={productionMultHelpTipOnClick}>
?
</div>
<br /> <br />
<p className={"tooltip"}>
Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")}
<span className={"tooltiptext"}>
Scientific Research increases the quality of the materials and products that you produce.
</span>
</p>
<button className={"help-tip"} onClick={openResearchPopup}>
Research
</button>
</div>
);
} }
function renderUpgrades(): React.ReactElement[] { function openResearchPopup(): void {
const upgrades = []; const popupId = "corporation-research-popup-box";
for (const index in IndustryUpgrades) { createPopup(popupId, ResearchPopup, {
const upgrade = IndustryUpgrades[index]; industry: division,
popupId: popupId,
});
}
// AutoBrew research disables the Coffee upgrade return (
if (division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") { <div>
continue; <Typography>
} Industry: {division.type} (Corp Funds: <Money money={corp.funds.toNumber()} />)
</Typography>
const i = upgrade[0]; <br />
const baseCost = upgrade[1]; <StatsTable
const priceMult = upgrade[2]; rows={[
let cost = 0; ["Awareness:", numeralWrapper.format(division.awareness, "0.000")],
switch (i) { ["Popularity:", numeralWrapper.format(division.popularity, "0.000")],
case 0: //Coffee, cost is static per employee ]}
cost = props.office.employees.length * baseCost; />
break; {advertisingInfo !== false && (
default: <Tooltip
cost = baseCost * Math.pow(priceMult, division.upgrades[i]); title={
break;
}
function onClick(): void {
if (corp.funds.lt(cost)) return;
corp.funds = corp.funds.minus(cost);
division.upgrade(upgrade, {
corporation: corp,
office: props.office,
});
props.rerender();
}
upgrades.push(
renderUpgrade({
key: index,
onClick: onClick,
text: (
<> <>
{upgrade[4]} - <MoneyCost money={cost} corp={corp} /> <Typography>Total multiplier for this industrys sales due to its awareness and popularity</Typography>
<StatsTable
rows={[
["Awareness Bonus:", "x" + numeralWrapper.format(Math.pow(awarenessFac, 0.85), "0.000")],
["Popularity Bonus:", "x" + numeralWrapper.format(Math.pow(popularityFac, 0.85), "0.000")],
["Ratio Multiplier:", "x" + numeralWrapper.format(Math.pow(ratioFac, 0.85), "0.000")],
]}
/>
</> </>
), }
tooltip: upgrade[5], >
}), <Typography>Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")}</Typography>
); </Tooltip>
)}
<br />
<StatsTable
rows={[
["Revenue:", <MoneyRate money={division.lastCycleRevenue.toNumber()} />],
["Expenses:", <MoneyRate money={division.lastCycleExpenses.toNumber()} />],
["Profit:", <MoneyRate money={profit} />],
]}
/>
<br />
<Box display="flex" alignItems="center">
<Tooltip
title={
<Typography>
Production gain from owning production-boosting materials such as hardware, Robots, AI Cores, and Real
Estate.
</Typography>
}
>
<Typography>Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")}</Typography>
</Tooltip>
<IconButton onClick={() => setHelpOpen(true)}>
<HelpIcon />
</IconButton>
<StaticModal open={helpOpen} onClose={() => setHelpOpen(false)}>
<Typography>
Owning Hardware, Robots, AI Cores, and Real Estate can boost your Industry's production. The effect these
materials have on your production varies between Industries. For example, Real Estate may be very effective
for some Industries, but ineffective for others.
<br />
<br />
This division's production multiplier is calculated by summing the individual production multiplier of each
of its office locations. This production multiplier is applied to each office. Therefore, it is beneficial
to expand into new cities as this can greatly increase the production multiplier of your entire Division.
<br />
<br />
Below are approximations for how effective each material is at boosting this industry's production
multiplier (Bigger bars = more effective):
<br />
<br />
Hardware:&nbsp;&nbsp;&nbsp; {convertEffectFacToGraphic(division.hwFac)}
<br />
Robots:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {convertEffectFacToGraphic(division.robFac)}
<br />
AI Cores:&nbsp;&nbsp;&nbsp; {convertEffectFacToGraphic(division.aiFac)}
<br />
Real Estate: {convertEffectFacToGraphic(division.reFac)}
</Typography>
</StaticModal>
</Box>
<Box display="flex" alignItems="center">
<Tooltip
title={
<Typography>
Scientific Research increases the quality of the materials and products that you produce.
</Typography>
}
>
<Typography>Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")}</Typography>
</Tooltip>
<Button sx={{ mx: 1 }} onClick={openResearchPopup}>
Research
</Button>
</Box>
</div>
);
}
function Upgrades(props: { office: OfficeSpace; rerender: () => void }): React.ReactElement {
const corp = useCorporation();
const division = useDivision();
const upgrades = [];
for (const index in IndustryUpgrades) {
const upgrade = IndustryUpgrades[index];
// AutoBrew research disables the Coffee upgrade
if (division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") {
continue;
} }
return upgrades; const i = upgrade[0];
} const baseCost = upgrade[1];
const priceMult = upgrade[2];
let cost = 0;
switch (i) {
case 0: //Coffee, cost is static per employee
cost = props.office.employees.length * baseCost;
break;
default:
cost = baseCost * Math.pow(priceMult, division.upgrades[i]);
break;
}
interface IRenderUpgradeProps { function onClick(): void {
key: string; if (corp.funds.lt(cost)) return;
onClick: () => void; corp.funds = corp.funds.minus(cost);
text: JSX.Element; division.upgrade(upgrade, {
tooltip: string; corporation: corp,
} office: props.office,
});
props.rerender();
}
function renderUpgrade(props: IRenderUpgradeProps): React.ReactElement { upgrades.push(
return ( <Tooltip key={index} title={upgrade[5]}>
<div className={"cmpy-mgmt-upgrade-div tooltip"} onClick={props.onClick} key={props.key}> <Button onClick={onClick}>
{props.text} {upgrade[4]} -&nbsp;
{props.tooltip != null && <span className={"tooltiptext"}>{props.tooltip}</span>} <MoneyCost money={cost} corp={corp} />
</div> </Button>
</Tooltip>,
); );
} }
const makeProductButton = renderMakeProductButton(); return <>{upgrades}</>;
}
interface IProps {
currentCity: string;
office: OfficeSpace;
rerender: () => void;
}
export function IndustryOverview(props: IProps): React.ReactElement {
const division = useDivision();
return ( return (
<Paper> <Paper>
{renderText()} <Text />
<br /> <br />
<Typography>Purchases & Upgrades</Typography> <Typography>Purchases & Upgrades</Typography>
{renderUpgrades()} <br /> <Upgrades office={props.office} rerender={props.rerender} /> <br />
{division.makesProducts && makeProductButton} {division.makesProducts && <MakeProductButton />}
</Paper> </Paper>
); );
} }

@ -1,6 +1,6 @@
// React Component for displaying an Industry's warehouse information // React Component for displaying an Industry's warehouse information
// (right-side panel in the Industry UI) // (right-side panel in the Industry UI)
import React from "react"; import React, { useState } from "react";
import { CorporationConstants } from "../data/Constants"; import { CorporationConstants } from "../data/Constants";
import { OfficeSpace } from "../OfficeSpace"; import { OfficeSpace } from "../OfficeSpace";
@ -15,7 +15,8 @@ import { SellMaterialPopup } from "./SellMaterialPopup";
import { SellProductPopup } from "./SellProductPopup"; import { SellProductPopup } from "./SellProductPopup";
import { PurchaseMaterialPopup } from "./PurchaseMaterialPopup"; import { PurchaseMaterialPopup } from "./PurchaseMaterialPopup";
import { ProductMarketTaPopup } from "./ProductMarketTaPopup"; import { ProductMarketTaPopup } from "./ProductMarketTaPopup";
import { SmartSupplyPopup } from "./SmartSupplyPopup"; import { SmartSupplyModal } from "./SmartSupplyModal";
import { MaterialSizes } from "../MaterialSizes";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { createPopup } from "../../ui/React/createPopup"; import { createPopup } from "../../ui/React/createPopup";
@ -29,6 +30,13 @@ import { MoneyCost } from "./MoneyCost";
import { isRelevantMaterial } from "./Helpers"; import { isRelevantMaterial } from "./Helpers";
import { IndustryProductEquation } from "./IndustryProductEquation"; import { IndustryProductEquation } from "./IndustryProductEquation";
import { PurchaseWarehouse } from "../Actions"; import { PurchaseWarehouse } from "../Actions";
import { useCorporation, useDivision } from "./Context";
import Typography from "@mui/material/Typography";
import Tooltip from "@mui/material/Tooltip";
import Paper from "@mui/material/Paper";
import Button from "@mui/material/Button";
import Box from "@mui/material/Box";
interface IProductProps { interface IProductProps {
corp: ICorporation; corp: ICorporation;
@ -41,8 +49,8 @@ interface IProductProps {
// Creates the UI for a single Product type // Creates the UI for a single Product type
function ProductComponent(props: IProductProps): React.ReactElement { function ProductComponent(props: IProductProps): React.ReactElement {
const corp = props.corp; const corp = useCorporation();
const division = props.division; const division = useDivision();
const city = props.city; const city = props.city;
const product = props.product; const product = props.product;
@ -136,7 +144,7 @@ function ProductComponent(props: IProductProps): React.ReactElement {
rerender: props.rerender, rerender: props.rerender,
product: product, product: product,
industry: division, industry: division,
corp: props.corp, corp: corp,
popupId: popupId, popupId: popupId,
player: props.player, player: props.player,
}); });
@ -164,21 +172,11 @@ function ProductComponent(props: IProductProps): React.ReactElement {
{hasUpgradeDashboard && ( {hasUpgradeDashboard && (
<div> <div>
<button className={"std-button"} onClick={openSellProductPopup}> <Button onClick={openSellProductPopup}>{sellButtonText}</Button>
{sellButtonText}
</button>
<br /> <br />
<button className={"std-button"} onClick={openLimitProductProdutionPopup}> <Button onClick={openLimitProductProdutionPopup}>{limitProductionButtonText}</Button>
{limitProductionButtonText} <Button onClick={openDiscontinueProductPopup}>Discontinue</Button>
</button> {division.hasResearch("Market-TA.I") && <Button onClick={openProductMarketTaPopup}>Market-TA</Button>}
<button className={"std-button"} onClick={openDiscontinueProductPopup}>
Discontinue
</button>
{division.hasResearch("Market-TA.I") && (
<button className={"std-button"} onClick={openProductMarketTaPopup}>
Market-TA
</button>
)}
</div> </div>
)} )}
</div> </div>
@ -227,29 +225,17 @@ function ProductComponent(props: IProductProps): React.ReactElement {
</p> </p>
<div> <div>
<button className={"std-button"} onClick={openSellProductPopup}> <Button onClick={openSellProductPopup}>{sellButtonText}</Button>
{sellButtonText}
</button>
<br /> <br />
<button className={"std-button"} onClick={openLimitProductProdutionPopup}> <Button onClick={openLimitProductProdutionPopup}>{limitProductionButtonText}</Button>
{limitProductionButtonText} <Button onClick={openDiscontinueProductPopup}>Discontinue</Button>
</button> {division.hasResearch("Market-TA.I") && <Button onClick={openProductMarketTaPopup}>Market-TA</Button>}
<button className={"std-button"} onClick={openDiscontinueProductPopup}>
Discontinue
</button>
{division.hasResearch("Market-TA.I") && (
<button className={"std-button"} onClick={openProductMarketTaPopup}>
Market-TA
</button>
)}
</div> </div>
</div> </div>
); );
} }
interface IMaterialProps { interface IMaterialProps {
corp: ICorporation;
division: IIndustry;
warehouse: Warehouse; warehouse: Warehouse;
city: string; city: string;
mat: Material; mat: Material;
@ -258,8 +244,8 @@ interface IMaterialProps {
// Creates the UI for a single Material type // Creates the UI for a single Material type
function MaterialComponent(props: IMaterialProps): React.ReactElement { function MaterialComponent(props: IMaterialProps): React.ReactElement {
const corp = props.corp; const corp = useCorporation();
const division = props.division; const division = useDivision();
const warehouse = props.warehouse; const warehouse = props.warehouse;
const city = props.city; const city = props.city;
const mat = props.mat; const mat = props.mat;
@ -291,7 +277,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
mat: mat, mat: mat,
industry: division, industry: division,
warehouse: warehouse, warehouse: warehouse,
corp: props.corp, corp: corp,
popupId: popupId, popupId: popupId,
}); });
} }
@ -300,7 +286,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
const popupId = "cmpy-mgmt-export-popup"; const popupId = "cmpy-mgmt-export-popup";
createPopup(popupId, ExportPopup, { createPopup(popupId, ExportPopup, {
mat: mat, mat: mat,
corp: props.corp, corp: corp,
popupId: popupId, popupId: popupId,
}); });
} }
@ -358,7 +344,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
const popupId = "cmpy-mgmt-material-sell-popup"; const popupId = "cmpy-mgmt-material-sell-popup";
createPopup(popupId, SellMaterialPopup, { createPopup(popupId, SellMaterialPopup, {
mat: mat, mat: mat,
corp: props.corp, corp: corp,
popupId: popupId, popupId: popupId,
}); });
} }
@ -368,13 +354,13 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
createPopup(popupId, MaterialMarketTaPopup, { createPopup(popupId, MaterialMarketTaPopup, {
mat: mat, mat: mat,
industry: division, industry: division,
corp: props.corp, corp: corp,
popupId: popupId, popupId: popupId,
}); });
} }
function shouldFlash(): boolean { function shouldFlash(): boolean {
return props.division.prodMats.includes(props.mat.name) && !mat.sllman[0]; return division.prodMats.includes(props.mat.name) && !mat.sllman[0];
} }
return ( return (
@ -409,33 +395,25 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
</div> </div>
<div style={{ display: "inline-block" }}> <div style={{ display: "inline-block" }}>
<button <Button
className={purchaseButtonClass} className={purchaseButtonClass}
onClick={openPurchaseMaterialPopup} onClick={openPurchaseMaterialPopup}
disabled={props.warehouse.smartSupplyEnabled && Object.keys(props.division.reqMats).includes(props.mat.name)} disabled={props.warehouse.smartSupplyEnabled && Object.keys(division.reqMats).includes(props.mat.name)}
> >
{purchaseButtonText} {purchaseButtonText}
{tutorial && ( {tutorial && (
<span className={"tooltiptext"}>Purchase your required materials to get production started!</span> <span className={"tooltiptext"}>Purchase your required materials to get production started!</span>
)} )}
</button> </Button>
{corp.unlockUpgrades[0] === 1 && ( {corp.unlockUpgrades[0] === 1 && <Button onClick={openExportPopup}>Export</Button>}
<button className={"std-button"} onClick={openExportPopup}>
Export
</button>
)}
<br /> <br />
<button className={`std-button${shouldFlash() ? " flashing-button" : ""}`} onClick={openSellMaterialPopup}> <Button className={`std-button${shouldFlash() ? " flashing-button" : ""}`} onClick={openSellMaterialPopup}>
{sellButtonText} {sellButtonText}
</button> </Button>
{division.hasResearch("Market-TA.I") && ( {division.hasResearch("Market-TA.I") && <Button onClick={openMaterialMarketTaPopup}>Market-TA</Button>}
<button className={"std-button"} onClick={openMaterialMarketTaPopup}>
Market-TA
</button>
)}
</div> </div>
</div> </div>
); );
@ -450,177 +428,188 @@ interface IProps {
rerender: () => void; rerender: () => void;
} }
export function IndustryWarehouse(props: IProps): React.ReactElement { function WarehouseRoot(props: IProps): React.ReactElement {
function renderWarehouseUI(): React.ReactElement { const corp = useCorporation();
if (props.warehouse === 0) return <></>; const division = useDivision();
// General Storage information at the top const [smartSupplyOpen, setSmartSupplyOpen] = useState(false);
const sizeUsageStyle = { if (props.warehouse === 0) return <></>;
color: props.warehouse.sizeUsed >= props.warehouse.size ? "red" : "white",
margin: "5px",
};
// Upgrade Warehouse size button // Upgrade Warehouse size button
const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, props.warehouse.level + 1); const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, props.warehouse.level + 1);
const canAffordUpgrade = props.corp.funds.gt(sizeUpgradeCost); const canAffordUpgrade = corp.funds.gt(sizeUpgradeCost);
const upgradeWarehouseClass = canAffordUpgrade ? "std-button" : "a-link-button-inactive"; function upgradeWarehouseOnClick(): void {
function upgradeWarehouseOnClick(): void { if (division === null) return;
if (props.division === null) return; if (props.warehouse === 0) return;
if (props.warehouse === 0) return; if (!canAffordUpgrade) return;
++props.warehouse.level; ++props.warehouse.level;
props.warehouse.updateSize(props.corp, props.division); props.warehouse.updateSize(corp, division);
props.corp.funds = props.corp.funds.minus(sizeUpgradeCost); corp.funds = corp.funds.minus(sizeUpgradeCost);
props.rerender();
}
function openSmartSupplyPopup(): void {
if (props.warehouse === 0) return;
const popupId = "cmpy-mgmt-smart-supply-popup";
createPopup(popupId, SmartSupplyPopup, {
division: props.division,
warehouse: props.warehouse,
corp: props.corp,
player: props.player,
popupId: popupId,
});
}
const ratioLines = [];
for (const matName in props.division.reqMats) {
if (props.division.reqMats.hasOwnProperty(matName)) {
const text = [" *", props.division.reqMats[matName], matName].join(" ");
ratioLines.push(
<div key={matName}>
<p>{text}</p>
</div>,
);
}
}
// Current State:
let stateText;
switch (props.division.state) {
case "START":
stateText = "Current state: Preparing...";
break;
case "PURCHASE":
stateText = "Current state: Purchasing materials...";
break;
case "PRODUCTION":
stateText = "Current state: Producing materials and/or products...";
break;
case "SALE":
stateText = "Current state: Selling materials and/or products...";
break;
case "EXPORT":
stateText = "Current state: Exporting materials and/or products...";
break;
default:
console.error(`Invalid state: ${props.division.state}`);
break;
}
// Create React components for materials
const mats = [];
for (const matName in props.warehouse.materials) {
if (props.warehouse.materials[matName] instanceof Material) {
// Only create UI for materials that are relevant for the industry
if (isRelevantMaterial(matName, props.division)) {
mats.push(
<MaterialComponent
rerender={props.rerender}
city={props.currentCity}
corp={props.corp}
division={props.division}
key={matName}
mat={props.warehouse.materials[matName]}
warehouse={props.warehouse}
/>,
);
}
}
}
// Create React components for products
const products = [];
if (props.division.makesProducts && Object.keys(props.division.products).length > 0) {
for (const productName in props.division.products) {
const product = props.division.products[productName];
if (product instanceof Product) {
products.push(
<ProductComponent
rerender={props.rerender}
player={props.player}
city={props.currentCity}
corp={props.corp}
division={props.division}
key={productName}
product={product}
/>,
);
}
}
}
return (
<div className={"cmpy-mgmt-warehouse-panel"}>
<p className={"tooltip"} style={sizeUsageStyle}>
Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "}
{numeralWrapper.formatBigNumber(props.warehouse.size)}
<span className={"tooltiptext"} dangerouslySetInnerHTML={{ __html: props.warehouse.breakdown }}></span>
</p>
<button className={upgradeWarehouseClass} onClick={upgradeWarehouseOnClick}>
Upgrade Warehouse Size - <MoneyCost money={sizeUpgradeCost} corp={props.corp} />
</button>
<p>This industry uses the following equation for it's production: </p>
<br />
<br />
<IndustryProductEquation division={props.division} />
<br />
<br />
<p>
To get started with production, purchase your required materials or import them from another of your company's
divisions.
</p>
<br />
<p>{stateText}</p>
{props.corp.unlockUpgrades[1] && (
<>
<button className="std-button" onClick={openSmartSupplyPopup}>
Configure Smart Supply
</button>
</>
)}
{mats}
{products}
</div>
);
}
function purchaseWarehouse(division: IIndustry, city: string): void {
PurchaseWarehouse(props.corp, division, city);
props.rerender(); props.rerender();
} }
if (props.warehouse instanceof Warehouse) { const ratioLines = [];
return renderWarehouseUI(); for (const matName in division.reqMats) {
} else { if (division.reqMats.hasOwnProperty(matName)) {
return ( const text = [" *", division.reqMats[matName], matName].join(" ");
<div className={"cmpy-mgmt-warehouse-panel"}> ratioLines.push(
<button <div key={matName}>
className={"std-button"} <p>{text}</p>
onClick={() => purchaseWarehouse(props.division, props.currentCity)} </div>,
disabled={props.corp.funds.lt(CorporationConstants.WarehouseInitialCost)} );
> }
Purchase Warehouse ( }
<MoneyCost money={CorporationConstants.WarehouseInitialCost} corp={props.corp} />)
</button> // Current State:
</div> let stateText;
switch (division.state) {
case "START":
stateText = "Current state: Preparing...";
break;
case "PURCHASE":
stateText = "Current state: Purchasing materials...";
break;
case "PRODUCTION":
stateText = "Current state: Producing materials and/or products...";
break;
case "SALE":
stateText = "Current state: Selling materials and/or products...";
break;
case "EXPORT":
stateText = "Current state: Exporting materials and/or products...";
break;
default:
console.error(`Invalid state: ${division.state}`);
break;
}
// Create React components for materials
const mats = [];
for (const matName in props.warehouse.materials) {
if (!(props.warehouse.materials[matName] instanceof Material)) continue;
// Only create UI for materials that are relevant for the industry
if (!isRelevantMaterial(matName, division)) continue;
mats.push(
<MaterialComponent
rerender={props.rerender}
city={props.currentCity}
key={matName}
mat={props.warehouse.materials[matName]}
warehouse={props.warehouse}
/>,
); );
} }
// Create React components for products
const products = [];
if (division.makesProducts && Object.keys(division.products).length > 0) {
for (const productName in division.products) {
const product = division.products[productName];
if (!(product instanceof Product)) continue;
products.push(
<ProductComponent
rerender={props.rerender}
player={props.player}
city={props.currentCity}
corp={corp}
division={division}
key={productName}
product={product}
/>,
);
}
}
let breakdown = <></>;
for (const matName in props.warehouse.materials) {
if (matName === "RealEstate") continue;
const mat = props.warehouse.materials[matName];
if (!MaterialSizes.hasOwnProperty(matName)) continue;
if (mat.qty === 0) continue;
breakdown = (
<>
{breakdown}
{matName}: {numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0")}
<br />
</>
);
}
return (
<div className={"cmpy-mgmt-warehouse-panel"}>
<Box display="flex" alignItems="center">
<Tooltip title={props.warehouse.sizeUsed !== 0 ? breakdown : ""}>
<Typography color={props.warehouse.sizeUsed >= props.warehouse.size ? "error" : "primary"}>
Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "}
{numeralWrapper.formatBigNumber(props.warehouse.size)}
</Typography>
</Tooltip>
<Button disabled={!canAffordUpgrade} onClick={upgradeWarehouseOnClick}>
Upgrade Warehouse Size -&nbsp;
<MoneyCost money={sizeUpgradeCost} corp={corp} />
</Button>
</Box>
<Typography>This industry uses the following equation for it's production: </Typography>
<br />
<Typography>
<IndustryProductEquation division={division} />
</Typography>
<br />
<Typography>
To get started with production, purchase your required materials or import them from another of your company's
divisions.
</Typography>
<br />
<Typography>{stateText}</Typography>
{corp.unlockUpgrades[1] && (
<>
<Button onClick={() => setSmartSupplyOpen(true)}>Configure Smart Supply</Button>
<SmartSupplyModal
open={smartSupplyOpen}
onClose={() => setSmartSupplyOpen(false)}
warehouse={props.warehouse}
/>
</>
)}
{mats}
{products}
</div>
);
}
export function IndustryWarehouse(props: IProps): React.ReactElement {
if (props.warehouse instanceof Warehouse) {
return <WarehouseRoot {...props} />;
} else {
return <EmptyWarehouse rerender={props.rerender} city={props.currentCity} />;
}
}
interface IEmptyProps {
city: string;
rerender: () => void;
}
function EmptyWarehouse(props: IEmptyProps): React.ReactElement {
const corp = useCorporation();
const division = useDivision();
const disabled = corp.funds.lt(CorporationConstants.WarehouseInitialCost);
function purchaseWarehouse(): void {
if (disabled) return;
PurchaseWarehouse(corp, division, props.city);
props.rerender();
}
return (
<Paper>
<Button onClick={purchaseWarehouse} disabled={disabled}>
Purchase Warehouse (
<MoneyCost money={CorporationConstants.WarehouseInitialCost} corp={corp} />)
</Button>
</Paper>
);
} }

@ -25,9 +25,7 @@ export function MainPanel(props: IProps): React.ReactElement {
if (division === undefined) throw new Error("Cannot find division"); if (division === undefined) throw new Error("Cannot find division");
return ( return (
<Context.Division.Provider value={division}> <Context.Division.Provider value={division}>
<div id="cmpy-mgmt-panel"> <CityTabs rerender={props.rerender} city={CityName.Sector12} />
<CityTabs rerender={props.rerender} city={CityName.Sector12} />
</div>
</Context.Division.Provider> </Context.Division.Provider>
); );
} }

@ -0,0 +1,193 @@
import React, { useState } from "react";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { Modal } from "../../ui/React/Modal";
import { Industries } from "../IndustryData";
import { MakeProduct } from "../Actions";
import { useCorporation, useDivision } from "./Context";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
import Button from "@mui/material/Button";
import MenuItem from "@mui/material/MenuItem";
import Select, { SelectChangeEvent } from "@mui/material/Select";
interface IProps {
open: boolean;
onClose: () => void;
}
function productPlaceholder(tpe: string): string {
if (tpe === Industries.Food) {
return "Restaurant Name";
} else if (tpe === Industries.Healthcare) {
return "Hospital Name";
} else if (tpe === Industries.RealEstate) {
return "Property Name";
}
return "Product Name";
}
// Create a popup that lets the player create a product for their current industry
export function MakeProductModal(props: IProps): React.ReactElement {
const corp = useCorporation();
const division = useDivision();
const allCities = Object.keys(division.offices).filter((cityName: string) => division.offices[cityName] !== 0);
const [city, setCity] = useState(allCities.length > 0 ? allCities[0] : "");
const [name, setName] = useState("");
const [design, setDesign] = useState<number | null>(null);
const [marketing, setMarketing] = useState<number | null>(null);
if (division.hasMaximumNumberProducts()) return <></>;
let createProductPopupText = <></>;
switch (division.type) {
case Industries.Food:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Build and manage a new restaurant!
</>
);
break;
case Industries.Tobacco:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Create a new tobacco product!
</>
);
break;
case Industries.Pharmaceutical:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Design and develop a new pharmaceutical drug!
</>
);
break;
case Industries.Computer:
case "Computer":
createProductPopupText = (
<>
{createProductPopupText}
<br />
Design and manufacture a new computer hardware product!
</>
);
break;
case Industries.Robotics:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Design and create a new robot or robotic system!
</>
);
break;
case Industries.Software:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Develop a new piece of software!
</>
);
break;
case Industries.Healthcare:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Build and manage a new hospital!
</>
);
break;
case Industries.RealEstate:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Develop a new piece of real estate property!
</>
);
break;
default:
createProductPopupText = (
<>
{createProductPopupText}
<br />
Create a new product!
</>
);
return <></>;
}
createProductPopupText = (
<>
{createProductPopupText}
<br />
<br />
To begin developing a product, first choose the city in which it will be designed. The stats of your employees in
the selected city affect the properties of the finished product, such as its quality, performance, and durability.
<br />
<br />
You can also choose to invest money in the design and marketing of the product. Investing money in its design will
result in a superior product. Investing money in marketing the product will help the product's sales.
</>
);
function makeProduct(): void {
if (design === null || marketing === null) return;
try {
MakeProduct(corp, division, city, name, design, marketing);
} catch (err) {
dialogBoxCreate(err + "");
}
props.onClose();
}
function onCityChange(event: SelectChangeEvent<string>): void {
setCity(event.target.value);
}
function onProductNameChange(event: React.ChangeEvent<HTMLInputElement>): void {
setName(event.target.value);
}
function onDesignChange(event: React.ChangeEvent<HTMLInputElement>): void {
if (event.target.value === "") setDesign(null);
else setDesign(parseFloat(event.target.value));
}
function onMarketingChange(event: React.ChangeEvent<HTMLInputElement>): void {
if (event.target.value === "") setMarketing(null);
else setMarketing(parseFloat(event.target.value));
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (event.keyCode === 13) makeProduct();
}
return (
<Modal open={props.open} onClose={props.onClose}>
<Typography>{createProductPopupText}</Typography>
<Select style={{ margin: "5px" }} onChange={onCityChange} defaultValue={city}>
{allCities.map((cityName: string) => (
<MenuItem key={cityName} value={cityName}>
{cityName}
</MenuItem>
))}
</Select>
<TextField onChange={onProductNameChange} placeholder={productPlaceholder(division.type)} />
<br />
<TextField onChange={onDesignChange} autoFocus={true} type="number" placeholder={"Design investment"} />
<TextField
onChange={onMarketingChange}
onKeyDown={onKeyDown}
type="number"
placeholder={"Marketing investment"}
/>
<Button onClick={makeProduct}>Develop Product</Button>
</Modal>
);
}

@ -1,108 +0,0 @@
import React, { useState } from "react";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { removePopup } from "../../ui/React/createPopup";
import { Industries } from "../IndustryData";
import { ICorporation } from "../ICorporation";
import { IIndustry } from "../IIndustry";
import { MakeProduct } from "../Actions";
interface IProps {
popupText: string;
division: IIndustry;
corp: ICorporation;
popupId: string;
}
function productPlaceholder(tpe: string): string {
if (tpe === Industries.Food) {
return "Restaurant Name";
} else if (tpe === Industries.Healthcare) {
return "Hospital Name";
} else if (tpe === Industries.RealEstate) {
return "Property Name";
}
return "Product Name";
}
// Create a popup that lets the player create a product for their current industry
export function MakeProductPopup(props: IProps): React.ReactElement {
const allCities = Object.keys(props.division.offices).filter(
(cityName: string) => props.division.offices[cityName] !== 0,
);
const [city, setCity] = useState(allCities.length > 0 ? allCities[0] : "");
const [name, setName] = useState("");
const [design, setDesign] = useState<number | null>(null);
const [marketing, setMarketing] = useState<number | null>(null);
if (props.division.hasMaximumNumberProducts()) return <></>;
function makeProduct(): void {
if (design === null || marketing === null) return;
try {
MakeProduct(props.corp, props.division, city, name, design, marketing);
} catch (err) {
dialogBoxCreate(err + "");
}
removePopup(props.popupId);
}
function onCityChange(event: React.ChangeEvent<HTMLSelectElement>): void {
setCity(event.target.value);
}
function onProductNameChange(event: React.ChangeEvent<HTMLInputElement>): void {
setName(event.target.value);
}
function onDesignChange(event: React.ChangeEvent<HTMLInputElement>): void {
if (event.target.value === "") setDesign(null);
else setDesign(parseFloat(event.target.value));
}
function onMarketingChange(event: React.ChangeEvent<HTMLInputElement>): void {
if (event.target.value === "") setMarketing(null);
else setMarketing(parseFloat(event.target.value));
}
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (event.keyCode === 13) makeProduct();
}
return (
<>
<p dangerouslySetInnerHTML={{ __html: props.popupText }} />
<select className="dropdown" style={{ margin: "5px" }} onChange={onCityChange} defaultValue={city}>
{allCities.map((cityName: string) => (
<option key={cityName} value={cityName}>
{cityName}
</option>
))}
</select>
<input
onChange={onProductNameChange}
className="text-input"
style={{ margin: "5px" }}
placeholder={productPlaceholder(props.division.type)}
/>
<br />
<input
onChange={onDesignChange}
autoFocus={true}
type="number"
className="text-input"
style={{ margin: "5px" }}
placeholder={"Design investment"}
/>
<input
onChange={onMarketingChange}
onKeyDown={onKeyDown}
type="number"
className="text-input"
style={{ margin: "5px" }}
placeholder={"Marketing investment"}
/>
<button className="std-button" onClick={makeProduct}>
Develop Product
</button>
</>
);
}

@ -6,6 +6,7 @@ import { CorporationConstants } from "../data/Constants";
import { Treant } from "treant-js"; import { Treant } from "treant-js";
import { IIndustry } from "../IIndustry"; import { IIndustry } from "../IIndustry";
import { Research } from "../Actions"; import { Research } from "../Actions";
import Typography from "@mui/material/Typography";
interface IProps { interface IProps {
industry: IIndustry; industry: IIndustry;

@ -1,12 +1,14 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Warehouse } from "../Warehouse"; import { Warehouse } from "../Warehouse";
import { ICorporation } from "../ICorporation";
import { IIndustry } from "../IIndustry";
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../Actions"; import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../Actions";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Material } from "../Material"; import { Material } from "../Material";
import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { Modal } from "../../ui/React/Modal";
import { useDivision } from "./Context";
import Typography from "@mui/material/Typography";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
interface ILeftoverProps { interface ILeftoverProps {
matName: string; matName: string;
@ -26,33 +28,31 @@ function Leftover(props: ILeftoverProps): React.ReactElement {
setChecked(event.target.checked); setChecked(event.target.checked);
} }
const matNameId = `${props.matName}-use-leftovers`;
return ( return (
<div key={props.matName}> <>
<label style={{ color: "white" }} htmlFor={matNameId}> <FormControlLabel
{props.warehouse.materials[props.matName].name} control={<Switch checked={checked} onChange={onChange} />}
</label> label={<Typography>{props.warehouse.materials[props.matName].name}</Typography>}
<input type={"checkbox"} id={matNameId} onChange={onChange} style={{ margin: "3px" }} checked={checked} /> />
<br /> <br />
</div> </>
); );
} }
interface IProps { interface IProps {
division: IIndustry; open: boolean;
onClose: () => void;
warehouse: Warehouse; warehouse: Warehouse;
corp: ICorporation;
player: IPlayer;
popupId: string;
} }
export function SmartSupplyPopup(props: IProps): React.ReactElement { export function SmartSupplyModal(props: IProps): React.ReactElement {
const division = useDivision();
const setRerender = useState(false)[1]; const setRerender = useState(false)[1];
function rerender(): void { function rerender(): void {
setRerender((old) => !old); setRerender((old) => !old);
} }
// Smart Supply Checkbox // Smart Supply Checkbox
const smartSupplyCheckboxId = "cmpy-mgmt-smart-supply-checkbox";
function smartSupplyOnChange(e: React.ChangeEvent<HTMLInputElement>): void { function smartSupplyOnChange(e: React.ChangeEvent<HTMLInputElement>): void {
SetSmartSupply(props.warehouse, e.target.checked); SetSmartSupply(props.warehouse, e.target.checked);
rerender(); rerender();
@ -62,25 +62,21 @@ export function SmartSupplyPopup(props: IProps): React.ReactElement {
const mats = []; const mats = [];
for (const matName in props.warehouse.materials) { for (const matName in props.warehouse.materials) {
if (!(props.warehouse.materials[matName] instanceof Material)) continue; if (!(props.warehouse.materials[matName] instanceof Material)) continue;
if (!Object.keys(props.division.reqMats).includes(matName)) continue; if (!Object.keys(division.reqMats).includes(matName)) continue;
mats.push(<Leftover key={matName} warehouse={props.warehouse} matName={matName} />); mats.push(<Leftover key={matName} warehouse={props.warehouse} matName={matName} />);
} }
return ( return (
<> <Modal open={props.open} onClose={props.onClose}>
<label style={{ color: "white" }} htmlFor={smartSupplyCheckboxId}> <>
Enable Smart Supply <FormControlLabel
</label> control={<Switch checked={props.warehouse.smartSupplyEnabled} onChange={smartSupplyOnChange} />}
<input label={<Typography>Enable Smart Supply</Typography>}
type={"checkbox"} />
id={smartSupplyCheckboxId} <br />
onChange={smartSupplyOnChange} <Typography>Use materials already in the warehouse instead of buying new ones, if available:</Typography>
style={{ margin: "3px" }} {mats}
checked={props.warehouse.smartSupplyEnabled} </>
/> </Modal>
<br />
<p>Use materials already in the warehouse instead of buying new ones, if available:</p>
{mats}
</>
); );
} }

@ -0,0 +1,16 @@
import React from "react";
import { Modal } from "./Modal";
interface IProps {
open: boolean;
onClose: () => void;
children: JSX.Element[] | JSX.Element | React.ReactElement[] | React.ReactElement;
}
export function StaticModal(props: IProps): React.ReactElement {
return (
<Modal open={props.open} onClose={props.onClose}>
{props.children}
</Modal>
);
}