diff --git a/src/Infiltration/ui/GameTimer.tsx b/src/Infiltration/ui/GameTimer.tsx index 7bd25e563..335fe4925 100644 --- a/src/Infiltration/ui/GameTimer.tsx +++ b/src/Infiltration/ui/GameTimer.tsx @@ -1,19 +1,8 @@ -import { LinearProgress, Paper } from "@mui/material"; -import { Theme } from "@mui/material/styles"; -import withStyles from "@mui/styles/withStyles"; +import { Paper } from "@mui/material"; import React, { useEffect, useState } from "react"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { use } from "../../ui/Context"; - -const TimerProgress = withStyles((theme: Theme) => ({ - root: { - backgroundColor: theme.palette.background.paper, - }, - bar: { - transition: "none", - backgroundColor: theme.palette.primary.main, - }, -}))(LinearProgress); +import { ProgressBar } from "../../ui/React/Progress"; interface IProps { millis: number; @@ -43,10 +32,10 @@ export function GameTimer(props: IProps): React.ReactElement { // TODO(hydroflame): there's like a bug where it triggers the end before the // bar physically reaches the end return props.noPaper ? ( - + ) : ( - + ); } diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx index ec43ce05d..82a98a706 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx @@ -1,23 +1,19 @@ +import { Box, Button, Paper, Tooltip, Typography } from "@mui/material"; import React, { useState } from "react"; - -import { Box, Paper, Typography, Button, Tooltip } from "@mui/material"; - import { CONSTANTS } from "../../../Constants"; import { Crimes } from "../../../Crime/Crimes"; -import { numeralWrapper } from "../../../ui/numeralFormat"; -import { createProgressBarText } from "../../../utils/helpers/createProgressBarText"; -import { use } from "../../../ui/Context"; import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum"; - +import { use } from "../../../ui/Context"; +import { numeralWrapper } from "../../../ui/numeralFormat"; +import { ProgressBar } from "../../../ui/React/Progress"; import { Sleeve } from "../Sleeve"; import { SleeveTaskType } from "../SleeveTaskTypesEnum"; - -import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal"; -import { TravelModal } from "./TravelModal"; -import { StatsElement, EarningsElement } from "./StatsElement"; -import { MoreStatsModal } from "./MoreStatsModal"; import { MoreEarningsModal } from "./MoreEarningsModal"; +import { MoreStatsModal } from "./MoreStatsModal"; +import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal"; +import { EarningsElement, StatsElement } from "./StatsElement"; import { TaskSelector } from "./TaskSelector"; +import { TravelModal } from "./TravelModal"; interface IProps { sleeve: Sleeve; @@ -131,74 +127,70 @@ export function SleeveElem(props: IProps): React.ReactElement { } return ( - - - - - - - - - Insufficient funds : ""}> - - - - - Unlocked when sleeve has fully recovered : "" - } - > - - - - - + <> + + + + + + + Insufficient funds : ""}> + + + + + Unlocked when sleeve has fully recovered : ""} + > + + + + - - - - - - {desc} - - {props.sleeve.currentTask === SleeveTaskType.Crime && - createProgressBarText({ - progress: props.sleeve.currentTaskTime / props.sleeve.currentTaskMaxTime, - totalTicks: 25, - })} - - - - setStatsOpen(false)} sleeve={props.sleeve} /> - setEarningsOpen(false)} sleeve={props.sleeve} /> - setTravelOpen(false)} - sleeve={props.sleeve} - rerender={props.rerender} - /> - setAugmentationsOpen(false)} - sleeve={props.sleeve} - /> - - - + + + + + + {desc} + + {props.sleeve.currentTask === SleeveTaskType.Crime && ( + + )} + + + + setStatsOpen(false)} sleeve={props.sleeve} /> + setEarningsOpen(false)} sleeve={props.sleeve} /> + setTravelOpen(false)} + sleeve={props.sleeve} + rerender={props.rerender} + /> + setAugmentationsOpen(false)} + sleeve={props.sleeve} + /> + ); } diff --git a/src/ui/React/Progress.tsx b/src/ui/React/Progress.tsx new file mode 100644 index 000000000..0a29ae311 --- /dev/null +++ b/src/ui/React/Progress.tsx @@ -0,0 +1,13 @@ +import LinearProgress from "@mui/material/LinearProgress"; +import { Theme } from "@mui/material/styles"; +import withStyles from "@mui/styles/withStyles"; + +export const ProgressBar = withStyles((theme: Theme) => ({ + root: { + backgroundColor: theme.palette.background.paper, + }, + bar: { + transition: "none", + backgroundColor: theme.palette.primary.main, + }, +}))(LinearProgress); diff --git a/src/ui/React/StatsRow.tsx b/src/ui/React/StatsRow.tsx index 405abcc26..030670791 100644 --- a/src/ui/React/StatsRow.tsx +++ b/src/ui/React/StatsRow.tsx @@ -16,19 +16,21 @@ interface IProps { name: string; color: string; classes?: any; - data: ITableRowData; + data?: ITableRowData; children?: React.ReactElement; } export const StatsRow = ({ name, color, classes = useStyles(), children, data }: IProps): React.ReactElement => { - let content; + let content = ""; - if (data.content !== undefined) { - content = data.content; - } else if (data.level !== undefined && data.exp !== undefined) { - content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`; - } else if (data.level !== undefined && data.exp === undefined) { - content = `${formatNumber(data.level, 0)}`; + if (data) { + if (data.content !== undefined) { + content = data.content; + } else if (data.level !== undefined && data.exp !== undefined) { + content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`; + } else if (data.level !== undefined && data.exp === undefined) { + content = `${formatNumber(data.level, 0)}`; + } } return ( diff --git a/src/ui/WorkInProgressRoot.tsx b/src/ui/WorkInProgressRoot.tsx index cce3a056c..bc266c22d 100644 --- a/src/ui/WorkInProgressRoot.tsx +++ b/src/ui/WorkInProgressRoot.tsx @@ -1,26 +1,46 @@ -import React, { useState, useEffect } from "react"; -import { use } from "./Context"; +import { Box, Container, Paper, Table, TableBody, Tooltip } from "@mui/material"; +import Button from "@mui/material/Button"; +import Typography from "@mui/material/Typography"; +import { uniqueId } from "lodash"; +import React, { useEffect, useState } from "react"; +import { Companies } from "../Company/Companies"; +import { Company } from "../Company/Company"; import { CONSTANTS } from "../Constants"; +import { Factions } from "../Faction/Factions"; +import { LocationName } from "../Locations/data/LocationNames"; +import { Locations } from "../Locations/Locations"; +import { Settings } from "../Settings/Settings"; +import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; +import { use } from "./Context"; import { numeralWrapper } from "./numeralFormat"; +import { Money } from "./React/Money"; +import { MoneyRate } from "./React/MoneyRate"; +import { ProgressBar } from "./React/Progress"; import { Reputation } from "./React/Reputation"; import { ReputationRate } from "./React/ReputationRate"; -import { MoneyRate } from "./React/MoneyRate"; -import { Money } from "./React/Money"; -import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; -import { Factions } from "../Faction/Factions"; -import { Company } from "../Company/Company"; -import { Companies } from "../Company/Companies"; -import { Locations } from "../Locations/Locations"; -import { LocationName } from "../Locations/data/LocationNames"; - -import Typography from "@mui/material/Typography"; -import Grid from "@mui/material/Grid"; -import Button from "@mui/material/Button"; - -import { createProgressBarText } from "../utils/helpers/createProgressBarText"; +import { StatsRow } from "./React/StatsRow"; const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle; +interface IWorkInfo { + buttons: { + cancel: () => void; + unfocus?: () => void; + }; + title: string | React.ReactElement; + + description?: string | React.ReactElement; + gains?: (string | React.ReactElement)[]; + progress?: { + elapsed?: number; + remaining?: number; + percentage?: number; + }; + + stopText: string; + stopTooltip?: string | React.ReactElement; +} + export function WorkInProgressRoot(): React.ReactElement { const setRerender = useState(false)[1]; function rerender(): void { @@ -35,499 +55,521 @@ export function WorkInProgressRoot(): React.ReactElement { const player = use.Player(); const router = use.Router(); - if (player.workType == CONSTANTS.WorkTypeFaction) { - const faction = Factions[player.currentWorkFactionName]; - if (!faction) { - return ( - <> - - You have not joined {player.currentWorkFactionName || "(Faction not found)"} yet or cannot work at this - time, please try again if you think this should have worked - - - - ); - } + const expGains = [ + player.workHackExpGained > 0 ? ( + + ) : ( + <> + ), + player.workStrExpGained > 0 ? ( + + ) : ( + <> + ), + player.workDefExpGained > 0 ? ( + + ) : ( + <> + ), + player.workDexExpGained > 0 ? ( + + ) : ( + <> + ), + player.workAgiExpGained > 0 ? ( + + ) : ( + <> + ), + player.workChaExpGained > 0 ? ( + + ) : ( + <> + ), + ]; - function cancel(): void { - router.toFaction(faction); - player.finishFactionWork(true); - } - function unfocus(): void { - router.toFaction(faction); - player.stopFocusing(); - } - return ( - - - - You are currently {player.currentWorkFactionDescription} for your faction {faction.name} -
- (Current Faction Reputation: - ).
- You have been doing this for {convertTimeMsToTimeElapsedString(player.timeWorked)} -
-
- You have earned:
-
- (){" "} -
-
- ( - ) reputation for this faction
-
- {player.workHackExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workHackExpGained)} ( - {numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp
- - )} -
- {player.workStrExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workStrExpGained)} ( - {numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp
- - )} - {player.workDefExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDefExpGained)} ( - {numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp
- - )} - {player.workDexExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDexExpGained)} ( - {numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp
- - )} - {player.workAgiExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workAgiExpGained)} ( - {numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp
- - )} -
- {player.workChaExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workChaExpGained)} ( - {numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp
- - )} -
- You will automatically finish after working for 20 hours. You can cancel earlier if you wish. -
- There is no penalty for cancelling earlier. -
-
- - - - -
- ); - } + let workInfo: IWorkInfo | null; - const className = player.className; - if (player.className !== "") { - function cancel(): void { - player.finishClass(true); - router.toCity(); - } + switch (player.workType) { + case CONSTANTS.WorkTypeFaction: { + const faction = Factions[player.currentWorkFactionName]; + if (!faction) { + workInfo = { + buttons: { + cancel: () => router.toFactions(), + }, + title: + `You have not joined ${player.currentWorkFactionName || "(Faction not found)"} at this time,` + + " please try again if you think this should have worked", - function unfocus(): void { - router.toCity(); - player.stopFocusing(); - } + stopText: "Back to Factions", + }; + } - let stopText = ""; - if ( - className == CONSTANTS.ClassGymStrength || - className == CONSTANTS.ClassGymDefense || - className == CONSTANTS.ClassGymDexterity || - className == CONSTANTS.ClassGymAgility - ) { - stopText = "Stop training at gym"; - } else { - stopText = "Stop taking course"; - } + function cancel(): void { + router.toFaction(faction); + player.finishFactionWork(true); + } + function unfocus(): void { + router.toFaction(faction); + player.stopFocusing(); + } - return ( - - - - You have been {className} for {convertTimeMsToTimeElapsedString(player.timeWorked)} -
-
- This has cost you:
- (){" "} -
-
- You have gained:
- {player.workHackExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workHackExpGained)} ( - {numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp
- - )} - {player.workStrExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workStrExpGained)} ( - {numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp
- - )} - {player.workDefExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDefExpGained)} ( - {numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp
- - )} - {player.workDexExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDexExpGained)} ( - {numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp
- - )} - {player.workAgiExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workAgiExpGained)} ( - {numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp
- - )} - {player.workChaExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workChaExpGained)} ( - {numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp
- - )} - You may cancel at any time -
-
- - - - -
- ); - } - - if (player.workType == CONSTANTS.WorkTypeCompany) { - const comp = Companies[player.companyName]; - if (comp == null || !(comp instanceof Company)) { - return ( - <> - - You cannot work for {player.companyName || "(Company not found)"} at this time, please try again if you - think this should have worked - - - - ); - } - - const companyRep = comp.playerReputation; - - function cancel(): void { - player.finishWork(true); - router.toJob(); - } - function unfocus(): void { - player.stopFocusing(); - router.toJob(); - } - - const position = player.jobs[player.companyName]; - - const penalty = player.cancelationPenalty(); - - const penaltyString = penalty === 0.5 ? "half" : "three-quarters"; - return ( - - - - You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "} - )
-
- You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} -
-
- You have earned:
-
- (){" "} -
-
- ( - ) reputation for this company
-
- {player.workHackExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workHackExpGained)} ( - {`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} - ) hacking exp
- - )} -
- {player.workStrExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workStrExpGained)} ( - {`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`} - ) strength exp
- - )} - {player.workDefExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDefExpGained)} ( - {`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`} - ) defense exp
- - )} - {player.workDexExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDexExpGained)} ( - {`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`} - ) dexterity exp
- - )} - {player.workAgiExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workAgiExpGained)} ( - {`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`} - ) agility exp
- - )} -
- {player.workChaExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workChaExpGained)} ( - {`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`} - ) charisma exp
- - )} -
- You will automatically finish after working for 8 hours. You can cancel earlier if you wish, but you will - only gain {penaltyString} of the reputation you've earned so far. -
-
- - - - -
- ); - } - - if (player.workType == CONSTANTS.WorkTypeCompanyPartTime) { - function cancel(): void { - player.finishWorkPartTime(true); - router.toJob(); - } - function unfocus(): void { - player.stopFocusing(); - router.toJob(); - } - const comp = Companies[player.companyName]; - let companyRep = 0; - if (comp == null || !(comp instanceof Company)) { - throw new Error(`Could not find Company: ${player.companyName}`); - } - companyRep = comp.playerReputation; - - const position = player.jobs[player.companyName]; - return ( - - - - You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "} - )
-
- You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} -
-
- You have earned:
-
- (){" "} -
-
- ( - - ) reputation for this company
-
- {player.workHackExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workHackExpGained)} ( - {`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} - ) hacking exp
- - )} -
- {player.workStrExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workStrExpGained)} ( - {`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`} - ) strength exp
- - )} - {player.workDefExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDefExpGained)} ( - {`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`} - ) defense exp
- - )} - {player.workDexExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workDexExpGained)} ( - {`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`} - ) dexterity exp
- - )} - {player.workAgiExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workAgiExpGained)} ( - {`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`} - ) agility exp
- - )} -
- {player.workChaExpGained > 0 && ( - <> - {numeralWrapper.formatExp(player.workChaExpGained)} ( - {`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`} - ) charisma exp
- - )} -
- You will automatically finish after working for 8 hours. You can cancel earlier if you wish, and there will - be no penalty because this is a part-time job. -
-
- - - - -
- ); - } - - if (player.crimeType !== "") { - const percent = Math.round((player.timeWorked / player.timeNeededToCompleteWork) * 100); - let numBars = Math.round(percent / 5); - if (numBars < 0) { - numBars = 0; - } - if (numBars > 20) { - numBars = 20; - } - // const progressBar = "[" + Array(numBars + 1).join("|") + Array(20 - numBars + 1).join(" ") + "]"; - const progressBar = createProgressBarText({ progress: (numBars + 1) / 20, totalTicks: 20 }); - - return ( - - - - You are attempting to {player.crimeType}. -
+ workInfo = { + buttons: { + cancel: cancel, + unfocus: unfocus, + }, + title: ( + <> + You are currently {player.currentWorkFactionDescription} for your faction {faction.name} + + ), + description: ( + <> + Current Faction Reputation: + + ), + gains: [ + player.workMoneyGained > 0 ? ( + + + ( + ) + + + ) : ( + <> + ), + - Time remaining: {convertTimeMsToTimeElapsedString(player.timeNeededToCompleteWork - player.timeWorked)} + ( + ) + , + ...expGains, + ], + progress: { + elapsed: player.timeWorked, + }, -
-
{progressBar}
-
-
- - - -
- ); + stopText: "Stop Faction work", + }; + + break; + } + + case CONSTANTS.WorkTypeStudyClass: { + const className = player.className; + function cancel(): void { + player.finishClass(true); + router.toCity(); + } + + function unfocus(): void { + router.toCity(); + player.stopFocusing(); + } + + let stopText = ""; + if ( + className === CONSTANTS.ClassGymStrength || + className === CONSTANTS.ClassGymDefense || + className === CONSTANTS.ClassGymDexterity || + className === CONSTANTS.ClassGymAgility + ) { + stopText = "Stop training at gym"; + } else { + stopText = "Stop taking course"; + } + + workInfo = { + buttons: { + cancel: cancel, + unfocus: unfocus, + }, + title: ( + <> + You are currently {className} + + ), + + gains: [ + + + ( + ) + + , + ...expGains, + ], + progress: { + elapsed: player.timeWorked, + }, + + stopText: stopText, + }; + + break; + } + + case CONSTANTS.WorkTypeCompany: { + const comp = Companies[player.companyName]; + if (comp == null || !(comp instanceof Company)) { + workInfo = { + buttons: { + cancel: () => router.toTerminal(), + }, + title: + `You cannot work for ${player.companyName || "(Company not found)"} at this time,` + + " please try again if you think this should have worked", + + stopText: "Back to Terminal", + }; + } + + const companyRep = comp.playerReputation; + + function cancel(): void { + player.finishWork(true); + router.toJob(); + } + function unfocus(): void { + player.stopFocusing(); + router.toJob(); + } + + const position = player.jobs[player.companyName]; + + const penalty = player.cancelationPenalty(); + + const penaltyString = penalty === 0.5 ? "half" : "three-quarters"; + + workInfo = { + buttons: { + cancel: cancel, + unfocus: unfocus, + }, + title: ( + <> + You are currently working as a {position} at {player.companyName} + + ), + + description: ( + <> + Current Company Reputation: + + ), + gains: [ + + + () + + , + + + ( + ) + + , + ...expGains, + ], + progress: { + elapsed: player.timeWorked, + }, + + stopText: "Stop working", + stopTooltip: + "You will automatically finish after working for 8 hours. You can cancel earlier if you wish" + + ` but you will only gain ${penaltyString} of the reputation you've earned so far.`, + }; + + break; + } + + case CONSTANTS.WorkTypeCompanyPartTime: { + function cancel(): void { + player.finishWorkPartTime(true); + router.toJob(); + } + function unfocus(): void { + player.stopFocusing(); + router.toJob(); + } + const comp = Companies[player.companyName]; + let companyRep = 0; + if (comp == null || !(comp instanceof Company)) { + throw new Error(`Could not find Company: ${player.companyName}`); + } + companyRep = comp.playerReputation; + + const position = player.jobs[player.companyName]; + + workInfo = { + buttons: { + cancel: cancel, + unfocus: unfocus, + }, + title: ( + <> + You are currently working as a {position} at {player.companyName} + + ), + + description: ( + <> + Current Company Reputation: + + ), + gains: [ + + + () + + , + + + ( + ) + + , + ...expGains, + ], + progress: { + elapsed: player.timeWorked, + }, + + stopText: "Stop working", + stopTooltip: + "You will automatically finish after working for 8 hours. You can cancel earlier if you wish" + + " and there will be no penalty because this is a part-time job.", + }; + + break; + } + + case CONSTANTS.WorkTypeCrime: { + const completion = Math.round((player.timeWorked / player.timeNeededToCompleteWork) * 100); + + workInfo = { + buttons: { + cancel: () => { + router.toLocation(Locations[LocationName.Slums]); + player.finishCrime(true); + }, + }, + title: `You are attempting to ${player.crimeType}`, + + progress: { + remaining: player.timeNeededToCompleteWork - player.timeWorked, + percentage: completion, + }, + + stopText: "Cancel crime", + }; + + break; + } + + case CONSTANTS.WorkTypeCreateProgram: { + function cancel(): void { + player.finishCreateProgramWork(true); + router.toTerminal(); + } + function unfocus(): void { + router.toTerminal(); + player.stopFocusing(); + } + + const completion = (player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100; + + workInfo = { + buttons: { + cancel: cancel, + unfocus: unfocus, + }, + title: ( + <> + You are currently working on coding {player.createProgramName} + + ), + + progress: { + elapsed: player.timeWorked, + percentage: completion, + }, + + stopText: "Stop creating program", + stopTooltip: "Your work will be saved and you can return to complete the program later.", + }; + + break; + } + + case CONSTANTS.WorkTypeGraftAugmentation: { + function cancel(): void { + player.finishGraftAugmentationWork(true); + router.toTerminal(); + } + function unfocus(): void { + router.toTerminal(); + player.stopFocusing(); + } + + const completion = (player.timeWorkedGraftAugmentation / player.timeNeededToCompleteWork) * 100; + + workInfo = { + buttons: { + cancel: cancel, + unfocus: unfocus, + }, + title: ( + <> + You are currently working on grafting {player.graftAugmentationName} + + ), + + progress: { + elapsed: player.timeWorked, + percentage: completion, + }, + + stopText: "Stop grafting", + stopTooltip: ( + <> + If you cancel, your work will not be saved, and the money you spent will not be returned + + ), + }; + + break; + } + + default: + router.toTerminal(); + workInfo = null; } - if (player.createProgramName !== "") { - function cancel(): void { - player.finishCreateProgramWork(true); - router.toTerminal(); - } - function unfocus(): void { - router.toTerminal(); - player.stopFocusing(); - } - return ( - - - - You are currently working on coding {player.createProgramName}.
-
- You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} -
-
- The program is {((player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100).toFixed(2)} - % complete.
- If you cancel, your work will be saved and you can come back to complete the program later. -
-
- - - - -
- ); + if (workInfo === null) { + return <>; } - if (player.graftAugmentationName !== "") { - function cancel(): void { - player.finishGraftAugmentationWork(true); - router.toTerminal(); - } - function unfocus(): void { - router.toTerminal(); - player.stopFocusing(); - } - return ( - - - - You are currently working on grafting {player.graftAugmentationName}. -
-
- You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} -
-
- The augmentation is{" "} - {((player.timeWorkedGraftAugmentation / player.timeNeededToCompleteWork) * 100).toFixed(2)}% done being - crafted. -
- If you cancel, your work will not be saved, and the money you spent will not be returned. -
-
- - - - -
+ const tooltipInfo = + typeof workInfo?.stopTooltip === "string" ? ( + {workInfo.stopTooltip} + ) : ( + workInfo.stopTooltip || <> ); - } - if (!player.workType) router.toTerminal(); + return ( + + + {workInfo.title} + {workInfo.description} + {workInfo.gains && ( + + + {workInfo.gains.map((row) => ( + {row} + ))} + +
+ )} +
+ + {workInfo.progress !== undefined && ( + + + {workInfo.progress.elapsed !== undefined && ( + {convertTimeMsToTimeElapsedString(workInfo.progress.elapsed)} elapsed + )} + {workInfo.progress.remaining !== undefined && ( + {convertTimeMsToTimeElapsedString(workInfo.progress.remaining)} remaining + )} + {workInfo.progress.percentage !== undefined && ( + {workInfo.progress.percentage.toFixed(2)}% done + )} + + {workInfo.progress.percentage !== undefined && ( + + )} + + )} - return <>; + + {workInfo.stopTooltip ? ( + + + + ) : ( + + )} + {workInfo.buttons.unfocus && ( + + )} + + +
+ ); }