-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
51 changed files
with
2,731 additions
and
272 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.header { | ||
text-align: center; | ||
margin: 2rem 0; | ||
} | ||
|
||
.header > p { | ||
padding: 0 2rem; | ||
} | ||
|
||
.form { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 1rem; | ||
} | ||
|
||
.formCompletion { | ||
background: #ebfbee; | ||
padding: 0.1rem 1rem; | ||
color: #2b8a3e; | ||
font-size: small; | ||
} | ||
|
||
@media (min-width: 48em) { | ||
.header { | ||
margin: 8.75rem 0 2rem 0; | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { useLocation } from 'react-router-dom'; | ||
import { StatusCodes } from 'http-status-codes'; | ||
|
||
import { useAuthorization } from '../../../hooks/useAuthorization'; | ||
import { LoginForm } from './LoginForm'; | ||
|
||
import classes from './login.module.css'; | ||
|
||
/** | ||
* Login page component. | ||
*/ | ||
function Login() { | ||
const [email, setEmail] = useState(''); | ||
const [password, setPassword] = useState(''); | ||
const [emailError, setEmailError] = useState(null); | ||
const [passwordError, setPasswordError] = useState(null); | ||
const { handleLogin, error } = useAuthorization(); | ||
const location = useLocation(); | ||
|
||
const login = async () => { | ||
setEmailError(null); | ||
setPasswordError(null); | ||
const { redirectTo } = location.state ?? {}; | ||
await handleLogin({ email, password, redirectTo }); | ||
}; | ||
|
||
useEffect(() => { | ||
if (error && error.status != StatusCodes.OK) { | ||
switch (error.status) { | ||
case StatusCodes.NOT_FOUND: | ||
setEmailError('The email you entered isn’t connected to an account.'); | ||
break; | ||
case StatusCodes.UNAUTHORIZED: | ||
setPasswordError('The password you’ve entered is incorrect.'); | ||
break; | ||
case StatusCodes.FORBIDDEN: | ||
setEmailError(error.message); | ||
break; | ||
default: | ||
setEmailError(`${error.status}: ${error.message}`); | ||
break; | ||
} | ||
} | ||
}, [error]); | ||
|
||
return ( | ||
<div> | ||
<h2 className={classes.header}>Login</h2> | ||
<LoginForm | ||
email={email} | ||
onEmailChange={(event) => { | ||
setEmailError(null); | ||
setEmail(event.target.value); | ||
}} | ||
emailError={emailError} | ||
password={password} | ||
onPasswordChange={(event) => { | ||
setPasswordError(null); | ||
setPassword(event.target.value); | ||
}} | ||
passwordError={passwordError} | ||
onLogin={login} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
export default Login; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
client/src/pages/auth/password-forgot/PasswordForgotForm.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import React from 'react'; | ||
import { Button, Container, Loader, TextInput } from '@mantine/core'; | ||
import PropTypes from 'prop-types'; | ||
import classes from '../form.module.css'; | ||
|
||
const formProps = { | ||
email: PropTypes.string.isRequired, | ||
emailError: PropTypes.string, | ||
onEmailChange: PropTypes.func.isRequired, | ||
onSubmit: PropTypes.func.isRequired, | ||
isLoading: PropTypes.bool.isRequired, | ||
formState: PropTypes.number.isRequired, | ||
}; | ||
/** | ||
* Reset Form component for Password Reset page | ||
* @param {PropTypes.InferProps<typeof formProps>} props | ||
*/ | ||
export function PasswordForgotForm({ | ||
email, | ||
emailError, | ||
onEmailChange, | ||
onSubmit, | ||
isLoading, | ||
formState, | ||
}) { | ||
return ( | ||
<form | ||
onSubmit={(event) => { | ||
event.preventDefault(); | ||
onSubmit(); | ||
}} | ||
> | ||
<Container size="25rem" className={classes.form}> | ||
<TextInput | ||
disabled={isLoading || formState == 2} | ||
name="email" | ||
label="Email" | ||
placeholder="user@email.com" | ||
value={email} | ||
onChange={onEmailChange} | ||
error={emailError} | ||
/> | ||
{formState == 1 && ( | ||
<Button type="submit" disabled={!email.length}> | ||
{isLoading ? <Loader size={20} /> : 'Send Password Reset'} | ||
</Button> | ||
)} | ||
{formState == 2 && ( | ||
<Container size="25rem" styles={{ root: { padding: 0 } }}> | ||
<div className={classes.formCompletion}> | ||
<p> | ||
Form Complete! You will receive a confirmation email shortly. | ||
Acceptance into SF life line will also be sent via the email | ||
address you submitted. | ||
</p> | ||
<p>Save this site to your browser window for convenience.</p> | ||
</div> | ||
</Container> | ||
)} | ||
</Container> | ||
</form> | ||
); | ||
} | ||
|
||
PasswordForgotForm.propTypes = formProps; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import React, { useState } from 'react'; | ||
import classes from '../form.module.css'; | ||
import { Flex } from '@mantine/core'; | ||
import { PasswordForgotForm } from './PasswordForgotForm'; | ||
|
||
/** | ||
* Password reset page | ||
*/ | ||
function PasswordForgot() { | ||
const [email, setEmail] = useState(''); | ||
const [emailError, setEmailError] = useState(null); | ||
const [isLoading, setIsLoading] = useState(false); | ||
const [formState, setFormState] = useState(1); | ||
|
||
/** | ||
* API call to send a request for a password reset to email on account profile | ||
*/ | ||
function sendPasswordReset() { | ||
setEmailError(null); | ||
setIsLoading(true); | ||
fetch('/api/v1/auth/password', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ email: email }), | ||
}) | ||
.then((response) => { | ||
if (!response.ok) { | ||
return Promise.reject(response); | ||
} | ||
setFormState(2); | ||
}) | ||
.catch((error) => { | ||
error.json().then(({ message }) => { | ||
setEmailError(message); | ||
}); | ||
}) | ||
.finally(() => { | ||
setIsLoading(false); | ||
}); | ||
} | ||
return ( | ||
<div> | ||
<div className={classes.header}> | ||
<h2>Forgot Password</h2> | ||
<p> | ||
Enter the email associated to your account and we will send a reset | ||
password link | ||
</p> | ||
</div> | ||
<Flex direction="column" gap="md"> | ||
<PasswordForgotForm | ||
email={email} | ||
emailError={emailError} | ||
onEmailChange={(event) => { | ||
setEmailError(null); | ||
setEmail(event.target.value); | ||
}} | ||
isLoading={isLoading} | ||
onSubmit={sendPasswordReset} | ||
formState={formState} | ||
/> | ||
</Flex> | ||
</div> | ||
); | ||
} | ||
|
||
export default PasswordForgot; |
Oops, something went wrong.