Refactor WeaponKeySelect

No longer makes an API call for each instantiation—instead we use the weapon keys downloaded on the server
This commit is contained in:
Justin Edmund 2023-07-03 19:05:05 -07:00
parent ad2b70e819
commit c65b2597aa
2 changed files with 97 additions and 122 deletions

View file

@ -3,26 +3,23 @@ import React, { useEffect, useState } from 'react'
import Select from '~components/common/Select' import Select from '~components/common/Select'
import SelectGroup from '~components/common/SelectGroup' import SelectGroup from '~components/common/SelectGroup'
import SelectItem from '~components/common/SelectItem' import SelectItem from '~components/common/SelectItem'
import api from '~utils/api'
import { appState } from '~utils/appState'
import styles from './index.module.scss' import styles from './index.module.scss'
// Props // Props
interface Props { interface Props {
open: boolean open: boolean
currentValue?: WeaponKey weaponKey?: WeaponKey
series: number series: number
slot: number slot: number
onChange?: (value: string, slot: number) => void onChange?: (value: WeaponKey, slot: number) => void
onOpenChange: () => void onOpenChange: () => void
onClose?: () => void onClose?: () => void
} }
const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>( // Constants
function useFieldSet(props, ref) {
const [open, setOpen] = useState(false)
const [keys, setKeys] = useState<WeaponKey[][]>([])
const pendulumNames = [ const pendulumNames = [
{ en: 'Pendulum', jp: 'ペンデュラム' }, { en: 'Pendulum', jp: 'ペンデュラム' },
{ en: 'Chain', jp: 'チェイン' }, { en: 'Chain', jp: 'チェイン' },
@ -36,15 +33,49 @@ const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
{ en: 'Gate of Omnipotence', jp: 'ガフスキー' }, { en: 'Gate of Omnipotence', jp: 'ガフスキー' },
] ]
useEffect(() => { const emptyWeaponKey: WeaponKey = {
const filterParams = { id: 'no-key',
params: { granblue_id: '-1',
series: props.series, series: 0,
slot: props.slot, slot: 0,
}, slug: '',
group: 0,
order: 0,
name: { en: '', ja: '' },
} }
function organizeWeaponKeys(weaponKeys: WeaponKey[]) { const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
function useFieldSet(
{ open, weaponKey, series, slot, onChange, onOpenChange, onClose },
ref
) {
const [keys, setKeys] = useState<WeaponKey[][]>([])
useEffect(() => {
const keys = flattenWeaponKeys()
const filteredKeys = filterWeaponKeys(keys)
setKeys(groupWeaponKeys(filteredKeys))
}, [series])
function flattenWeaponKeys() {
const keys: WeaponKey[] = []
for (let setName of Object.keys(appState.weaponKeys)) {
const set = appState.weaponKeys[setName]
set.map((key) => keys.push(key))
}
return keys
}
function filterWeaponKeys(weaponKeys: WeaponKey[]) {
// Filter weapon keys based on the series and slot provided
return weaponKeys.filter(
(key) => key.series == series && key.slot == slot
)
}
function groupWeaponKeys(weaponKeys: WeaponKey[]) {
const numGroups = Math.max.apply( const numGroups = Math.max.apply(
Math, Math,
weaponKeys.map((key) => key.group) weaponKeys.map((key) => key.group)
@ -55,18 +86,9 @@ const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
if (values.length > 0) groupedKeys[i] = values if (values.length > 0) groupedKeys[i] = values
} }
setKeys(groupedKeys.filter(() => true)) return groupedKeys.filter(() => true)
} }
function fetchWeaponKeys() {
api.endpoints.weapon_keys
.getAll(filterParams)
.then((response) => organizeWeaponKeys(response.data))
}
fetchWeaponKeys()
}, [props.series, props.slot])
function weaponKeyGroup(index: number) { function weaponKeyGroup(index: number) {
;['α', 'β', 'γ', 'Δ'].sort((a, b) => a.localeCompare(b, 'el')) ;['α', 'β', 'γ', 'Δ'].sort((a, b) => a.localeCompare(b, 'el'))
@ -90,19 +112,16 @@ const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
}) })
let name: { [key: string]: string } = {} let name: { [key: string]: string } = {}
if (props.series == 2 && index == 0) name = pendulumNames[0] if (series == 2 && index == 0) name = pendulumNames[0]
else if (props.series == 2 && props.slot == 1 && index == 1) else if (series == 2 && slot == 1 && index == 1) name = pendulumNames[1]
name = pendulumNames[1] else if (series === 3) name = telumaNames[0]
else if (props.series == 3) name = telumaNames[0] else if (series === 17) name = gauphNames[slot]
else if (props.series == 17) name = gauphNames[props.slot] else if (series === 24) name = emblemNames[index]
else if (props.series == 24) name = emblemNames[index]
return ( return (
<SelectGroup <SelectGroup
key={index} key={index}
label={ label={series == 17 && slot == 2 ? name.en : `${name.en}s`}
props.series == 17 && props.slot == 2 ? name.en : `${name.en}s`
}
separator={false} separator={false}
> >
{options} {options}
@ -111,32 +130,34 @@ const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
} }
function handleChange(value: string) { function handleChange(value: string) {
if (props.onChange) props.onChange(value, props.slot) const keys = flattenWeaponKeys()
const found = keys.find((key) => key.id == value)
const weaponKey = found ? found : emptyWeaponKey
if (onChange) onChange(weaponKey, slot)
} }
const emptyOption = () => { const emptyOption = () => {
let name = '' let name = ''
if (props.series == 2) name = pendulumNames[0].en if (series === 2) name = pendulumNames[0].en
else if (props.series == 3) name = telumaNames[0].en else if (series === 3) name = telumaNames[0].en
else if (props.series == 17) name = gauphNames[props.slot].en else if (series === 17) name = gauphNames[slot].en
else if (props.series == 24) name = emblemNames[0].en else if (series === 24) name = emblemNames[0].en
return `No ${name}` return `No ${name}`
} }
return ( return (
<Select <Select
key={`weapon-key-${props.slot}`} key={`weapon-key-${slot}`}
value={props.currentValue ? props.currentValue.id : 'no-key'} value={weaponKey ? weaponKey.id : emptyWeaponKey.id}
open={props.open} open={open}
onClose={props.onClose} onClose={onClose}
onOpenChange={props.onOpenChange} onOpenChange={onOpenChange}
onValueChange={handleChange} onValueChange={handleChange}
ref={ref} ref={ref}
triggerClass="modal"
overlayVisible={false} overlayVisible={false}
> >
<SelectItem key="no-key" value="no-key"> <SelectItem key={emptyWeaponKey.id} value={emptyWeaponKey.id}>
{emptyOption()} {emptyOption()}
</SelectItem> </SelectItem>
{Array.from(Array(keys?.length)).map((x, i) => { {Array.from(Array(keys?.length)).map((x, i) => {

View file

@ -1,36 +1,3 @@
.Weapon.DialogContent {
gap: $unit;
min-width: 480px;
@include breakpoint(phone) {
min-width: inherit;
}
.DialogHeader {
transition: 0.18s padding-top ease-in-out;
position: sticky;
top: 0;
&.Scrolled {
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: 0 1px 12px rgba(0, 0, 0, 0.34);
padding-top: $unit-2x;
}
img {
transition: 0.2s width ease-in-out;
width: $unit-6x !important;
}
.DialogTitle {
font-size: $font-large;
}
.SubTitle {
display: none;
}
}
.mods { .mods {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -52,17 +19,4 @@
background-color: $grey-90; background-color: $grey-90;
} }
} }
.Button {
font-size: $font-regular;
padding: ($unit * 1.5) ($unit * 2);
width: 100%;
&.btn-disabled {
background: $grey-90;
color: $grey-70;
cursor: not-allowed;
}
}
}
} }