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 = ( -
- {character?.name.en} - { (props.editable) ? : '' } -
- ) + function passUncapData(uncap: number) { + if (props.gridCharacter) + props.updateUncap(props.gridCharacter.id, props.position, uncap) + } - const editableImage = ( - - {image} - - ) + const image = ( +
+ {character?.name.en} + {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 = ( -
- {summon?.name.en} - { (props.editable) ? : '' } -
- ) + function passUncapData(uncap: number) { + if (props.gridSummon) + props.updateUncap(props.gridSummon.id, props.position, uncap) + } - const editableImage = ( - - {image} - - ) + const image = ( +
+ {summon?.name.en} + {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 = ( -
- {weapon?.name.en} - { (props.editable) ? : '' } -
+ return ( + weapon.ax > 0 || + (weapon.series && [2, 3, 17, 22, 24].includes(weapon.series)) ) + } - const editableImage = ( - - {image} - - ) + const image = ( +
+ {weapon?.name.en} + {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)[]