Update Gang equip. page UI

This commit is contained in:
nickofolas 2022-01-22 11:16:51 -06:00
parent 310374dc56
commit 3921457ee6
2 changed files with 181 additions and 108 deletions

@ -2,20 +2,27 @@
* React Component for the popup that manages gang members upgrades * React Component for the popup that manages gang members upgrades
*/ */
import React, { useState } from "react"; import React, { useState } from "react";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { numeralWrapper } from "../../ui/numeralFormat";
import { GangMemberUpgrades } from "../GangMemberUpgrades";
import { GangMemberUpgrade } from "../GangMemberUpgrade";
import { Money } from "../../ui/React/Money";
import { useGang } from "./Context"; import { useGang } from "./Context";
import { GangMember } from "../GangMember"; import { generateTableRow } from "./GangMemberStats";
import { UpgradeType } from "../data/upgrades";
import { use } from "../../ui/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 Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import { MenuItem, Table, TableBody, TextField } from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import { numeralWrapper } from "../../ui/numeralFormat";
import { GangMemberUpgrades } from "../GangMemberUpgrades";
import { GangMemberUpgrade } from "../GangMemberUpgrade";
import { Money } from "../../ui/React/Money";
import { GangMember } from "../GangMember";
import { UpgradeType } from "../data/upgrades";
import { use } from "../../ui/Context";
import { Settings } from "../../Settings/Settings";
import { characterOverviewStyles as useStyles } from "../../ui/React/CharacterOverview";
interface INextRevealProps { interface INextRevealProps {
upgrades: string[]; upgrades: string[];
@ -46,12 +53,10 @@ function NextReveal(props: INextRevealProps): React.ReactElement {
function PurchasedUpgrade({ upgName }: { upgName: string }): React.ReactElement { function PurchasedUpgrade({ upgName }: { upgName: string }): React.ReactElement {
const upg = GangMemberUpgrades[upgName]; const upg = GangMemberUpgrades[upgName];
return ( return (
<Paper sx={{ mx: 1, p: 1 }}> <Paper sx={{ p: 1 }}>
<Box display="flex">
<Tooltip title={<Typography dangerouslySetInnerHTML={{ __html: upg.desc }} />}> <Tooltip title={<Typography dangerouslySetInnerHTML={{ __html: upg.desc }} />}>
<Typography>{upg.name}</Typography> <Typography>{upg.name}</Typography>
</Tooltip> </Tooltip>
</Box>
</Paper> </Paper>
); );
} }
@ -72,8 +77,8 @@ function UpgradeButton(props: IUpgradeButtonProps): React.ReactElement {
return ( return (
<Tooltip title={<Typography dangerouslySetInnerHTML={{ __html: props.upg.desc }} />}> <Tooltip title={<Typography dangerouslySetInnerHTML={{ __html: props.upg.desc }} />}>
<span> <span>
<Typography>{props.upg.name}</Typography> <Button onClick={onClick} sx={{ display: 'flex', flexDirection: 'column', width: '100%', height: '100%' }}>
<Button onClick={onClick}> <Typography sx={{ display: 'block' }}>{props.upg.name}</Typography>
<Money money={gang.getUpgradeCost(props.upg)} /> <Money money={gang.getUpgradeCost(props.upg)} />
</Button> </Button>
</span> </span>
@ -86,12 +91,16 @@ interface IPanelProps {
} }
function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement { function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
const classes = useStyles();
const gang = useGang(); const gang = useGang();
const player = use.Player(); const player = use.Player();
const setRerender = useState(false)[1]; const setRerender = useState(false)[1];
const [currentCategory, setCurrentCategory] = useState("Weapons");
function rerender(): void { function rerender(): void {
setRerender((old) => !old); setRerender((old) => !old);
} }
function filterUpgrades(list: string[], type: UpgradeType): GangMemberUpgrade[] { function filterUpgrades(list: string[], type: UpgradeType): GangMemberUpgrade[] {
return Object.keys(GangMemberUpgrades) return Object.keys(GangMemberUpgrades)
.filter((upgName: string) => { .filter((upgName: string) => {
@ -103,12 +112,26 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
}) })
.map((upgName: string) => GangMemberUpgrades[upgName]); .map((upgName: string) => GangMemberUpgrades[upgName]);
} }
const onChange = (event: SelectChangeEvent<string>): void => {
setCurrentCategory(event.target.value);
rerender()
}
const weaponUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Weapon); const weaponUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Weapon);
const armorUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Armor); const armorUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Armor);
const vehicleUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Vehicle); const vehicleUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Vehicle);
const rootkitUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Rootkit); const rootkitUpgrades = filterUpgrades(props.member.upgrades, UpgradeType.Rootkit);
const augUpgrades = filterUpgrades(props.member.augmentations, UpgradeType.Augmentation); const augUpgrades = filterUpgrades(props.member.augmentations, UpgradeType.Augmentation);
const categories: { [key: string]: (GangMemberUpgrade[] | UpgradeType)[] } = {
'Weapons': [weaponUpgrades, UpgradeType.Weapon],
'Armor': [armorUpgrades, UpgradeType.Armor],
'Vehicles': [vehicleUpgrades, UpgradeType.Vehicle],
'Rootkits': [rootkitUpgrades, UpgradeType.Rootkit],
'Augmentations': [augUpgrades, UpgradeType.Augmentation]
};
const asc = { const asc = {
hack: props.member.calculateAscensionMult(props.member.hack_asc_points), hack: props.member.calculateAscensionMult(props.member.hack_asc_points),
str: props.member.calculateAscensionMult(props.member.str_asc_points), str: props.member.calculateAscensionMult(props.member.str_asc_points),
@ -119,26 +142,89 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
}; };
return ( return (
<Paper> <Paper>
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', m: 1, gap: 1 }}>
<span>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{props.member.name} ({props.member.task}) {props.member.name} ({props.member.task})
</Typography> </Typography>
<Tooltip
title={
<Typography> <Typography>
Hack: {props.member.hack} (x Hk: x{numeralWrapper.formatMultiplier(props.member.hack_mult * asc.hack)}(x
{formatNumber(props.member.hack_mult * asc.hack, 2)})<br /> {numeralWrapper.formatMultiplier(props.member.hack_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.hack)}{" "}
Str: {props.member.str} (x Asc)
{formatNumber(props.member.str_mult * asc.str, 2)})<br />
Def: {props.member.def} (x
{formatNumber(props.member.def_mult * asc.def, 2)})<br />
Dex: {props.member.dex} (x
{formatNumber(props.member.dex_mult * asc.dex, 2)})<br />
Agi: {props.member.agi} (x
{formatNumber(props.member.agi_mult * asc.agi, 2)})<br />
Cha: {props.member.cha} (x
{formatNumber(props.member.cha_mult * asc.cha, 2)})
</Typography>
<Box display="flex" flexWrap="wrap">
<Typography>Purchased Upgrades: </Typography>
<br /> <br />
St: x{numeralWrapper.formatMultiplier(props.member.str_mult * asc.str)}
(x{numeralWrapper.formatMultiplier(props.member.str_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.str)}{" "}
Asc)
<br />
Df: x{numeralWrapper.formatMultiplier(props.member.def_mult * asc.def)}
(x{numeralWrapper.formatMultiplier(props.member.def_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.def)}{" "}
Asc)
<br />
Dx: x{numeralWrapper.formatMultiplier(props.member.dex_mult * asc.dex)}
(x{numeralWrapper.formatMultiplier(props.member.dex_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.dex)}{" "}
Asc)
<br />
Ag: x{numeralWrapper.formatMultiplier(props.member.agi_mult * asc.agi)}
(x{numeralWrapper.formatMultiplier(props.member.agi_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.agi)}{" "}
Asc)
<br />
Ch: x{numeralWrapper.formatMultiplier(props.member.cha_mult * asc.cha)}
(x{numeralWrapper.formatMultiplier(props.member.cha_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.cha)}{" "}
Asc)
</Typography>
}
>
<Table>
<TableBody>
{generateTableRow("Hacking", props.member.hack, props.member.hack_exp, Settings.theme.hack, classes)}
{generateTableRow("Strength", props.member.str, props.member.str_exp, Settings.theme.combat, classes)}
{generateTableRow("Defense", props.member.def, props.member.def_exp, Settings.theme.combat, classes)}
{generateTableRow("Dexterity", props.member.dex, props.member.dex_exp, Settings.theme.combat, classes)}
{generateTableRow("Agility", props.member.agi, props.member.agi_exp, Settings.theme.combat, classes)}
{generateTableRow("Charisma", props.member.cha, props.member.cha_exp, Settings.theme.cha, classes)}
</TableBody>
</Table>
</Tooltip>
</span>
<span>
<Select onChange={onChange} value={currentCategory} sx={{ width: '100%', mb: 1 }}>
{Object.keys(categories).map((k, i) => (
<MenuItem key={i + 1} value={k}>
<Typography variant="h6">{k}</Typography>
</MenuItem>
))}
</Select>
<Box sx={{ width: '100%' }}>
{(categories[currentCategory][0] as GangMemberUpgrade[]).length === 0 && (
<Typography>
All upgrades owned!
</Typography>
)}
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr' }}>
{(categories[currentCategory][0] as GangMemberUpgrade[]).map((upg) => (
<UpgradeButton
key={upg.name}
rerender={rerender}
member={props.member}
upg={upg}
/>
))}
</Box>
<NextReveal
type={categories[currentCategory][1] as UpgradeType}
upgrades={props.member.upgrades}
/>
</Box>
</span>
</Box>
<Typography sx={{ mx: 1 }}>Purchased Upgrades: </Typography>
<Box display="grid" sx={{ gridTemplateColumns: 'repeat(4, 1fr)', m: 1 }}>
{props.member.upgrades.map((upg: string) => ( {props.member.upgrades.map((upg: string) => (
<PurchasedUpgrade key={upg} upgName={upg} /> <PurchasedUpgrade key={upg} upgName={upg} />
))} ))}
@ -146,59 +232,22 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
<PurchasedUpgrade key={upg} upgName={upg} /> <PurchasedUpgrade key={upg} upgName={upg} />
))} ))}
</Box> </Box>
<Box display="flex" justifyContent="space-around">
<Box>
<Typography variant="h6" color="primary">
Weapons
</Typography>
{weaponUpgrades.map((upg) => (
<UpgradeButton key={upg.name} rerender={rerender} member={props.member} upg={upg} />
))}
<NextReveal type={UpgradeType.Weapon} upgrades={props.member.upgrades} />
</Box>
<Box>
<Typography variant="h6" color="primary">
Armor
</Typography>
{armorUpgrades.map((upg) => (
<UpgradeButton key={upg.name} rerender={rerender} member={props.member} upg={upg} />
))}
<NextReveal type={UpgradeType.Armor} upgrades={props.member.upgrades} />
</Box>
<Box>
<Typography variant="h6" color="primary">
Vehicles
</Typography>
{vehicleUpgrades.map((upg) => (
<UpgradeButton key={upg.name} rerender={rerender} member={props.member} upg={upg} />
))}
<NextReveal type={UpgradeType.Vehicle} upgrades={props.member.upgrades} />
</Box>
<Box>
<Typography variant="h6" color="primary">
Rootkits
</Typography>
{rootkitUpgrades.map((upg) => (
<UpgradeButton key={upg.name} rerender={rerender} member={props.member} upg={upg} />
))}
<NextReveal type={UpgradeType.Rootkit} upgrades={props.member.upgrades} />
</Box>
<Box>
<Typography variant="h6" color="primary">
Augmentations
</Typography>
{augUpgrades.map((upg) => (
<UpgradeButton key={upg.name} rerender={rerender} member={props.member} upg={upg} />
))}
<NextReveal type={UpgradeType.Augmentation} upgrades={props.member.upgrades} />
</Box>
</Box>
</Paper > </Paper >
); );
} }
export function EquipmentsSubpage(): React.ReactElement { export function EquipmentsSubpage(): React.ReactElement {
const gang = useGang(); const gang = useGang();
const [filter, setFilter] = useState("");
const handleFilterChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
setFilter(event.target.value.toLowerCase());
}
const members = gang.members
.filter((member) => member && member.name.toLowerCase().includes(filter));
return ( return (
<> <>
<Tooltip <Tooltip
@ -209,11 +258,26 @@ export function EquipmentsSubpage(): React.ReactElement {
</Typography> </Typography>
} }
> >
<Typography>Discount: -{numeralWrapper.formatPercentage(1 - 1 / gang.getDiscount())}</Typography> <Typography sx={{ m: 1 }}>Discount: -{numeralWrapper.formatPercentage(1 - 1 / gang.getDiscount())}</Typography>
</Tooltip> </Tooltip>
{gang.members.map((member: GangMember) => (
<TextField
value={filter}
onChange={handleFilterChange}
autoFocus
InputProps={{
startAdornment: <SearchIcon />,
spellCheck: false
}}
placeholder="Filter by member name"
sx={{ m: 1, width: '15%' }}
/>
<Box display="grid" sx={{ gridTemplateColumns: '1fr 1fr', width: 'fit-content' }}>
{members.map((member: GangMember) => (
<GangMemberUpgradePanel key={member.name} member={member} /> <GangMemberUpgradePanel key={member.name} member={member} />
))} ))}
</Box>
</> </>
); );
} }

@ -25,19 +25,14 @@ interface IProps {
member: GangMember; member: GangMember;
} }
export function GangMemberStats(props: IProps): React.ReactElement { export const generateTableRow = (
const classes = useStyles(); name: string,
level: number,
const asc = { exp: number,
hack: props.member.calculateAscensionMult(props.member.hack_asc_points), color: string,
str: props.member.calculateAscensionMult(props.member.str_asc_points), // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
def: props.member.calculateAscensionMult(props.member.def_asc_points), classes: any
dex: props.member.calculateAscensionMult(props.member.dex_asc_points), ): React.ReactElement => {
agi: props.member.calculateAscensionMult(props.member.agi_asc_points),
cha: props.member.calculateAscensionMult(props.member.cha_asc_points),
};
const generateTableRow = (name: string, level: number, exp: number, color: string): React.ReactElement => {
return ( return (
<TableRow> <TableRow>
<TableCell classes={{ root: classes.cellNone }}> <TableCell classes={{ root: classes.cellNone }}>
@ -52,6 +47,20 @@ export function GangMemberStats(props: IProps): React.ReactElement {
) )
} }
export function GangMemberStats(props: IProps): React.ReactElement {
const classes = useStyles();
const asc = {
hack: props.member.calculateAscensionMult(props.member.hack_asc_points),
str: props.member.calculateAscensionMult(props.member.str_asc_points),
def: props.member.calculateAscensionMult(props.member.def_asc_points),
dex: props.member.calculateAscensionMult(props.member.dex_asc_points),
agi: props.member.calculateAscensionMult(props.member.agi_asc_points),
cha: props.member.calculateAscensionMult(props.member.cha_asc_points),
};
const gang = useGang(); const gang = useGang();
const data = [ const data = [
[`Money:`, <MoneyRate money={5 * props.member.calculateMoneyGain(gang)} />], [`Money:`, <MoneyRate money={5 * props.member.calculateMoneyGain(gang)} />],
@ -93,12 +102,12 @@ export function GangMemberStats(props: IProps): React.ReactElement {
> >
<Table sx={{ display: 'table', mb: 1, width: '100%' }}> <Table sx={{ display: 'table', mb: 1, width: '100%' }}>
<TableBody> <TableBody>
{generateTableRow("Hacking", props.member.hack, props.member.hack_exp, Settings.theme.hack)} {generateTableRow("Hacking", props.member.hack, props.member.hack_exp, Settings.theme.hack, classes)}
{generateTableRow("Strength", props.member.str, props.member.str_exp, Settings.theme.combat)} {generateTableRow("Strength", props.member.str, props.member.str_exp, Settings.theme.combat, classes)}
{generateTableRow("Defense", props.member.def, props.member.def_exp, Settings.theme.combat)} {generateTableRow("Defense", props.member.def, props.member.def_exp, Settings.theme.combat, classes)}
{generateTableRow("Dexterity", props.member.dex, props.member.dex_exp, Settings.theme.combat)} {generateTableRow("Dexterity", props.member.dex, props.member.dex_exp, Settings.theme.combat, classes)}
{generateTableRow("Agility", props.member.agi, props.member.agi_exp, Settings.theme.combat)} {generateTableRow("Agility", props.member.agi, props.member.agi_exp, Settings.theme.combat, classes)}
{generateTableRow("Charisma", props.member.cha, props.member.cha_exp, Settings.theme.cha)} {generateTableRow("Charisma", props.member.cha, props.member.cha_exp, Settings.theme.cha, classes)}
<TableRow> <TableRow>
<TableCell classes={{ root: classes.cellNone }}> <TableCell classes={{ root: classes.cellNone }}>
<br /> <br />