mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 05:54:07 +01:00
Update login page and fix bug
This commit is contained in:
parent
ca8e1d87dc
commit
91aac3dec6
@ -7,14 +7,9 @@ const baseURL = import.meta.env.VITE_BASE_URL;
|
||||
const apiUserLogin = (data) => {
|
||||
return axiosInstance
|
||||
.post("token/obtain/", data)
|
||||
.then((response) => {
|
||||
console.log(response.statusText);
|
||||
|
||||
return response;
|
||||
})
|
||||
.then((response) => response)
|
||||
.catch((error) => {
|
||||
console.log("apiUserLogin error: ", error);
|
||||
return error;
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
91
frontend/src/components/FlaotingParticles.jsx
Normal file
91
frontend/src/components/FlaotingParticles.jsx
Normal file
@ -0,0 +1,91 @@
|
||||
import { useCallback } from "react";
|
||||
import Particles from "react-tsparticles";
|
||||
import { loadFull } from "tsparticles";
|
||||
|
||||
export function FloatingParticles() {
|
||||
const particlesInit = useCallback(async (engine) => {
|
||||
await loadFull(engine);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
zIndex: 0,
|
||||
backgroundColor: "#EBF2FA",
|
||||
}}>
|
||||
<Particles
|
||||
id="particles"
|
||||
init={particlesInit}
|
||||
className="-z-10"
|
||||
options={{
|
||||
fpsLimit: 240,
|
||||
smooth: true,
|
||||
interactivity: {
|
||||
events: {
|
||||
onClick: {
|
||||
enable: true,
|
||||
mode: "push",
|
||||
},
|
||||
onHover: {
|
||||
enable: true,
|
||||
mode: "repulse",
|
||||
},
|
||||
resize: true,
|
||||
},
|
||||
modes: {
|
||||
push: {
|
||||
quantity: 4,
|
||||
},
|
||||
repulse: {
|
||||
distance: 200,
|
||||
duration: 0.4,
|
||||
},
|
||||
},
|
||||
},
|
||||
particles: {
|
||||
color: {
|
||||
value: "#4f46e5",
|
||||
},
|
||||
links: {
|
||||
color: "#818cf8",
|
||||
distance: 150,
|
||||
enable: true,
|
||||
opacity: 0.5,
|
||||
width: 1,
|
||||
},
|
||||
move: {
|
||||
direction: "none",
|
||||
enable: true,
|
||||
outModes: {
|
||||
default: "bounce",
|
||||
},
|
||||
random: false,
|
||||
speed: 2,
|
||||
straight: false,
|
||||
},
|
||||
number: {
|
||||
density: {
|
||||
enable: true,
|
||||
area: 800,
|
||||
},
|
||||
value: 40,
|
||||
},
|
||||
opacity: {
|
||||
value: 0.5,
|
||||
},
|
||||
shape: {
|
||||
type: "square",
|
||||
},
|
||||
size: {
|
||||
value: { min: 4, max: 5 },
|
||||
},
|
||||
},
|
||||
detectRetina: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,23 +1,19 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useNavigate, redirect } from "react-router-dom";
|
||||
import { useGoogleLogin } from "@react-oauth/google";
|
||||
import refreshAccessToken from "./refreshAcessToken";
|
||||
import axiosapi from "../../api/AuthenticationApi";
|
||||
import { FcGoogle } from "react-icons/fc";
|
||||
import { useAuth } from "src/hooks/AuthHooks";
|
||||
import { FloatingParticles } from "../FlaotingParticles";
|
||||
import { NavPreLogin } from "../navigations/NavPreLogin";
|
||||
|
||||
function LoginPage() {
|
||||
const { setIsAuthenticated } = useAuth();
|
||||
const Navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (!refreshAccessToken()) {
|
||||
Navigate("/");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const handleEmailChange = (event) => {
|
||||
setEmail(event.target.value);
|
||||
@ -26,6 +22,7 @@ function LoginPage() {
|
||||
const handlePasswordChange = (event) => {
|
||||
setPassword(event.target.value);
|
||||
};
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
@ -36,17 +33,13 @@ function LoginPage() {
|
||||
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;
|
||||
setIsAuthenticated(true);
|
||||
redirect("/");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("Login failed");
|
||||
console.log(err);
|
||||
setError("Incorrect username or password");
|
||||
});
|
||||
};
|
||||
|
||||
@ -70,72 +63,80 @@ function LoginPage() {
|
||||
},
|
||||
onError: (errorResponse) => console.log(errorResponse),
|
||||
});
|
||||
{
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen flex items-center justify-center bg-gradient-to-r from-zinc-100 via-gray-200 to-zinc-100">
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute inset-0 grid grid-cols-2 -space-x-52 opacity-40"
|
||||
>
|
||||
<div className="blur-[106px] h-56 bg-gradient-to-br from-pink-600 to-fuchsia-300"></div>
|
||||
<div className="blur-[106px] h-32 bg-gradient-to-r from-fuchsia-500 to-orange-500"></div>
|
||||
</div>
|
||||
{/* Login Box */}
|
||||
<div className="w-1/4 flex items-center justify-center">
|
||||
<div className="w-96 bg-white rounded-lg p-8 shadow-md space-y-4 z-10">
|
||||
<h2 className="text-3xl font-bold text-center">Login</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-success 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()}
|
||||
>
|
||||
<FcGoogle className="rounded-full bg-white" />
|
||||
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>
|
||||
<NavPreLogin text="Don't have account?" btn_text="Sign Up" link="/signup" />
|
||||
<div className="flex flex-row bg-neutral-400">
|
||||
{/* Login Box */}
|
||||
<div className="flex items-center justify-center flex-1 z-50">
|
||||
<div className="w-100 bg-white border-solid rounded-lg p-8 shadow space-y-4">
|
||||
<h2 className="text-3xl font-bold">Log in to your account</h2>
|
||||
{/* Error Message */}
|
||||
{error && (
|
||||
<div role="alert" className="alert alert-error">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="stroke-current shrink-0 h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>{error}</span>
|
||||
</div>
|
||||
)}
|
||||
{/* 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"
|
||||
value={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"
|
||||
value={password}
|
||||
onChange={handlePasswordChange}
|
||||
/>
|
||||
</div>
|
||||
{/* Login Button */}
|
||||
<button className="btn bg-blue-700 hover:bg-blue-900 w-full text-white font-bold" onClick={handleSubmit}>
|
||||
Login
|
||||
</button>
|
||||
<div className="divider">OR</div>
|
||||
{/* Login with Google Button */}
|
||||
<button className="btn bg-gray-200 btn-outline w-full " onClick={() => googleLoginImplicit()}>
|
||||
<FcGoogle className="rounded-full bg-white" />
|
||||
Login with Google
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-1/2 bg-#ebf2fa h-screen z-0">
|
||||
<FloatingParticles />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,119 +1,19 @@
|
||||
import { useCallback } from "react";
|
||||
import Particles from "react-tsparticles";
|
||||
import { loadFull } from "tsparticles";
|
||||
import { FloatingParticles } from "../FlaotingParticles";
|
||||
|
||||
export function LandingPage() {
|
||||
const particlesInit = useCallback(async (engine) => {
|
||||
console.log(engine);
|
||||
await loadFull(engine);
|
||||
}, []);
|
||||
|
||||
const particlesLoaded = useCallback(async (container) => {
|
||||
console.log(container);
|
||||
}, []);
|
||||
return (
|
||||
<div className="bg-black">
|
||||
<div>
|
||||
{/* Particles Container */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
zIndex: 0,
|
||||
backgroundColor: "black",
|
||||
}}
|
||||
>
|
||||
<Particles
|
||||
id="particles"
|
||||
init={particlesInit}
|
||||
loaded={particlesLoaded}
|
||||
className="-z-10"
|
||||
options={{
|
||||
fpsLimit: 240,
|
||||
smooth: true,
|
||||
interactivity: {
|
||||
events: {
|
||||
onClick: {
|
||||
enable: true,
|
||||
mode: "push",
|
||||
},
|
||||
onHover: {
|
||||
enable: true,
|
||||
mode: "repulse",
|
||||
},
|
||||
resize: true,
|
||||
},
|
||||
modes: {
|
||||
push: {
|
||||
quantity: 4,
|
||||
},
|
||||
repulse: {
|
||||
distance: 200,
|
||||
duration: 0.4,
|
||||
},
|
||||
},
|
||||
},
|
||||
particles: {
|
||||
color: {
|
||||
value: "#4f46e5",
|
||||
},
|
||||
links: {
|
||||
color: "#818cf8",
|
||||
distance: 150,
|
||||
enable: true,
|
||||
opacity: 0.5,
|
||||
width: 1,
|
||||
},
|
||||
move: {
|
||||
direction: "none",
|
||||
enable: true,
|
||||
outModes: {
|
||||
default: "bounce",
|
||||
},
|
||||
random: false,
|
||||
speed: 2,
|
||||
straight: false,
|
||||
},
|
||||
number: {
|
||||
density: {
|
||||
enable: true,
|
||||
area: 800,
|
||||
},
|
||||
value: 100,
|
||||
},
|
||||
opacity: {
|
||||
value: 0.5,
|
||||
},
|
||||
shape: {
|
||||
type: "square",
|
||||
},
|
||||
size: {
|
||||
value: { min: 4, max: 5 },
|
||||
},
|
||||
},
|
||||
detectRetina: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<FloatingParticles />
|
||||
{/* Navbar */}
|
||||
<div className="navbar bg-white z-10">
|
||||
<div className="navbar-start z-10">
|
||||
<a className="btn btn-ghost text-xl z-10 text-white">TurTask</a>
|
||||
</div>
|
||||
<div className="navbar-end space-x-3 pr-2 z-10">
|
||||
<a className="btn z-10" href="/login">
|
||||
Login
|
||||
</a>
|
||||
<a className="btn z-10" href="/signup">
|
||||
Sign Up
|
||||
</a>
|
||||
</div>
|
||||
<div className="navbar-end space-x-3 z-10"></div>
|
||||
</div>
|
||||
<div className="relative" id="home">
|
||||
<div className="max-w-7xl mx-auto px-6 md:px-12 xl:px-6">
|
||||
<div className="relative pt-36 ml-auto">
|
||||
<div className="lg:w-2/3 text-center mx-auto">
|
||||
<h1 className="text-gray-100 font-bold text-5xl md:text-6xl xl:text-7xl">
|
||||
<h1 className="text-#143D6C font-bold text-5xl md:text-6xl xl:text-7xl">
|
||||
Manage your task with{" "}
|
||||
<span className="text-primary">
|
||||
TurTask
|
||||
@ -124,19 +24,12 @@ export function LandingPage() {
|
||||
</label>
|
||||
</span>
|
||||
</h1>
|
||||
<p className="mt-8 text-gray-400">
|
||||
Unleash productivity with our all-in-one task and project
|
||||
management solution. Streamline your workflow, automate tasks,
|
||||
and conquer projects effortlessly.
|
||||
</p>
|
||||
<div className="mt-16 flex flex-wrap justify-center gap-y-4 gap-x-6">
|
||||
<p className="mt-8 text-#143D6C">Unleash productivity with our personal task and project management.</p>
|
||||
<div className="mt-8 flex flex-wrap justify-center gap-y-4 gap-x-6">
|
||||
<a
|
||||
href="/login"
|
||||
className="relative flex h-11 w-full items-center justify-center px-6 before:absolute before:inset-0 before:rounded-full before:bg-primary before:transition before:duration-300 hover:before:scale-105 active:duration-75 active:before:scale-95 sm:w-max"
|
||||
>
|
||||
<span className="relative text-base font-semibold text-white">
|
||||
Get started
|
||||
</span>
|
||||
className="relative flex h-11 w-full items-center justify-center px-6 before:absolute before:inset-0 before:rounded-full before:bg-primary before:transition before:duration-300 hover:before:scale-105 active:duration-75 active:before:scale-95 sm:w-max">
|
||||
<span className="relative text-base font-semibold text-white">Get started</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
16
frontend/src/components/navigations/NavPreLogin.jsx
Normal file
16
frontend/src/components/navigations/NavPreLogin.jsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export const NavPreLogin = ({ text, btn_text, link }) => {
|
||||
return (
|
||||
<div className="navbar bg-base-100 sticky top-0 z-50 border-2 border-neutral-400">
|
||||
<div className="navbar-start"></div>
|
||||
<div className="navbar-center hidden lg:flex"></div>
|
||||
<div className="navbar-end space-x-3">
|
||||
<p className="font-bold">{text}</p>
|
||||
<Link to={link} className="btn bg-blue-700 hover:bg-blue-900 text-white font-bold">
|
||||
{btn_text}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user