first
This commit is contained in:
39
src/sections/auth/AuthCard.js
Normal file
39
src/sections/auth/AuthCard.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
|
||||
// ==============================|| AUTHENTICATION - CARD WRAPPER ||============================== //
|
||||
|
||||
const AuthCard = ({ children, ...other }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<MainCard
|
||||
sx={{
|
||||
maxWidth: { xs: 400, lg: 475 },
|
||||
margin: { xs: 2.5, md: 3 },
|
||||
'& > *': {
|
||||
flexGrow: 1,
|
||||
flexBasis: '50%'
|
||||
}
|
||||
}}
|
||||
content={false}
|
||||
{...other}
|
||||
border={false}
|
||||
boxShadow
|
||||
shadow={theme.customShadows.z1}
|
||||
>
|
||||
<Box sx={{ p: { xs: 2, sm: 3, md: 4, xl: 5 } }}>{children}</Box>
|
||||
</MainCard>
|
||||
);
|
||||
};
|
||||
|
||||
AuthCard.propTypes = {
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
export default AuthCard;
|
||||
55
src/sections/auth/AuthWrapper.js
Normal file
55
src/sections/auth/AuthWrapper.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// material-ui
|
||||
import { Box, Grid } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import AuthFooter from 'components/cards/AuthFooter';
|
||||
import Logo from 'components/logo';
|
||||
import AuthCard from './AuthCard';
|
||||
|
||||
// assets
|
||||
import AuthBackground from 'assets/images/auth/AuthBackground';
|
||||
|
||||
// ==============================|| AUTHENTICATION - WRAPPER ||============================== //
|
||||
|
||||
const AuthWrapper = ({ children }) => (
|
||||
<Box sx={{ minHeight: '100vh' }}>
|
||||
<AuthBackground />
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justifyContent="flex-end"
|
||||
sx={{
|
||||
minHeight: '100vh'
|
||||
}}
|
||||
>
|
||||
<Grid item xs={12} sx={{ ml: 3, mt: 3 }}>
|
||||
<Logo />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
sx={{ minHeight: { xs: 'calc(100vh - 210px)', sm: 'calc(100vh - 134px)', md: 'calc(100vh - 112px)' } }}
|
||||
>
|
||||
<Grid item>
|
||||
<AuthCard>{children}</AuthCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} sx={{ m: 3, mt: 1 }}>
|
||||
<AuthFooter />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
|
||||
AuthWrapper.propTypes = {
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
export default AuthWrapper;
|
||||
66
src/sections/auth/auth-forms/AuthCodeVerification.js
Normal file
66
src/sections/auth/auth-forms/AuthCodeVerification.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { Button, Grid, Stack, Typography } from '@mui/material';
|
||||
|
||||
// third-party
|
||||
import OtpInput from 'react18-input-otp';
|
||||
|
||||
// project import
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
import { ThemeMode } from 'config';
|
||||
|
||||
// ============================|| STATIC - CODE VERIFICATION ||============================ //
|
||||
|
||||
const AuthCodeVerification = () => {
|
||||
const theme = useTheme();
|
||||
const [otp, setOtp] = useState();
|
||||
|
||||
const borderColor = theme.palette.mode === ThemeMode.DARK ? theme.palette.grey[200] : theme.palette.grey[300];
|
||||
|
||||
return (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<OtpInput
|
||||
value={otp}
|
||||
onChange={(otp) => setOtp(otp)}
|
||||
numInputs={4}
|
||||
containerStyle={{ justifyContent: 'space-between' }}
|
||||
inputStyle={{
|
||||
width: '100%',
|
||||
margin: '8px',
|
||||
padding: '10px',
|
||||
border: `1px solid ${borderColor}`,
|
||||
borderRadius: 4,
|
||||
':hover': {
|
||||
borderColor: theme.palette.primary.main
|
||||
}
|
||||
}}
|
||||
focusStyle={{
|
||||
outline: 'none',
|
||||
boxShadow: theme.customShadows.primary,
|
||||
border: `1px solid ${theme.palette.primary.main}`
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<AnimateButton>
|
||||
<Button disableElevation fullWidth size="large" type="submit" variant="contained">
|
||||
Continue
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="baseline">
|
||||
<Typography>Did not receive the email? Check your spam filter, or</Typography>
|
||||
<Typography variant="body1" sx={{ minWidth: 85, ml: 2, textDecoration: 'none', cursor: 'pointer' }} color="primary">
|
||||
Resend code
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthCodeVerification;
|
||||
126
src/sections/auth/auth-forms/AuthForgotPassword.js
Normal file
126
src/sections/auth/auth-forms/AuthForgotPassword.js
Normal file
@@ -0,0 +1,126 @@
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import { Button, FormHelperText, Grid, InputLabel, OutlinedInput, Stack, Typography } from '@mui/material';
|
||||
|
||||
// third party
|
||||
import * as Yup from 'yup';
|
||||
import { Formik } from 'formik';
|
||||
|
||||
// project import
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
|
||||
import useAuth from 'hooks/useAuth';
|
||||
import useScriptRef from 'hooks/useScriptRef';
|
||||
import { dispatch } from 'store';
|
||||
import { openSnackbar } from 'store/reducers/snackbar';
|
||||
|
||||
// ============================|| FIREBASE - FORGOT PASSWORD ||============================ //
|
||||
|
||||
const AuthForgotPassword = () => {
|
||||
const scriptedRef = useScriptRef();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { isLoggedIn, resetPassword } = useAuth();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Formik
|
||||
initialValues={{
|
||||
email: '',
|
||||
submit: null
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required')
|
||||
})}
|
||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
||||
try {
|
||||
await resetPassword(values.email).then(
|
||||
() => {
|
||||
setStatus({ success: true });
|
||||
setSubmitting(false);
|
||||
dispatch(
|
||||
openSnackbar({
|
||||
open: true,
|
||||
message: 'Check mail for reset password link',
|
||||
variant: 'alert',
|
||||
alert: {
|
||||
color: 'success'
|
||||
},
|
||||
close: false
|
||||
})
|
||||
);
|
||||
setTimeout(() => {
|
||||
navigate(isLoggedIn ? '/auth/check-mail' : '/check-mail', { replace: true });
|
||||
}, 1500);
|
||||
|
||||
// WARNING: do not set any formik state here as formik might be already destroyed here. You may get following error by doing so.
|
||||
// Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.
|
||||
// To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
|
||||
// github issue: https://github.com/formium/formik/issues/2430
|
||||
},
|
||||
(err) => {
|
||||
setStatus({ success: false });
|
||||
setErrors({ submit: err.message });
|
||||
setSubmitting(false);
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: false });
|
||||
setErrors({ submit: err.message });
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
||||
<form noValidate onSubmit={handleSubmit}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="email-forgot">Email Address</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.email && errors.email)}
|
||||
id="email-forgot"
|
||||
type="email"
|
||||
value={values.email}
|
||||
name="email"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="Enter email address"
|
||||
inputProps={{}}
|
||||
/>
|
||||
{touched.email && errors.email && (
|
||||
<FormHelperText error id="helper-text-email-forgot">
|
||||
{errors.email}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
{errors.submit && (
|
||||
<Grid item xs={12}>
|
||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12} sx={{ mb: -2 }}>
|
||||
<Typography variant="caption">Do not forgot to check SPAM box.</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<AnimateButton>
|
||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
||||
Send Password Reset Email
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthForgotPassword;
|
||||
176
src/sections/auth/auth-forms/AuthLogin.js
Normal file
176
src/sections/auth/auth-forms/AuthLogin.js
Normal file
@@ -0,0 +1,176 @@
|
||||
import React from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
FormHelperText,
|
||||
Grid,
|
||||
Link,
|
||||
InputAdornment,
|
||||
InputLabel,
|
||||
OutlinedInput,
|
||||
Stack,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
// third party
|
||||
import * as Yup from 'yup';
|
||||
import { Formik } from 'formik';
|
||||
|
||||
// project import
|
||||
import useAuth from 'hooks/useAuth';
|
||||
import useScriptRef from 'hooks/useScriptRef';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
|
||||
// assets
|
||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
||||
|
||||
// ============================|| JWT - LOGIN ||============================ //
|
||||
|
||||
const AuthLogin = () => {
|
||||
const [checked, setChecked] = React.useState(false);
|
||||
|
||||
const { login } = useAuth();
|
||||
const scriptedRef = useScriptRef();
|
||||
|
||||
const [showPassword, setShowPassword] = React.useState(false);
|
||||
const handleClickShowPassword = () => {
|
||||
setShowPassword(!showPassword);
|
||||
};
|
||||
|
||||
const handleMouseDownPassword = (event) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Formik
|
||||
initialValues={{
|
||||
email: 'info@codedthemes.com',
|
||||
password: '123456',
|
||||
submit: null
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required'),
|
||||
password: Yup.string().max(255).required('Password is required')
|
||||
})}
|
||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
||||
try {
|
||||
await login(values.email, values.password);
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: true });
|
||||
setSubmitting(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: false });
|
||||
setErrors({ submit: err.message });
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
||||
<form noValidate onSubmit={handleSubmit}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="email-login">Email Address</InputLabel>
|
||||
<OutlinedInput
|
||||
id="email-login"
|
||||
type="email"
|
||||
value={values.email}
|
||||
name="email"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="Enter email address"
|
||||
fullWidth
|
||||
error={Boolean(touched.email && errors.email)}
|
||||
/>
|
||||
{touched.email && errors.email && (
|
||||
<FormHelperText error id="standard-weight-helper-text-email-login">
|
||||
{errors.email}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="password-login">Password</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.password && errors.password)}
|
||||
id="-password-login"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={values.password}
|
||||
name="password"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
endAdornment={
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle password visibility"
|
||||
onClick={handleClickShowPassword}
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
edge="end"
|
||||
color="secondary"
|
||||
>
|
||||
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
}
|
||||
placeholder="Enter password"
|
||||
/>
|
||||
{touched.password && errors.password && (
|
||||
<FormHelperText error id="standard-weight-helper-text-password-login">
|
||||
{errors.password}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sx={{ mt: -1 }}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
onChange={(event) => setChecked(event.target.checked)}
|
||||
name="checked"
|
||||
color="primary"
|
||||
size="small"
|
||||
/>
|
||||
}
|
||||
label={<Typography variant="h6">Keep me sign in</Typography>}
|
||||
/>
|
||||
<Link variant="h6" component={RouterLink} to="/forgot-password" color="text.primary">
|
||||
Forgot Password?
|
||||
</Link>
|
||||
</Stack>
|
||||
</Grid>
|
||||
{errors.submit && (
|
||||
<Grid item xs={12}>
|
||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<AnimateButton>
|
||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
||||
Login
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthLogin;
|
||||
282
src/sections/auth/auth-forms/AuthRegister.js
Normal file
282
src/sections/auth/auth-forms/AuthRegister.js
Normal file
@@ -0,0 +1,282 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link as RouterLink, useNavigate } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
Grid,
|
||||
Link,
|
||||
InputAdornment,
|
||||
InputLabel,
|
||||
OutlinedInput,
|
||||
Stack,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
// third party
|
||||
import * as Yup from 'yup';
|
||||
import { Formik } from 'formik';
|
||||
|
||||
// project import
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
|
||||
import useAuth from 'hooks/useAuth';
|
||||
import useScriptRef from 'hooks/useScriptRef';
|
||||
import { dispatch } from 'store';
|
||||
import { openSnackbar } from 'store/reducers/snackbar';
|
||||
import { strengthColor, strengthIndicator } from 'utils/password-strength';
|
||||
|
||||
// assets
|
||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
||||
|
||||
// ============================|| JWT - REGISTER ||============================ //
|
||||
|
||||
const AuthRegister = () => {
|
||||
const { register } = useAuth();
|
||||
const scriptedRef = useScriptRef();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [level, setLevel] = useState();
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const handleClickShowPassword = () => {
|
||||
setShowPassword(!showPassword);
|
||||
};
|
||||
|
||||
const handleMouseDownPassword = (event) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const changePassword = (value) => {
|
||||
const temp = strengthIndicator(value);
|
||||
setLevel(strengthColor(temp));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
changePassword('');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Formik
|
||||
initialValues={{
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
email: '',
|
||||
company: '',
|
||||
password: '',
|
||||
submit: null
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
firstname: Yup.string().max(255).required('First Name is required'),
|
||||
lastname: Yup.string().max(255).required('Last Name is required'),
|
||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required'),
|
||||
password: Yup.string().max(255).required('Password is required')
|
||||
})}
|
||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
||||
try {
|
||||
await register(values.email, values.password, values.firstname, values.lastname);
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: true });
|
||||
setSubmitting(false);
|
||||
dispatch(
|
||||
openSnackbar({
|
||||
open: true,
|
||||
message: 'Your registration has been successfully completed.',
|
||||
variant: 'alert',
|
||||
alert: {
|
||||
color: 'success'
|
||||
},
|
||||
close: false
|
||||
})
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
navigate('/login', { replace: true });
|
||||
}, 1500);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: false });
|
||||
setErrors({ submit: err.message });
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
||||
<form noValidate onSubmit={handleSubmit}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="firstname-signup">First Name*</InputLabel>
|
||||
<OutlinedInput
|
||||
id="firstname-login"
|
||||
type="firstname"
|
||||
value={values.firstname}
|
||||
name="firstname"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="John"
|
||||
fullWidth
|
||||
error={Boolean(touched.firstname && errors.firstname)}
|
||||
/>
|
||||
{touched.firstname && errors.firstname && (
|
||||
<FormHelperText error id="helper-text-firstname-signup">
|
||||
{errors.firstname}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="lastname-signup">Last Name*</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.lastname && errors.lastname)}
|
||||
id="lastname-signup"
|
||||
type="lastname"
|
||||
value={values.lastname}
|
||||
name="lastname"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="Doe"
|
||||
inputProps={{}}
|
||||
/>
|
||||
{touched.lastname && errors.lastname && (
|
||||
<FormHelperText error id="helper-text-lastname-signup">
|
||||
{errors.lastname}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="company-signup">Company</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.company && errors.company)}
|
||||
id="company-signup"
|
||||
value={values.company}
|
||||
name="company"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="Demo Inc."
|
||||
inputProps={{}}
|
||||
/>
|
||||
{touched.company && errors.company && (
|
||||
<FormHelperText error id="helper-text-company-signup">
|
||||
{errors.company}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="email-signup">Email Address*</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.email && errors.email)}
|
||||
id="email-login"
|
||||
type="email"
|
||||
value={values.email}
|
||||
name="email"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="demo@company.com"
|
||||
inputProps={{}}
|
||||
/>
|
||||
{touched.email && errors.email && (
|
||||
<FormHelperText error id="helper-text-email-signup">
|
||||
{errors.email}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="password-signup">Password</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.password && errors.password)}
|
||||
id="password-signup"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={values.password}
|
||||
name="password"
|
||||
onBlur={handleBlur}
|
||||
onChange={(e) => {
|
||||
handleChange(e);
|
||||
changePassword(e.target.value);
|
||||
}}
|
||||
endAdornment={
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle password visibility"
|
||||
onClick={handleClickShowPassword}
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
edge="end"
|
||||
color="secondary"
|
||||
>
|
||||
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
}
|
||||
placeholder="******"
|
||||
inputProps={{}}
|
||||
/>
|
||||
{touched.password && errors.password && (
|
||||
<FormHelperText error id="helper-text-password-signup">
|
||||
{errors.password}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
<FormControl fullWidth sx={{ mt: 2 }}>
|
||||
<Grid container spacing={2} alignItems="center">
|
||||
<Grid item>
|
||||
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="subtitle1" fontSize="0.75rem">
|
||||
{level?.label}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="body2">
|
||||
By Signing up, you agree to our
|
||||
<Link variant="subtitle2" component={RouterLink} to="#">
|
||||
Terms of Service
|
||||
</Link>
|
||||
and
|
||||
<Link variant="subtitle2" component={RouterLink} to="#">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
</Typography>
|
||||
</Grid>
|
||||
{errors.submit && (
|
||||
<Grid item xs={12}>
|
||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<AnimateButton>
|
||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
||||
Create Account
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthRegister;
|
||||
201
src/sections/auth/auth-forms/AuthResetPassword.js
Normal file
201
src/sections/auth/auth-forms/AuthResetPassword.js
Normal file
@@ -0,0 +1,201 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// material-ui
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
Grid,
|
||||
InputAdornment,
|
||||
InputLabel,
|
||||
OutlinedInput,
|
||||
Stack,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
// third party
|
||||
import * as Yup from 'yup';
|
||||
import { Formik } from 'formik';
|
||||
|
||||
// project import
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import AnimateButton from 'components/@extended/AnimateButton';
|
||||
|
||||
import useAuth from 'hooks/useAuth';
|
||||
import useScriptRef from 'hooks/useScriptRef';
|
||||
import { dispatch } from 'store';
|
||||
import { openSnackbar } from 'store/reducers/snackbar';
|
||||
import { strengthColor, strengthIndicator } from 'utils/password-strength';
|
||||
|
||||
// assets
|
||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
||||
|
||||
// ============================|| STATIC - RESET PASSWORD ||============================ //
|
||||
|
||||
const AuthResetPassword = () => {
|
||||
const scriptedRef = useScriptRef();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { isLoggedIn } = useAuth();
|
||||
|
||||
const [level, setLevel] = useState();
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const handleClickShowPassword = () => {
|
||||
setShowPassword(!showPassword);
|
||||
};
|
||||
|
||||
const handleMouseDownPassword = (event) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const changePassword = (value) => {
|
||||
const temp = strengthIndicator(value);
|
||||
setLevel(strengthColor(temp));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
changePassword('');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
submit: null
|
||||
}}
|
||||
validationSchema={Yup.object().shape({
|
||||
password: Yup.string().max(255).required('Password is required'),
|
||||
confirmPassword: Yup.string()
|
||||
.required('Confirm Password is required')
|
||||
.test('confirmPassword', 'Both Password must be match!', (confirmPassword, yup) => yup.parent.password === confirmPassword)
|
||||
})}
|
||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
||||
try {
|
||||
// password reset
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: true });
|
||||
setSubmitting(false);
|
||||
|
||||
dispatch(
|
||||
openSnackbar({
|
||||
open: true,
|
||||
message: 'Successfuly reset password.',
|
||||
variant: 'alert',
|
||||
alert: {
|
||||
color: 'success'
|
||||
},
|
||||
close: false
|
||||
})
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
navigate(isLoggedIn ? '/auth/login' : '/login', { replace: true });
|
||||
}, 1500);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (scriptedRef.current) {
|
||||
setStatus({ success: false });
|
||||
setErrors({ submit: err.message });
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
||||
<form noValidate onSubmit={handleSubmit}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="password-reset">Password</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.password && errors.password)}
|
||||
id="password-reset"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={values.password}
|
||||
name="password"
|
||||
onBlur={handleBlur}
|
||||
onChange={(e) => {
|
||||
handleChange(e);
|
||||
changePassword(e.target.value);
|
||||
}}
|
||||
endAdornment={
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle password visibility"
|
||||
onClick={handleClickShowPassword}
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
edge="end"
|
||||
color="secondary"
|
||||
>
|
||||
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
}
|
||||
placeholder="Enter password"
|
||||
/>
|
||||
{touched.password && errors.password && (
|
||||
<FormHelperText error id="helper-text-password-reset">
|
||||
{errors.password}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
<FormControl fullWidth sx={{ mt: 2 }}>
|
||||
<Grid container spacing={2} alignItems="center">
|
||||
<Grid item>
|
||||
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="subtitle1" fontSize="0.75rem">
|
||||
{level?.label}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1}>
|
||||
<InputLabel htmlFor="confirm-password-reset">Confirm Password</InputLabel>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
error={Boolean(touched.confirmPassword && errors.confirmPassword)}
|
||||
id="confirm-password-reset"
|
||||
type="password"
|
||||
value={values.confirmPassword}
|
||||
name="confirmPassword"
|
||||
onBlur={handleBlur}
|
||||
onChange={handleChange}
|
||||
placeholder="Enter confirm password"
|
||||
/>
|
||||
{touched.confirmPassword && errors.confirmPassword && (
|
||||
<FormHelperText error id="helper-text-confirm-password-reset">
|
||||
{errors.confirmPassword}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</Stack>
|
||||
</Grid>
|
||||
|
||||
{errors.submit && (
|
||||
<Grid item xs={12}>
|
||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<AnimateButton>
|
||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
||||
Reset Password
|
||||
</Button>
|
||||
</AnimateButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthResetPassword;
|
||||
82
src/sections/auth/auth-forms/FirebaseSocial.js
Normal file
82
src/sections/auth/auth-forms/FirebaseSocial.js
Normal file
@@ -0,0 +1,82 @@
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { useMediaQuery, Button, Stack } from '@mui/material';
|
||||
|
||||
// project import
|
||||
import useAuth from 'hooks/useAuth';
|
||||
|
||||
// assets
|
||||
import Google from 'assets/images/icons/google.svg';
|
||||
import Twitter from 'assets/images/icons/twitter.svg';
|
||||
import Facebook from 'assets/images/icons/facebook.svg';
|
||||
|
||||
// ==============================|| FIREBASE - SOCIAL BUTTON ||============================== //
|
||||
|
||||
const FirebaseSocial = () => {
|
||||
const theme = useTheme();
|
||||
const matchDownSM = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
|
||||
const { firebaseFacebookSignIn, firebaseGoogleSignIn, firebaseTwitterSignIn } = useAuth();
|
||||
const googleHandler = async () => {
|
||||
try {
|
||||
await firebaseGoogleSignIn();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const twitterHandler = async () => {
|
||||
try {
|
||||
await firebaseTwitterSignIn();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const facebookHandler = async () => {
|
||||
try {
|
||||
await firebaseFacebookSignIn();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={matchDownSM ? 1 : 2}
|
||||
justifyContent={matchDownSM ? 'space-around' : 'space-between'}
|
||||
sx={{ '& .MuiButton-startIcon': { mr: matchDownSM ? 0 : 1, ml: matchDownSM ? 0 : -0.5 } }}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
fullWidth={!matchDownSM}
|
||||
startIcon={<img src={Google} alt="Google" />}
|
||||
onClick={googleHandler}
|
||||
>
|
||||
{!matchDownSM && 'Google'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
fullWidth={!matchDownSM}
|
||||
startIcon={<img src={Twitter} alt="Twitter" />}
|
||||
onClick={twitterHandler}
|
||||
>
|
||||
{!matchDownSM && 'Twitter'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
fullWidth={!matchDownSM}
|
||||
startIcon={<img src={Facebook} alt="Facebook" />}
|
||||
onClick={facebookHandler}
|
||||
>
|
||||
{!matchDownSM && 'Facebook'}
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default FirebaseSocial;
|
||||
Reference in New Issue
Block a user