// Core dependencies import React, { useEffect, useState } from 'react' import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import classNames from 'classnames' // UI Dependencies import Input from '~components/Input' import Select from '~components/Select' import SelectItem from '~components/SelectItem' // Styles and icons import './index.scss' // Types interface Props { object: 'ax' | 'weapon_awakening' | 'character_awakening' | 'ring' | 'earring' dataSet: ItemSkill[] selectValue: number selectDisabled: boolean inputValue: number awakeningLevel?: number onOpenChange?: (open: boolean) => void sendValidity: (isValid: boolean) => void sendValues: (type: number, level: number) => void } const defaultProps = { selectDisabled: false, } const SelectWithInput = ({ object, dataSet, selectDisabled, selectValue, inputValue, onOpenChange, sendValidity, sendValues, }: Props) => { const router = useRouter() const locale = router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en' const { t } = useTranslation('common') // UI state const [open, setOpen] = useState(false) // Field properties // prettier-ignore const [currentItemSkill, setCurrentItemSkill] = useState(undefined) const [fieldInputValue, setFieldInputValue] = useState(inputValue) const [error, setError] = useState('') // Refs const input = React.createRef() // Classes const inputClasses = classNames({ Bound: true, Hidden: currentItemSkill?.id === 0, }) const errorClasses = classNames({ errors: true, visible: error !== '', }) // Hooks // Set default values from props useEffect(() => { const found = dataSet.find((sk) => sk.id === selectValue) if (found) { setCurrentItemSkill(found) setFieldInputValue(inputValue) } }, [selectValue, inputValue]) // Methods: UI state management function changeOpen() { if (!selectDisabled) { setOpen(!open) if (onOpenChange) onOpenChange(!open) } } function onClose() { if (onOpenChange) onOpenChange(false) } // Methods: Rendering function generateOptions() { let options: React.ReactNode[] = dataSet.map((skill, i) => { return ( {skill.name[locale]} ) }) return options } // Methods: User input detection 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) { const value = parseFloat(event.target.value) if (handleInputError(value)) setFieldInputValue(value) if (currentItemSkill) sendValues(currentItemSkill.id, value) } // Methods: Handle error function handleInputError(value: number) { let error = '' if (currentItemSkill) { if (value < currentItemSkill.minValue) { error = t(`${object}.errors.value_too_low`, { minValue: currentItemSkill.minValue, }) } else if (value > currentItemSkill.maxValue) { error = t(`${object}.errors.value_too_high`, { maxValue: currentItemSkill.maxValue, }) } else if (!currentItemSkill.fractional && value % 1 != 0) { error = t(`${object}.errors.value_not_whole`) } else if (!value || value <= 0) { error = t(`${object}.errors.value_empty`) } else { error = '' } } setError(error) return error.length === 0 } const rangeString = () => { let placeholder = '' if (currentItemSkill) { const minValue = currentItemSkill.minValue const maxValue = currentItemSkill.maxValue placeholder = `${minValue}~${maxValue}` } return placeholder } return (

{error}

) } SelectWithInput.defaultProps = defaultProps export default SelectWithInput