From 7eeb8fcfe89b2a525816fe8fe799f756302f5896 Mon Sep 17 00:00:00 2001 From: ahmedmgamal94 <98055904+ahmedmgamal94@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:13:07 -0700 Subject: [PATCH] total stat display added to the armor customization component --- src/components/LoadoutCustomization.tsx | 14 ++- src/features/subclass/TotalStatsDisplay.tsx | 132 ++++++++++++++++++++ 2 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 src/features/subclass/TotalStatsDisplay.tsx diff --git a/src/components/LoadoutCustomization.tsx b/src/components/LoadoutCustomization.tsx index ade3ae3..3445534 100644 --- a/src/components/LoadoutCustomization.tsx +++ b/src/components/LoadoutCustomization.tsx @@ -8,6 +8,7 @@ import AbilitiesModification from '../features/subclass/AbilitiesModification'; import ShareLoadout from '../features/loadouts/components/ShareLoadout'; import { SubclassConfig } from '../types/d2l-types'; import SaveLoadout from '../features/loadouts/components/SaveLoadout'; +import TotalStatsDisplay from '../features/subclass/TotalStatsDisplay'; interface LoadoutCustomizationProps { onBackClick: () => void; @@ -100,8 +101,17 @@ const LoadoutCustomization: React.FC = ({ - - FREE SPACE FOR SOMETHING + + diff --git a/src/features/subclass/TotalStatsDisplay.tsx b/src/features/subclass/TotalStatsDisplay.tsx new file mode 100644 index 0000000..b3f1703 --- /dev/null +++ b/src/features/subclass/TotalStatsDisplay.tsx @@ -0,0 +1,132 @@ +import React, { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import { styled } from '@mui/material/styles'; +import { Box, Typography, Grid } from '@mui/material'; +import { RootState } from '../../store'; +import { StatName, DestinyArmor } from '../../types/d2l-types'; +import { STATS } from '../../lib/bungie_api/constants'; +import { ManifestArmorStatMod, ManifestStatPlug } from '../../types/manifest-types'; + +const StatsContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + padding: theme.spacing(1), + backgroundColor: 'rgba(0, 0, 0, 0.5)', + backdropFilter: 'blur(10px)', + borderRadius: theme.shape.borderRadius, +})); + +const StatItem = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + margin: theme.spacing(0, 1), +})); + +const StatIcon = styled('img')({ + width: 24, + height: 24, +}); + +const StatValue = styled(Typography)({ + color: 'white', + fontWeight: 'bold', +}); + +const statIcons: Record = { + mobility: 'assets/mob.png', + resilience: 'assets/res.png', + recovery: 'assets/rec.png', + discipline: 'assets/disc.png', + intellect: 'assets/int.png', + strength: 'assets/str.png', +}; + +function isStatsMod(mod: unknown): mod is ManifestArmorStatMod { + return ( + typeof mod === 'object' && + mod !== null && + ('mobilityMod' in mod || + 'resilienceMod' in mod || + 'recoveryMod' in mod || + 'disciplineMod' in mod || + 'intellectMod' in mod || + 'strengthMod' in mod) + ); +} + +const TotalStatsDisplay: React.FC = () => { + const loadout = useSelector((state: RootState) => state.loadoutConfig.loadout); + + const totalStats = useMemo(() => { + const stats: Record = { + mobility: 0, + resilience: 0, + recovery: 0, + discipline: 0, + intellect: 0, + strength: 0, + }; + + // Sum up armor stats + const armorPieces: DestinyArmor[] = [ + loadout.helmet, + loadout.gauntlets, + loadout.chestArmor, + loadout.legArmor, + loadout.classArmor, + ]; + armorPieces.forEach((armor) => { + (STATS as StatName[]).forEach((stat) => { + stats[stat] += Number(armor[stat]) || 0; + }); + }); + + // Add stats from armor mods in slot 0 + const armorMods = [ + loadout.helmetMods[0], + loadout.gauntletsMods[0], + loadout.chestArmorMods[0], + loadout.legArmorMods[0], + loadout.classArmorMods[0], + ]; + + armorMods.forEach((mod) => { + if (isStatsMod(mod)) { + (STATS as StatName[]).forEach((stat) => { + const modStat = `${stat}Mod` as keyof ManifestStatPlug; + stats[stat] += Number(mod[modStat]) || 0; + }); + } + }); + + // Add stats from fragments + loadout.subclassConfig.fragments.forEach((fragment) => { + (STATS as StatName[]).forEach((stat) => { + const fragmentStat = `${stat}Mod` as keyof typeof fragment; + stats[stat] += Number(fragment[fragmentStat]) || 0; + }); + }); + + return stats; + }, [loadout]); + + return ( + + + {(STATS as StatName[]).map((stat) => ( + + + + {totalStats[stat]} + + + ))} + + + ); +}; + +export default TotalStatsDisplay;