From 4106daefae5e77644fa6dd2f294f2c123cc56c88 Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Fri, 26 Apr 2024 10:07:18 -0400 Subject: [PATCH] feat(app): validate factory mode slideout input add validation and errors to input on factory mode slideout initial step closes PLAT-281 --- .../FactoryModeSlideout.tsx | 69 +++++++++++++++---- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/app/src/organisms/Devices/RobotSettings/AdvancedTab/AdvancedTabSlideouts/FactoryModeSlideout.tsx b/app/src/organisms/Devices/RobotSettings/AdvancedTab/AdvancedTabSlideouts/FactoryModeSlideout.tsx index 870f76fde80..a564f62a37c 100644 --- a/app/src/organisms/Devices/RobotSettings/AdvancedTab/AdvancedTabSlideouts/FactoryModeSlideout.tsx +++ b/app/src/organisms/Devices/RobotSettings/AdvancedTab/AdvancedTabSlideouts/FactoryModeSlideout.tsx @@ -26,8 +26,11 @@ import { InputField } from '../../../../../atoms/InputField' import { MultiSlideout } from '../../../../../atoms/Slideout/MultiSlideout' import { FileUpload } from '../../../../../molecules/FileUpload' import { UploadInput } from '../../../../../molecules/UploadInput' +import { useRobot } from '../../../../../organisms/Devices/hooks' +import { getRobotSerialNumber } from '../../../../../redux/discovery' import { restartRobot } from '../../../../../redux/robot-admin' +import type { FieldError, Resolver } from 'react-hook-form' import type { RobotSettingsField } from '@opentrons/api-client' import type { Dispatch } from '../../../../../redux/types' @@ -39,7 +42,7 @@ interface FactoryModeSlideoutProps { } interface FormValues { - passwordInput: string + factoryModeInput: string } export function FactoryModeSlideout({ @@ -58,6 +61,10 @@ export function FactoryModeSlideout({ ) const isOEMMode = oemModeSetting?.value ?? null + const robot = useRobot(robotName) + const sn = robot?.status != null ? getRobotSerialNumber(robot) : null + const last = sn?.substring(sn.length - 4) + const [currentStep, setCurrentStep] = React.useState(1) const [toggleValue, setToggleValue] = React.useState(false) const [file, setFile] = React.useState(null) @@ -86,22 +93,54 @@ export function FactoryModeSlideout({ }, }) + const validate = ( + data: FormValues, + errors: Record + ): Record => { + const factoryModeInput = data.factoryModeInput + let errorMessage: string | undefined + if (factoryModeInput.length > 0 && factoryModeInput !== last) { + errorMessage = t('invalid_password') + } + + const updatedErrors = + errorMessage != null + ? { + ...errors, + factoryModeInput: { + type: 'error', + message: errorMessage, + }, + } + : errors + return updatedErrors + } + + const resolver: Resolver = values => { + let errors = {} + errors = validate(values, errors) + return { values, errors } + } + const { - handleSubmit, + clearErrors, control, formState: { errors }, - trigger, + handleSubmit, } = useForm({ defaultValues: { - passwordInput: '', + factoryModeInput: '', }, + mode: 'onSubmit', + resolver, + reValidateMode: 'onSubmit', }) - const onSubmit = (data: FormValues): void => { + + const onSubmit = (): void => { setCurrentStep(2) } const handleSubmitFactoryPassword = (): void => { - // TODO: validation and errors: PLAT-281 void handleSubmit(onSubmit)() } @@ -153,7 +192,11 @@ export function FactoryModeSlideout({ footer={ <> {currentStep === 1 ? ( - + {t('shared:next')} ) : null} @@ -182,15 +225,15 @@ export function FactoryModeSlideout({ ( ) => { field.onChange(e) - trigger('passwordInput') + clearErrors() }} value={field.value} error={fieldState.error?.message && ' '} @@ -199,13 +242,13 @@ export function FactoryModeSlideout({ /> )} /> - {errors.passwordInput != null ? ( + {errors.factoryModeInput != null ? ( - {errors.passwordInput.message} + {errors.factoryModeInput.message} ) : null}