1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-28 17:55:15 +02:00
unleash.unleash/frontend/src/component/user/common/ResetPasswordForm/ResetPasswordForm.tsx
Nick b4197e54e6 fix: input fields (PR #1110 from NickMolloy/improve-input-attributes)
* Use correct input type

"string" is not a valid input type: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types
"text" is the actual valid value.

* Use correct autocomplete values for credential fields
"true", "on", and "confirm-password" are not valid autocomplete values https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
2022-06-22 11:05:03 +02:00

161 lines
5.1 KiB
TypeScript

import { Button } from '@mui/material';
import classnames from 'classnames';
import React, {
Dispatch,
SetStateAction,
SyntheticEvent,
useCallback,
useEffect,
useState,
} from 'react';
import { useNavigate } from 'react-router';
import { useThemeStyles } from 'themes/themeStyles';
import { OK } from 'constants/statusCodes';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import ResetPasswordError from '../ResetPasswordError/ResetPasswordError';
import PasswordChecker from './PasswordChecker/PasswordChecker';
import PasswordMatcher from './PasswordMatcher/PasswordMatcher';
import { useStyles } from './ResetPasswordForm.styles';
import { formatApiPath } from 'utils/formatPath';
import PasswordField from 'component/common/PasswordField/PasswordField';
interface IResetPasswordProps {
token: string;
setLoading: Dispatch<SetStateAction<boolean>>;
}
const ResetPasswordForm = ({ token, setLoading }: IResetPasswordProps) => {
const { classes: styles } = useStyles();
const { classes: themeStyles } = useThemeStyles();
const [apiError, setApiError] = useState(false);
const [password, setPassword] = useState('');
const [showPasswordChecker, setShowPasswordChecker] = useState(false);
const [confirmPassword, setConfirmPassword] = useState('');
const [matchingPasswords, setMatchingPasswords] = useState(false);
const [validOwaspPassword, setValidOwaspPassword] = useState(false);
const navigate = useNavigate();
const submittable = matchingPasswords && validOwaspPassword;
const setValidOwaspPasswordMemo = useCallback(setValidOwaspPassword, [
setValidOwaspPassword,
]);
useEffect(() => {
if (!password) {
setValidOwaspPassword(false);
}
if (password === confirmPassword) {
setMatchingPasswords(true);
} else {
setMatchingPasswords(false);
}
}, [password, confirmPassword]);
const makeResetPasswordReq = () => {
const path = formatApiPath('auth/reset/password');
return fetch(path, {
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
token,
password,
}),
});
};
const submitResetPassword = async () => {
setLoading(true);
try {
const res = await makeResetPasswordReq();
setLoading(false);
if (res.status === OK) {
navigate('login?reset=true');
setApiError(false);
} else {
setApiError(true);
}
} catch (e) {
setApiError(true);
setLoading(false);
}
};
const handleSubmit = (e: SyntheticEvent) => {
e.preventDefault();
if (submittable) {
submitResetPassword();
}
};
const started = Boolean(password && confirmPassword);
return (
<>
<ConditionallyRender
condition={apiError}
show={<ResetPasswordError />}
/>
<form
onSubmit={handleSubmit}
className={classnames(
themeStyles.contentSpacingY,
styles.container
)}
>
<PasswordField
placeholder="Password"
value={password || ''}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setPassword(e.target.value)
}
onFocus={() => setShowPasswordChecker(true)}
autoComplete="new-password"
data-loading
/>
<PasswordField
value={confirmPassword || ''}
placeholder="Confirm password"
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setConfirmPassword(e.target.value)
}
autoComplete="new-password"
data-loading
/>
<ConditionallyRender
condition={showPasswordChecker}
show={
<PasswordChecker
password={password}
callback={setValidOwaspPasswordMemo}
style={{ marginBottom: '1rem' }}
/>
}
/>
<PasswordMatcher
started={started}
matchingPasswords={matchingPasswords}
/>
<Button
variant="contained"
color="primary"
type="submit"
className={styles.button}
data-loading
disabled={!submittable}
>
Submit
</Button>
</form>
</>
);
};
export default ResetPasswordForm;