From e88bd67464010a3efa819d5b22c20beafec20ae1 Mon Sep 17 00:00:00 2001 From: ahmedmgamal94 <98055904+ahmedmgamal94@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:45:31 -0700 Subject: [PATCH 1/2] hover cards for abiltites need description for fragment need armor mod hover --- src/components/HoverCard.tsx | 175 ++++++++++++++++++ src/features/profile/destiny-profile.ts | 1 + .../subclass/AbilitiesModification.tsx | 50 +++-- src/features/subclass/TotalStatsDisplay.tsx | 4 +- 4 files changed, 208 insertions(+), 22 deletions(-) create mode 100644 src/components/HoverCard.tsx diff --git a/src/components/HoverCard.tsx b/src/components/HoverCard.tsx new file mode 100644 index 0000000..77453d0 --- /dev/null +++ b/src/components/HoverCard.tsx @@ -0,0 +1,175 @@ +import React, { useState } from 'react'; +import { styled, Typography } from '@mui/material'; +import { db } from '../store/db'; +import { + ManifestSubclass, + ManifestAspect, + ManifestStatPlug, + ManifestPlug, +} from '../types/manifest-types'; + +type HoverCardItem = + | ManifestSubclass + | ManifestAspect + | ManifestStatPlug + | ManifestPlug + | undefined + | null; + +interface HoverCardProps { + item: HoverCardItem; + children: React.ReactNode; +} + +const HoverCardContainer = styled('div')(({ theme }) => ({ + position: 'absolute', + top: '-100%', + left: '100%', + zIndex: 1600, + padding: theme.spacing(1.5), + backgroundColor: 'rgba(0, 0, 0, 0.8)', + borderRadius: theme.shape.borderRadius, + boxShadow: theme.shadows[10], + width: '250px', + pointerEvents: 'none', + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(1), + fontFamily: 'Helvetica, Arial, sans-serif', +})); + +const HoverCardTitle = styled(Typography)({ + fontFamily: 'Helvetica, Arial, sans-serif', + fontWeight: 'bold', + fontSize: '16px', + textAlign: 'center', + color: '#ffffff', +}); + +const HoverCardIcon = styled('img')({ + width: '100%', + height: 'auto', + objectFit: 'contain', + margin: '8px 0', +}); + +const HoverCardDescription = styled(Typography)({ + fontFamily: 'Helvetica, Arial, sans-serif', + fontSize: '14px', + color: '#cccccc', +}); + +const HoverCardStatsList = styled('ul')({ + margin: '4px 0', + paddingLeft: '20px', + color: '#cccccc', + listStyleType: 'none', +}); + +const HoverCard: React.FC = ({ item, children }) => { + const [hoverData, setHoverData] = useState(null); + + const handleMouseEnter = async () => { + if (!item) { + console.log('No item provided'); + return; + } + + const itemHash = item.itemHash; + console.log('Hovering over item with itemHash:', itemHash); + + try { + let fullData; + + fullData = await db.manifestSubclass.where('itemHash').equals(itemHash).first(); + if (fullData) { + setHoverData({ ...fullData, type: 'subclass' }); + return; + } + + fullData = await db.manifestSubclassAspectsDef.where('itemHash').equals(itemHash).first(); + if (fullData) { + setHoverData({ ...fullData, type: 'aspect' }); + return; + } + + fullData = await db.manifestSubclassFragmentsDef.where('itemHash').equals(itemHash).first(); + if (fullData) { + setHoverData({ ...fullData, type: 'fragment' }); + return; + } + + fullData = await db.manifestSubclassModDef.where('itemHash').equals(itemHash).first(); + if (fullData) { + setHoverData({ ...fullData, type: 'ability' }); + return; + } + + console.log('Item not found in any table'); + } catch (error) { + console.error('Error fetching item data:', error); + } + }; + + const handleMouseLeave = () => { + setHoverData(null); + }; + + const renderDescription = () => { + if (!hoverData) return null; + + switch (hoverData.type) { + case 'ability': + case 'subclass': + return {hoverData.description}; + + case 'aspect': + return {hoverData.flavorText}; + + case 'fragment': + const modValues = [ + { name: 'Mobility', value: hoverData.mobilityMod }, + { name: 'Resilience', value: hoverData.resilienceMod }, + { name: 'Recovery', value: hoverData.recoveryMod }, + { name: 'Discipline', value: hoverData.disciplineMod }, + { name: 'Intellect', value: hoverData.intellectMod }, + { name: 'Strength', value: hoverData.strengthMod }, + ]; + + const nonZeroMods = modValues.filter((mod) => mod.value !== 0); + + if (nonZeroMods.length > 0) { + return ( + + {nonZeroMods.map((mod, index) => ( +
  • {`${mod.name}: ${mod.value > 0 ? '+' : ''}${mod.value}`}
  • + ))} +
    + ); + } + return ; + + default: + return ; + } + }; + + return ( +
    + {children} + {hoverData && ( + + {hoverData.name} + + {renderDescription()} + + )} +
    + ); +}; + +export default HoverCard; diff --git a/src/features/profile/destiny-profile.ts b/src/features/profile/destiny-profile.ts index 5b4bc45..2af1e34 100644 --- a/src/features/profile/destiny-profile.ts +++ b/src/features/profile/destiny-profile.ts @@ -428,6 +428,7 @@ async function buildSubclassConfig(item: any, character: Character, itemComponen icon: subclass.icon, screenshot: subclass.screenshot, isOwned: subclass.isOwned, + secondaryIcon: subclass.secondaryIcon }; character.subclasses[subclass.damageType] = { diff --git a/src/features/subclass/AbilitiesModification.tsx b/src/features/subclass/AbilitiesModification.tsx index d801fcc..02afeca 100644 --- a/src/features/subclass/AbilitiesModification.tsx +++ b/src/features/subclass/AbilitiesModification.tsx @@ -6,9 +6,15 @@ import { PLUG_CATEGORY_HASH } from '../../lib/bungie_api/subclass-constants'; import { RootState } from '../../store'; import { db } from '../../store/db'; import { updateSubclassMods } from '../../store/LoadoutReducer'; -import { ManifestPlug, ManifestAspect, ManifestStatPlug } from '../../types/manifest-types'; +import { + ManifestPlug, + ManifestAspect, + ManifestStatPlug, + ManifestSubclass, +} from '../../types/manifest-types'; import { DamageType, SubclassConfig } from '../../types/d2l-types'; import { EMPTY_ASPECT, EMPTY_FRAGMENT } from '../../lib/bungie_api/constants'; +import HoverCard from '../../components/HoverCard'; interface AbilitiesModificationProps { subclass: SubclassConfig; @@ -325,19 +331,21 @@ const AbilitiesModification: React.FC = ({ subclass onMouseEnter={(e) => handleMouseEnter(e, slotId)} onMouseLeave={handleMouseLeave} > - - {isEmptyMod && ( - - {isDisabled ? 'Locked' : 'Empty'} - - )} - + + + {isEmptyMod && ( + + {isDisabled ? 'Locked' : 'Empty'} + + )} + + {isHovered && !isDisabled && ( = ({ subclass }} > {mods[category]?.map((mod) => ( - handleModSelect(category, mod, index)} - style={{ backgroundImage: `url(${mod.icon})` }} - title={mod.name} - /> + + handleModSelect(category, mod, index)} + style={{ backgroundImage: `url(${mod.icon})` }} + title={mod.name} + /> + ))} )} @@ -430,4 +439,5 @@ const AbilitiesModification: React.FC = ({ subclass ); }; + export default AbilitiesModification; diff --git a/src/features/subclass/TotalStatsDisplay.tsx b/src/features/subclass/TotalStatsDisplay.tsx index b3f1703..38eba4d 100644 --- a/src/features/subclass/TotalStatsDisplay.tsx +++ b/src/features/subclass/TotalStatsDisplay.tsx @@ -13,9 +13,9 @@ const StatsContainer = styled(Box)(({ theme }) => ({ alignItems: 'center', justifyContent: 'center', padding: theme.spacing(1), - backgroundColor: 'rgba(0, 0, 0, 0.5)', + backgroundColor: 'rgba(255, 255, 255, 0.1)', backdropFilter: 'blur(10px)', - borderRadius: theme.shape.borderRadius, + borderRadius: '0px', })); const StatItem = styled(Box)(({ theme }) => ({ From 30ac05ff78240329461d5be46144146fb1adcd90 Mon Sep 17 00:00:00 2001 From: ahmedmgamal94 <98055904+ahmedmgamal94@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:49:01 -0700 Subject: [PATCH 2/2] fixed postion --- src/components/HoverCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/HoverCard.tsx b/src/components/HoverCard.tsx index 77453d0..0cc8f42 100644 --- a/src/components/HoverCard.tsx +++ b/src/components/HoverCard.tsx @@ -24,11 +24,11 @@ interface HoverCardProps { const HoverCardContainer = styled('div')(({ theme }) => ({ position: 'absolute', top: '-100%', - left: '100%', + right: '100%', zIndex: 1600, padding: theme.spacing(1.5), backgroundColor: 'rgba(0, 0, 0, 0.8)', - borderRadius: theme.shape.borderRadius, + borderRadius: '0px', boxShadow: theme.shadows[10], width: '250px', pointerEvents: 'none',