diff --git a/components/CharacterUnit/index.tsx b/components/CharacterUnit/index.tsx
index 337357e3..13e46635 100644
--- a/components/CharacterUnit/index.tsx
+++ b/components/CharacterUnit/index.tsx
@@ -1,130 +1,137 @@
-import React, { useEffect, useState } from 'react'
-import { useRouter } from 'next/router'
-import { useSnapshot } from 'valtio'
-import { useTranslation } from 'next-i18next'
-import classnames from 'classnames'
+import React, { useEffect, useState } from "react"
+import { useRouter } from "next/router"
+import { useSnapshot } from "valtio"
+import { useTranslation } from "next-i18next"
+import classnames from "classnames"
-import { appState } from '~utils/appState'
+import { appState } from "~utils/appState"
-import CharacterHovercard from '~components/CharacterHovercard'
-import SearchModal from '~components/SearchModal'
-import UncapIndicator from '~components/UncapIndicator'
-import PlusIcon from '~public/icons/Add.svg'
+import CharacterHovercard from "~components/CharacterHovercard"
+import SearchModal from "~components/SearchModal"
+import UncapIndicator from "~components/UncapIndicator"
+import PlusIcon from "~public/icons/Add.svg"
-import './index.scss'
-import { getRedirectStatus } from 'next/dist/lib/load-custom-routes'
+import type { SearchableObject } from "~types"
+
+import "./index.scss"
interface Props {
- gridCharacter: GridCharacter | undefined
- position: number
- editable: boolean
- updateObject: (object: Character | Weapon | Summon, position: number) => void
- updateUncap: (id: string, position: number, uncap: number) => void
+ gridCharacter?: GridCharacter
+ position: number
+ editable: boolean
+ updateObject: (object: SearchableObject, position: number) => void
+ updateUncap: (id: string, position: number, uncap: number) => void
}
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 locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
+ const router = useRouter()
+ const locale =
+ router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en"
- const [imageUrl, setImageUrl] = useState('')
+ const [imageUrl, setImageUrl] = useState("")
- const classes = classnames({
- CharacterUnit: true,
- 'editable': props.editable,
- 'filled': (props.gridCharacter !== undefined)
- })
+ const classes = classnames({
+ CharacterUnit: true,
+ editable: props.editable,
+ filled: props.gridCharacter !== undefined,
+ })
- const gridCharacter = props.gridCharacter
- const character = gridCharacter?.object
+ const gridCharacter = props.gridCharacter
+ const character = gridCharacter?.object
- useEffect(() => {
- generateImageUrl()
- })
+ useEffect(() => {
+ generateImageUrl()
+ })
- function generateImageUrl() {
- let imgSrc = ""
-
- if (props.gridCharacter) {
- const character = props.gridCharacter.object!
+ function generateImageUrl() {
+ let imgSrc = ""
- // Change the image based on the uncap level
- let suffix = '01'
- 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'
+ if (props.gridCharacter) {
+ const character = props.gridCharacter.object!
- // Special casing for Lyria (and Young Cat eventually)
- if (props.gridCharacter.object.granblue_id === '3030182000') {
- let element = 1
- if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) {
- element = grid.weapons.mainWeapon.element
- } else if (party.element != 0) {
- element = party.element
- }
+ // Change the image based on the uncap level
+ let suffix = "01"
+ 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"
- suffix = `${suffix}_0${element}`
- }
-
- imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-main/${character.granblue_id}_${suffix}.jpg`
+ // Special casing for Lyria (and Young Cat eventually)
+ if (props.gridCharacter.object.granblue_id === "3030182000") {
+ let element = 1
+ 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) {
- if (props.gridCharacter)
- props.updateUncap(props.gridCharacter.id, props.position, uncap)
- }
+ setImageUrl(imgSrc)
+ }
- const image = (
-
-

- { (props.editable) ?
: '' }
-
- )
+ function passUncapData(uncap: number) {
+ if (props.gridCharacter)
+ props.updateUncap(props.gridCharacter.id, props.position, uncap)
+ }
- const editableImage = (
-
- {image}
-
- )
+ const image = (
+
+

+ {props.editable ? (
+
+
+
+ ) : (
+ ""
+ )}
+
+ )
- const unitContent = (
-
- { (props.editable) ? editableImage : image }
- { (gridCharacter && character) ?
- : '' }
-
{character?.name[locale]}
-
- )
+ const editableImage = (
+
+ {image}
+
+ )
- const withHovercard = (
-
- {unitContent}
-
- )
+ const unitContent = (
+
+ {props.editable ? editableImage : image}
+ {gridCharacter && character ? (
+
+ ) : (
+ ""
+ )}
+
{character?.name[locale]}
+
+ )
- return (
- (gridCharacter && !props.editable) ? withHovercard : unitContent
- )
+ const withHovercard = (
+
+ {unitContent}
+
+ )
+
+ return gridCharacter && !props.editable ? withHovercard : unitContent
}
export default CharacterUnit
diff --git a/components/SearchModal/index.tsx b/components/SearchModal/index.tsx
index 45d9b5ce..e049a33e 100644
--- a/components/SearchModal/index.tsx
+++ b/components/SearchModal/index.tsx
@@ -17,13 +17,14 @@ import SummonSearchFilterBar from "~components/SummonSearchFilterBar"
import CharacterResult from "~components/CharacterResult"
import WeaponResult from "~components/WeaponResult"
import SummonResult from "~components/SummonResult"
+import type { SearchableObject, SearchableObjectArray } from "~types"
import "./index.scss"
import CrossIcon from "~public/icons/Cross.svg"
import cloneDeep from "lodash.clonedeep"
interface Props {
- send: (object: Character | Weapon | Summon, position: number) => any
+ send: (object: SearchableObject, position: number) => any
placeholderText: string
fromPosition: number
object: "weapons" | "characters" | "summons"
@@ -51,7 +52,7 @@ const SearchModal = (props: Props) => {
const [filters, setFilters] = useState<{ [key: string]: number[] }>()
const [open, setOpen] = useState(false)
const [query, setQuery] = useState("")
- const [results, setResults] = useState<(Weapon | Summon | Character)[]>([])
+ const [results, setResults] = useState([])
// Pagination states
const [recordCount, setRecordCount] = useState(0)
@@ -99,10 +100,7 @@ const SearchModal = (props: Props) => {
})
}
- function replaceResults(
- count: number,
- list: Weapon[] | Summon[] | Character[]
- ) {
+ function replaceResults(count: number, list: SearchableObjectArray) {
if (count > 0) {
setResults(list)
} else {
@@ -110,26 +108,36 @@ const SearchModal = (props: Props) => {
}
}
- function appendResults(list: Weapon[] | Summon[] | Character[]) {
+ function appendResults(list: SearchableObjectArray) {
setResults([...results, ...list])
}
- function storeRecentResult(result: Character | Weapon | Summon) {
+ function storeRecentResult(result: SearchableObject) {
const key = `recent_${props.object}`
const cookie = getCookie(key)
- const cookieObj: Character[] | Weapon[] | Summon[] = cookie
+ const cookieObj: SearchableObjectArray = cookie
? JSON.parse(cookie as string)
: []
- let recents: Character[] | Weapon[] | Summon[] = []
+ let recents: SearchableObjectArray = []
if (props.object === "weapons") {
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)
}
} else if (props.object === "summons") {
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)
}
}
@@ -139,7 +147,7 @@ const SearchModal = (props: Props) => {
sendData(result)
}
- function sendData(result: Character | Weapon | Summon) {
+ function sendData(result: SearchableObject) {
props.send(result, props.fromPosition)
openChange()
}
diff --git a/components/SummonUnit/index.tsx b/components/SummonUnit/index.tsx
index 7128551f..462a9db0 100644
--- a/components/SummonUnit/index.tsx
+++ b/components/SummonUnit/index.tsx
@@ -1,120 +1,143 @@
-import React, { useEffect, useState } from 'react'
-import { useRouter } from 'next/router'
-import { useTranslation } from 'next-i18next'
-import classnames from 'classnames'
+import React, { useEffect, useState } from "react"
+import { useRouter } from "next/router"
+import { useTranslation } from "next-i18next"
+import classnames from "classnames"
-import SearchModal from '~components/SearchModal'
-import SummonHovercard from '~components/SummonHovercard'
-import UncapIndicator from '~components/UncapIndicator'
-import PlusIcon from '~public/icons/Add.svg'
+import SearchModal from "~components/SearchModal"
+import SummonHovercard from "~components/SummonHovercard"
+import UncapIndicator from "~components/UncapIndicator"
+import PlusIcon from "~public/icons/Add.svg"
-import './index.scss'
+import type { SearchableObject } from "~types"
+
+import "./index.scss"
interface Props {
- gridSummon: GridSummon | undefined
- unitType: 0 | 1 | 2
- position: number
- editable: boolean
- updateObject: (object: Character | Weapon | Summon, position: number) => void
- updateUncap: (id: string, position: number, uncap: number) => void
+ gridSummon: GridSummon | undefined
+ unitType: 0 | 1 | 2
+ position: number
+ editable: boolean
+ updateObject: (object: SearchableObject, position: number) => void
+ updateUncap: (id: string, position: number, uncap: number) => void
}
const SummonUnit = (props: Props) => {
- const { t } = useTranslation('common')
-
- const [imageUrl, setImageUrl] = useState('')
+ const { t } = useTranslation("common")
- const router = useRouter()
- const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
+ const [imageUrl, setImageUrl] = useState("")
- const classes = classnames({
- SummonUnit: true,
- 'main': props.unitType == 0,
- 'grid': props.unitType == 1,
- 'friend': props.unitType == 2,
- 'editable': props.editable,
- 'filled': (props.gridSummon !== undefined)
- })
+ const router = useRouter()
+ const locale =
+ router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en"
- const gridSummon = props.gridSummon
- const summon = gridSummon?.object
+ const classes = classnames({
+ SummonUnit: true,
+ main: props.unitType == 0,
+ grid: props.unitType == 1,
+ friend: props.unitType == 2,
+ editable: props.editable,
+ filled: props.gridSummon !== undefined,
+ })
- useEffect(() => {
- generateImageUrl()
- })
+ const gridSummon = props.gridSummon
+ const summon = gridSummon?.object
- function generateImageUrl() {
- let imgSrc = ""
- if (props.gridSummon) {
- const summon = props.gridSummon.object!
+ useEffect(() => {
+ generateImageUrl()
+ })
- const upgradedSummons = [
- '2040094000', '2040100000', '2040080000', '2040098000',
- '2040090000', '2040084000', '2040003000', '2040056000',
- '2040020000', '2040034000', '2040028000', '2040027000',
- '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`
- }
-
- setImageUrl(imgSrc)
+ function generateImageUrl() {
+ let imgSrc = ""
+ if (props.gridSummon) {
+ const summon = props.gridSummon.object!
+
+ const upgradedSummons = [
+ "2040094000",
+ "2040100000",
+ "2040080000",
+ "2040098000",
+ "2040090000",
+ "2040084000",
+ "2040003000",
+ "2040056000",
+ "2040020000",
+ "2040034000",
+ "2040028000",
+ "2040027000",
+ "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) {
- if (props.gridSummon)
- props.updateUncap(props.gridSummon.id, props.position, uncap)
- }
+ setImageUrl(imgSrc)
+ }
- const image = (
-
-

- { (props.editable) ?
: '' }
-
- )
+ function passUncapData(uncap: number) {
+ if (props.gridSummon)
+ props.updateUncap(props.gridSummon.id, props.position, uncap)
+ }
- const editableImage = (
-
- {image}
-
- )
+ const image = (
+
+

+ {props.editable ? (
+
+
+
+ ) : (
+ ""
+ )}
+
+ )
- const unitContent = (
-
- { (props.editable) ? editableImage : image }
- { (gridSummon) ?
- : ''
- }
-
{summon?.name[locale]}
-
- )
+ const editableImage = (
+
+ {image}
+
+ )
- const withHovercard = (
-
- {unitContent}
-
- )
+ const unitContent = (
+
+ {props.editable ? editableImage : image}
+ {gridSummon ? (
+
+ ) : (
+ ""
+ )}
+
{summon?.name[locale]}
+
+ )
- return (gridSummon && !props.editable) ? withHovercard : unitContent
+ const withHovercard = (
+ {unitContent}
+ )
+
+ return gridSummon && !props.editable ? withHovercard : unitContent
}
export default SummonUnit
diff --git a/components/WeaponUnit/index.tsx b/components/WeaponUnit/index.tsx
index faecf00f..51edee6e 100644
--- a/components/WeaponUnit/index.tsx
+++ b/components/WeaponUnit/index.tsx
@@ -1,131 +1,145 @@
-import React, { useEffect, useState } from 'react'
-import { useRouter } from 'next/router'
-import { useTranslation } from 'next-i18next'
-import classnames from 'classnames'
+import React, { useEffect, useState } from "react"
+import { useRouter } from "next/router"
+import { useTranslation } from "next-i18next"
+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'
+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"
-import { ButtonType } from '~utils/enums'
+import { ButtonType } from "~utils/enums"
+import type { SearchableObject } from "~types"
-import PlusIcon from '~public/icons/Add.svg'
-import './index.scss'
+import PlusIcon from "~public/icons/Add.svg"
+import "./index.scss"
interface Props {
- gridWeapon: GridWeapon | undefined
- unitType: 0 | 1
- position: number
- editable: boolean
- updateObject: (object: Character | Weapon | Summon, position: number) => void
- updateUncap: (id: string, position: number, uncap: number) => void
+ gridWeapon: GridWeapon | undefined
+ unitType: 0 | 1
+ position: number
+ editable: boolean
+ updateObject: (object: SearchableObject, position: number) => void
+ updateUncap: (id: string, position: number, uncap: number) => void
}
const WeaponUnit = (props: Props) => {
- const { t } = useTranslation('common')
+ const { t } = useTranslation("common")
- const [imageUrl, setImageUrl] = useState('')
+ const [imageUrl, setImageUrl] = useState("")
- const router = useRouter()
- const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
+ const router = useRouter()
+ const locale =
+ router.locale && ["en", "ja"].includes(router.locale) ? router.locale : "en"
- const classes = classnames({
- WeaponUnit: true,
- 'mainhand': props.unitType == 0,
- 'grid': props.unitType == 1,
- 'editable': props.editable,
- 'filled': (props.gridWeapon !== undefined)
- })
+ const classes = classnames({
+ WeaponUnit: true,
+ mainhand: props.unitType == 0,
+ grid: props.unitType == 1,
+ editable: props.editable,
+ filled: props.gridWeapon !== undefined,
+ })
- const gridWeapon = props.gridWeapon
- const weapon = gridWeapon?.object
+ const gridWeapon = props.gridWeapon
+ const weapon = gridWeapon?.object
- useEffect(() => {
- generateImageUrl()
- })
+ useEffect(() => {
+ generateImageUrl()
+ })
- function generateImageUrl() {
- let imgSrc = ""
- if (props.gridWeapon) {
- const weapon = props.gridWeapon.object!
-
- if (props.unitType == 0) {
- 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`
- else
- imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg`
- } else {
- 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`
- else
- imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
- }
- }
-
- setImageUrl(imgSrc)
+ function generateImageUrl() {
+ let imgSrc = ""
+ if (props.gridWeapon) {
+ const weapon = props.gridWeapon.object!
+
+ if (props.unitType == 0) {
+ 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`
+ else
+ imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg`
+ } else {
+ 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`
+ else
+ imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
+ }
}
- function passUncapData(uncap: number) {
- if (props.gridWeapon)
- props.updateUncap(props.gridWeapon.id, props.position, uncap)
- }
+ setImageUrl(imgSrc)
+ }
- function canBeModified(gridWeapon: GridWeapon) {
- const weapon = gridWeapon.object
+ function passUncapData(uncap: number) {
+ if (props.gridWeapon)
+ props.updateUncap(props.gridWeapon.id, props.position, uncap)
+ }
- return weapon.ax > 0 ||
- (weapon.series) && [2, 3, 17, 22, 24].includes(weapon.series)
- }
+ function canBeModified(gridWeapon: GridWeapon) {
+ const weapon = gridWeapon.object
- const image = (
-
-

- { (props.editable) ?
: '' }
-
+ return (
+ weapon.ax > 0 ||
+ (weapon.series && [2, 3, 17, 22, 24].includes(weapon.series))
)
+ }
- const editableImage = (
-
- {image}
-
- )
+ const image = (
+
+

+ {props.editable ? (
+
+
+
+ ) : (
+ ""
+ )}
+
+ )
- const unitContent = (
-
- { (props.editable && gridWeapon && canBeModified(gridWeapon)) ?
-
-
-
- : '' }
- { (props.editable) ? editableImage : image }
- { (gridWeapon) ?
-
: ''
- }
-
{weapon?.name[locale]}
-
- )
+ const editableImage = (
+
+ {image}
+
+ )
- const withHovercard = (
-
- {unitContent}
-
- )
+ const unitContent = (
+
+ {props.editable && gridWeapon && canBeModified(gridWeapon) ? (
+
+
+
+
+
+ ) : (
+ ""
+ )}
+ {props.editable ? editableImage : image}
+ {gridWeapon ? (
+
+ ) : (
+ ""
+ )}
+
{weapon?.name[locale]}
+
+ )
- return (gridWeapon && !props.editable) ? withHovercard : unitContent
+ const withHovercard = (
+ {unitContent}
+ )
+
+ return gridWeapon && !props.editable ? withHovercard : unitContent
}
export default WeaponUnit
diff --git a/types/index.d.ts b/types/index.d.ts
new file mode 100644
index 00000000..be978e8d
--- /dev/null
+++ b/types/index.d.ts
@@ -0,0 +1,2 @@
+export type SearchableObject = Character | Weapon | Summon | JobSkill
+export type SearchableObjectArray = (Character | Weapon | Summon | JobSkill)[]