feat: initial commit and template import
This commit is contained in:
86
src/pages/Auth/Auth.styles.js
Normal file
86
src/pages/Auth/Auth.styles.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
export const FormSX = {
|
||||
p: 3,
|
||||
zIndex: 1,
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
boxShadow: 6,
|
||||
userSelect: 'none',
|
||||
overflow: 'hidden',
|
||||
position: 'absolute',
|
||||
borderRadius: '10px',
|
||||
transition: 'transform 0.3s',
|
||||
width: { xs: '90%', sm: 400 },
|
||||
transform: 'translate(-50%, -50%)',
|
||||
|
||||
img: {
|
||||
p: '16px 32px',
|
||||
},
|
||||
|
||||
button: {
|
||||
height: '3rem',
|
||||
color: 'white',
|
||||
textShadow: '1px 1px 1px rgba(0, 0, 0, 0.6)',
|
||||
},
|
||||
|
||||
a: {
|
||||
fontWeight: '500',
|
||||
lineHeight: '19px',
|
||||
color: 'primary.main',
|
||||
transition: 'color 0.3s',
|
||||
textShadow: '1px 1px 1px rgba(0, 0, 0, 0.6)',
|
||||
},
|
||||
|
||||
'@keyframes wawes': {
|
||||
from: {
|
||||
transform: 'rotate(0deg)',
|
||||
},
|
||||
to: {
|
||||
transform: 'rotate(360deg)',
|
||||
},
|
||||
},
|
||||
|
||||
'&::before, &::after': {
|
||||
content: '""',
|
||||
zIndex: -1,
|
||||
width: '600px',
|
||||
height: '800px',
|
||||
position: 'absolute',
|
||||
borderRadius: '40% 45% 35% 40%',
|
||||
},
|
||||
|
||||
'&::before': {
|
||||
top: '-35%',
|
||||
left: '75%',
|
||||
animation: 'wawes 6s linear infinite',
|
||||
background:
|
||||
'linear-gradient(90deg, rgba(0, 101, 243, 0.2) 0%, rgba(0, 120, 255, 0.4) 100%)',
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
top: '-30%',
|
||||
left: '70%',
|
||||
animation: 'wawes 8s linear infinite',
|
||||
background:
|
||||
'linear-gradient(90deg, rgba(0, 110, 255, 0.5) 0%, rgba(0, 120, 255, 0.3) 100%)',
|
||||
},
|
||||
|
||||
'& span': {
|
||||
fontSize: '0.75rem',
|
||||
},
|
||||
'& input': {
|
||||
fontSize: '16px',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
'& label.Mui-focused ': {
|
||||
pt: 0.2,
|
||||
},
|
||||
'& .MuiFormLabel-root': {
|
||||
fontSize: '16px',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'&:hover fieldset': {
|
||||
borderColor: 'primary.main',
|
||||
},
|
||||
},
|
||||
};
|
||||
37
src/pages/Auth/AuthOutlet.jsx
Normal file
37
src/pages/Auth/AuthOutlet.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Stack, useTheme, Typography } from '@mui/material';
|
||||
import { FormSX } from './Auth.styles';
|
||||
|
||||
function AuthOutlet({ children, header }) {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<form>
|
||||
<Stack
|
||||
gap={3}
|
||||
sx={{
|
||||
...FormSX,
|
||||
border: `1px solid ${theme.palette.grey.border}`,
|
||||
background: theme.palette.grey[50],
|
||||
}}
|
||||
>
|
||||
{header ? (
|
||||
<Typography textAlign="center" variant="h2">
|
||||
{header}
|
||||
</Typography>
|
||||
) : (
|
||||
<img
|
||||
src={
|
||||
theme.palette.mode === 'dark'
|
||||
? 'https://picsum.photos/100/50'
|
||||
: 'https://picsum.photos/200/300'
|
||||
}
|
||||
alt="logo"
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</Stack>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export default AuthOutlet;
|
||||
105
src/pages/Auth/Login.jsx
Normal file
105
src/pages/Auth/Login.jsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
Box,
|
||||
Stack,
|
||||
Typography,
|
||||
TextField,
|
||||
InputAdornment,
|
||||
Button,
|
||||
Link,
|
||||
IconButton,
|
||||
} from '@mui/material';
|
||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import AuthOutlet from './AuthOutlet';
|
||||
|
||||
function Login() {
|
||||
const email = React.useRef(null);
|
||||
const password = React.useRef(null);
|
||||
const navigate = useNavigate();
|
||||
const [showPassword, setShowPassword] = React.useState(false);
|
||||
const handleClickShowPassword = () => setShowPassword(!showPassword);
|
||||
const handleMouseDownPassword = () => setShowPassword(!showPassword);
|
||||
|
||||
const loginHandler = async (e) => {
|
||||
e.preventDefault();
|
||||
const user = email.current.value.replace(/\s+/g, '');
|
||||
const pwd = password.current.value.replace(/\s+/g, '');
|
||||
if (user === '') {
|
||||
// Please enter your email.
|
||||
email.current.focus();
|
||||
} else if (pwd === '') {
|
||||
// 'Please enter your password.'
|
||||
password.current.focus();
|
||||
} else {
|
||||
// do login stuff
|
||||
}
|
||||
};
|
||||
|
||||
/** Focus email input when component mounted. */
|
||||
React.useEffect(() => {
|
||||
email.current.focus();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AuthOutlet>
|
||||
<TextField
|
||||
inputRef={email}
|
||||
type="email"
|
||||
label="E-mail"
|
||||
variant="outlined"
|
||||
autoComplete="off"
|
||||
/>
|
||||
<Stack gap={1}>
|
||||
<TextField
|
||||
inputRef={password}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
label="Password"
|
||||
variant="outlined"
|
||||
sx={{ '& .MuiInputBase-root ': { pr: '4px' } }}
|
||||
autoComplete="new-password"
|
||||
InputProps={{
|
||||
// <-- This is where the toggle button sis added.
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle password visibility"
|
||||
onClick={handleClickShowPassword}
|
||||
onMouseDown={handleMouseDownPassword}
|
||||
>
|
||||
{showPassword ? <VisibilityIcon /> : <VisibilityOffIcon />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Link
|
||||
variant="body2"
|
||||
textAlign="right"
|
||||
onClick={() => navigate('/forgot-password')}
|
||||
>
|
||||
Forgot password?
|
||||
</Link>
|
||||
|
||||
<Button variant="contained" onClick={loginHandler}>
|
||||
Sign in
|
||||
</Button>
|
||||
</Stack>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Typography variant="body2" component="p">
|
||||
Dont you have an account?
|
||||
</Typography>
|
||||
<Link
|
||||
variant="body2"
|
||||
sx={{ display: 'inline', ml: 1 }}
|
||||
onClick={() => navigate('/register')}
|
||||
>
|
||||
Register
|
||||
</Link>
|
||||
</Box>
|
||||
</AuthOutlet>
|
||||
);
|
||||
}
|
||||
|
||||
export default Login;
|
||||
121
src/pages/Auth/Register.jsx
Normal file
121
src/pages/Auth/Register.jsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import React from 'react';
|
||||
import { Box, Stack, Typography, TextField, Button, Link } from '@mui/material';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import AuthOutlet from './AuthOutlet';
|
||||
|
||||
function Register() {
|
||||
const ad = React.useRef(null);
|
||||
const soyad = React.useRef(null);
|
||||
const email = React.useRef(null);
|
||||
const password = React.useRef(null);
|
||||
const passwordConf = React.useRef(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const registerHandler = async (e) => {
|
||||
e.preventDefault();
|
||||
const FirstName = ad.current.value.replace(/\s+/g, '');
|
||||
const LastName = soyad.current.value.replace(/\s+/g, '');
|
||||
const Email = email.current.value.replace(/\s+/g, '');
|
||||
const Password = password.current.value.replace(/\s+/g, '');
|
||||
const pwdConf = passwordConf.current.value.replace(/\s+/g, '');
|
||||
if (FirstName === '') {
|
||||
// 'Please enter name.'
|
||||
ad.current.focus();
|
||||
} else if (LastName === '') {
|
||||
// 'Please enter surname.'
|
||||
soyad.current.focus();
|
||||
} else if (Email === '') {
|
||||
// 'Please enter email.'
|
||||
email.current.focus();
|
||||
} else if (!/^[\w-.]+@([\w-]+\.)+[\w-]{1,20}$/.test(Email)) {
|
||||
// 'Please enter real email.'
|
||||
email.current.focus();
|
||||
} else if (Password === '') {
|
||||
// 'Please enter password.'
|
||||
password.current.focus();
|
||||
} else if (pwdConf === '') {
|
||||
// 'Please enter password again.'
|
||||
passwordConf.current.focus();
|
||||
} else if (Password !== pwdConf) {
|
||||
// 'Passwords do not match.'
|
||||
password.current.focus();
|
||||
} else if (Password.length < 6) {
|
||||
// 'Password must be at least 6 characters.'
|
||||
password.current.focus();
|
||||
} else if (
|
||||
!/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{6,}$/.test(Password)
|
||||
) {
|
||||
// 'Password must contain at least one uppercase letter, one lowercase letter and one number.',
|
||||
password.current.focus();
|
||||
} else {
|
||||
// do register stuff
|
||||
}
|
||||
};
|
||||
|
||||
/** Focus name input when component mounted. */
|
||||
React.useEffect(() => {
|
||||
ad.current.focus();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AuthOutlet>
|
||||
<Stack direction="row" gap={3} sx={{ alignItems: 'center' }}>
|
||||
<TextField
|
||||
inputRef={ad}
|
||||
label="Name"
|
||||
type="text"
|
||||
variant="outlined"
|
||||
autoComplete="off"
|
||||
/>
|
||||
<TextField
|
||||
inputRef={soyad}
|
||||
label="Surname"
|
||||
type="text"
|
||||
variant="outlined"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
<TextField
|
||||
inputRef={email}
|
||||
type="email"
|
||||
label="E-mail"
|
||||
variant="outlined"
|
||||
autoComplete="off"
|
||||
/>
|
||||
<TextField
|
||||
inputRef={password}
|
||||
type="password"
|
||||
autoComplete="new-password"
|
||||
label="Password"
|
||||
variant="outlined"
|
||||
/>
|
||||
<TextField
|
||||
inputRef={passwordConf}
|
||||
hidden
|
||||
type="password"
|
||||
autoComplete="new-password"
|
||||
label="Password (again)"
|
||||
variant="outlined"
|
||||
/>
|
||||
|
||||
<Button variant="contained" onClick={registerHandler}>
|
||||
Sign Up
|
||||
</Button>
|
||||
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Typography variant="body2" component="p">
|
||||
Alredy have an account?
|
||||
</Typography>
|
||||
<Link
|
||||
variant="body2"
|
||||
sx={{ display: 'inline', ml: 1 }}
|
||||
onClick={() => navigate('/login')}
|
||||
>
|
||||
Sign In
|
||||
</Link>
|
||||
</Box>
|
||||
</AuthOutlet>
|
||||
);
|
||||
}
|
||||
|
||||
export default Register;
|
||||
Reference in New Issue
Block a user