Skip to content

Commit

Permalink
Merge pull request #462 from etn-ccis/bug/4649-420-change-password-su…
Browse files Browse the repository at this point in the history
…ccess-screen

Bug/4649 420 change password success screen
  • Loading branch information
surajeaton authored Sep 11, 2023
2 parents 2b2fe68 + 9c4a089 commit a2a0c37
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 77 deletions.
20 changes: 19 additions & 1 deletion login-workflow/docs/components/change-password-dialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,26 @@ import { AuthContextProvider, ChangePasswordDialog } from '@brightlayer-ui/react
| nextLabel | `string` | The label to display for the next button. | `t('bluiCommon:ACTIONS.OKAY')` |
| currentPasswordChange | `(currentPassword: string) => void` | Callback called when the current password field input changes. | |
| enableButton | `boolean \| (() => boolean)` | True if the next button should be enabled. | `false` |
| onSubmit | `() => void` | Called when the next button is clicked. | |
| onFinish | `() => void` | Called when the button is clicked on success screen. | |
| onSubmit | `() => void \| Promise<void>` | Called when the next button is clicked. | |
| onPrevious | `() => void` | Callback called when the previous/back/cancel button is clicked. | |
| loading | `boolean` | Whether or not the dialog is loading. | |
| showSuccessScreen | `boolean` | Used to determine whether to show a success screen after the form is submitted. | |
| slots | `ChangePasswordDialogSlots` | Components to use in place of the defaults. See [ChangePasswordDialogSlots](#changepassworddialogslots) | |
| slotProps | `ChangePasswordDialogSlotsProps` | Props to pass to the custom slot components. See [ChangePasswordDialogSlotsProps](#changepassworddialogslotsprops) | |


### ChangePasswordDialogSlots

| Key | Type | Description |
| ------------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
| SuccessScreen | `(props: SuccessScreenProps) => JSX.Element` | A custom success screen component to render. See [SuccessScreen](./success.md) |

### ChangePasswordDialogSlotsProps

| Key | Type | Description |
| ------------- | -------------------- | --------------------------------------------------------------------------------------- |
| SuccessScreen | `SuccessScreenProps` | Props to pass to the custom success screen component. See [SuccessScreen](./success.md) |


Props from the underlying MUI [Dialog](https://mui.com/material-ui/react-dialog/) are also available.
2 changes: 0 additions & 2 deletions login-workflow/example/src/actions/AuthUIActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,6 @@ export const ProjectAuthUIActions: AuthUIActionsWithApp = (appHelper) => ({
if (isRandomFailure()) {
throw new Error('Sorry, there was a problem sending your request.');
}
LocalStorage.clearAuthCredentials();
appHelper.onUserNotAuthenticated();
return;
},
});
10 changes: 10 additions & 0 deletions login-workflow/example/src/components/ChangePassword.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import React from 'react';
import { ChangePasswordDialog } from '@brightlayer-ui/react-auth-workflow';
import { useApp } from '../contexts/AppContextProvider';
import { LocalStorage } from '../store/local-storage';
import { useNavigate } from 'react-router-dom';

export const ChangePassword = (): JSX.Element => {
const app = useApp();
const navigate = useNavigate();
const logOut = (): void => {
app.setShowChangePasswordDialog(false);
LocalStorage.clearAuthCredentials();
app.onUserNotAuthenticated();
navigate('/login');
};

return (
<ChangePasswordDialog
open={app.showChangePasswordDialog}
onPrevious={(): void => app.setShowChangePasswordDialog(false)}
onSubmit={(): void => app.setShowChangePasswordDialog(false)}
onFinish={(): void => logOut()}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import '@testing-library/jest-dom';
import { cleanup, fireEvent, render, RenderResult, screen } from '@testing-library/react';
import { cleanup, fireEvent, render, RenderResult, screen, waitFor } from '@testing-library/react';
import { ChangePasswordDialog } from './ChangePasswordDialog';
import { AuthContextProvider } from '../../contexts';
import { BrowserRouter } from 'react-router-dom';
Expand Down Expand Up @@ -71,4 +71,32 @@ describe('Change Password Dialog tests', () => {
fireEvent.change(confirmPasswordInput, { target: { value: 'Abc@1234' } });
expect(confirmPasswordInput).toHaveValue('Abc@1234');
});

it('should show success screen, when okay button is clicked', async () => {
const { getByLabelText } = renderer({
open: true,
showSuccessScreen: true,
PasswordProps: {
newPasswordLabel: 'New Password',
confirmPasswordLabel: 'Confirm New Password',
onPasswordChange: updateFields,
passwordRequirements: [],
},
});

const currentPasswordInput = getByLabelText('Current Password');
fireEvent.change(currentPasswordInput, { target: { value: 'Abc@1234' } });
const newPasswordInput = getByLabelText('New Password');
const confirmPasswordInput = getByLabelText('Confirm New Password');
fireEvent.change(newPasswordInput, { target: { value: 'Abc@1234' } });
expect(newPasswordInput).toHaveValue('Abc@1234');
fireEvent.change(confirmPasswordInput, { target: { value: 'Abc@1234' } });
expect(confirmPasswordInput).toHaveValue('Abc@1234');

fireEvent.click(screen.getByText('Okay'));
expect(screen.getByText('Okay')).toBeEnabled();
fireEvent.click(screen.getByText('Okay'));

await waitFor(() => expect(screen.getByText('Your password was successfully reset.')));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useAuthContext } from '../../contexts';
import { useLanguageLocale } from '../../hooks';
import { ChangePasswordDialogBase } from './ChangePasswordDialogBase';
import { ChangePasswordDialogProps } from './types';
import CheckCircle from '@mui/icons-material/CheckCircle';

/**
* Component that renders a dialog with textField to enter current password and a change password form with a new password and confirm password inputs.
Expand All @@ -16,7 +17,12 @@ import { ChangePasswordDialogProps } from './types';
* @param nextLabel label to display for the next button
* @param currentPasswordChange called when the current password field changes
* @param enableButton boolean to enable and disable the button
* @param onFinish function called when the button is clicked on success screen
* @param onSubmit Callback function to call when the form is submitted
* @param onPrevious function called when the previous button is clicked
* @param showSuccessScreen boolean that determines whether to show the success screen or not
* @param slots used for ChangePasswordDialog SuccessScreen props
* @param slotProps props that will be passed to the SuccessScreen component
*
* @category Component
*/
Expand All @@ -30,7 +36,8 @@ export const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props)
const [confirmInput, setConfirmInput] = useState('');
const [showErrorDialog, setShowErrorDialog] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const { actions, navigate, routeConfig } = useAuthContext();
const [showSuccessScreen, setShowSuccessScreen] = useState(false);
const { actions } = useAuthContext();

const {
open,
Expand All @@ -41,6 +48,7 @@ export const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props)
nextLabel = t('bluiCommon:ACTIONS.OKAY'),
onPrevious,
onSubmit,
onFinish,
PasswordProps,
ErrorDialogProps,
} = props;
Expand All @@ -63,14 +71,27 @@ export const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props)
try {
setIsLoading(true);
await actions.changePassword(currentInput, passwordInput);
await onSubmit();
if (props.showSuccessScreen === false) {
onFinish();
}
setShowSuccessScreen(true);
} catch {
setShowErrorDialog(true);
} finally {
setIsLoading(false);
}
}
}, [checkPasswords, currentInput, passwordInput, actions, setIsLoading, setShowErrorDialog, onSubmit]);
}, [
checkPasswords,
currentInput,
passwordInput,
actions,
setIsLoading,
setShowErrorDialog,
onSubmit,
onFinish,
props.showSuccessScreen,
]);

const passwordProps = {
newPasswordLabel: t('bluiAuth:CHANGE_PASSWORD.NEW_PASSWORD'),
Expand Down Expand Up @@ -113,12 +134,31 @@ export const ChangePasswordDialog: React.FC<ChangePasswordDialogProps> = (props)
currentPasswordChange={(currentPwd): void => setCurrentInput(currentPwd)}
enableButton={checkPasswords}
onPrevious={onPrevious}
PasswordProps={passwordProps}
ErrorDialogProps={errorDialogProps}
onSubmit={async (): Promise<void> => {
await changePasswordSubmit();
navigate(routeConfig.LOGIN);
}}
PasswordProps={passwordProps}
ErrorDialogProps={errorDialogProps}
slotProps={{
SuccessScreen: {
icon: <CheckCircle color="primary" sx={{ fontSize: 100 }} />,
messageTitle: t('bluiAuth:PASSWORD_RESET.SUCCESS_MESSAGE'),
message: t('bluiAuth:CHANGE_PASSWORD.SUCCESS_MESSAGE'),
onDismiss: (): void => {
onFinish();
},
WorkflowCardActionsProps: {
showPrevious: false,
fullWidthButton: true,
showNext: true,
nextLabel: t('bluiCommon:ACTIONS.DONE'),
onNext: (): void => {
onFinish();
},
},
},
}}
showSuccessScreen={showSuccessScreen}
/>
);
};
Loading

0 comments on commit a2a0c37

Please sign in to comment.