diff --git a/src/Corporation/ui/Industry.jsx b/src/Corporation/ui/Industry.jsx index 6d290d467..4b5988c1d 100644 --- a/src/Corporation/ui/Industry.jsx +++ b/src/Corporation/ui/Industry.jsx @@ -20,7 +20,12 @@ export class Industry extends BaseReactComponent { return (
- +
diff --git a/src/Corporation/ui/IndustryOffice.jsx b/src/Corporation/ui/IndustryOffice.tsx similarity index 60% rename from src/Corporation/ui/IndustryOffice.jsx rename to src/Corporation/ui/IndustryOffice.tsx index 8f1dfa540..93758e70f 100644 --- a/src/Corporation/ui/IndustryOffice.jsx +++ b/src/Corporation/ui/IndustryOffice.tsx @@ -1,120 +1,136 @@ // React Component for displaying an Industry's OfficeSpace information // (bottom-left panel in the Industry UI) -import React from "react"; -import { BaseReactComponent } from "./BaseReactComponent"; +import React, { useState } from "react"; import { OfficeSpace } from "../OfficeSpace"; +import { Employee } from "../Employee"; import { EmployeePositions } from "../EmployeePositions"; import { numeralWrapper } from "../../ui/numeralFormat"; import { getSelectText } from "../../../utils/uiHelpers/getSelectData"; -export class IndustryOffice extends BaseReactComponent { - constructor(props) { - super(props); +interface IProps { + routing: any; + eventHandler: any; + corp: any; + currentCity: string; +} - this.state = { - city: "", - division: "", - employeeManualAssignMode: false, - employee: null, // Reference to employee being referenced if in Manual Mode - numEmployees: 0, - numOperations: 0, - numEngineers: 0, - numBusiness: 0, - numManagement: 0, - numResearch: 0, - numUnassigned: 0, - numTraining: 0, - } +export function IndustryOffice(props: IProps): React.ReactElement { + const [employeeManualAssignMode, setEmployeeManualAssignMode] = useState(false); + const [city, setCity] = useState(""); + const [divisionName, setDivisionName] = useState(""); + const [employee, setEmployee] = useState(null); + const [numEmployees, setNumEmployees] = useState(0); + const [numOperations, setNumOperations] = useState(0); + const [numEngineers, setNumEngineers] = useState(0); + const [numBusiness, setNumBusiness] = useState(0); + const [numManagement, setNumManagement] = useState(0); + const [numResearch, setNumResearch] = useState(0); + const [numUnassigned, setNumUnassigned] = useState(0); + const [numTraining, setNumTraining] = useState(0); - this.updateEmployeeCount(); // This function validates division and office refs + function resetEmployeeCount() { + setNumEmployees(0); + setNumOperations(0); + setNumEngineers(0); + setNumBusiness(0); + setNumManagement(0); + setNumResearch(0); + setNumUnassigned(0); + setNumTraining(0); } - resetEmployeeCount() { - this.state.numEmployees = 0; - this.state.numOperations = 0; - this.state.numEngineers = 0; - this.state.numBusiness = 0; - this.state.numManagement = 0; - this.state.numResearch = 0; - this.state.numUnassigned = 0; - this.state.numTraining = 0; - } - - updateEmployeeCount() { - const division = this.routing().currentDivision; + function updateEmployeeCount() { + const division = props.routing.currentDivision; if (division == null) { throw new Error(`Routing does not hold reference to the current Industry`); } - const office = division.offices[this.props.currentCity]; + const office = division.offices[props.currentCity]; if (!(office instanceof OfficeSpace)) { - throw new Error(`Current City (${this.props.currentCity}) for UI does not have an OfficeSpace object`); + throw new Error(`Current City (${props.currentCity}) for UI does not have an OfficeSpace object`); } // If we're in a new city, we have to reset the state - if (division.name !== this.state.division || this.props.currentCity !== this.state.city) { - this.resetEmployeeCount(); - this.state.division = division.name; - this.state.city = this.props.currentCity; + if (division.name !== divisionName || props.currentCity !== city) { + resetEmployeeCount(); + setDivisionName(division.name); + setCity(props.currentCity); } - // Calculate how many NEW emplyoees we need to account for + // Calculate how many NEW employees we need to account for const currentNumEmployees = office.employees.length; + let newOperations = numOperations; + let newEngineers = numEngineers; + let newBusiness = numBusiness; + let newManagement = numManagement; + let newResearch = numResearch; + let newUnassigned = numUnassigned; + let newTraining = numTraining; + // Record the number of employees in each position, for NEW employees only - for (let i = this.state.numEmployees; i < office.employees.length; ++i) { + for (let i = numEmployees; i < office.employees.length; ++i) { switch (office.employees[i].pos) { case EmployeePositions.Operations: - ++this.state.numOperations; + newOperations++; break; case EmployeePositions.Engineer: - ++this.state.numEngineers; + newEngineers++; break; case EmployeePositions.Business: - ++this.state.numBusiness; + newBusiness++; break; case EmployeePositions.Management: - ++this.state.numManagement; + newManagement++; break; case EmployeePositions.RandD: - ++this.state.numResearch; + newResearch++; break; case EmployeePositions.Unassigned: - ++this.state.numUnassigned; + newUnassigned++; break; case EmployeePositions.Training: - ++this.state.numTraining; + newTraining++; break; default: console.error("Unrecognized employee position: " + office.employees[i].pos); break; } } + if(newOperations !== numOperations) setNumOperations(newOperations); + if(newEngineers !== numEngineers) setNumEngineers(newEngineers); + if(newBusiness !== numBusiness) setNumBusiness(newBusiness); + if(newManagement !== numManagement) setNumManagement(newManagement); + if(newResearch !== numResearch) setNumResearch(newResearch); + if(newUnassigned !== numUnassigned) setNumUnassigned(newUnassigned); + if(newTraining !== numTraining) setNumTraining(newTraining); - this.state.numEmployees = currentNumEmployees; + if(currentNumEmployees !== numEmployees) setNumEmployees(currentNumEmployees); } - // Renders the "Employee Management" section of the Office UI - renderEmployeeManagement() { - this.updateEmployeeCount(); + updateEmployeeCount(); - if (this.state.employeeManualAssignMode) { - return this.renderManualEmployeeManagement(); + // Renders the "Employee Management" section of the Office UI + function renderEmployeeManagement() { + updateEmployeeCount(); + + if (employeeManualAssignMode) { + return renderManualEmployeeManagement(); } else { - return this.renderAutomaticEmployeeManagement(); + return renderAutomaticEmployeeManagement(); } } - renderAutomaticEmployeeManagement() { - const division = this.routing().currentDivision; // Validated in constructor - const office = division.offices[this.props.currentCity]; // Validated in constructor - const vechain = (this.corp().unlockUpgrades[4] === 1); // Has Vechain upgrade + function renderAutomaticEmployeeManagement() { + const division = props.routing.currentDivision; // Validated in constructor + const office = division.offices[props.currentCity]; // Validated in constructor + const vechain = (props.corp.unlockUpgrades[4] === 1); // Has Vechain upgrade const switchModeOnClick = () => { - this.state.employeeManualAssignMode = true; - this.corp().rerender(); + setEmployeeManualAssignMode(true); + props.corp.rerender(); } // Calculate average morale, happiness, and energy. Also salary @@ -135,87 +151,87 @@ export class IndustryOffice extends BaseReactComponent { } // Helper functions for (re-)assigning employees to different positions - const assignEmployee = (to) => { - if (this.state.numUnassigned <= 0) { + function assignEmployee(to: string) { + if (numUnassigned <= 0) { console.warn("Cannot assign employee. No unassigned employees available"); return; } switch (to) { case EmployeePositions.Operations: - ++this.state.numOperations; + setNumOperations(n => n+1); break; case EmployeePositions.Engineer: - ++this.state.numEngineers; + setNumEngineers(n => n+1); break; case EmployeePositions.Business: - ++this.state.numBusiness; + setNumBusiness(n => n+1); break; case EmployeePositions.Management: - ++this.state.numManagement; + setNumManagement(n => n+1); break; case EmployeePositions.RandD: - ++this.state.numResearch; + setNumResearch(n => n+1); break; case EmployeePositions.Unassigned: - ++this.state.numUnassigned; + setNumUnassigned(n => n+1); break; case EmployeePositions.Training: - ++this.state.numTraining; + setNumTraining(n => n+1); break; default: console.error("Unrecognized employee position: " + to); break; } - --this.state.numUnassigned; + setNumUnassigned(n => n-1); office.assignEmployeeToJob(to); - office.calculateEmployeeProductivity({ corporation: this.corp(), industry:division }); - this.corp().rerender(); + office.calculateEmployeeProductivity({ corporation: props.corp, industry:division }); + props.corp.rerender(); } - const unassignEmployee = (from) => { - function logWarning(pos) { + function unassignEmployee(from: string) { + function logWarning(pos: string) { console.warn(`Cannot unassign from ${pos} because there is nobody assigned to that position`); } switch (from) { case EmployeePositions.Operations: - if (this.state.numOperations <= 0) { return logWarning(EmployeePositions.Operations); } - --this.state.numOperations; + if (numOperations <= 0) { return logWarning(EmployeePositions.Operations); } + setNumOperations(n => n-1); break; case EmployeePositions.Engineer: - if (this.state.numEngineers <= 0) { return logWarning(EmployeePositions.Operations); } - --this.state.numEngineers; + if (numEngineers <= 0) { return logWarning(EmployeePositions.Operations); } + setNumEngineers(n => n-1); break; case EmployeePositions.Business: - if (this.state.numBusiness <= 0) { return logWarning(EmployeePositions.Operations); } - --this.state.numBusiness; + if (numBusiness <= 0) { return logWarning(EmployeePositions.Operations); } + setNumBusiness(n => n-1); break; case EmployeePositions.Management: - if (this.state.numManagement <= 0) { return logWarning(EmployeePositions.Operations); } - --this.state.numManagement; + if (numManagement <= 0) { return logWarning(EmployeePositions.Operations); } + setNumManagement(n => n-1); break; case EmployeePositions.RandD: - if (this.state.numResearch <= 0) { return logWarning(EmployeePositions.Operations); } - --this.state.numResearch; + if (numResearch <= 0) { return logWarning(EmployeePositions.Operations); } + setNumResearch(n => n-1); break; case EmployeePositions.Unassigned: console.warn(`Tried to unassign from the Unassigned position`); break; case EmployeePositions.Training: - if (this.state.numTraining <= 0) { return logWarning(EmployeePositions.Operations); } - --this.state.numTraining; + if (numTraining <= 0) { return logWarning(EmployeePositions.Operations); } + setNumTraining(n => n-1); break; default: console.error("Unrecognized employee position: " + from); break; } - ++this.state.numUnassigned; + setNumUnassigned(n => n+1); office.unassignEmployeeFromJob(from); - office.calculateEmployeeProductivity({ corporation: this.corp(), industry:division }); - this.corp().rerender(); + office.calculateEmployeeProductivity({ corporation: props.corp, industry:division }); + props.corp.rerender(); } const positionHeaderStyle = { @@ -223,67 +239,67 @@ export class IndustryOffice extends BaseReactComponent { margin: "5px 0px 5px 0px", width: "50%", } - const assignButtonClass = this.state.numUnassigned > 0 ? "std-button" : "a-link-button-inactive"; + const assignButtonClass = numUnassigned > 0 ? "std-button" : "a-link-button-inactive"; const operationAssignButtonOnClick = () => { assignEmployee(EmployeePositions.Operations); - this.corp().rerender(); + props.corp.rerender(); } const operationUnassignButtonOnClick = () => { unassignEmployee(EmployeePositions.Operations); - this.corp().rerender(); + props.corp.rerender(); } - const operationUnassignButtonClass = this.state.numOperations > 0 ? "std-button" : "a-link-button-inactive"; + const operationUnassignButtonClass = numOperations > 0 ? "std-button" : "a-link-button-inactive"; const engineerAssignButtonOnClick = () => { assignEmployee(EmployeePositions.Engineer); - this.corp().rerender(); + props.corp.rerender(); } const engineerUnassignButtonOnClick = () => { unassignEmployee(EmployeePositions.Engineer); - this.corp().rerender(); + props.corp.rerender(); } - const engineerUnassignButtonClass = this.state.numEngineers > 0 ? "std-button" : "a-link-button-inactive"; + const engineerUnassignButtonClass = numEngineers > 0 ? "std-button" : "a-link-button-inactive"; const businessAssignButtonOnClick = () => { assignEmployee(EmployeePositions.Business); - this.corp().rerender(); + props.corp.rerender(); } const businessUnassignButtonOnClick = () => { unassignEmployee(EmployeePositions.Business); - this.corp().rerender(); + props.corp.rerender(); } - const businessUnassignButtonClass = this.state.numBusiness > 0 ? "std-button" : "a-link-button-inactive"; + const businessUnassignButtonClass = numBusiness > 0 ? "std-button" : "a-link-button-inactive"; const managementAssignButtonOnClick = () => { assignEmployee(EmployeePositions.Management); - this.corp().rerender(); + props.corp.rerender(); } const managementUnassignButtonOnClick = () => { unassignEmployee(EmployeePositions.Management); - this.corp().rerender(); + props.corp.rerender(); } - const managementUnassignButtonClass = this.state.numManagement > 0 ? "std-button" : "a-link-button-inactive"; + const managementUnassignButtonClass = numManagement > 0 ? "std-button" : "a-link-button-inactive"; const rndAssignButtonOnClick = () => { assignEmployee(EmployeePositions.RandD); - this.corp().rerender(); + props.corp.rerender(); } const rndUnassignButtonOnClick = () => { unassignEmployee(EmployeePositions.RandD); - this.corp().rerender(); + props.corp.rerender(); } - const rndUnassignButtonClass = this.state.numResearch > 0 ? "std-button" : "a-link-button-inactive"; + const rndUnassignButtonClass = numResearch > 0 ? "std-button" : "a-link-button-inactive"; const trainingAssignButtonOnClick = () => { assignEmployee(EmployeePositions.Training); - this.corp().rerender(); + props.corp.rerender(); } const trainingUnassignButtonOnClick = () => { unassignEmployee(EmployeePositions.Training); - this.corp().rerender(); + props.corp.rerender(); } - const trainingUnassignButtonClass = this.state.numTraining > 0 ? "std-button" : "a-link-button-inactive"; + const trainingUnassignButtonClass = numTraining > 0 ? "std-button" : "a-link-button-inactive"; return (
@@ -295,7 +311,7 @@ export class IndustryOffice extends BaseReactComponent { -

Unassigned Employees: {this.state.numUnassigned}

+

Unassigned Employees: {numUnassigned}


Avg Employee Morale: {numeralWrapper.format(avgMorale, "0.000")}

@@ -344,7 +360,7 @@ export class IndustryOffice extends BaseReactComponent { }

- {EmployeePositions.Operations} ({this.state.numOperations}) + {EmployeePositions.Operations} ({numOperations}) Manages supply chain operations. Improves the amount of Materials and Products you produce. @@ -354,7 +370,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Engineer} ({this.state.numEngineers}) + {EmployeePositions.Engineer} ({numEngineers}) Develops and maintains products and production systems. Increases the quality of everything you produce. Also increases the amount you produce (not as much @@ -366,7 +382,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Business} ({this.state.numBusiness}) + {EmployeePositions.Business} ({numBusiness}) Handles sales and finances. Improves the amount of Materials and Products you can sell. @@ -376,7 +392,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Management} ({this.state.numManagement}) + {EmployeePositions.Management} ({numManagement}) Leads and oversees employees and office operations. Improves the effectiveness of Engineer and Operations employees @@ -387,7 +403,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.RandD} ({this.state.numResearch}) + {EmployeePositions.RandD} ({numResearch}) Research new innovative ways to improve the company. Generates Scientific Research @@ -397,7 +413,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Training} ({this.state.numTraining}) + {EmployeePositions.Training} ({numTraining}) Set employee to training, which will increase some of their stats. Employees in training do not affect any company operations. @@ -408,14 +424,14 @@ export class IndustryOffice extends BaseReactComponent { ) } - renderManualEmployeeManagement() { - const corp = this.corp(); - const division = this.routing().currentDivision; // Validated in constructor - const office = division.offices[this.props.currentCity]; // Validated in constructor + function renderManualEmployeeManagement() { + const corp = props.corp; + const division = props.routing.currentDivision; // Validated in constructor + const office = division.offices[props.currentCity]; // Validated in constructor const switchModeOnClick = () => { - this.state.employeeManualAssignMode = false; - this.corp().rerender(); + setEmployeeManualAssignMode(false); + props.corp.rerender(); } const employeeInfoDivStyle = { @@ -430,11 +446,11 @@ export class IndustryOffice extends BaseReactComponent { employees.push() } - const employeeSelectorOnChange = (e) => { + const employeeSelectorOnChange = (e: React.ChangeEvent) => { const name = getSelectText(e.target); for (let i = 0; i < office.employees.length; ++i) { if (name === office.employees[i].name) { - this.state.employee = office.employees[i]; + setEmployee(office.employees[i]); break; } } @@ -443,8 +459,8 @@ export class IndustryOffice extends BaseReactComponent { } // Employee Positions Selector - const emp = this.state.employee; - let employeePositionSelectorInitialValue = null; + const emp = employee; + let employeePositionSelectorInitialValue = ""; const employeePositions = []; const positionNames = Object.values(EmployeePositions); for (let i = 0; i < positionNames.length; ++i) { @@ -454,10 +470,11 @@ export class IndustryOffice extends BaseReactComponent { } } - const employeePositionSelectorOnChange = (e) => { + function employeePositionSelectorOnChange(e: React.ChangeEvent) { + if(employee === null) return; const pos = getSelectText(e.target); - this.state.employee.pos = pos; - this.resetEmployeeCount(); + employee.pos = pos; + resetEmployeeCount(); corp.rerender(); } @@ -486,29 +503,29 @@ export class IndustryOffice extends BaseReactComponent { {employees} { - this.state.employee != null && + employee != null &&

- Morale: {numeralWrapper.format(this.state.employee.mor, nf)} + Morale: {numeralWrapper.format(employee.mor, nf)}
- Happiness: {numeralWrapper.format(this.state.employee.hap, nf)} + Happiness: {numeralWrapper.format(employee.hap, nf)}
- Energy: {numeralWrapper.format(this.state.employee.ene, nf)} + Energy: {numeralWrapper.format(employee.ene, nf)}
Intelligence: {numeralWrapper.format(effInt, nf)}
Charisma: {numeralWrapper.format(effCha, nf)}
- Experience: {numeralWrapper.format(this.state.employee.exp, nf)} + Experience: {numeralWrapper.format(employee.exp, nf)}
Creativity: {numeralWrapper.format(effCre, nf)}
Efficiency: {numeralWrapper.format(effEff, nf)}
- Salary: {numeralWrapper.formatMoney(this.state.employee.sal)} + Salary: {numeralWrapper.formatMoney(employee.sal)}

} { - this.state.employee != null && + employee != null && @@ -518,89 +535,87 @@ export class IndustryOffice extends BaseReactComponent { ) } - render() { - const corp = this.corp(); - const division = this.routing().currentDivision; // Validated in constructor - const office = division.offices[this.props.currentCity]; // Validated in constructor + const corp = props.corp; + const division = props.routing.currentDivision; // Validated in constructor + const office = division.offices[props.currentCity]; // Validated in constructor - const buttonStyle = { - fontSize: "13px", - } - - // Hire Employee button - let hireEmployeeButtonClass = "tooltip"; - if (office.atCapacity()) { - hireEmployeeButtonClass += " a-link-button-inactive"; - } else { - hireEmployeeButtonClass += " std-button"; - if (office.employees.length === 0) { - hireEmployeeButtonClass += " flashing-button"; - } - } - - const hireEmployeeButtonOnClick = () => { - office.findEmployees({ corporation: corp, industry: division }); - } - - // Autohire employee button - let autohireEmployeeButtonClass = "tooltip"; - if (office.atCapacity()) { - autohireEmployeeButtonClass += " a-link-button-inactive"; - } else { - autohireEmployeeButtonClass += " std-button"; - } - const autohireEmployeeButtonOnClick = () => { - if (office.atCapacity()) { return; } - office.hireRandomEmployee(); - this.corp().rerender(); - } - - // Upgrade Office Size Button - const upgradeOfficeSizeOnClick = this.eventHandler().createUpgradeOfficeSizePopup.bind(this.eventHandler(), office); - - // Throw Office Party - const throwOfficePartyOnClick = this.eventHandler().createThrowOfficePartyPopup.bind(this.eventHandler(), office); - - return ( -
-

Office Space

-

Size: {office.employees.length} / {office.size} employees

- - -
- - { - !division.hasResearch("AutoPartyManager") && - - } -
- - {this.renderEmployeeManagement()} -
- ) + const buttonStyle = { + fontSize: "13px", } + + // Hire Employee button + let hireEmployeeButtonClass = "tooltip"; + if (office.atCapacity()) { + hireEmployeeButtonClass += " a-link-button-inactive"; + } else { + hireEmployeeButtonClass += " std-button"; + if (office.employees.length === 0) { + hireEmployeeButtonClass += " flashing-button"; + } + } + + const hireEmployeeButtonOnClick = () => { + office.findEmployees({ corporation: corp, industry: division }); + } + + // Autohire employee button + let autohireEmployeeButtonClass = "tooltip"; + if (office.atCapacity()) { + autohireEmployeeButtonClass += " a-link-button-inactive"; + } else { + autohireEmployeeButtonClass += " std-button"; + } + const autohireEmployeeButtonOnClick = () => { + if (office.atCapacity()) { return; } + office.hireRandomEmployee(); + props.corp.rerender(); + } + + // Upgrade Office Size Button + const upgradeOfficeSizeOnClick = props.eventHandler.createUpgradeOfficeSizePopup.bind(props.eventHandler, office); + + // Throw Office Party + const throwOfficePartyOnClick = props.eventHandler.createThrowOfficePartyPopup.bind(props.eventHandler, office); + + return ( +
+

Office Space

+

Size: {office.employees.length} / {office.size} employees

+ + +
+ + { + !division.hasResearch("AutoPartyManager") && + + } +
+ + {renderEmployeeManagement()} +
+ ) }