Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/dragoni7/d2loadouts into …
Browse files Browse the repository at this point in the history
…refresh-profile-data
  • Loading branch information
dragoni7 committed Sep 15, 2024
2 parents 54f7965 + 6becb93 commit 6c0f425
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 22 deletions.
175 changes: 175 additions & 0 deletions src/components/HoverCard.tsx
Original file line number Diff line number Diff line change
@@ -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%',
right: '100%',
zIndex: 1600,
padding: theme.spacing(1.5),
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderRadius: '0px',
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<HoverCardProps> = ({ item, children }) => {
const [hoverData, setHoverData] = useState<any | null>(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 <HoverCardDescription>{hoverData.description}</HoverCardDescription>;

case 'aspect':
return <HoverCardDescription>{hoverData.flavorText}</HoverCardDescription>;

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 (
<HoverCardStatsList>
{nonZeroMods.map((mod, index) => (
<li key={index}>{`${mod.name}: ${mod.value > 0 ? '+' : ''}${mod.value}`}</li>
))}
</HoverCardStatsList>
);
}
return <HoverCardDescription></HoverCardDescription>;

default:
return <HoverCardDescription></HoverCardDescription>;
}
};

return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={{ position: 'relative' }}
>
{children}
{hoverData && (
<HoverCardContainer>
<HoverCardTitle variant="h6">{hoverData.name}</HoverCardTitle>
<HoverCardIcon src={hoverData.secondaryIcon || hoverData.icon} alt={hoverData.name} />
{renderDescription()}
</HoverCardContainer>
)}
</div>
);
};

export default HoverCard;
50 changes: 30 additions & 20 deletions src/features/subclass/AbilitiesModification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -325,19 +331,21 @@ const AbilitiesModification: React.FC<AbilitiesModificationProps> = ({ subclass
onMouseEnter={(e) => handleMouseEnter(e, slotId)}
onMouseLeave={handleMouseLeave}
>
<SlotComponent
style={{
backgroundImage: currentMod ? `url(${currentMod.icon})` : 'none',
opacity: isDisabled ? 0.5 : 1,
pointerEvents: isDisabled ? 'none' : 'auto',
}}
>
{isEmptyMod && (
<Typography variant="caption" style={{ color: 'rgba(255, 255, 255, 0.7)' }}>
{isDisabled ? 'Locked' : 'Empty'}
</Typography>
)}
</SlotComponent>
<HoverCard item={currentMod}>
<SlotComponent
style={{
backgroundImage: currentMod ? `url(${currentMod.icon})` : 'none',
opacity: isDisabled ? 0.5 : 1,
pointerEvents: isDisabled ? 'none' : 'auto',
}}
>
{isEmptyMod && (
<Typography variant="caption" style={{ color: 'rgba(255, 255, 255, 0.7)' }}>
{isDisabled ? 'Locked' : 'Empty'}
</Typography>
)}
</SlotComponent>
</HoverCard>
{isHovered && !isDisabled && (
<SubmenuContainer
style={{
Expand All @@ -346,12 +354,13 @@ const AbilitiesModification: React.FC<AbilitiesModificationProps> = ({ subclass
}}
>
{mods[category]?.map((mod) => (
<OptionButton
key={mod.itemHash}
onClick={() => handleModSelect(category, mod, index)}
style={{ backgroundImage: `url(${mod.icon})` }}
title={mod.name}
/>
<HoverCard item={mod} key={mod.itemHash}>
<OptionButton
onClick={() => handleModSelect(category, mod, index)}
style={{ backgroundImage: `url(${mod.icon})` }}
title={mod.name}
/>
</HoverCard>
))}
</SubmenuContainer>
)}
Expand Down Expand Up @@ -430,4 +439,5 @@ const AbilitiesModification: React.FC<AbilitiesModificationProps> = ({ subclass
</Container>
);
};

export default AbilitiesModification;
4 changes: 2 additions & 2 deletions src/features/subclass/TotalStatsDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => ({
Expand Down
1 change: 1 addition & 0 deletions src/util/profile-characters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ async function buildSubclassConfig(item: any, itemComponents: any): Promise<Subc
icon: subclass.icon,
screenshot: subclass.screenshot,
isOwned: subclass.isOwned,
secondaryIcon: subclass.secondaryIcon
};

const subclassConfig: SubclassConfig = {
Expand Down

0 comments on commit 6c0f425

Please sign in to comment.