From 510fcedf90d9aac5cfee608888530b870a9eb1f1 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 30 Sep 2021 13:51:55 -0400 Subject: [PATCH] convert some corp to mui --- src/Corporation/Industry.ts | 3 - src/Corporation/Warehouse.ts | 8 - src/Corporation/ui/Industry.tsx | 13 +- src/Corporation/ui/IndustryOffice.tsx | 2 +- src/Corporation/ui/IndustryOverview.tsx | 502 ++++++++---------- src/Corporation/ui/IndustryWarehouse.tsx | 437 ++++++++------- src/Corporation/ui/MainPanel.tsx | 4 +- src/Corporation/ui/MakeProductModal.tsx | 193 +++++++ src/Corporation/ui/MakeProductPopup.tsx | 108 ---- src/Corporation/ui/ResearchPopup.tsx | 1 + ...rtSupplyPopup.tsx => SmartSupplyModal.tsx} | 60 +-- src/ui/React/StaticModal.tsx | 16 + 12 files changed, 691 insertions(+), 656 deletions(-) create mode 100644 src/Corporation/ui/MakeProductModal.tsx delete mode 100644 src/Corporation/ui/MakeProductPopup.tsx rename src/Corporation/ui/{SmartSupplyPopup.tsx => SmartSupplyModal.tsx} (55%) create mode 100644 src/ui/React/StaticModal.tsx diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts index 5a895b083..1bcd03041 100644 --- a/src/Corporation/Industry.ts +++ b/src/Corporation/Industry.ts @@ -385,9 +385,6 @@ export class Industry implements IIndustry { const prod = this.products[prodName]; if (prod === undefined) continue; 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) + "
"; - } } } } diff --git a/src/Corporation/Warehouse.ts b/src/Corporation/Warehouse.ts index 381ac9867..e0a83fa62 100644 --- a/src/Corporation/Warehouse.ts +++ b/src/Corporation/Warehouse.ts @@ -15,10 +15,6 @@ interface IConstructorParams { } 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 level = 1; @@ -90,14 +86,10 @@ export class Warehouse { // Re-calculate how much space is being used by this Warehouse updateMaterialSizeUsed(): void { this.sizeUsed = 0; - this.breakdown = ""; for (const matName in this.materials) { const mat = this.materials[matName]; if (MaterialSizes.hasOwnProperty(matName)) { this.sizeUsed += mat.qty * MaterialSizes[matName]; - if (mat.qty > 0) { - this.breakdown += matName + ": " + numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0") + "
"; - } } } if (this.sizeUsed > this.size) { diff --git a/src/Corporation/ui/Industry.tsx b/src/Corporation/ui/Industry.tsx index 42e3a244c..9a5f65eb1 100644 --- a/src/Corporation/ui/Industry.tsx +++ b/src/Corporation/ui/Industry.tsx @@ -9,6 +9,7 @@ import { Warehouse } from "../Warehouse"; import { OfficeSpace } from "../OfficeSpace"; import { use } from "../../ui/Context"; import { useCorporation, useDivision } from "./Context"; +import Box from "@mui/material/Box"; interface IProps { city: string; @@ -22,12 +23,12 @@ export function Industry(props: IProps): React.ReactElement { const corp = useCorporation(); const division = useDivision(); return ( -
-
+ + -
-
+ + -
-
+ + ); } diff --git a/src/Corporation/ui/IndustryOffice.tsx b/src/Corporation/ui/IndustryOffice.tsx index 2ab9624f3..e4ced1c07 100644 --- a/src/Corporation/ui/IndustryOffice.tsx +++ b/src/Corporation/ui/IndustryOffice.tsx @@ -432,7 +432,7 @@ export function IndustryOffice(props: IProps): React.ReactElement { Automatically hires an employee and gives him/her a random name}> diff --git a/src/Corporation/ui/IndustryOverview.tsx b/src/Corporation/ui/IndustryOverview.tsx index bd2526631..c9a512568 100644 --- a/src/Corporation/ui/IndustryOverview.tsx +++ b/src/Corporation/ui/IndustryOverview.tsx @@ -1,101 +1,74 @@ // React Component for displaying an Industry's overview information // (top-left panel in the Industry UI) -import React from "react"; +import React, { useState } from "react"; import { OfficeSpace } from "../OfficeSpace"; import { Industries } from "../IndustryData"; import { IndustryUpgrades } from "../IndustryUpgrades"; import { numeralWrapper } from "../../ui/numeralFormat"; -import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; -import { MakeProductPopup } from "./MakeProductPopup"; +import { MakeProductModal } from "./MakeProductModal"; import { ResearchPopup } from "./ResearchPopup"; import { createPopup } from "../../ui/React/createPopup"; 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 { useCorporation, useDivision } from "./Context"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Tooltip from "@mui/material/Tooltip"; 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 { - currentCity: string; - office: OfficeSpace; - rerender: () => void; -} - -export function IndustryOverview(props: IProps): React.ReactElement { +function MakeProductButton(): React.ReactElement { const corp = useCorporation(); const division = useDivision(); - function renderMakeProductButton(): React.ReactElement { - 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 += - "

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.

" + - "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 [makeOpen, setMakeOpen] = useState(false); - const hasMaxProducts = division.hasMaximumNumberProducts(); + const hasMaxProducts = division.hasMaximumNumberProducts(); - function openMakeProductPopup(): void { - const popupId = "cmpy-mgmt-create-product-popup"; - createPopup(popupId, MakeProductPopup, { - popupText: createProductPopupText, - division: division, - corp: corp, - popupId: popupId, - }); - } + function shouldFlash(): boolean { + return Object.keys(division.products).length === 0; + } - function shouldFlash(): boolean { - return Object.keys(division.products).length === 0; - } + let createProductButtonText = ""; + 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 ( + <> - - ); + 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 { - 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 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.

" + - "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.

" + - "Below are approximations for how effective each material is at boosting " + - "this industry's production multiplier (Bigger bars = more effective):

" + - `Hardware:    ${convertEffectFacToGraphic(division.hwFac)}
` + - `Robots:      ${convertEffectFacToGraphic(division.robFac)}
` + - `AI Cores:    ${convertEffectFacToGraphic(division.aiFac)}
` + - `Real Estate: ${convertEffectFacToGraphic(division.reFac)}`, - ); - } - - function openResearchPopup(): void { - const popupId = "corporation-research-popup-box"; - createPopup(popupId, ResearchPopup, { - industry: division, - popupId: popupId, - }); - } - - return ( -
- - Industry: {division.type} (Corp Funds: ) -

- Awareness: {numeralWrapper.format(division.awareness, "0.000")}
- Popularity: {numeralWrapper.format(division.popularity, "0.000")}
- {advertisingInfo !== false && ( -

- Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")} - - Total multiplier for this industrys sales due to its awareness and popularity -
- 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")} -
-

- )} - {advertisingInfo} -
-
-
- - - - - - - - - - - - - - - -
-

Revenue:

-
-

- / s -

-
-

Expenses:

-
-

- / s -

-
-

Profit:

-
-

- / s -

-
-
-

- Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")} - - Production gain from owning production-boosting materials such as hardware, Robots, AI Cores, and Real - Estate - -

-
- ? -
-

-

- Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")} - - Scientific Research increases the quality of the materials and products that you produce. - -

- -
- ); + function convertEffectFacToGraphic(fac: number): string { + return createProgressBarText({ + progress: fac, + totalTicks: 20, + }); } - function renderUpgrades(): React.ReactElement[] { - const upgrades = []; - for (const index in IndustryUpgrades) { - const upgrade = IndustryUpgrades[index]; + function openResearchPopup(): void { + const popupId = "corporation-research-popup-box"; + createPopup(popupId, ResearchPopup, { + industry: division, + popupId: popupId, + }); + } - // AutoBrew research disables the Coffee upgrade - if (division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") { - continue; - } - - 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; - } - - 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: ( + return ( +
+ + Industry: {division.type} (Corp Funds: ) + +
+ + {advertisingInfo !== false && ( + - {upgrade[4]} - + Total multiplier for this industrys sales due to its awareness and popularity + - ), - tooltip: upgrade[5], - }), - ); + } + > + Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")} + + )} +
+ ], + ["Expenses:", ], + ["Profit:", ], + ]} + /> +
+ + + Production gain from owning production-boosting materials such as hardware, Robots, AI Cores, and Real + Estate. + + } + > + Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")} + + setHelpOpen(true)}> + + + setHelpOpen(false)}> + + 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. +
+
+ 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. +
+
+ Below are approximations for how effective each material is at boosting this industry's production + multiplier (Bigger bars = more effective): +
+
+ Hardware:    {convertEffectFacToGraphic(division.hwFac)} +
+ Robots:      {convertEffectFacToGraphic(division.robFac)} +
+ AI Cores:    {convertEffectFacToGraphic(division.aiFac)} +
+ Real Estate: {convertEffectFacToGraphic(division.reFac)} +
+
+
+ + + + Scientific Research increases the quality of the materials and products that you produce. + + } + > + Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")} + + + +
+ ); +} + +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 { - key: string; - onClick: () => void; - text: JSX.Element; - tooltip: string; - } + 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(); + } - function renderUpgrade(props: IRenderUpgradeProps): React.ReactElement { - return ( -
- {props.text} - {props.tooltip != null && {props.tooltip}} -
+ upgrades.push( + + + , ); } - const makeProductButton = renderMakeProductButton(); + return <>{upgrades}; +} + +interface IProps { + currentCity: string; + office: OfficeSpace; + rerender: () => void; +} + +export function IndustryOverview(props: IProps): React.ReactElement { + const division = useDivision(); return ( - {renderText()} +
Purchases & Upgrades - {renderUpgrades()}
- {division.makesProducts && makeProductButton} +
+ {division.makesProducts && }
); } diff --git a/src/Corporation/ui/IndustryWarehouse.tsx b/src/Corporation/ui/IndustryWarehouse.tsx index fdeabb08c..1853390c6 100644 --- a/src/Corporation/ui/IndustryWarehouse.tsx +++ b/src/Corporation/ui/IndustryWarehouse.tsx @@ -1,6 +1,6 @@ // React Component for displaying an Industry's warehouse information // (right-side panel in the Industry UI) -import React from "react"; +import React, { useState } from "react"; import { CorporationConstants } from "../data/Constants"; import { OfficeSpace } from "../OfficeSpace"; @@ -15,7 +15,8 @@ import { SellMaterialPopup } from "./SellMaterialPopup"; import { SellProductPopup } from "./SellProductPopup"; import { PurchaseMaterialPopup } from "./PurchaseMaterialPopup"; import { ProductMarketTaPopup } from "./ProductMarketTaPopup"; -import { SmartSupplyPopup } from "./SmartSupplyPopup"; +import { SmartSupplyModal } from "./SmartSupplyModal"; +import { MaterialSizes } from "../MaterialSizes"; import { numeralWrapper } from "../../ui/numeralFormat"; import { createPopup } from "../../ui/React/createPopup"; @@ -29,6 +30,13 @@ import { MoneyCost } from "./MoneyCost"; import { isRelevantMaterial } from "./Helpers"; import { IndustryProductEquation } from "./IndustryProductEquation"; 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 { corp: ICorporation; @@ -41,8 +49,8 @@ interface IProductProps { // Creates the UI for a single Product type function ProductComponent(props: IProductProps): React.ReactElement { - const corp = props.corp; - const division = props.division; + const corp = useCorporation(); + const division = useDivision(); const city = props.city; const product = props.product; @@ -136,7 +144,7 @@ function ProductComponent(props: IProductProps): React.ReactElement { rerender: props.rerender, product: product, industry: division, - corp: props.corp, + corp: corp, popupId: popupId, player: props.player, }); @@ -164,21 +172,11 @@ function ProductComponent(props: IProductProps): React.ReactElement { {hasUpgradeDashboard && (
- +
- - - {division.hasResearch("Market-TA.I") && ( - - )} + + + {division.hasResearch("Market-TA.I") && }
)} @@ -227,29 +225,17 @@ function ProductComponent(props: IProductProps): React.ReactElement {

- +
- - - {division.hasResearch("Market-TA.I") && ( - - )} + + + {division.hasResearch("Market-TA.I") && }
); } interface IMaterialProps { - corp: ICorporation; - division: IIndustry; warehouse: Warehouse; city: string; mat: Material; @@ -258,8 +244,8 @@ interface IMaterialProps { // Creates the UI for a single Material type function MaterialComponent(props: IMaterialProps): React.ReactElement { - const corp = props.corp; - const division = props.division; + const corp = useCorporation(); + const division = useDivision(); const warehouse = props.warehouse; const city = props.city; const mat = props.mat; @@ -291,7 +277,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement { mat: mat, industry: division, warehouse: warehouse, - corp: props.corp, + corp: corp, popupId: popupId, }); } @@ -300,7 +286,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement { const popupId = "cmpy-mgmt-export-popup"; createPopup(popupId, ExportPopup, { mat: mat, - corp: props.corp, + corp: corp, popupId: popupId, }); } @@ -358,7 +344,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement { const popupId = "cmpy-mgmt-material-sell-popup"; createPopup(popupId, SellMaterialPopup, { mat: mat, - corp: props.corp, + corp: corp, popupId: popupId, }); } @@ -368,13 +354,13 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement { createPopup(popupId, MaterialMarketTaPopup, { mat: mat, industry: division, - corp: props.corp, + corp: corp, popupId: popupId, }); } 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 ( @@ -409,33 +395,25 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
- + - {corp.unlockUpgrades[0] === 1 && ( - - )} + {corp.unlockUpgrades[0] === 1 && }
- + - {division.hasResearch("Market-TA.I") && ( - - )} + {division.hasResearch("Market-TA.I") && }
); @@ -450,177 +428,188 @@ interface IProps { rerender: () => void; } -export function IndustryWarehouse(props: IProps): React.ReactElement { - function renderWarehouseUI(): React.ReactElement { - if (props.warehouse === 0) return <>; - // General Storage information at the top - const sizeUsageStyle = { - color: props.warehouse.sizeUsed >= props.warehouse.size ? "red" : "white", - margin: "5px", - }; +function WarehouseRoot(props: IProps): React.ReactElement { + const corp = useCorporation(); + const division = useDivision(); + const [smartSupplyOpen, setSmartSupplyOpen] = useState(false); + if (props.warehouse === 0) return <>; - // Upgrade Warehouse size button - const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, props.warehouse.level + 1); - const canAffordUpgrade = props.corp.funds.gt(sizeUpgradeCost); - const upgradeWarehouseClass = canAffordUpgrade ? "std-button" : "a-link-button-inactive"; - function upgradeWarehouseOnClick(): void { - if (props.division === null) return; - if (props.warehouse === 0) return; - ++props.warehouse.level; - props.warehouse.updateSize(props.corp, props.division); - props.corp.funds = props.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( -
-

{text}

-
, - ); - } - } - - // 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( - , - ); - } - } - } - - // 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( - , - ); - } - } - } - - return ( -
-

- Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "} - {numeralWrapper.formatBigNumber(props.warehouse.size)} - -

- - - -

This industry uses the following equation for it's production:

-
-
- -
-
-

- To get started with production, purchase your required materials or import them from another of your company's - divisions. -

-
- -

{stateText}

- - {props.corp.unlockUpgrades[1] && ( - <> - - - )} - - {mats} - - {products} -
- ); - } - - function purchaseWarehouse(division: IIndustry, city: string): void { - PurchaseWarehouse(props.corp, division, city); + // Upgrade Warehouse size button + const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, props.warehouse.level + 1); + const canAffordUpgrade = corp.funds.gt(sizeUpgradeCost); + function upgradeWarehouseOnClick(): void { + if (division === null) return; + if (props.warehouse === 0) return; + if (!canAffordUpgrade) return; + ++props.warehouse.level; + props.warehouse.updateSize(corp, division); + corp.funds = corp.funds.minus(sizeUpgradeCost); props.rerender(); } - if (props.warehouse instanceof Warehouse) { - return renderWarehouseUI(); - } else { - return ( -
- -
+ const ratioLines = []; + for (const matName in division.reqMats) { + if (division.reqMats.hasOwnProperty(matName)) { + const text = [" *", division.reqMats[matName], matName].join(" "); + ratioLines.push( +
+

{text}

+
, + ); + } + } + + // Current State: + 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( + , ); } + + // 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( + , + ); + } + } + + 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")} +
+ + ); + } + + return ( +
+ + + = props.warehouse.size ? "error" : "primary"}> + Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "} + {numeralWrapper.formatBigNumber(props.warehouse.size)} + + + + + + + This industry uses the following equation for it's production: +
+ + + +
+ + To get started with production, purchase your required materials or import them from another of your company's + divisions. + +
+ + {stateText} + + {corp.unlockUpgrades[1] && ( + <> + + setSmartSupplyOpen(false)} + warehouse={props.warehouse} + /> + + )} + + {mats} + + {products} +
+ ); +} + +export function IndustryWarehouse(props: IProps): React.ReactElement { + if (props.warehouse instanceof Warehouse) { + return ; + } else { + return ; + } +} + +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 ( + + + + ); } diff --git a/src/Corporation/ui/MainPanel.tsx b/src/Corporation/ui/MainPanel.tsx index a1f0aac20..de67e222a 100644 --- a/src/Corporation/ui/MainPanel.tsx +++ b/src/Corporation/ui/MainPanel.tsx @@ -25,9 +25,7 @@ export function MainPanel(props: IProps): React.ReactElement { if (division === undefined) throw new Error("Cannot find division"); return ( -
- -
+
); } diff --git a/src/Corporation/ui/MakeProductModal.tsx b/src/Corporation/ui/MakeProductModal.tsx new file mode 100644 index 000000000..e040bfdfd --- /dev/null +++ b/src/Corporation/ui/MakeProductModal.tsx @@ -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(null); + const [marketing, setMarketing] = useState(null); + if (division.hasMaximumNumberProducts()) return <>; + + let createProductPopupText = <>; + switch (division.type) { + case Industries.Food: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Build and manage a new restaurant! + + ); + break; + case Industries.Tobacco: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Create a new tobacco product! + + ); + break; + case Industries.Pharmaceutical: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Design and develop a new pharmaceutical drug! + + ); + break; + case Industries.Computer: + case "Computer": + createProductPopupText = ( + <> + {createProductPopupText} +
+ Design and manufacture a new computer hardware product! + + ); + break; + case Industries.Robotics: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Design and create a new robot or robotic system! + + ); + break; + case Industries.Software: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Develop a new piece of software! + + ); + break; + case Industries.Healthcare: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Build and manage a new hospital! + + ); + break; + case Industries.RealEstate: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Develop a new piece of real estate property! + + ); + break; + default: + createProductPopupText = ( + <> + {createProductPopupText} +
+ Create a new product! + + ); + return <>; + } + createProductPopupText = ( + <> + {createProductPopupText} +
+
+ 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. +
+
+ 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): void { + setCity(event.target.value); + } + + function onProductNameChange(event: React.ChangeEvent): void { + setName(event.target.value); + } + + function onDesignChange(event: React.ChangeEvent): void { + if (event.target.value === "") setDesign(null); + else setDesign(parseFloat(event.target.value)); + } + + function onMarketingChange(event: React.ChangeEvent): void { + if (event.target.value === "") setMarketing(null); + else setMarketing(parseFloat(event.target.value)); + } + + function onKeyDown(event: React.KeyboardEvent): void { + if (event.keyCode === 13) makeProduct(); + } + + return ( + + {createProductPopupText} + + +
+ + + +
+ ); +} diff --git a/src/Corporation/ui/MakeProductPopup.tsx b/src/Corporation/ui/MakeProductPopup.tsx deleted file mode 100644 index 439e9a078..000000000 --- a/src/Corporation/ui/MakeProductPopup.tsx +++ /dev/null @@ -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(null); - const [marketing, setMarketing] = useState(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): void { - setCity(event.target.value); - } - - function onProductNameChange(event: React.ChangeEvent): void { - setName(event.target.value); - } - - function onDesignChange(event: React.ChangeEvent): void { - if (event.target.value === "") setDesign(null); - else setDesign(parseFloat(event.target.value)); - } - - function onMarketingChange(event: React.ChangeEvent): void { - if (event.target.value === "") setMarketing(null); - else setMarketing(parseFloat(event.target.value)); - } - - function onKeyDown(event: React.KeyboardEvent): void { - if (event.keyCode === 13) makeProduct(); - } - - return ( - <> -

- - -
- - - - - ); -} diff --git a/src/Corporation/ui/ResearchPopup.tsx b/src/Corporation/ui/ResearchPopup.tsx index 294d24a2b..2f3ecaf66 100644 --- a/src/Corporation/ui/ResearchPopup.tsx +++ b/src/Corporation/ui/ResearchPopup.tsx @@ -6,6 +6,7 @@ import { CorporationConstants } from "../data/Constants"; import { Treant } from "treant-js"; import { IIndustry } from "../IIndustry"; import { Research } from "../Actions"; +import Typography from "@mui/material/Typography"; interface IProps { industry: IIndustry; diff --git a/src/Corporation/ui/SmartSupplyPopup.tsx b/src/Corporation/ui/SmartSupplyModal.tsx similarity index 55% rename from src/Corporation/ui/SmartSupplyPopup.tsx rename to src/Corporation/ui/SmartSupplyModal.tsx index 50554c030..d853ec2f7 100644 --- a/src/Corporation/ui/SmartSupplyPopup.tsx +++ b/src/Corporation/ui/SmartSupplyModal.tsx @@ -1,12 +1,14 @@ import React, { useState } from "react"; import { Warehouse } from "../Warehouse"; -import { ICorporation } from "../ICorporation"; -import { IIndustry } from "../IIndustry"; import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../Actions"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import { Material } from "../Material"; 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 { matName: string; @@ -26,33 +28,31 @@ function Leftover(props: ILeftoverProps): React.ReactElement { setChecked(event.target.checked); } - const matNameId = `${props.matName}-use-leftovers`; return ( -

- - + <> + } + label={{props.warehouse.materials[props.matName].name}} + />
-
+ ); } interface IProps { - division: IIndustry; + open: boolean; + onClose: () => void; 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]; function rerender(): void { setRerender((old) => !old); } + // Smart Supply Checkbox - const smartSupplyCheckboxId = "cmpy-mgmt-smart-supply-checkbox"; function smartSupplyOnChange(e: React.ChangeEvent): void { SetSmartSupply(props.warehouse, e.target.checked); rerender(); @@ -62,25 +62,21 @@ export function SmartSupplyPopup(props: IProps): React.ReactElement { const mats = []; for (const matName in props.warehouse.materials) { 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(); } return ( - <> - - -
-

Use materials already in the warehouse instead of buying new ones, if available:

- {mats} - + + <> + } + label={Enable Smart Supply} + /> +
+ Use materials already in the warehouse instead of buying new ones, if available: + {mats} + +
); } diff --git a/src/ui/React/StaticModal.tsx b/src/ui/React/StaticModal.tsx new file mode 100644 index 000000000..d0277a510 --- /dev/null +++ b/src/ui/React/StaticModal.tsx @@ -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 ( + + {props.children} + + ); +}