import React , { useEffect , useMemo , useState } from 'react' ; import { ErrorMessage } from '@hookform/error-message' ; import usePasswordRules from '../hooks/usePasswordRules' ; import { PasswordInput , PasswordRules } from '../components/PasswordInput' ; import { FieldMargin } from '../components/Form.style' ; import ButtonSolid , { ButtonTypes , } from '@weco/common/views/components/ButtonSolid/ButtonSolid' ; import { TextInputErrorMessage } from '@weco/common/views/components/TextInput/TextInput' ; import { useForm , useWatch } from 'react-hook-form' ; import { ModalContainer , ModalTitle , StatusAlert } from './MyAccount.style' ; import { ChangeDetailsModalContentProps } from './ChangeDetailsModal' ; import { UpdatePasswordError , useUpdatePassword , } from '../hooks/useUpdatePassword' ; import { Loading } from './Loading' ; import { validPasswordPattern } from '../components/ValidationPatterns' ; import Space from '@weco/common/views/components/styled/Space' ; type ChangePasswordInputs = { password : string ; newPassword : string ; confirmation : string ; } ; export const ChangePassword = ( { onComplete , isActive , setIsModalLoading , } ) => { const defaultValues = useMemo ( ( ) => ( { password : '' , newPassword : '' , confirmation : '' , } ) , [ ] ) ; const { updatePassword , isLoading , error } = useUpdatePassword ( ) ; const { control , getValues , setError , formState , handleSubmit , trigger , reset , } = useForm < ChangePasswordInputs > ( { defaultValues , } ) ; const [ submissionErrorMessage , setSubmissionErrorMessage ] = useState < string | null > ( null ) ; useEffect ( ( ) => { setIsModalLoading ( isLoading ) ; } , [ isLoading ] ) ; const newPasswordInput = useWatch ( { control , name : 'newPassword' } ) as string ; const passwordRules = usePasswordRules ( newPasswordInput ) ; useEffect ( ( ) => { reset ( defaultValues ) ; } , [ reset , defaultValues , isActive ] ) ; useEffect ( ( ) => { switch ( error ) { case UpdatePasswordError . INCORRECT_PASSWORD : { setError ( 'password' , { type : 'manual' , message : 'Incorrect password' , } ) ; break ; } case UpdatePasswordError . BRUTE_FORCE_BLOCKED : { setSubmissionErrorMessage ( 'Your account has been blocked after multiple consecutive login attempts' ) ; break ; } case UpdatePasswordError . DID_NOT_MEET_POLICY : { setError ( 'newPassword' , { type : 'manual' , message : 'Password does not meet the policy' , } ) ; break ; } case UpdatePasswordError . UNKNOWN : { setSubmissionErrorMessage ( 'An unknown error occurred' ) ; break ; } } } , [ error , setError , formState . submitCount ] ) ; if ( isLoading ) { return < Loading />; } return ( < ModalContainer > < ModalTitle > Change password < /ModalTitle> { submissionErrorMessage && ( < StatusAlert type = "failure" > { submissionErrorMessage } < /StatusAlert>)} < form onSubmit = { handleSubmit ( data => updatePassword ( { password : data . password , newPassword : data . newPassword } , onComplete ) ) } > < FieldMargin > < PasswordInput label = "Current password" id = "change-password-current" name = "password" control = { control } rules = { { required : 'Enter your current password' } } /> < ErrorMessage errors = { formState . errors } name = "password" render = { ( { message } ) => ( < TextInputErrorMessage > { message } < /TextInputErrorMessage>)}/ > < /FieldMargin> < FieldMargin > < PasswordInput label = "Create new password" id = "change-password-new" name = "newPassword" control = { control } rules = { { required : 'Enter your new password' , pattern : { value : validPasswordPattern , message : 'Enter a valid password' , } , } } /> < ErrorMessage errors = { formState . errors } name = "newPassword" render = { ( { message } ) => ( < TextInputErrorMessage > { message } < /TextInputErrorMessage>)}/ > < /FieldMargin> < FieldMargin > < PasswordInput label = "Re-enter new password" id = "change-password-confirm" name = "confirmation" control = { control } rules = { { required : 'Confirm your new password' , validate : async ( value ) => { const isNewPasswordValid = await trigger ( 'newPassword' ) ; if ( isNewPasswordValid ) { return ( value === getValues ( 'newPassword' ) || 'Passwords do not match' ) ; } return true ; } , } } /> < ErrorMessage errors = { formState . errors } name = "confirmation" render = { ( { message } ) => ( < TextInputErrorMessage > { message } < /TextInputErrorMessage>)}/ > < Space v = { { size : 's' , properties : [ 'margin-top' ] } } > < PasswordRules { ... passwordRules } / > < /Space> < /FieldMargin> < Space v = { { size : 'l' , properties : [ 'margin-top' ] } } > < ButtonSolid type = { ButtonTypes . submit } text = "Update password" / > < /Space> < /form> < /ModalContainer>); } ;