Fix AwakeningSelect component

It was completely broken for weapons. We managed to fix the problem by refactoring how data is sent to SelectWithInput but I fear the root error is still there.

We also cleaned the component up a bit.
This commit is contained in:
Justin Edmund 2023-01-20 19:29:07 -08:00
parent 39940abf9f
commit 6023f9ab6a
5 changed files with 60 additions and 87 deletions

View file

@ -1,51 +1,41 @@
import React, { useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import cloneDeep from 'lodash.clonedeep'
import SelectWithInput from '~components/SelectWithInput'
import SelectItem from '~components/SelectItem'
import classNames from 'classnames'
import { weaponAwakening, characterAwakening } from '~data/awakening'
import type { Awakening } from '~data/awakening'
import './index.scss'
interface Props {
object: 'character' | 'weapon'
awakeningType?: number
awakeningLevel?: number
type?: number
level?: number
onOpenChange?: (open: boolean) => void
sendValidity: (isValid: boolean) => void
sendValues: (type: number, level: number) => void
}
const AwakeningSelect = (props: Props) => {
const router = useRouter()
const locale =
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
const { t } = useTranslation('common')
const [open, setOpen] = useState(false)
// States
// Data states
const [awakeningType, setAwakeningType] = useState(
props.object === 'weapon' ? -1 : 1
props.object === 'weapon' ? 0 : 1
)
const [awakeningLevel, setAwakeningLevel] = useState(1)
const [maxValue, setMaxValue] = useState(1)
const [error, setError] = useState('')
// Data
const dataSet = () => {
if (props.object === 'character') return characterAwakening
else {
const weaponDataSet = weaponAwakening
const chooseDataset = () => {
let list: ItemSkill[] = []
weaponDataSet.unshift({
switch (props.object) {
case 'character':
list = characterAwakening
break
case 'weapon':
// WARNING: Clonedeep is masking a deeper error
// which is running this method every time this component is rerendered
// causing multiple "No awakening" items to be added
const awakening = cloneDeep(weaponAwakening)
awakening.unshift({
id: 0,
name: {
en: 'No awakening',
@ -56,48 +46,30 @@ const AwakeningSelect = (props: Props) => {
maxValue: 0,
fractional: false,
})
return weaponDataSet
}
list = awakening
break
}
// Classes
const inputClasses = classNames({
Bound: true,
Hidden: awakeningType === -1,
})
const errorClasses = classNames({
errors: true,
visible: error !== '',
})
// Set max value based on object type
useEffect(() => {
if (props.object === 'character') setMaxValue(9)
else if (props.object === 'weapon') setMaxValue(15)
}, [props.object])
return list
}
// Set default awakening and level based on object type
useEffect(() => {
let defaultAwakening = 1
if (props.object === 'weapon') defaultAwakening = -1
const defaultAwakening = props.object === 'weapon' ? 0 : 1
const type = props.type != undefined ? props.type : defaultAwakening
setAwakeningType(
props.awakeningType != undefined ? props.awakeningType : defaultAwakening
)
setAwakeningLevel(props.awakeningLevel ? props.awakeningLevel : 1)
}, [props.object, props.awakeningType, props.awakeningLevel])
setAwakeningType(type)
setAwakeningLevel(props.level ? props.level : 1)
}, [props.object, props.type, props.level])
// Send validity of form when awakening level changes
useEffect(() => {
props.sendValidity(awakeningLevel > 0 && error === '')
}, [props.sendValidity, awakeningLevel, error])
props.sendValidity(awakeningLevel > 0)
}, [props.sendValidity, awakeningLevel])
// Classes
function changeOpen() {
setOpen(!open)
if (props.onOpenChange) props.onOpenChange(!open)
function changeOpen(open: boolean) {
if (props.onOpenChange) props.onOpenChange(open)
}
function handleValueChange(type: number, level: number) {
@ -110,7 +82,7 @@ const AwakeningSelect = (props: Props) => {
<div className="Awakening">
<SelectWithInput
object={`${props.object}_awakening`}
dataSet={dataSet()}
dataSet={chooseDataset()}
selectValue={awakeningType}
inputValue={awakeningLevel}
onOpenChange={changeOpen}

View file

@ -254,8 +254,8 @@ const CharacterModal = ({
<h3>{t('modals.characters.subtitles.awakening')}</h3>
<AwakeningSelect
object="character"
awakeningType={awakeningType}
awakeningLevel={awakeningLevel}
type={awakeningType}
level={awakeningLevel}
sendValidity={receiveValidity}
sendValues={receiveAwakeningValues}
/>

View file

@ -72,8 +72,11 @@ const SelectWithInput = ({
// Set default values from props
useEffect(() => {
setCurrentItemSkill(dataSet.find((sk) => sk.id === selectValue))
const found = dataSet.find((sk) => sk.id === selectValue)
if (found) {
setCurrentItemSkill(found)
setFieldInputValue(inputValue)
}
}, [selectValue, inputValue])
// Methods: UI state management
@ -98,14 +101,6 @@ const SelectWithInput = ({
)
})
if (object === 'weapon_awakening') {
options?.unshift(
<SelectItem key={-1} value={-1}>
{t(`${object}.no_type`)}
</SelectItem>
)
}
return options
}
@ -113,12 +108,18 @@ const SelectWithInput = ({
function handleSelectChange(rawValue: string) {
const value = parseInt(rawValue)
const skill = dataSet.find((sk) => sk.id === value)
if (skill) {
setCurrentItemSkill(skill)
sendValues(skill.id, fieldInputValue)
}
}
function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
const value = parseFloat(event.target.value)
if (handleInputError(value)) setFieldInputValue(value)
if (currentItemSkill) sendValues(currentItemSkill.id, value)
}
// Methods: Handle error
@ -169,7 +170,7 @@ const SelectWithInput = ({
open={open}
disabled={selectDisabled}
onValueChange={handleSelectChange}
onOpenChange={() => changeOpen()}
onOpenChange={changeOpen}
onClose={onClose}
triggerClass="modal"
>

View file

@ -64,7 +64,7 @@ const WeaponModal = ({ gridWeapon, children }: Props) => {
const [element, setElement] = useState(-1)
const [awakeningType, setAwakeningType] = useState(-1)
const [awakeningType, setAwakeningType] = useState(0)
const [awakeningLevel, setAwakeningLevel] = useState(1)
const [primaryAxModifier, setPrimaryAxModifier] = useState(-1)
@ -298,8 +298,8 @@ const WeaponModal = ({ gridWeapon, children }: Props) => {
<h3>{t('modals.weapon.subtitles.awakening')}</h3>
<AwakeningSelect
object="weapon"
awakeningType={gridWeapon.awakening?.type}
awakeningLevel={gridWeapon.awakening?.level}
type={gridWeapon.awakening?.type}
level={gridWeapon.awakening?.level}
onOpenChange={receiveAwakeningOpen}
sendValidity={receiveValidity}
sendValues={receiveAwakeningValues}

View file

@ -84,7 +84,7 @@ const WeaponUnit = (props: Props) => {
props.gridWeapon &&
props.gridWeapon.object.awakening &&
props.gridWeapon.awakening &&
props.gridWeapon.awakening.type >= 0 &&
props.gridWeapon.awakening.type > 0 &&
props.gridWeapon.awakening.type != null
) {
const awakening = weaponAwakening.find(