mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 22:14:07 +01:00
Modify Login Page
This commit is contained in:
parent
97e1557a56
commit
93c8df313f
@ -3,12 +3,11 @@ import { BrowserRouter, Route, Routes, Link } from 'react-router-dom';
|
|||||||
|
|
||||||
import TestAuth from './components/testAuth';
|
import TestAuth from './components/testAuth';
|
||||||
import IconSideNav from './components/IconSideNav';
|
import IconSideNav from './components/IconSideNav';
|
||||||
import AuthenticantionPage from './components/authentication/AuthenticationPage';
|
import LoginPage from './components/authentication/LoginPage';
|
||||||
import SignUpPage from './components/authentication/SignUpPage';
|
import SignUpPage from './components/authentication/SignUpPage';
|
||||||
import NavBar from './components/Nav/Navbar';
|
import NavBar from './components/Nav/Navbar';
|
||||||
import Home from './components/Home';
|
import Home from './components/Home';
|
||||||
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
@ -16,7 +15,7 @@ const App = () => {
|
|||||||
<NavBar/>
|
<NavBar/>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Home/>}/>
|
<Route path="/" element={<Home/>}/>
|
||||||
<Route path="/login" element={<AuthenticantionPage/>}/>
|
<Route path="/login" element={<LoginPage/>}/>
|
||||||
<Route path="/signup" element={<SignUpPage/>}/>
|
<Route path="/signup" element={<SignUpPage/>}/>
|
||||||
<Route path="/testAuth" element={<TestAuth/>}/>
|
<Route path="/testAuth" element={<TestAuth/>}/>
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|||||||
@ -1,206 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { useGoogleLogin } from '@react-oauth/google';
|
|
||||||
import Avatar from '@mui/material/Avatar';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import CssBaseline from '@mui/material/CssBaseline';
|
|
||||||
import TextField from '@mui/material/TextField';
|
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
|
||||||
import Link from '@mui/material/Link';
|
|
||||||
import Divider from '@mui/material/Divider';
|
|
||||||
import Paper from '@mui/material/Paper';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Grid from '@mui/material/Grid';
|
|
||||||
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
|
||||||
|
|
||||||
import refreshAccessToken from './refreshAcesstoken';
|
|
||||||
import axiosapi from '../../api/axiosapi';
|
|
||||||
|
|
||||||
|
|
||||||
function Copyright(props) {
|
|
||||||
return (
|
|
||||||
<Typography variant="body2" color="text.secondary" align="center" {...props}>
|
|
||||||
{'Copyright © '}
|
|
||||||
<Link color="inherit" href="https://github.com/TurTaskProject/TurTaskWeb">
|
|
||||||
TurTask
|
|
||||||
</Link>{' '}
|
|
||||||
{new Date().getFullYear()}
|
|
||||||
{'.'}
|
|
||||||
</Typography>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const defaultTheme = createTheme();
|
|
||||||
|
|
||||||
export default function SignInSide() {
|
|
||||||
|
|
||||||
const Navigate = useNavigate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!refreshAccessToken()) {
|
|
||||||
Navigate("/");
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const [email, setEmail] = useState("");
|
|
||||||
const [username, setUsername] = useState("");
|
|
||||||
const [password, setPassword] = useState("");
|
|
||||||
|
|
||||||
const handleUsernameChange = (event) => {
|
|
||||||
setUsername(event.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleEmailChange = (event) => {
|
|
||||||
setEmail(event.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePasswordChange = (event) => {
|
|
||||||
setPassword(event.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// Send a POST request to the authentication API
|
|
||||||
axiosapi.apiUserLogin({
|
|
||||||
email: email,
|
|
||||||
username: username,
|
|
||||||
password: password
|
|
||||||
}).then(res => {
|
|
||||||
// On successful login, store tokens and set the authorization header
|
|
||||||
localStorage.setItem('access_token', res.data.access);
|
|
||||||
localStorage.setItem('refresh_token', res.data.refresh);
|
|
||||||
axiosapi.axiosInstance.defaults.headers['Authorization'] = "Bearer " + res.data.access;
|
|
||||||
Navigate('/');
|
|
||||||
}).catch(err => {
|
|
||||||
console.log('Login failed'); // Handle login failure
|
|
||||||
console.log(err)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const googleLoginImplicit = useGoogleLogin({
|
|
||||||
flow: 'auth-code',
|
|
||||||
redirect_uri: 'postmessage',
|
|
||||||
onSuccess: async (response) => {
|
|
||||||
try {
|
|
||||||
const loginResponse = await axiosapi.googleLogin(response.code);
|
|
||||||
if (loginResponse && loginResponse.data) {
|
|
||||||
const { access_token, refresh_token } = loginResponse.data;
|
|
||||||
|
|
||||||
// Save the tokens in localStorage
|
|
||||||
localStorage.setItem('access_token', access_token);
|
|
||||||
localStorage.setItem('refresh_token', refresh_token);
|
|
||||||
Navigate('/');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error with the POST request:', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onError: errorResponse => console.log(errorResponse),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ThemeProvider theme={defaultTheme}>
|
|
||||||
<Grid container component="main" sx={{ height: '100vh' }}>
|
|
||||||
<CssBaseline />
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={false}
|
|
||||||
sm={4}
|
|
||||||
md={7}
|
|
||||||
sx={{
|
|
||||||
backgroundImage: 'url(https://source.unsplash.com/random?wallpapers)',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundColor: (t) =>
|
|
||||||
t.palette.mode === 'light' ? t.palette.grey[50] : t.palette.grey[900],
|
|
||||||
backgroundSize: 'cover',
|
|
||||||
backgroundPosition: 'center',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
my: 8,
|
|
||||||
mx: 4,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
|
|
||||||
<LockOutlinedIcon />
|
|
||||||
</Avatar>
|
|
||||||
<Typography component="h1" variant="h5">
|
|
||||||
Sign in
|
|
||||||
</Typography>
|
|
||||||
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 1 }}>
|
|
||||||
<TextField
|
|
||||||
margin="normal"
|
|
||||||
required
|
|
||||||
fullWidth
|
|
||||||
id="email"
|
|
||||||
label="Email Address"
|
|
||||||
name="email"
|
|
||||||
autoComplete="email"
|
|
||||||
autoFocus
|
|
||||||
onChange={handleEmailChange}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
margin="normal"
|
|
||||||
required
|
|
||||||
fullWidth
|
|
||||||
name="password"
|
|
||||||
label="Password"
|
|
||||||
type="password"
|
|
||||||
id="password"
|
|
||||||
autoComplete="current-password"
|
|
||||||
onChange={handlePasswordChange}
|
|
||||||
/>
|
|
||||||
<FormControlLabel
|
|
||||||
control={<Checkbox value="remember" color="primary" />}
|
|
||||||
label="Remember me"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
fullWidth
|
|
||||||
variant="contained"
|
|
||||||
sx={{ mt: 3, mb: 2 }}
|
|
||||||
>
|
|
||||||
Sign In
|
|
||||||
</Button>
|
|
||||||
<Divider>OR</Divider>
|
|
||||||
<Box py={2}>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
color="secondary"
|
|
||||||
onClick={() => googleLoginImplicit()}
|
|
||||||
>
|
|
||||||
Sign in with Google 🚀
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs>
|
|
||||||
<Link href="#" variant="body2">
|
|
||||||
Forgot password?
|
|
||||||
</Link>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Link href="#" variant="body2">
|
|
||||||
{"Don't have an account? Sign Up"}
|
|
||||||
</Link>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Copyright sx={{ mt: 5 }} />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
143
frontend/src/components/authentication/LoginPage.jsx
Normal file
143
frontend/src/components/authentication/LoginPage.jsx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useGoogleLogin } from "@react-oauth/google"
|
||||||
|
|
||||||
|
import refreshAccessToken from './refreshAcesstoken';
|
||||||
|
import axiosapi from '../../api/axiosapi';
|
||||||
|
|
||||||
|
function LoginPage() {
|
||||||
|
const Navigate = useNavigate();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!refreshAccessToken()) {
|
||||||
|
Navigate("/");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
|
||||||
|
const handleEmailChange = event => {
|
||||||
|
setEmail(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePasswordChange = event => {
|
||||||
|
setPassword(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = event => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Send a POST request to the authentication API
|
||||||
|
axiosapi
|
||||||
|
.apiUserLogin({
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
// On successful login, store tokens and set the authorization header
|
||||||
|
localStorage.setItem("access_token", res.data.access);
|
||||||
|
localStorage.setItem("refresh_token", res.data.refresh);
|
||||||
|
axiosapi.axiosInstance.defaults.headers["Authorization"] = "Bearer " + res.data.access;
|
||||||
|
Navigate("/");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log("Login failed");
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const googleLoginImplicit = useGoogleLogin({
|
||||||
|
flow: "auth-code",
|
||||||
|
redirect_uri: "postmessage",
|
||||||
|
onSuccess: async response => {
|
||||||
|
try {
|
||||||
|
const loginResponse = await axiosapi.googleLogin(response.code);
|
||||||
|
if (loginResponse && loginResponse.data) {
|
||||||
|
const { access_token, refresh_token } = loginResponse.data;
|
||||||
|
|
||||||
|
localStorage.setItem("access_token", access_token);
|
||||||
|
localStorage.setItem("refresh_token", refresh_token);
|
||||||
|
Navigate("/");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error with the POST request:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: errorResponse => console.log(errorResponse),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<html data-theme="night">
|
||||||
|
<div className="min-h-screen flex">
|
||||||
|
{/* Left Section (Login Box) */}
|
||||||
|
<div className="w-1/2 flex items-center justify-center">
|
||||||
|
<div className="w-96 bg-neutral rounded-lg p-8 shadow-md space-y-4">
|
||||||
|
<h2 className="text-2xl font-semibold text-left">Log in to your account</h2>
|
||||||
|
{/* Email Input */}
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label" htmlFor="email">
|
||||||
|
<p className="text-bold">
|
||||||
|
Email<span className="text-red-500 text-bold">*</span>
|
||||||
|
</p>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="input"
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
placeholder="Enter your email"
|
||||||
|
onChange={handleEmailChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* Password Input */}
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label" htmlFor="password">
|
||||||
|
<p className="text-bold">
|
||||||
|
Password<span className="text-red-500 text-bold">*</span>
|
||||||
|
</p>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="input"
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
placeholder="Enter your password"
|
||||||
|
onChange={handlePasswordChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* Login Button */}
|
||||||
|
<button className="btn btn-primary w-full" onClick={handleSubmit}>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
<div className="divider">OR</div>
|
||||||
|
{/* Login with Google Button */}
|
||||||
|
<button className="btn btn-outline btn-secondary w-full" onClick={() => googleLoginImplicit()}>
|
||||||
|
Login with Google
|
||||||
|
</button>
|
||||||
|
{/* Forgot Password Link */}
|
||||||
|
<div className="justify-left">
|
||||||
|
<a href="#" className="text-blue-500 text-sm text-left">
|
||||||
|
Forgot your password?
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Section (Blurred Image Background) */}
|
||||||
|
<div className="w-1/2 relative">
|
||||||
|
<div
|
||||||
|
className="w-full h-full bg-cover bg-center"
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url("https://th.bing.com/th/id/OIG.9byG0pWUCcbGL7Kly9tA?pid=ImgGn&w=1024&h=1024&rs=1")',
|
||||||
|
filter: "blur(2px) brightness(.5)",
|
||||||
|
}}></div>
|
||||||
|
|
||||||
|
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white text-2xl font-semibold">
|
||||||
|
Text Overlay
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoginPage;
|
||||||
Loading…
Reference in New Issue
Block a user