Add type alias for searchable objects

This commit is contained in:
Justin Edmund 2022-11-30 05:19:43 -08:00
parent 322964d767
commit 73944becf4
5 changed files with 368 additions and 314 deletions

View file

@ -1,130 +1,137 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from "react"
import { useRouter } from 'next/router' import { useRouter } from "next/router"
import { useSnapshot } from 'valtio' import { useSnapshot } from "valtio"
import { useTranslation } from 'next-i18next' import { useTranslation } from "next-i18next"
import classnames from 'classnames' import classnames from "classnames"
import { appState } from '~utils/appState' import { appState } from "~utils/appState"
import CharacterHovercard from '~components/CharacterHovercard' import CharacterHovercard from "~components/CharacterHovercard"
import SearchModal from '~components/SearchModal' import SearchModal from "~components/SearchModal"
import UncapIndicator from '~components/UncapIndicator' import UncapIndicator from "~components/UncapIndicator"
import PlusIcon from '~public/icons/Add.svg' import PlusIcon from "~public/icons/Add.svg"
import './index.scss' import type { SearchableObject } from "~types"
import { getRedirectStatus } from 'next/dist/lib/load-custom-routes'
import "./index.scss"
interface Props { interface Props {
gridCharacter: GridCharacter | undefined gridCharacter?: GridCharacter
position: number position: number
editable: boolean editable: boolean
updateObject: (object: Character | Weapon | Summon, position: number) => void updateObject: (object: SearchableObject, position: number) => void
updateUncap: (id: string, position: number, uncap: number) => void updateUncap: (id: string, position: number, uncap: number) => void
} }
const CharacterUnit = (props: Props) => { const CharacterUnit = (props: Props) => {
const { t } = useTranslation('common') const { t } = useTranslation("common")
const { party, grid } = useSnapshot(appState) const { party, grid } = useSnapshot(appState)
const router = useRouter() const router = useRouter()
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en' const locale =
router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en"
const [imageUrl, setImageUrl] = useState('') const [imageUrl, setImageUrl] = useState("")
const classes = classnames({ const classes = classnames({
CharacterUnit: true, CharacterUnit: true,
'editable': props.editable, editable: props.editable,
'filled': (props.gridCharacter !== undefined) filled: props.gridCharacter !== undefined,
}) })
const gridCharacter = props.gridCharacter const gridCharacter = props.gridCharacter
const character = gridCharacter?.object const character = gridCharacter?.object
useEffect(() => { useEffect(() => {
generateImageUrl() generateImageUrl()
}) })
function generateImageUrl() { function generateImageUrl() {
let imgSrc = "" let imgSrc = ""
if (props.gridCharacter) {
const character = props.gridCharacter.object!
// Change the image based on the uncap level if (props.gridCharacter) {
let suffix = '01' const character = props.gridCharacter.object!
if (props.gridCharacter.uncap_level == 6)
suffix = '04'
else if (props.gridCharacter.uncap_level == 5)
suffix = '03'
else if (props.gridCharacter.uncap_level > 2)
suffix = '02'
// Special casing for Lyria (and Young Cat eventually) // Change the image based on the uncap level
if (props.gridCharacter.object.granblue_id === '3030182000') { let suffix = "01"
let element = 1 if (props.gridCharacter.uncap_level == 6) suffix = "04"
if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) { else if (props.gridCharacter.uncap_level == 5) suffix = "03"
element = grid.weapons.mainWeapon.element else if (props.gridCharacter.uncap_level > 2) suffix = "02"
} else if (party.element != 0) {
element = party.element
}
suffix = `${suffix}_0${element}` // Special casing for Lyria (and Young Cat eventually)
} if (props.gridCharacter.object.granblue_id === "3030182000") {
let element = 1
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-main/${character.granblue_id}_${suffix}.jpg` if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) {
element = grid.weapons.mainWeapon.element
} else if (party.element != 0) {
element = party.element
} }
setImageUrl(imgSrc) suffix = `${suffix}_0${element}`
}
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-main/${character.granblue_id}_${suffix}.jpg`
} }
function passUncapData(uncap: number) { setImageUrl(imgSrc)
if (props.gridCharacter) }
props.updateUncap(props.gridCharacter.id, props.position, uncap)
}
const image = ( function passUncapData(uncap: number) {
<div className="CharacterImage"> if (props.gridCharacter)
<img alt={character?.name.en} className="grid_image" src={imageUrl} /> props.updateUncap(props.gridCharacter.id, props.position, uncap)
{ (props.editable) ? <span className='icon'><PlusIcon /></span> : '' } }
</div>
)
const editableImage = ( const image = (
<SearchModal <div className="CharacterImage">
placeholderText={t('search.placeholders.character')} <img alt={character?.name.en} className="grid_image" src={imageUrl} />
fromPosition={props.position} {props.editable ? (
object="characters" <span className="icon">
send={props.updateObject}> <PlusIcon />
{image} </span>
</SearchModal> ) : (
) ""
)}
</div>
)
const unitContent = ( const editableImage = (
<div className={classes}> <SearchModal
{ (props.editable) ? editableImage : image } placeholderText={t("search.placeholders.character")}
{ (gridCharacter && character) ? fromPosition={props.position}
<UncapIndicator object="characters"
type="character" send={props.updateObject}
flb={character.uncap.flb || false} >
ulb={character.uncap.ulb || false} {image}
uncapLevel={gridCharacter.uncap_level} </SearchModal>
updateUncap={passUncapData} )
special={character.special}
/> : '' }
<h3 className="CharacterName">{character?.name[locale]}</h3>
</div>
)
const withHovercard = ( const unitContent = (
<CharacterHovercard gridCharacter={gridCharacter!}> <div className={classes}>
{unitContent} {props.editable ? editableImage : image}
</CharacterHovercard> {gridCharacter && character ? (
) <UncapIndicator
type="character"
flb={character.uncap.flb || false}
ulb={character.uncap.ulb || false}
uncapLevel={gridCharacter.uncap_level}
updateUncap={passUncapData}
special={character.special}
/>
) : (
""
)}
<h3 className="CharacterName">{character?.name[locale]}</h3>
</div>
)
return ( const withHovercard = (
(gridCharacter && !props.editable) ? withHovercard : unitContent <CharacterHovercard gridCharacter={gridCharacter!}>
) {unitContent}
</CharacterHovercard>
)
return gridCharacter && !props.editable ? withHovercard : unitContent
} }
export default CharacterUnit export default CharacterUnit

View file

@ -17,13 +17,14 @@ import SummonSearchFilterBar from "~components/SummonSearchFilterBar"
import CharacterResult from "~components/CharacterResult" import CharacterResult from "~components/CharacterResult"
import WeaponResult from "~components/WeaponResult" import WeaponResult from "~components/WeaponResult"
import SummonResult from "~components/SummonResult" import SummonResult from "~components/SummonResult"
import type { SearchableObject, SearchableObjectArray } from "~types"
import "./index.scss" import "./index.scss"
import CrossIcon from "~public/icons/Cross.svg" import CrossIcon from "~public/icons/Cross.svg"
import cloneDeep from "lodash.clonedeep" import cloneDeep from "lodash.clonedeep"
interface Props { interface Props {
send: (object: Character | Weapon | Summon, position: number) => any send: (object: SearchableObject, position: number) => any
placeholderText: string placeholderText: string
fromPosition: number fromPosition: number
object: "weapons" | "characters" | "summons" object: "weapons" | "characters" | "summons"
@ -51,7 +52,7 @@ const SearchModal = (props: Props) => {
const [filters, setFilters] = useState<{ [key: string]: number[] }>() const [filters, setFilters] = useState<{ [key: string]: number[] }>()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [query, setQuery] = useState("") const [query, setQuery] = useState("")
const [results, setResults] = useState<(Weapon | Summon | Character)[]>([]) const [results, setResults] = useState<SearchableObjectArray>([])
// Pagination states // Pagination states
const [recordCount, setRecordCount] = useState(0) const [recordCount, setRecordCount] = useState(0)
@ -99,10 +100,7 @@ const SearchModal = (props: Props) => {
}) })
} }
function replaceResults( function replaceResults(count: number, list: SearchableObjectArray) {
count: number,
list: Weapon[] | Summon[] | Character[]
) {
if (count > 0) { if (count > 0) {
setResults(list) setResults(list)
} else { } else {
@ -110,26 +108,36 @@ const SearchModal = (props: Props) => {
} }
} }
function appendResults(list: Weapon[] | Summon[] | Character[]) { function appendResults(list: SearchableObjectArray) {
setResults([...results, ...list]) setResults([...results, ...list])
} }
function storeRecentResult(result: Character | Weapon | Summon) { function storeRecentResult(result: SearchableObject) {
const key = `recent_${props.object}` const key = `recent_${props.object}`
const cookie = getCookie(key) const cookie = getCookie(key)
const cookieObj: Character[] | Weapon[] | Summon[] = cookie const cookieObj: SearchableObjectArray = cookie
? JSON.parse(cookie as string) ? JSON.parse(cookie as string)
: [] : []
let recents: Character[] | Weapon[] | Summon[] = [] let recents: SearchableObjectArray = []
if (props.object === "weapons") { if (props.object === "weapons") {
recents = cloneDeep(cookieObj as Weapon[]) || [] recents = cloneDeep(cookieObj as Weapon[]) || []
if (!recents.find((item) => item.granblue_id === result.granblue_id)) { if (
!recents.find(
(item) =>
(item as Weapon).granblue_id === (result as Weapon).granblue_id
)
) {
recents.unshift(result as Weapon) recents.unshift(result as Weapon)
} }
} else if (props.object === "summons") { } else if (props.object === "summons") {
recents = cloneDeep(cookieObj as Summon[]) || [] recents = cloneDeep(cookieObj as Summon[]) || []
if (!recents.find((item) => item.granblue_id === result.granblue_id)) { if (
!recents.find(
(item) =>
(item as Summon).granblue_id === (result as Summon).granblue_id
)
) {
recents.unshift(result as Summon) recents.unshift(result as Summon)
} }
} }
@ -139,7 +147,7 @@ const SearchModal = (props: Props) => {
sendData(result) sendData(result)
} }
function sendData(result: Character | Weapon | Summon) { function sendData(result: SearchableObject) {
props.send(result, props.fromPosition) props.send(result, props.fromPosition)
openChange() openChange()
} }

View file

@ -1,120 +1,143 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from "react"
import { useRouter } from 'next/router' import { useRouter } from "next/router"
import { useTranslation } from 'next-i18next' import { useTranslation } from "next-i18next"
import classnames from 'classnames' import classnames from "classnames"
import SearchModal from '~components/SearchModal' import SearchModal from "~components/SearchModal"
import SummonHovercard from '~components/SummonHovercard' import SummonHovercard from "~components/SummonHovercard"
import UncapIndicator from '~components/UncapIndicator' import UncapIndicator from "~components/UncapIndicator"
import PlusIcon from '~public/icons/Add.svg' import PlusIcon from "~public/icons/Add.svg"
import './index.scss' import type { SearchableObject } from "~types"
import "./index.scss"
interface Props { interface Props {
gridSummon: GridSummon | undefined gridSummon: GridSummon | undefined
unitType: 0 | 1 | 2 unitType: 0 | 1 | 2
position: number position: number
editable: boolean editable: boolean
updateObject: (object: Character | Weapon | Summon, position: number) => void updateObject: (object: SearchableObject, position: number) => void
updateUncap: (id: string, position: number, uncap: number) => void updateUncap: (id: string, position: number, uncap: number) => void
} }
const SummonUnit = (props: Props) => { const SummonUnit = (props: Props) => {
const { t } = useTranslation('common') const { t } = useTranslation("common")
const [imageUrl, setImageUrl] = useState('')
const router = useRouter() const [imageUrl, setImageUrl] = useState("")
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
const classes = classnames({ const router = useRouter()
SummonUnit: true, const locale =
'main': props.unitType == 0, router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en"
'grid': props.unitType == 1,
'friend': props.unitType == 2,
'editable': props.editable,
'filled': (props.gridSummon !== undefined)
})
const gridSummon = props.gridSummon const classes = classnames({
const summon = gridSummon?.object SummonUnit: true,
main: props.unitType == 0,
grid: props.unitType == 1,
friend: props.unitType == 2,
editable: props.editable,
filled: props.gridSummon !== undefined,
})
useEffect(() => { const gridSummon = props.gridSummon
generateImageUrl() const summon = gridSummon?.object
})
function generateImageUrl() { useEffect(() => {
let imgSrc = "" generateImageUrl()
if (props.gridSummon) { })
const summon = props.gridSummon.object!
const upgradedSummons = [ function generateImageUrl() {
'2040094000', '2040100000', '2040080000', '2040098000', let imgSrc = ""
'2040090000', '2040084000', '2040003000', '2040056000', if (props.gridSummon) {
'2040020000', '2040034000', '2040028000', '2040027000', const summon = props.gridSummon.object!
'2040046000', '2040047000'
] const upgradedSummons = [
"2040094000",
let suffix = '' "2040100000",
if (upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 && props.gridSummon.uncap_level == 5) "2040080000",
suffix = '_02' "2040098000",
"2040090000",
// Generate the correct source for the summon "2040084000",
if (props.unitType == 0 || props.unitType == 2) "2040003000",
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${summon.granblue_id}${suffix}.jpg` "2040056000",
else "2040020000",
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg` "2040034000",
} "2040028000",
"2040027000",
setImageUrl(imgSrc) "2040046000",
"2040047000",
]
let suffix = ""
if (
upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 &&
props.gridSummon.uncap_level == 5
)
suffix = "_02"
// Generate the correct source for the summon
if (props.unitType == 0 || props.unitType == 2)
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${summon.granblue_id}${suffix}.jpg`
else
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg`
} }
function passUncapData(uncap: number) { setImageUrl(imgSrc)
if (props.gridSummon) }
props.updateUncap(props.gridSummon.id, props.position, uncap)
}
const image = ( function passUncapData(uncap: number) {
<div className="SummonImage"> if (props.gridSummon)
<img alt={summon?.name.en} className="grid_image" src={imageUrl} /> props.updateUncap(props.gridSummon.id, props.position, uncap)
{ (props.editable) ? <span className='icon'><PlusIcon /></span> : '' } }
</div>
)
const editableImage = ( const image = (
<SearchModal <div className="SummonImage">
placeholderText={t('search.placeholders.summon')} <img alt={summon?.name.en} className="grid_image" src={imageUrl} />
fromPosition={props.position} {props.editable ? (
object="summons" <span className="icon">
send={props.updateObject}> <PlusIcon />
{image} </span>
</SearchModal> ) : (
) ""
)}
</div>
)
const unitContent = ( const editableImage = (
<div className={classes}> <SearchModal
{ (props.editable) ? editableImage : image } placeholderText={t("search.placeholders.summon")}
{ (gridSummon) ? fromPosition={props.position}
<UncapIndicator object="summons"
type="summon" send={props.updateObject}
ulb={gridSummon.object.uncap.ulb || false} >
flb={gridSummon.object.uncap.flb || false} {image}
uncapLevel={gridSummon.uncap_level} </SearchModal>
updateUncap={passUncapData} )
special={false}
/> : ''
}
<h3 className="SummonName">{summon?.name[locale]}</h3>
</div>
)
const withHovercard = ( const unitContent = (
<SummonHovercard gridSummon={gridSummon!}> <div className={classes}>
{unitContent} {props.editable ? editableImage : image}
</SummonHovercard> {gridSummon ? (
) <UncapIndicator
type="summon"
ulb={gridSummon.object.uncap.ulb || false}
flb={gridSummon.object.uncap.flb || false}
uncapLevel={gridSummon.uncap_level}
updateUncap={passUncapData}
special={false}
/>
) : (
""
)}
<h3 className="SummonName">{summon?.name[locale]}</h3>
</div>
)
return (gridSummon && !props.editable) ? withHovercard : unitContent const withHovercard = (
<SummonHovercard gridSummon={gridSummon!}>{unitContent}</SummonHovercard>
)
return gridSummon && !props.editable ? withHovercard : unitContent
} }
export default SummonUnit export default SummonUnit

View file

@ -1,131 +1,145 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from "react"
import { useRouter } from 'next/router' import { useRouter } from "next/router"
import { useTranslation } from 'next-i18next' import { useTranslation } from "next-i18next"
import classnames from 'classnames' import classnames from "classnames"
import SearchModal from '~components/SearchModal' import SearchModal from "~components/SearchModal"
import WeaponModal from '~components/WeaponModal' import WeaponModal from "~components/WeaponModal"
import WeaponHovercard from '~components/WeaponHovercard' import WeaponHovercard from "~components/WeaponHovercard"
import UncapIndicator from '~components/UncapIndicator' import UncapIndicator from "~components/UncapIndicator"
import Button from '~components/Button' import Button from "~components/Button"
import { ButtonType } from '~utils/enums' import { ButtonType } from "~utils/enums"
import type { SearchableObject } from "~types"
import PlusIcon from '~public/icons/Add.svg' import PlusIcon from "~public/icons/Add.svg"
import './index.scss' import "./index.scss"
interface Props { interface Props {
gridWeapon: GridWeapon | undefined gridWeapon: GridWeapon | undefined
unitType: 0 | 1 unitType: 0 | 1
position: number position: number
editable: boolean editable: boolean
updateObject: (object: Character | Weapon | Summon, position: number) => void updateObject: (object: SearchableObject, position: number) => void
updateUncap: (id: string, position: number, uncap: number) => void updateUncap: (id: string, position: number, uncap: number) => void
} }
const WeaponUnit = (props: Props) => { const WeaponUnit = (props: Props) => {
const { t } = useTranslation('common') const { t } = useTranslation("common")
const [imageUrl, setImageUrl] = useState('') const [imageUrl, setImageUrl] = useState("")
const router = useRouter() const router = useRouter()
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en' const locale =
router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en"
const classes = classnames({ const classes = classnames({
WeaponUnit: true, WeaponUnit: true,
'mainhand': props.unitType == 0, mainhand: props.unitType == 0,
'grid': props.unitType == 1, grid: props.unitType == 1,
'editable': props.editable, editable: props.editable,
'filled': (props.gridWeapon !== undefined) filled: props.gridWeapon !== undefined,
}) })
const gridWeapon = props.gridWeapon const gridWeapon = props.gridWeapon
const weapon = gridWeapon?.object const weapon = gridWeapon?.object
useEffect(() => { useEffect(() => {
generateImageUrl() generateImageUrl()
}) })
function generateImageUrl() { function generateImageUrl() {
let imgSrc = "" let imgSrc = ""
if (props.gridWeapon) { if (props.gridWeapon) {
const weapon = props.gridWeapon.object! const weapon = props.gridWeapon.object!
if (props.unitType == 0) { if (props.unitType == 0) {
if (props.gridWeapon.object.element == 0 && props.gridWeapon.element) if (props.gridWeapon.object.element == 0 && props.gridWeapon.element)
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${props.gridWeapon.element}.jpg` imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${props.gridWeapon.element}.jpg`
else else
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg` imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg`
} else { } else {
if (props.gridWeapon.object.element == 0 && props.gridWeapon.element) if (props.gridWeapon.object.element == 0 && props.gridWeapon.element)
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${props.gridWeapon.element}.jpg` imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${props.gridWeapon.element}.jpg`
else else
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg` imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
} }
}
setImageUrl(imgSrc)
} }
function passUncapData(uncap: number) { setImageUrl(imgSrc)
if (props.gridWeapon) }
props.updateUncap(props.gridWeapon.id, props.position, uncap)
}
function canBeModified(gridWeapon: GridWeapon) { function passUncapData(uncap: number) {
const weapon = gridWeapon.object if (props.gridWeapon)
props.updateUncap(props.gridWeapon.id, props.position, uncap)
}
return weapon.ax > 0 || function canBeModified(gridWeapon: GridWeapon) {
(weapon.series) && [2, 3, 17, 22, 24].includes(weapon.series) const weapon = gridWeapon.object
}
const image = ( return (
<div className="WeaponImage"> weapon.ax > 0 ||
<img alt={weapon?.name.en} className="grid_image" src={imageUrl} /> (weapon.series && [2, 3, 17, 22, 24].includes(weapon.series))
{ (props.editable) ? <span className='icon'><PlusIcon /></span> : '' }
</div>
) )
}
const editableImage = ( const image = (
<SearchModal <div className="WeaponImage">
placeholderText={t('search.placeholders.weapon')} <img alt={weapon?.name.en} className="grid_image" src={imageUrl} />
fromPosition={props.position} {props.editable ? (
object="weapons" <span className="icon">
send={props.updateObject}> <PlusIcon />
{image} </span>
</SearchModal> ) : (
) ""
)}
</div>
)
const unitContent = ( const editableImage = (
<div className={classes}> <SearchModal
{ (props.editable && gridWeapon && canBeModified(gridWeapon)) ? placeholderText={t("search.placeholders.weapon")}
<WeaponModal gridWeapon={gridWeapon}> fromPosition={props.position}
<div> object="weapons"
<Button icon="settings" type={ButtonType.IconOnly}/> send={props.updateObject}
</div> >
</WeaponModal>: '' } {image}
{ (props.editable) ? editableImage : image } </SearchModal>
{ (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[locale]}</h3>
</div>
)
const withHovercard = ( const unitContent = (
<WeaponHovercard gridWeapon={gridWeapon!}> <div className={classes}>
{unitContent} {props.editable && gridWeapon && canBeModified(gridWeapon) ? (
</WeaponHovercard> <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[locale]}</h3>
</div>
)
return (gridWeapon && !props.editable) ? withHovercard : unitContent const withHovercard = (
<WeaponHovercard gridWeapon={gridWeapon!}>{unitContent}</WeaponHovercard>
)
return gridWeapon && !props.editable ? withHovercard : unitContent
} }
export default WeaponUnit export default WeaponUnit

2
types/index.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
export type SearchableObject = Character | Weapon | Summon | JobSkill
export type SearchableObjectArray = (Character | Weapon | Summon | JobSkill)[]