Add and implement WeaponHovercard component

This commit is contained in:
Justin Edmund 2022-03-04 00:16:58 -08:00
parent be60319f98
commit f950543c96
4 changed files with 327 additions and 21 deletions

View file

@ -0,0 +1,41 @@
.Weapon.Hovercard {
.skills {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-right: $unit * 2;
.axSkill {
align-items: center;
display: flex;
flex-direction: row;
&.primary img {
height: 64px;
width: 64px;
}
&.secondary {
gap: $unit * 1.5;
img {
height: 36px;
width: 36px;
}
}
span {
font-size: $font-small;
font-weight: $medium;
text-align: center;
}
}
}
.weaponKeys {
display: flex;
flex-direction: column;
font-size: $normal;
gap: $unit / 2;
}
}

View file

@ -0,0 +1,161 @@
import React from 'react'
import * as HoverCard from '@radix-ui/react-hover-card'
import WeaponLabelIcon from '~components/WeaponLabelIcon'
import UncapIndicator from '~components/UncapIndicator'
import { axData } from '~utils/axData'
import './index.scss'
import { keys } from 'lodash'
interface Props {
gridWeapon: GridWeapon
children: React.ReactNode
}
interface KeyNames {
[key: string]: {
en: string,
jp: string
}
}
const WeaponHovercard = (props: Props) => {
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
const WeaponKeyNames: KeyNames = {
'2': {
en: 'Pendulum',
jp: ''
},
'3': {
en: 'Teluma',
jp: ''
},
'17': {
en: 'Gauph Key',
jp: ''
},
'22': {
en: 'Emblem',
jp: ''
}
}
const tintElement = (props.gridWeapon.object.element == 0 && props.gridWeapon.element) ? Element[props.gridWeapon.element] : Element[props.gridWeapon.object.element]
const wikiUrl = `https://gbf.wiki/${props.gridWeapon.object.name.en.replaceAll(' ', '_')}`
const createPrimaryAxSkillString = () => {
const primaryAxSkills = axData[props.gridWeapon.object.ax - 1]
if (props.gridWeapon.ax) {
const simpleAxSkill = props.gridWeapon.ax[0]
const axSkill = primaryAxSkills.find(skill => skill.id == simpleAxSkill.modifier)
return `${axSkill?.name.en} +${simpleAxSkill.strength}${ (axSkill?.suffix) ? axSkill.suffix : '' }`
}
return ''
}
const createSecondaryAxSkillString = () => {
const primaryAxSkills = axData[props.gridWeapon.object.ax - 1]
if (props.gridWeapon.ax) {
const primarySimpleAxSkill = props.gridWeapon.ax[0]
const secondarySimpleAxSkill = props.gridWeapon.ax[1]
const primaryAxSkill = primaryAxSkills.find(skill => skill.id == primarySimpleAxSkill.modifier)
if (primaryAxSkill && primaryAxSkill.secondary) {
const secondaryAxSkill = primaryAxSkill.secondary.find(skill => skill.id == secondarySimpleAxSkill.modifier)
return `${secondaryAxSkill?.name.en} +${secondarySimpleAxSkill.strength}${ (secondaryAxSkill?.suffix) ? secondaryAxSkill.suffix : '' }`
}
}
return ''
}
function weaponImage() {
const weapon = props.gridWeapon.object
if (props.gridWeapon.object.element == 0 && props.gridWeapon.element)
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${props.gridWeapon.element}.jpg`
else
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
}
const keysSection = (
<section className="weaponKeys">
{ (WeaponKeyNames[props.gridWeapon.object.series]) ?
<h5 className={tintElement}>{ WeaponKeyNames[props.gridWeapon.object.series].en }s</h5> : ''
}
{ (props.gridWeapon.weapon_keys) ?
Array.from(Array(props.gridWeapon.weapon_keys.length)).map((x, i) => {
return (
<div className="weaponKey" key={props.gridWeapon.weapon_keys![i].id}>
<span>{props.gridWeapon.weapon_keys![i].name.en}</span>
</div>
)
}) : '' }
</section>
)
const axSection = (
<section className="axSkills">
<h5 className={tintElement}>AX Skills</h5>
<div className="skills">
<div className="primary axSkill">
<img src={`/icons/ax/primary_${ (props.gridWeapon.ax) ? props.gridWeapon.ax[0].modifier : '' }.png`} />
<span>{createPrimaryAxSkillString()}</span>
</div>
{ (props.gridWeapon.ax && props.gridWeapon.ax[1].modifier && props.gridWeapon.ax[1].strength) ?
<div className="secondary axSkill">
<img src={`/icons/ax/secondary_${ (props.gridWeapon.ax) ? props.gridWeapon.ax[1].modifier : '' }.png`} />
<span>{createSecondaryAxSkillString()}</span>
</div> : ''}
</div>
</section>
)
return (
<HoverCard.Root>
<HoverCard.Trigger>
{ props.children }
</HoverCard.Trigger>
<HoverCard.Content className="Weapon Hovercard">
<div className="top">
<div className="title">
<h4>{ props.gridWeapon.object.name.en }</h4>
<img alt={props.gridWeapon.object.name.en} src={weaponImage()} />
</div>
<div className="subInfo">
<div className="icons">
{ (props.gridWeapon.object.element !== 0 || (props.gridWeapon.object.element === 0 && props.gridWeapon.element != null)) ?
<WeaponLabelIcon labelType={ (props.gridWeapon.object.element === 0 && props.gridWeapon.element !== 0) ? Element[props.gridWeapon.element] : Element[props.gridWeapon.object.element] } />
: '' }
<WeaponLabelIcon labelType={ Proficiency[props.gridWeapon.object.proficiency] } />
</div>
<UncapIndicator
type="weapon"
ulb={props.gridWeapon.object.uncap.ulb || false}
flb={props.gridWeapon.object.uncap.flb || false}
special={false}
/>
</div>
</div>
{ (props.gridWeapon.object.ax > 0 && props.gridWeapon.ax && props.gridWeapon.ax[0].modifier && props.gridWeapon.ax[0].strength ) ? axSection : '' }
{ (props.gridWeapon.weapon_keys && props.gridWeapon.weapon_keys.length > 0) ? keysSection : '' }
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">View more on gbf.wiki</a>
<HoverCard.Arrow />
</HoverCard.Content>
</HoverCard.Root>
)
}
export default WeaponHovercard

View file

@ -3,6 +3,7 @@ import classnames from 'classnames'
import SearchModal from '~components/SearchModal'
import WeaponModal from '~components/WeaponModal'
import WeaponHovercard from '~components/WeaponHovercard'
import UncapIndicator from '~components/UncapIndicator'
import Button from '~components/Button'
@ -88,28 +89,38 @@ const WeaponUnit = (props: Props) => {
</SearchModal>
)
return (
const unitContent = (
<div>
<div className={classes}>
{ (props.editable && gridWeapon && canBeModified(gridWeapon)) ?
<WeaponModal gridWeapon={gridWeapon}>
<div>
<Button icon="settings" type={ButtonType.IconOnly}/>
</div>
</WeaponModal>: '' }
{ (props.editable) ? editableImage : image }
{ (gridWeapon) ?
<UncapIndicator
type="weapon"
ulb={gridWeapon.object.uncap.ulb || false}
flb={gridWeapon.object.uncap.flb || false}
uncapLevel={gridWeapon.uncap_level}
updateUncap={passUncapData}
special={false}
/> : ''
}
<h3 className="WeaponName">{weapon?.name.en}</h3>
</div>
{ (props.editable && gridWeapon && canBeModified(gridWeapon)) ?
<WeaponModal gridWeapon={gridWeapon}>
<div>
<Button icon="settings" type={ButtonType.IconOnly}/>
</div>
</WeaponModal>: '' }
{ (props.editable) ? editableImage : image }
{ (gridWeapon) ?
<UncapIndicator
type="weapon"
ulb={gridWeapon.object.uncap.ulb || false}
flb={gridWeapon.object.uncap.flb || false}
uncapLevel={gridWeapon.uncap_level}
updateUncap={passUncapData}
special={false}
/> : ''
}
<h3 className="WeaponName">{weapon?.name.en}</h3>
</div>
)
const withHovercard = (
<WeaponHovercard gridWeapon={gridWeapon!}>
{unitContent}
</WeaponHovercard>
)
return (
<div className={classes}>
{ (gridWeapon) ? withHovercard : unitContent }
</div>
)
}

View file

@ -175,6 +175,99 @@ select {
}
}
.Hovercard {
background: #222;
border-radius: $unit;
color: white;
display: flex;
flex-direction: column;
gap: $unit * 2;
padding: $unit * 2;
min-width: 300px;
.top {
display: flex;
flex-direction: column;
gap: $unit / 2;
.title {
align-items: center;
display: flex;
flex-direction: row;
gap: $unit * 2;
h4 {
flex-grow: 1;
font-size: $font-medium;
line-height: 1.2;
min-width: 140px;
}
img {
height: auto;
width: 100px;
}
}
.subInfo {
align-items: center;
display: flex;
flex-direction: row;
gap: $unit * 2;
.icons {
display: flex;
flex-direction: row;
flex-grow: 1;
gap: $unit;
}
.UncapIndicator {
width: 100px;
}
}
}
section {
h5 {
font-size: $font-small;
font-weight: $medium;
opacity: 0.7;
&.wind {
color: $wind-bg-light;
}
&.fire {
color: $fire-bg-light;
}
&.water {
color: $water-bg-light;
}
&.earth {
color: $earth-bg-light;
}
&.dark {
color: $dark-bg-light;
}
&.light {
color: $light-bg-light;
}
}
}
a.Button {
display: block;
padding: $unit * 1.5;
text-align: center;
}
}
#Teams, #Profile {
display: flex;
height: 100%;