diff --git a/components/AxSelect/index.scss b/components/AxSelect/index.scss index 52aab9b0..559645d3 100644 --- a/components/AxSelect/index.scss +++ b/components/AxSelect/index.scss @@ -1,30 +1,48 @@ -.AXSet { +.AXSelect { display: flex; - flex-direction: row; + flex-direction: column; gap: $unit; - &.hidden { - display: none; - } + .AXSet { + &.hidden { + display: none; + } - select { - flex-grow: 1; - } + .errors { + color: $error; + display: none; + padding: $unit 0; - .Input { - -webkit-font-smoothing: antialiased; - border: none; - background-color: $grey-90; - border-radius: 6px; - box-sizing: border-box; - color: $grey-00; - height: $unit * 6; - display: block; - font-size: $font-regular; - padding: $unit; - text-align: right; - min-width: 100px; - width: 100px; - } + &.visible { + display: block; + } + } + .fields { + display: flex; + flex-direction: row; + gap: $unit; + + select { + flex-grow: 1; + margin: 0; + } + + .Input { + -webkit-font-smoothing: antialiased; + border: none; + background-color: $grey-90; + border-radius: 6px; + box-sizing: border-box; + color: $grey-00; + height: $unit * 6; + display: block; + font-size: $font-regular; + padding: $unit; + text-align: right; + min-width: 100px; + width: 100px; + } + } + } } \ No newline at end of file diff --git a/components/AxSelect/index.tsx b/components/AxSelect/index.tsx index b6798e74..0eeb169f 100644 --- a/components/AxSelect/index.tsx +++ b/components/AxSelect/index.tsx @@ -5,13 +5,36 @@ import { axData } from '~utils/axData' import './index.scss' +interface ErrorMap { + [index: string]: string + axValue1: string + axValue2: string +} + interface Props { axType: number currentSkills?: SimpleAxSkill[], + sendValidity: (isValid: boolean) => void sendValues: (primaryAxModifier: number, primaryAxValue: number, secondaryAxModifier: number, secondaryAxValue: number) => void } const AXSelect = (props: Props) => { + // Set up form states and error handling + const [errors, setErrors] = useState({ + axValue1: '', + axValue2: '' + }) + + const primaryErrorClasses = classNames({ + 'errors': true, + 'visible': errors.axValue1.length > 0 + }) + + const secondaryErrorClasses = classNames({ + 'errors': true, + 'visible': errors.axValue2.length > 0 + }) + // Refs const primaryAxModifierSelect = React.createRef() const primaryAxValueInput = React.createRef() @@ -112,11 +135,44 @@ const AXSelect = (props: Props) => { } function handleInputChange(event: React.ChangeEvent) { + let newErrors = {...errors} + if (primaryAxValueInput.current == event.target) { - setPrimaryAxValue(parseFloat(event.target.value)) + const primaryAxSkill = axData[props.axType - 1][primaryAxModifier] + const value = parseFloat(event.target.value) + + if (value < primaryAxSkill.minValue) { + newErrors.axValue1 = `${primaryAxSkill.name.en} must be at least ${primaryAxSkill.minValue}${ (primaryAxSkill.suffix) ? primaryAxSkill.suffix : ''}` + } else if (value > primaryAxSkill.maxValue) { + newErrors.axValue1 = `${primaryAxSkill.name.en} cannot be greater than ${primaryAxSkill.maxValue}${ (primaryAxSkill.suffix) ? primaryAxSkill.suffix : ''}` + } else { + newErrors.axValue1 = '' + setPrimaryAxValue(parseFloat(event.target.value)) + } } else { - setSecondaryAxValue(parseFloat(event.target.value)) + const primaryAxSkill = axData[props.axType - 1][primaryAxModifier] + const value = parseFloat(event.target.value) + + if (primaryAxSkill.secondary) { + const secondaryAxSkill = primaryAxSkill.secondary.find(skill => skill.id == secondaryAxModifier) + + if (secondaryAxSkill) { + if (value < secondaryAxSkill.minValue) { + newErrors.axValue2 = `${secondaryAxSkill.name.en} must be at least ${secondaryAxSkill.minValue}${ (secondaryAxSkill.suffix) ? secondaryAxSkill.suffix : ''}` + } else if (value > secondaryAxSkill.maxValue) { + newErrors.axValue2 = `${secondaryAxSkill.name.en} cannot be greater than ${secondaryAxSkill.maxValue}${ (secondaryAxSkill.suffix) ? secondaryAxSkill.suffix : ''}` + } else if (!secondaryAxSkill.suffix && value % 1 !== 0) { + newErrors.axValue2 = `${secondaryAxSkill.name.en} must be a whole number` + } else { + newErrors.axValue2 = '' + setSecondaryAxValue(parseFloat(event.target.value)) + } + } + } } + + props.sendValidity(newErrors.axValue1 === '' && newErrors.axValue2 === '') + setErrors(newErrors) } function setupInput(ax: AxSkill | undefined, element: HTMLInputElement) { @@ -144,13 +200,19 @@ const AXSelect = (props: Props) => { return (
- - +
+ + +
+

{errors.axValue1}

- - +
+ + +
+

{errors.axValue2}

) diff --git a/components/WeaponModal/index.tsx b/components/WeaponModal/index.tsx index 0873456d..eba61367 100644 --- a/components/WeaponModal/index.tsx +++ b/components/WeaponModal/index.tsx @@ -49,6 +49,7 @@ const WeaponModal = (props: Props) => { // State const [open, setOpen] = useState(false) + const [formValid, setFormValid] = useState(false) const [element, setElement] = useState(-1) const [primaryAxModifier, setPrimaryAxModifier] = useState(-1) @@ -64,6 +65,10 @@ const WeaponModal = (props: Props) => { setSecondaryAxValue(secondaryAxValue) } + function receiveAxValidity(isValid: boolean) { + setFormValid(isValid) + } + function receiveElementValue(element: string) { setElement(parseInt(element)) } @@ -164,6 +169,7 @@ const WeaponModal = (props: Props) => { @@ -171,6 +177,7 @@ const WeaponModal = (props: Props) => { } function openChange(open: boolean) { + setFormValid(false) setOpen(open) } @@ -197,7 +204,7 @@ const WeaponModal = (props: Props) => { { (props.gridWeapon.object.element == 0) ? elementSelect() : '' } { ([2, 3, 17, 24].includes(props.gridWeapon.object.series)) ? keySelect() : '' } { (props.gridWeapon.object.ax > 0) ? axSelect() : '' } - +