@brightlayer-ui/react-auth-workflow
Version:
Re-usable workflow components for Authentication and Registration within Eaton applications.
132 lines (131 loc) • 6.26 kB
JavaScript
import React, { useCallback, useRef, useState } from 'react';
import { defaultPasswordRequirements } from '../../constants/index.js';
import { useAuthContext } from '../../contexts/index.js';
import { ChangePasswordDialogBase } from './ChangePasswordDialogBase.js';
import CheckCircle from '@mui/icons-material/CheckCircle';
import { useTranslation } from 'react-i18next';
import { useErrorManager } from '../../contexts/ErrorContext/useErrorManager.js';
/**
* Component that renders a dialog with textField to enter current password and a change password form with a new password and confirm password inputs.
* It includes callbacks so you can respond to changes in the inputs.
*
* @param {ChangePasswordDialogProps} props - props of changePassword dailog
*
* @category Component
*/
export const ChangePasswordDialog = (props) => {
const { t } = useTranslation();
const passwordRef = useRef(null);
const confirmRef = useRef(null);
const { open, dialogTitle = t('bluiAuth:CHANGE_PASSWORD.PASSWORD'), dialogDescription = t('bluiAuth:CHANGE_PASSWORD.PASSWORD_INFO'), currentPasswordLabel = t('bluiCommon:LABELS.CURRENT_PASSWORD'), previousLabel = t('bluiCommon:ACTIONS.BACK'), nextLabel = t('bluiCommon:ACTIONS.OKAY'), onPrevious, onFinish, PasswordProps, loading, currentPasswordTextFieldProps, slots = {}, slotProps = {}, } = props;
const [currentInput, setCurrentInput] = useState('');
const [passwordInput, setPasswordInput] = useState('');
const [confirmInput, setConfirmInput] = useState('');
const [isLoading, setIsLoading] = useState(loading);
const [showSuccessScreen, setShowSuccessScreen] = useState(false);
const { actions, navigate, routeConfig } = useAuthContext();
const { triggerError, errorManagerConfig } = useErrorManager();
const [hasVerifyCodeError, setHasVerifyCodeError] = useState(false);
const handleErrorClose = useCallback(() => {
if (hasVerifyCodeError) {
navigate(routeConfig.LOGIN);
}
props.errorDisplayConfig?.onClose?.();
errorManagerConfig.onClose?.();
}, [hasVerifyCodeError, navigate, routeConfig.LOGIN, props.errorDisplayConfig, errorManagerConfig]);
const errorDisplayConfig = {
...errorManagerConfig,
...props.errorDisplayConfig,
onClose: handleErrorClose,
};
const passwordReqs = PasswordProps?.passwordRequirements ?? defaultPasswordRequirements(t);
const updateFields = useCallback((fields) => {
setPasswordInput(fields.password);
setConfirmInput(fields.confirm);
}, [setPasswordInput, setConfirmInput]);
const areValidMatchingPasswords = useCallback(() => {
if (passwordReqs?.length === 0) {
return confirmInput === passwordInput;
}
for (const req of passwordReqs) {
if (!new RegExp(req.regex).test(passwordInput))
return false;
}
return confirmInput === passwordInput;
}, [passwordReqs, passwordInput, confirmInput]);
const checkPasswords = currentInput !== '' && passwordInput !== '' && confirmInput !== '' && areValidMatchingPasswords();
const changePasswordSubmit = useCallback(async () => {
if (checkPasswords) {
try {
setIsLoading(true);
await actions.changePassword(currentInput, passwordInput);
if (props.showSuccessScreen === false) {
onFinish?.();
}
setShowSuccessScreen(true);
}
catch (_error) {
setHasVerifyCodeError(true);
triggerError(_error);
}
finally {
setIsLoading(false);
}
}
}, [
checkPasswords,
currentInput,
passwordInput,
actions,
setIsLoading,
onFinish,
props.showSuccessScreen,
triggerError,
]);
const passwordProps = {
newPasswordLabel: t('bluiAuth:CHANGE_PASSWORD.NEW_PASSWORD'),
confirmPasswordLabel: t('bluiAuth:CHANGE_PASSWORD.CONFIRM_NEW_PASSWORD'),
passwordRef,
confirmRef,
initialNewPasswordValue: passwordInput,
initialConfirmPasswordValue: confirmInput,
passwordRequirements: passwordReqs,
passwordNotMatchError: t('bluiCommon:FORMS.PASS_MATCH_ERROR'),
...PasswordProps,
onPasswordChange: (passwordData) => {
updateFields(passwordData);
PasswordProps?.onPasswordChange?.(passwordData);
},
onSubmit: async () => {
await changePasswordSubmit();
PasswordProps?.onSubmit?.();
},
};
return (React.createElement(ChangePasswordDialogBase, { open: open, loading: isLoading, dialogTitle: dialogTitle, dialogDescription: dialogDescription, currentPasswordLabel: currentPasswordLabel, previousLabel: previousLabel, nextLabel: nextLabel, currentPasswordChange: (currentPwd) => {
setCurrentInput(currentPwd);
props?.currentPasswordChange?.(currentPwd);
}, enableButton: checkPasswords, onPrevious: onPrevious, PasswordProps: passwordProps, currentPasswordTextFieldProps: currentPasswordTextFieldProps, onSubmit: async () => {
await changePasswordSubmit();
}, slots: slots, slotProps: {
SuccessScreen: {
EmptyStateProps: {
icon: React.createElement(CheckCircle, { color: "primary", sx: { fontSize: 100 } }),
title: t('bluiAuth:PASSWORD_RESET.SUCCESS_MESSAGE'),
description: t('bluiAuth:CHANGE_PASSWORD.SUCCESS_MESSAGE'),
},
onDismiss: () => {
onFinish?.();
},
WorkflowCardActionsProps: {
showPrevious: false,
fullWidthButton: true,
showNext: true,
nextLabel: t('bluiCommon:ACTIONS.DONE'),
onNext: () => {
onFinish?.();
},
},
...slotProps.SuccessScreen,
},
}, showSuccessScreen: showSuccessScreen, errorDisplayConfig: errorDisplayConfig }));
};