From 6023f9ab6a2e98dc42450100a7ac401ef739dfdb Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Fri, 20 Jan 2023 19:29:07 -0800 Subject: [PATCH] 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. --- components/AwakeningSelect/index.tsx | 110 ++++++++++----------------- components/CharacterModal/index.tsx | 4 +- components/SelectWithInput/index.tsx | 25 +++--- components/WeaponModal/index.tsx | 6 +- components/WeaponUnit/index.tsx | 2 +- 5 files changed, 60 insertions(+), 87 deletions(-) diff --git a/components/AwakeningSelect/index.tsx b/components/AwakeningSelect/index.tsx index bc5a512c..ec90f169 100644 --- a/components/AwakeningSelect/index.tsx +++ b/components/AwakeningSelect/index.tsx @@ -1,103 +1,75 @@ 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({ - id: 0, - name: { - en: 'No awakening', - ja: '覚醒なし', - }, - slug: 'no-awakening', - minValue: 0, - maxValue: 0, - fractional: false, - }) - - return weaponDataSet + 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', + ja: '覚醒なし', + }, + slug: 'no-awakening', + minValue: 0, + maxValue: 0, + fractional: false, + }) + list = awakening + break } + + return list } - // 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]) - // 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) => {
{t('modals.characters.subtitles.awakening')} diff --git a/components/SelectWithInput/index.tsx b/components/SelectWithInput/index.tsx index 156b92ff..7c88dfc6 100644 --- a/components/SelectWithInput/index.tsx +++ b/components/SelectWithInput/index.tsx @@ -72,8 +72,11 @@ const SelectWithInput = ({ // Set default values from props useEffect(() => { - setCurrentItemSkill(dataSet.find((sk) => sk.id === selectValue)) - setFieldInputValue(inputValue) + 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( - - {t(`${object}.no_type`)} - - ) - } - return options } @@ -113,12 +108,18 @@ const SelectWithInput = ({ function handleSelectChange(rawValue: string) { const value = parseInt(rawValue) const skill = dataSet.find((sk) => sk.id === value) - setCurrentItemSkill(skill) + + if (skill) { + setCurrentItemSkill(skill) + sendValues(skill.id, fieldInputValue) + } } function handleInputChange(event: React.ChangeEvent) { 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" > diff --git a/components/WeaponModal/index.tsx b/components/WeaponModal/index.tsx index 3fe3ad4e..a4471448 100644 --- a/components/WeaponModal/index.tsx +++ b/components/WeaponModal/index.tsx @@ -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) => {

{t('modals.weapon.subtitles.awakening')}

{ 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(